commit a7e7ca03502ecd8466996a9fcf285697a33aa98a Author: Mahdi Dibaiee Date: Fri Jul 24 11:14:18 2015 +0430 initial commit diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..deb174c --- /dev/null +++ b/.jshintrc @@ -0,0 +1,5 @@ +{ + "esnext": true, + "globalstrict": true, + "globals": ["module", "console", "process", "require"] +} \ No newline at end of file diff --git a/.tmp/test.js b/.tmp/test.js new file mode 100644 index 0000000..f8c2c14 --- /dev/null +++ b/.tmp/test.js @@ -0,0 +1,47 @@ +"use strict"; + +var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + +var chai = _interopRequire(require("chai")); + +var _dataStructuresTrie = require("../data-structures/trie"); + +var Node = _dataStructuresTrie.Node; +var Trie = _dataStructuresTrie.Trie; + +chai.should(); + +test("Construct new Trie", function () { + var trie = new Trie(); + + trie.root.children.length.should.equal(0); +}); + +test("Add new parent values", function () { + var trie = new Trie(); + + trie.add("a"); + trie.add("b"); + trie.add("c"); + trie.add("t"); + + trie.root.children.length.should.equal(4); +}); + +test("Adding values with existing parents", function () { + var trie = new Trie(); + + trie.add("a"); + trie.add("ab"); + trie.add("aba"); + trie.add("abas"); + + var parent = trie.root; + for (var i = 0; i < 3; i++) { + parent.children.length.should.equal(1); + parent = parent.children[0]; + } + + parent.children.length.should.equal(0); +}); + diff --git a/README.md b/README.md new file mode 100644 index 0000000..8c6c5be --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +The algorithms are written in ES6, use `babel-node` to run them. + +Most algorithms have a `-debug` version which includes logs and stuff to understand the algorithm runtime better. + +I wanted to add tests for all algorithms but I haven't yet. + +Feel free to fill an issue or create a pull request! 😜 diff --git a/data-structures/binary-tree.js b/data-structures/binary-tree.js new file mode 100644 index 0000000..b8e3861 --- /dev/null +++ b/data-structures/binary-tree.js @@ -0,0 +1,95 @@ +'use strict'; + +import _ from '../utils'; + +class Node { + constructor(value) { + this.value = value; + this.right = null; + this.left = null; + } +} + +class BinaryTree { + constructor(value) { + this.root = new Node(value); + this.length = 1; + } + + search(key, node = this.root) { + if (!node || node.value === key) { + return node; + } else if (node.value > key) { + return this.search(key, node.left); + } else { + return this.search(key, node.right); + } + } + + insert(value, node = this.root, parent = null, dir) { + if (!node) { + parent[dir] = new Node(value); + } else if (node.value > value) { + this.insert(value, node.left, node, 'left'); + } else { + this.insert(value, node.right, node, 'right'); + } + } + + remove(value, node = this.root, parent = null) { + if (!node) { + return null; + } + + // specified parent means we're recursing to delete, and + // checking has been already done + if (node.value === value || parent) { + + // number of children, !! converts to boolean, + converts to number + // false yields 0, true yields 1 + const children = +!!node.left + +!!node.right; + if (!children) { + parent.right = null; + } else if (children === 1) { + node = node.left || node.right; + } else { + node.value = node.right.value; + return this.remove(value, node.right, node, true); + } + } else if (node.value > value) { + return this.remove(value, node.left); + } else { + return this.remove(value, node.right); + } + } + // in-order + traverse(cb, node = this.root) { + if (!node) { + return; + } + + // left + this.traverse(cb, node.left); + // parent + cb(node.value); + // right + this.traverse(cb, node.right); + } +} + +let test = new BinaryTree(10); + +test.insert(6); +test.insert(18); +test.insert(4); +test.insert(8); +test.insert(15); +test.insert(21); + +_.inspect(test); + +_.log('Traverse: '); + +test.traverse(value => { + _.print(value + ' '); +}); diff --git a/data-structures/linked-lists.js b/data-structures/linked-lists.js new file mode 100644 index 0000000..17be278 --- /dev/null +++ b/data-structures/linked-lists.js @@ -0,0 +1,144 @@ +'use strict'; + +import _ from '../utils'; + +export class Node { + constructor(value, next = null) { + this.value = value; + this.next = next; + } +} + +export class List { + constructor(root) { + this.root = root; + this.length = 1; + } + + append(value) { + let node = this.root; + + while (node.next !== null) { + node = node.next; + } + + this.length++; + let newNode = new Node(value); + node.next = newNode; + + return newNode; + } + + delete(value, node = this.root) { + if (node === this.root && node.value === value) { + this.root = this.root.next; + return; + } + + while (node.next) { + if (node.next.value === value) { + node.next = node.next.next; + this.length--; + } + node = node.next; + } + } + + // Cracking the Coding Interview challenges + deleteDuplicates() { + let node = this.root; + + do { + this.delete(node.value, node.next); + node = node.next; + } while (node.next !== null) + } + + last(n) { + let target = this.length - n; + + let i = 0; + let node = this.root; + + while (i < target && node.next !== null) { + node = node.next; + i++; + } + + return node; + } + + partition(x) { + let less = [], + greater = []; + + let node = this.root; + + while (node !== null) { + if (node.value < x) { + less.push(node.value); + } else { + greater.push(node.value); + } + + node = node.next; + } + + this.root = new Node(less[0]); + less.slice(1).concat(greater).reduce((a, b) => { + a.next = new Node(b); + return a.next; + }, this.root); + } +} + +// Cracking the Coding Interview 2.5 +// Numbers are reversed (617 == 7 -> 1 -> 6 ) +const addLists = (first, last) => { + let num = 0; + + let nodes = [first.root, last.root]; + let place = 1; + while (nodes[0] !== null) { + let currentSum = (nodes[0].value + nodes[1].value) * place; + place *= 10; + + num += currentSum; + + nodes = [nodes[0].next, nodes[1].next]; + } + + return num; +}; + +let test = new List(new Node(10, new Node(5))); + +test.append(20); +test.append(8); + +test.delete(10); +test.delete(20); + +// Test deleteDuplicates +test.append(21); +let testNode = test.append(32); +test.append(21); +test.append(42); +test.append(21); +test.append(7); + +test.deleteDuplicates(); + +// Test last-nth +_.log(test.last(2).value === 42); + +// Test partition +_.log('Partition around 8'); +test.partition(8); + +_.log('Sum 7 -> 1 -> 6 AND 5 -> 9 -> 2'); +let n1 = new List(new Node(7, new Node(1, new Node(6)))); +let n2 = new List(new Node(5, new Node(9, new Node(2)))); +_.log(addLists(n1, n2) === 912); + +_.inspect(test); diff --git a/data-structures/tests/linked-lists.js b/data-structures/tests/linked-lists.js new file mode 100644 index 0000000..a556b17 --- /dev/null +++ b/data-structures/tests/linked-lists.js @@ -0,0 +1,11 @@ +import chai from 'chai'; +import {Node, List} from '../linked-lists'; + +chai.should(); + +test('Constructing new Lists', () => { + let list = new List(new Node(10, new Node(5))); + + list.root.value.should.equal(10); + list.root.next.value.should.equal(5); +}); diff --git a/data-structures/tests/trie.js b/data-structures/tests/trie.js new file mode 100644 index 0000000..fecdf14 --- /dev/null +++ b/data-structures/tests/trie.js @@ -0,0 +1,38 @@ +import chai from 'chai'; +import {Node, Trie} from '../trie'; + +chai.should(); + +test('Construct new Trie', () => { + let trie = new Trie(); + + trie.root.children.length.should.equal(0); +}); + +test('Add new parent values', () => { + let trie = new Trie(); + + trie.add('a'); + trie.add('b'); + trie.add('c'); + trie.add('t'); + + trie.root.children.length.should.equal(4); +}); + +test('Adding values with existing parents', () => { + let trie = new Trie(); + + trie.add('a'); + trie.add('ab'); + trie.add('aba'); + trie.add('abas'); + + let parent = trie.root; + for (let i = 0; i < 3; i++) { + parent.children.length.should.equal(1); + parent = parent.children[0]; + } + + parent.children.length.should.equal(0); +}); diff --git a/data-structures/trie.js b/data-structures/trie.js new file mode 100644 index 0000000..6cc5d4a --- /dev/null +++ b/data-structures/trie.js @@ -0,0 +1,28 @@ +'use strict'; + +import _ from '../utils'; + +export class Node { + constructor(value) { + this.value = value; + this.children = []; + } +} + +export class Trie { + constructor() { + this.root = new Node(); + } + + add(value, node = this.root, iteration = 0) { + let parent = node.children.find(n => { + return n.value[iteration] === value[iteration]; + }); + + if (parent) { + this.add(value, parent, iteration + 1); + } else { + node.children.push(new Node(value)); + } + } +} diff --git a/index.js b/index.js new file mode 100644 index 0000000..d1c7947 --- /dev/null +++ b/index.js @@ -0,0 +1,10 @@ +var child = require('child_process'), + args = process.argv.slice(1); + +if (args.indexOf('test') > -1) { + var path = args[2]; + + var tmp = '.tmp/test.js'; + child.execSync('babel ' + path + ' > ' + tmp); + child.execSync('mocha ' + tmp); +} diff --git a/maze/recursive-backtracker-debug.js b/maze/recursive-backtracker-debug.js new file mode 100644 index 0000000..2e1c611 --- /dev/null +++ b/maze/recursive-backtracker-debug.js @@ -0,0 +1,85 @@ +'use strict'; + +import _ from '../utils'; + +let width = parseInt(_.args[0], 10) || 10, + height = parseInt(_.args[1], 10) || 10; + +// Generate the two-dimensional array +let grid = new Array(width); + +for(let i = 0; i < width; i++) { + grid[i] = new Array(height); +} + +grid.width = width; +grid.height = height; + +// define directions in bits so we can use bitwise flags +// to merge and compare +// left 1 right 2 +// top 4 bottom 8 +let directions = [1, 2, 4, 8]; +let opposite = { + 1: 2, + 2: 1, + 4: 8, + 8: 4 +}; + +// Used to sort randomly +const randomSort = () => + Math.random() > 0.5 ? 1 : -1; + +function walker(cx, cy, grid) { + _.debug(`walker running for ${cx}, ${cy}`); + + let destination = directions.sort(randomSort); + + destination.forEach(function(dir) { + _.debug(` - direction: ${dir}`); + + // find the next block + let nx = cx + (dir === 1 ? -1 : dir === 2 ? 1 : 0), + ny = cy + (dir === 4 ? -1 : dir === 8 ? 1 : 0); + + _.debug(` - trying next block nx=${nx} ny=${ny}`); + + // Make sure the next block is in grid and we haven't visited it before + if(nx < grid.width && nx >= 0 && ny < grid.height && ny >= 0 && !grid[nx][ny]) { + _.debug(` - ${grid[cx][cy]} |= ${dir}`); + _.debug(` - ${grid[nx][ny]} |= ${opposite[dir]}`); + grid[cx][cy] |= dir; + grid[nx][ny] = opposite[dir]; + + walker(nx, ny, grid); + } + }); +} + +walker(0, 0, grid); + +_.debug(grid); + +function draw(grid) { + _.log(' ' + '_'.repeat(grid.width*2 - 1)); + + for(let i = 0; i < grid.width; i++) { + _.print('|'); + for(let j = 0; j < grid.height; j++) { + let c = grid[i][j]; + + // bottom lines + if((c & 8) === 0) _.print(" "); + else _.print("_"); + + // right lines + if((c & 2) === 0) _.print(" "); + else _.print("|"); + } + _.print('|'); + _.print('\n'); + } +} + +draw(grid); diff --git a/maze/recursive-backtracker.js b/maze/recursive-backtracker.js new file mode 100644 index 0000000..9f6d048 --- /dev/null +++ b/maze/recursive-backtracker.js @@ -0,0 +1,75 @@ +'use strict'; + +import _ from '../utils'; + +let width = parseInt(_.args[0], 10) || 10, + height = parseInt(_.args[1], 10) || 10; + +// Generate the two-dimensional array +let grid = new Array(width); + +for(let i = 0; i < width; i++) { + grid[i] = new Array(height); +} + +grid.width = width; +grid.height = height; + +// define directions in bits so we can use bitwise flags +// to merge and compare +// left 1 right 2 +// top 4 bottom 8 +let directions = [1, 2, 4, 8]; +let opposite = { + 1: 2, + 2: 1, + 4: 8, + 8: 4 +}; + +// Used to sort randomly +const randomSort = () => + Math.random() > 0.5 ? 1 : -1; + +function walker(cx, cy, grid) { + let destination = directions.sort(randomSort); + + destination.forEach(function(dir) { + // find the next block + let nx = cx + (dir === 1 ? -1 : dir === 2 ? 1 : 0), + ny = cy + (dir === 4 ? -1 : dir === 8 ? 1 : 0); + + // Make sure the next block is in grid and we haven't visited it before + if(nx < grid.width && nx >= 0 && ny < grid.height && ny >= 0 && !grid[nx][ny]) { + grid[cx][cy] |= dir; + grid[nx][ny] = opposite[dir]; + + walker(nx, ny, grid); + } + }); +} + +walker(0, 0, grid); + +function draw(grid) { + _.log(' ' + '_'.repeat(grid.width*2 - 1)); + + for(let i = 0; i < grid.width; i++) { + _.print('|'); + for(let j = 0; j < grid.height; j++) { + let c = grid[i][j]; + + // bottom lines + if((c & 8) === 0) _.print(" "); + else _.print("_"); + + // right lines + if((c & 2) === 0) _.print(" "); + else _.print("|"); + } + _.print('|'); + _.print('\n'); + } +} + +draw(grid); diff --git a/node_modules/babel/README.md b/node_modules/babel/README.md new file mode 100644 index 0000000..7af3d66 --- /dev/null +++ b/node_modules/babel/README.md @@ -0,0 +1,5 @@ +# babel-cli + +Babel CLI + +For more information please look at [babel](https://github.com/babel/babel). diff --git a/node_modules/babel/bin/_babel-node b/node_modules/babel/bin/_babel-node new file mode 100644 index 0000000..3f635d6 --- /dev/null +++ b/node_modules/babel/bin/_babel-node @@ -0,0 +1,142 @@ +#!/usr/bin/env node + +var pathIsAbsolute = require("path-is-absolute"); +var commander = require("commander"); +var Module = require("module"); +var babel = require("babel-core"); +var inspect = require("util").inspect; +var path = require("path"); +var repl = require("repl"); +var util = require("babel-core").util; +var vm = require("vm"); +var _ = require("lodash"); + +var program = new commander.Command("babel-node"); + +program.option("-e, --eval [script]", "Evaluate script"); +program.option("-p, --print [code]", "Evaluate script and print result"); +program.option("-i, --ignore [regex]", "Ignore all files that match this regex when using the require hook"); +program.option("-x, --extensions [extensions]", "List of extensions to hook into [.es6,.js,.es,.jsx]"); +program.option("-r, --stage [stage]", "Enable support for specific ECMAScript stages"); +program.option("-w, --whitelist [whitelist]", "Whitelist of transformers to ONLY use", util.list); +program.option("-b, --blacklist [blacklist]", "Blacklist of transformers to NOT use", util.list); +program.option("-o, --optional [optional]", "List of optional transformers to enable", util.list); + +var pkg = require("../package.json"); +program.version(pkg.version); +program.usage("[options] [ -e script | script.js ] [arguments]"); +program.parse(process.argv); + +// + +babel.register({ + extensions: program.extensions, + blacklist: program.blacklist, + whitelist: program.whitelist, + optional: program.optional, + ignore: program.ignore, + stage: program.stage, +}); + +// + +var _eval = function (code, filename) { + if (!code) return undefined; + + code = babel.transform(code, { + filename: filename, + blacklist: program.blacklist, + whitelist: program.whitelist, + optional: program.optional, + stage: program.stage + }).code; + + return vm.runInThisContext(code, { + filename: filename + }); +}; + +if (program.eval || program.print) { + var code = program.eval; + if (!code || code === true) code = program.print; + + global.__filename = "[eval]"; + global.__dirname = process.cwd(); + + var module = new Module(global.__filename); + module.filename = global.__filename; + module.paths = Module._nodeModulePaths(global.__dirname); + + global.exports = module.exports; + global.module = module; + global.require = module.require.bind(module); + + var result = _eval(code, global.__filename); + if (program.print) { + var output = _.isString(result) ? result : inspect(result); + process.stdout.write(output + "\n"); + } +} else { + if (program.args.length) { + // slice all arguments up to the first filename since they're babel args that we handle + var args = process.argv.slice(2); + + var i = 0; + var ignoreNext = false; + _.each(args, function (arg, i2) { + if (ignoreNext) { + ignoreNext = false; + return; + } + + if (arg[0] === "-") { + var parsedArg = program[arg.slice(2)]; + if (parsedArg && parsedArg !== true) { + ignoreNext = true; + } + } else { + i = i2; + return false; + } + }); + args = args.slice(i); + + // make the filename absolute + var filename = args[0]; + if (!pathIsAbsolute(filename)) args[0] = path.join(process.cwd(), filename); + + // add back on node and concat the sliced args + process.argv = ["node"].concat(args); + + Module.runMain(); + } else { + replStart(); + } +} + +function replStart() { + repl.start({ + prompt: "> ", + input: process.stdin, + output: process.stdout, + eval: replEval, + useGlobal: true + }); +} + +function replEval(code, context, filename, callback) { + var err; + var result; + + try { + if (code[0] === "(" && code[code.length - 1] === ")") { + code = code.slice(1, -1); // remove "(" and ")" + } + + result = _eval(code, filename); + } catch (e) { + err = e; + } + + callback(err, result); +} diff --git a/node_modules/babel/bin/babel-external-helpers b/node_modules/babel/bin/babel-external-helpers new file mode 100755 index 0000000..8c85f03 --- /dev/null +++ b/node_modules/babel/bin/babel-external-helpers @@ -0,0 +1,13 @@ +#!/usr/bin/env node + +var commander = require("commander"); +var util = require("babel-core").util; +var runtime = require("babel-core").buildExternalHelpers; + +commander.option("-l, --whitelist [whitelist]", "Whitelist of helpers to ONLY include", util.list); +commander.option("-t, --output-type [type]", "Type of output (global|umd|var)", "global"); + +commander.usage("[options]"); +commander.parse(process.argv); + +console.log(runtime(commander.whitelist, commander.outputType)); diff --git a/node_modules/babel/bin/babel-node b/node_modules/babel/bin/babel-node new file mode 100755 index 0000000..20f2a44 --- /dev/null +++ b/node_modules/babel/bin/babel-node @@ -0,0 +1,448 @@ +#!/usr/bin/env node + +/** + * This tiny wrapper file checks for known node flags and appends them + * when found, before invoking the "real" _babel-node(1) executable. + */ + +var args = [__dirname + "/_babel-node"]; + +var babelArgs = process.argv.slice(2); +var userArgs; + +// separate node arguments from script arguments +var argSeparator = babelArgs.indexOf("--"); +if (argSeparator > -1) { + userArgs = babelArgs.slice(argSeparator); // including the -- + babelArgs = babelArgs.slice(0, argSeparator); +} + +babelArgs.forEach(function(arg){ + var flag = arg.split("=")[0]; + + switch (flag) { + case "-d": + args.unshift("--debug"); + break; + + case "debug": + case "--debug": + case "--debug-brk": + args.unshift(arg); + break; + + case "-gc": + case "--expose-gc": + args.unshift("--expose-gc"); + break; + + case "--use_strict": + case "--es_staging": + case "--harmony": + case "--harmony_shipping": + case "--harmony_modules": + case "--harmony_arrays": + case "--harmony_array_includes": + case "--harmony_regexps": + case "--harmony_arrow_functions": + case "--harmony_proxies": + case "--harmony_sloppy": + case "--harmony_unicode": + case "--harmony_tostring": + case "--harmony_numeric_literals": + case "--harmony_strings": + case "--harmony_scoping": + case "--harmony_classes": + case "--harmony_object_literals": + case "--harmony_templates": + case "--compiled_keyed_generic_loads": + case "--pretenuring_call_new": + case "--allocation_site_pretenuring": + case "--trace_pretenuring": + case "--trace_pretenuring_statistics": + case "--track_fields": + case "--track_double_fields": + case "--track_heap_object_fields": + case "--track_computed_fields": + case "--track_field_types": + case "--smi_binop": + case "--vector_ics": + case "--optimize_for_size": + case "--unbox_double_arrays": + case "--string_slices": + case "--crankshaft": + case "--hydrogen_filter": + case "--use_gvn": + case "--gvn_iterations": + case "--use_canonicalizing": + case "--use_inlining": + case "--use_escape_analysis": + case "--use_allocation_folding": + case "--use_local_allocation_folding": + case "--use_write_barrier_elimination": + case "--max_inlining_levels": + case "--max_inlined_source_size": + case "--max_inlined_nodes": + case "--max_inlined_nodes_cumulative": + case "--loop_invariant_code_motion": + case "--fast_math": + case "--collect_megamorphic_maps_from_stub_cache": + case "--hydrogen_stats": + case "--trace_check_elimination": + case "--trace_hydrogen": + case "--trace_hydrogen_filter": + case "--trace_hydrogen_stubs": + case "--trace_hydrogen_file": + case "--trace_phase": + case "--trace_inlining": + case "--trace_load_elimination": + case "--trace_store_elimination": + case "--trace_alloc": + case "--trace_all_uses": + case "--trace_range": + case "--trace_gvn": + case "--trace_representation": + case "--trace_removable_simulates": + case "--trace_escape_analysis": + case "--trace_allocation_folding": + case "--trace_track_allocation_sites": + case "--trace_migration": + case "--trace_generalization": + case "--stress_pointer_maps": + case "--stress_environments": + case "--deopt_every_n_times": + case "--deopt_every_n_garbage_collections": + case "--print_deopt_stress": + case "--trap_on_deopt": + case "--trap_on_stub_deopt": + case "--deoptimize_uncommon_cases": + case "--polymorphic_inlining": + case "--use_osr": + case "--array_bounds_checks_elimination": + case "--trace_bce": + case "--array_bounds_checks_hoisting": + case "--array_index_dehoisting": + case "--analyze_environment_liveness": + case "--load_elimination": + case "--check_elimination": + case "--store_elimination": + case "--dead_code_elimination": + case "--fold_constants": + case "--trace_dead_code_elimination": + case "--unreachable_code_elimination": + case "--trace_osr": + case "--stress_runs": + case "--lookup_sample_by_shared": + case "--cache_optimized_code": + case "--flush_optimized_code_cache": + case "--inline_construct": + case "--inline_arguments": + case "--inline_accessors": + case "--escape_analysis_iterations": + case "--optimize_for_in": + case "--concurrent_recompilation": + case "--job_based_recompilation": + case "--trace_concurrent_recompilation": + case "--concurrent_recompilation_queue_length": + case "--concurrent_recompilation_delay": + case "--block_concurrent_recompilation": + case "--concurrent_osr": + case "--omit_map_checks_for_leaf_maps": + case "--turbo_filter": + case "--trace_turbo": + case "--trace_turbo_graph": + case "--trace_turbo_cfg_file": + case "--trace_turbo_types": + case "--trace_turbo_scheduler": + case "--trace_turbo_reduction": + case "--trace_turbo_jt": + case "--turbo_asm": + case "--turbo_verify": + case "--turbo_stats": + case "--turbo_types": + case "--turbo_source_positions": + case "--context_specialization": + case "--turbo_deoptimization": + case "--turbo_inlining": + case "--turbo_inlining_intrinsics": + case "--trace_turbo_inlining": + case "--loop_assignment_analysis": + case "--turbo_profiling": + case "--turbo_reuse_spill_slots": + case "--turbo_delay_ssa_decon": + case "--turbo_move_optimization": + case "--turbo_jt": + case "--typed_array_max_size_in_heap": + case "--frame_count": + case "--interrupt_budget": + case "--type_info_threshold": + case "--generic_ic_threshold": + case "--self_opt_count": + case "--trace_opt_verbose": + case "--debug_code": + case "--code_comments": + case "--enable_sse3": + case "--enable_sse4_1": + case "--enable_sahf": + case "--enable_avx": + case "--enable_fma3": + case "--enable_vfp3": + case "--enable_armv7": + case "--enable_armv8": + case "--enable_neon": + case "--enable_sudiv": + case "--enable_mls": + case "--enable_movw_movt": + case "--enable_unaligned_accesses": + case "--enable_32dregs": + case "--enable_vldr_imm": + case "--force_long_branches": + case "--expose_natives_as": + case "--expose_debug_as": + case "--expose_free_buffer": + case "--expose_gc": + case "--expose_gc_as": + case "--expose_externalize_string": + case "--expose_trigger_failure": + case "--stack_trace_limit": + case "--builtins_in_stack_traces": + case "--disable_native_files": + case "--inline_new": + case "--trace_codegen": + case "--trace": + case "--mask_constants_with_cookie": + case "--lazy": + case "--trace_opt": + case "--trace_opt_stats": + case "--opt": + case "--always_opt": + case "--always_osr": + case "--prepare_always_opt": + case "--trace_deopt": + case "--trace_stub_failures": + case "--serialize_toplevel": + case "--serialize_inner": + case "--trace_serializer": + case "--min_preparse_length": + case "--max_opt_count": + case "--compilation_cache": + case "--cache_prototype_transitions": + case "--cpu_profiler_sampling_interval": + case "--trace_debug_json": + case "--trace_js_array_abuse": + case "--trace_external_array_abuse": + case "--trace_array_abuse": + case "--enable_liveedit": + case "--hard_abort": + case "--stack_size": + case "--max_stack_trace_source_length": + case "--always_inline_smi_code": + case "--min_semi_space_size": + case "--target_semi_space_size": + case "--max_semi_space_size": + case "--semi_space_growth_factor": + case "--experimental_new_space_growth_heuristic": + case "--max_old_space_size": + case "--initial_old_space_size": + case "--max_executable_size": + case "--gc_global": + case "--gc_interval": + case "--trace_gc": + case "--trace_gc_nvp": + case "--trace_gc_ignore_scavenger": + case "--trace_idle_notification": + case "--trace_idle_notification_verbose": + case "--print_cumulative_gc_stat": + case "--print_max_heap_committed": + case "--trace_gc_verbose": + case "--trace_fragmentation": + case "--collect_maps": + case "--weak_embedded_maps_in_optimized_code": + case "--weak_embedded_objects_in_optimized_code": + case "--flush_code": + case "--flush_code_incrementally": + case "--trace_code_flushing": + case "--age_code": + case "--incremental_marking": + case "--incremental_marking_steps": + case "--concurrent_sweeping": + case "--trace_incremental_marking": + case "--track_gc_object_stats": + case "--heap_profiler_trace_objects": + case "--use_idle_notification": + case "--use_ic": + case "--trace_ic": + case "--native_code_counters": + case "--always_compact": + case "--never_compact": + case "--compact_code_space": + case "--incremental_code_compaction": + case "--cleanup_code_caches_at_gc": + case "--use_marking_progress_bar": + case "--zap_code_space": + case "--random_seed": + case "--trace_weak_arrays": + case "--track_prototype_users": + case "--use_verbose_printer": + case "--allow_natives_syntax": + case "--trace_parse": + case "--trace_sim": + case "--debug_sim": + case "--check_icache": + case "--stop_sim_at": + case "--sim_stack_alignment": + case "--sim_stack_size": + case "--log_regs_modified": + case "--log_colour": + case "--ignore_asm_unimplemented_break": + case "--trace_sim_messages": + case "--stack_trace_on_illegal": + case "--abort_on_uncaught_exception": + case "--randomize_hashes": + case "--hash_seed": + case "--profile_deserialization": + case "--regexp_optimization": + case "--testing_bool_flag": + case "--testing_maybe_bool_flag": + case "--testing_int_flag": + case "--testing_float_flag": + case "--testing_string_flag": + case "--testing_prng_seed": + case "--testing_serialization_file": + case "--startup_blob": + case "--profile_hydrogen_code_stub_compilation": + case "--predictable": + case "--help": + case "--dump_counters": + case "--debugger": + case "--map_counters": + case "--js_arguments": + case "--gdbjit": + case "--gdbjit_full": + case "--gdbjit_dump": + case "--gdbjit_dump_filter": + case "--force_marking_deque_overflows": + case "--stress_compaction": + case "--log": + case "--log_all": + case "--log_api": + case "--log_code": + case "--log_gc": + case "--log_handles": + case "--log_snapshot_positions": + case "--log_suspect": + case "--prof": + case "--prof_browser_mode": + case "--log_regexp": + case "--logfile": + case "--logfile_per_isolate": + case "--ll_prof": + case "--perf_basic_prof": + case "--perf_jit_prof": + case "--gc_fake_mmap": + case "--log_internal_timer_events": + case "--log_timer_events": + case "--log_instruction_stats": + case "--log_instruction_file": + case "--log_instruction_period": + case "--redirect_code_traces": + case "--redirect_code_traces_to": + case "--hydrogen_track_positions": + case "--trace_elements_transitions": + case "--trace_creation_allocation_sites": + case "--print_code_stubs": + case "--test_secondary_stub_cache": + case "--test_primary_stub_cache": + case "--print_code": + case "--print_opt_code": + case "--print_unopt_code": + case "--print_code_verbose": + case "--print_builtin_code": + case "--sodium": + case "--print_all_code": + case "--es5_readonly": + case "--es52_globals": + case "--harmony_typeof": + case "--harmony_collections": + case "--packed_arrays": + case "--smi_only_arrays": + case "--clever_optimizations": + case "--use_range": + case "--eliminate_dead_phis": + case "--optimize_closures": + case "--loop_weight": + case "--opt_safe_uint32_operations": + case "--parallel_recompilation": + case "--trace_parallel_recompilation": + case "--parallel_recompilation_queue_length": + case "--experimental_profiler": + case "--watch_ic_patching": + case "--self_optimization": + case "--direct_self_opt": + case "--retry_self_opt": + case "--count_based_interrupts": + case "--interrupt_at_exit": + case "--weighted_back_edges": + case "--debug_code (generate extra code": + case "--enable_sse2": + case "--enable_cmov": + case "--enable_rdtsc": + case "--enable_vfp2": + case "--enable_fpu": + case "--stack_trace_on_abort": + case "--always_full_compiler": + case "--debugger_auto_break": + case "--break_on_abort": + case "--max_new_space_size": + case "--trace_external_memory": + case "--lazy_sweeping": + case "--trace_exception": + case "--preallocate_message_memory": + case "--preemption": + case "--extra_code": + case "--remote_debugger": + case "--debugger_agent": + case "--debugger_port": + case "--debug_compile_events": + case "--debug_script_collected_events": + case "--gdbjit": + case "--log_runtime": + case "--prof_auto": + case "--prof_lazy": + case "--sliding_state_window": + args.unshift(arg); + break; + + default: + if (arg.indexOf("--trace") === 0) { + args.unshift(arg); + } else { + args.push(arg); + } + break; + } +}); + +// append arguments passed after -- +if (argSeparator > -1) { + args = args.concat(userArgs); +} + +try { + var kexec = require("kexec"); + kexec(process.argv[0], args); +} catch (err) { + if (err.code !== "MODULE_NOT_FOUND") throw err; + + var child_process = require("child_process"); + var proc = child_process.spawn(process.argv[0], args, { stdio: "inherit" }); + proc.on("exit", function (code, signal) { + process.on("exit", function () { + if (signal) { + process.kill(process.pid, signal); + } else { + process.exit(code); + } + }) + }); +} diff --git a/node_modules/babel/bin/babel/dir.js b/node_modules/babel/bin/babel/dir.js new file mode 100644 index 0000000..6e0e0cd --- /dev/null +++ b/node_modules/babel/bin/babel/dir.js @@ -0,0 +1,78 @@ +var outputFileSync = require("output-file-sync"); +var chokidar = require("chokidar"); +var path = require("path"); +var util = require("./util"); +var fs = require("fs"); +var _ = require("lodash"); + +module.exports = function (commander, filenames, opts) { + var write = function (src, relative) { + // remove extension and then append back on .js + relative = relative.replace(/\.(\w*?)$/, "") + ".js"; + + var dest = path.join(commander.outDir, relative); + + var data = util.compile(src, { + sourceFileName: path.relative(dest + "/..", src) + }); + + if (commander.sourceMaps && commander.sourceMaps !== "inline") { + var mapLoc = dest + ".map"; + data.code = util.addSourceMappingUrl(data.code, mapLoc); + outputFileSync(mapLoc, JSON.stringify(data.map)); + } + + outputFileSync(dest, data.code); + + console.log(src + " -> " + dest); + }; + + var handleFile = function (src, filename) { + if (util.shouldIgnore(src)) return; + + if (util.canCompile(filename)) { + write(src, filename); + } else if (commander.copyFiles) { + outputFileSync(path.join(commander.outDir, filename), fs.readFileSync(src)); + } + }; + + var handle = function (filename) { + if (!fs.existsSync(filename)) return; + + var stat = fs.statSync(filename); + + if (stat.isDirectory(filename)) { + var dirname = filename; + + _.each(util.readdir(dirname), function (filename) { + var src = path.join(dirname, filename); + handleFile(src, filename); + }); + } else { + write(filename, filename); + } + }; + + _.each(filenames, handle); + + if (commander.watch) { + _.each(filenames, function (dirname) { + var watcher = chokidar.watch(dirname, { + persistent: true, + ignoreInitial: true + }); + + _.each(["add", "change"], function (type) { + watcher.on(type, function (filename) { + var relative = path.relative(dirname, filename) || filename; + try { + handleFile(filename, relative); + } catch (err) { + console.error(err.stack); + } + }); + }); + }); + } +}; diff --git a/node_modules/babel/bin/babel/file.js b/node_modules/babel/bin/babel/file.js new file mode 100644 index 0000000..4d905a4 --- /dev/null +++ b/node_modules/babel/bin/babel/file.js @@ -0,0 +1,143 @@ +var convertSourceMap = require("convert-source-map"); +var sourceMap = require("source-map"); +var chokidar = require("chokidar"); +var path = require("path"); +var util = require("./util"); +var fs = require("fs"); +var _ = require("lodash"); + +module.exports = function (commander, filenames, opts) { + if (commander.sourceMaps === "inline") { + opts.sourceMaps = true; + } + + var results = []; + + var buildResult = function () { + var map = new sourceMap.SourceMapGenerator({ + file: commander.outFile || "stdout" + }); + + var code = ""; + var offset = 0; + + _.each(results, function (result) { + var filename = result.filename; + code += result.code + "\n"; + + if (result.map) { + var consumer = new sourceMap.SourceMapConsumer(result.map); + + map._sources.add(filename); + map.setSourceContent(filename, result.actual); + + consumer.eachMapping(function (mapping) { + map._mappings.add({ + generatedLine: mapping.generatedLine + offset, + generatedColumn: mapping.generatedColumn, + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + source: filename + }); + }); + + offset = code.split("\n").length; + } + }); + + if (commander.sourceMaps === "inline" || (!commander.outFile && commander.sourceMaps)) { + code += "\n" + convertSourceMap.fromObject(map).toComment(); + } + + return { + map: map, + code: code + }; + }; + + var output = function () { + var result = buildResult(); + + if (commander.outFile) { + if (commander.sourceMaps && commander.sourceMaps !== "inline") { + var mapLoc = commander.outFile + ".map"; + result.code = util.addSourceMappingUrl(result.code, mapLoc); + fs.writeFileSync(mapLoc, JSON.stringify(result.map)); + } + + fs.writeFileSync(commander.outFile, result.code); + } else { + process.stdout.write(result.code + "\n"); + } + }; + + var stdin = function () { + var code = ""; + + process.stdin.setEncoding("utf8"); + + process.stdin.on("readable", function () { + var chunk = process.stdin.read(); + if (chunk !== null) code += chunk; + }); + + process.stdin.on("end", function () { + results.push(util.transform(commander.filename, code)); + output(); + }); + }; + + var walk = function () { + var _filenames = []; + results = []; + + _.each(filenames, function (filename) { + if (!fs.existsSync(filename)) return; + + var stat = fs.statSync(filename); + if (stat.isDirectory()) { + var dirname = filename; + + _.each(util.readdirFilter(filename), function (filename) { + _filenames.push(path.join(dirname, filename)); + }); + } else { + _filenames.push(filename); + } + }); + + _.each(_filenames, function (filename) { + if (util.shouldIgnore(filename)) return; + + results.push(util.compile(filename)); + }); + + output(); + }; + + var files = function () { + walk(); + + if (commander.watch) { + chokidar.watch(filenames, { + persistent: true, + ignoreInitial: true + }).on("all", function (type, filename) { + if (type === "add" || type === "change") { + console.log(type, filename); + try { + walk(); + } catch (err) { + console.error(err.stack); + } + } + }); + } + }; + + if (filenames.length) { + files(); + } else { + stdin(); + } +}; diff --git a/node_modules/babel/bin/babel/index.js b/node_modules/babel/bin/babel/index.js new file mode 100755 index 0000000..48b214d --- /dev/null +++ b/node_modules/babel/bin/babel/index.js @@ -0,0 +1,122 @@ +#!/usr/bin/env node + +var commander = require("commander"); +var transform = require("babel-core").transform; +var kebabCase = require("lodash/string/kebabCase"); +var options = require("babel-core").options; +var util = require("babel-core").util; +var each = require("lodash/collection/each"); +var keys = require("lodash/object/keys"); +var fs = require("fs"); + +each(options, function (option, key) { + if (option.hidden) return; + + var arg = kebabCase(key); + + if (option.type !== "boolean") { + arg += " [" + (option.type || "string") + "]"; + } + + if (option.type === "boolean" && option.default === true) { + arg = "no-" + arg; + } + + arg = "--" + arg; + + if (option.shorthand) { + arg = "-" + option.shorthand + ", " + arg; + } + + var desc = []; + if (option.deprecated) desc.push("[DEPRECATED] " + option.deprecated); + if (option.description) desc.push(option.description); + + commander.option(arg, desc.join(" ")); +}) + +commander.option("-w, --watch", "Recompile files on changes"); +commander.option("-o, --out-file [out]", "Compile all input files into a single file"); +commander.option("-d, --out-dir [out]", "Compile an input directory of modules into an output directory"); +commander.option("-D, --copy-files", "When compiling a directory copy over non-compilable files"); + +commander.on("--help", function () { + var outKeys = function (title, obj) { + console.log(" " + title + ":"); + console.log(); + + each(keys(obj).sort(), function (key) { + if (key[0] === "_") return; + + if (obj[key].optional) key = "[" + key + "]"; + + console.log(" - " + key); + }); + + console.log(); + }; + + outKeys("Transformers", transform.transformers); + outKeys("Module formatters", transform.moduleFormatters); +}); + +var pkg = require("../../package.json"); +commander.version(pkg.version); +commander.usage("[options] "); +commander.parse(process.argv); + +// + +var errors = []; + +var filenames = commander.args; + +each(filenames, function (filename) { + if (!fs.existsSync(filename)) { + errors.push(filename + " doesn't exist"); + } +}); + +if (commander.outDir && !filenames.length) { + errors.push("filenames required for --out-dir"); +} + +if (commander.outFile && commander.outDir) { + errors.push("cannot have --out-file and --out-dir"); +} + +if (commander.watch) { + if (!commander.outFile && !commander.outDir) { + errors.push("--watch requires --out-file or --out-dir"); + } + + if (!filenames.length) { + errors.push("--watch requires filenames"); + } +} + +if (errors.length) { + console.error(errors.join(". ")); + process.exit(2); +} + +// + +var opts = exports.opts = {}; + +each(options, function (opt, key) { + opts[key] = commander[key]; +}); + +opts.ignore = util.arrayify(opts.ignore, util.regexify); +opts.only = util.arrayify(opts.only, util.regexify); + +var fn; + +if (commander.outDir) { + fn = require("./dir"); +} else { + fn = require("./file"); +} + +fn(commander, filenames, exports.opts); diff --git a/node_modules/babel/bin/babel/util.js b/node_modules/babel/bin/babel/util.js new file mode 100644 index 0000000..1de4d89 --- /dev/null +++ b/node_modules/babel/bin/babel/util.js @@ -0,0 +1,42 @@ +var readdir = require("fs-readdir-recursive"); +var index = require("./index"); +var babel = require("babel-core"); +var util = require("babel-core").util; +var path = require("path"); +var fs = require("fs"); +var _ = require("lodash"); + +exports.readdirFilter = function (filename) { + return readdir(filename).filter(function (filename) { + return util.canCompile(filename); + }); +}; + +exports.readdir = readdir; + +exports.canCompile = util.canCompile; + +exports.shouldIgnore = function (loc) { + return util.shouldIgnore(loc, index.opts.ignore, index.opts.only); +}; + +exports.addSourceMappingUrl = function (code, loc) { + return code + "\n//# sourceMappingURL=" + path.basename(loc); +}; + +exports.transform = function (filename, code, opts) { + opts = _.defaults(opts || {}, index.opts); + opts.filename = filename; + opts.ignore = null; + opts.only = null; + + var result = babel.transform(code, opts); + result.filename = filename; + result.actual = code; + return result; +}; + +exports.compile = function (filename, opts) { + var code = fs.readFileSync(filename, "utf8"); + return exports.transform(filename, code, opts); +}; diff --git a/node_modules/babel/index.js b/node_modules/babel/index.js new file mode 100644 index 0000000..4a0e83d --- /dev/null +++ b/node_modules/babel/index.js @@ -0,0 +1 @@ +module.exports = require("babel-core"); diff --git a/node_modules/babel/node_modules/babel-core/CHANGELOG-6to5.md b/node_modules/babel/node_modules/babel-core/CHANGELOG-6to5.md new file mode 100644 index 0000000..6005a2d --- /dev/null +++ b/node_modules/babel/node_modules/babel-core/CHANGELOG-6to5.md @@ -0,0 +1,1093 @@ +# 6to5 Changelog + +## 3.6.6 + + * **Internal** + * Upgrade `core-js`. + * **Bug Fix** + * Fix temp variables not being properly pushed inside of `while` loops. + * **New Feature** + * Add `auxiliaryComment`/`--auxiliary-comment` option that prepends comments to auxiliary helpers. + +## 3.6.5 + + * **Internal** + * Upgrade `core-js`. + * **Bug Fix** + * Fix block scoping leaking variables in IIFE mode. + * Fix tail call transformer exploding on return statements as the consequent of an if statement. + * **New Feature** + * Add `validation.react` transformer. + +## 3.6.4 + + * **New Feature** + * Add support for flow type casts and module types. + +## 3.6.3 + + * **Internal** + * Upgrade `acorn-6to5`. + * Use `default` property on `6to5-runtime`. + +## 3.6.2 + + * **Polish** + * Use better iterator detection in `slicedToArray` helper and add support for it to the `selfContained` transformer. + +## 3.6.1 + + * **Bug Fix** + * Multiline JSX string literals are now supported. + * Fix scope tracking import specifiers incorrectly. + * Fix templates incorrectly recursing into their replacements. + * **Internal** + * Type inferrence now extends to function return types. + * Upgrade `acorn-6to5`. + +## 3.6.0 + + * **New Feature** + * Add playground class property initializers. + * **Polish** + * Completely reimplemented scope tracking, can now track types and optimise certain helpers based on it. + * Extremely fast tail recursion optimisation implementation. Thanks [@RReverser](https://github.com/RReverser)! + * **Internal** + * `kexec` has been removed as an optional dependency and must be user installed. + * Upgrade `regenerator-6to5`. + * Upgrade `acorn-6to5`. + * Upgrade `core-js`. + +## 3.5.3 + + * Enable `es6.tailCall` transformer with the first implementation that only works with self referencing calls until we can implement nested tail calls elegantly. + +## 3.5.2 + + * Disable `es6.tailCall` temporairly after reports of it breaking. + +## 3.5.1 + + * **Polish** + * Allow tail calls to work across files without the runtime. + * **Internal** + * Upgrade `acorn-6to5`. + +## 3.5.0 + + * **Bug Fix** + * Destructuring patterns as the left operator in `ForInStatement`/`ForOfStatement`. + * **Polish** + * Make default parameter IIFE invocation smarter. + * Make `__esModule` flag non-enumerable. Thanks [@daliwali](https://github.com/daliwali)! + * **Internal** + * More performance improvements. + * Parsing is now ~30% faster thanks to [marijnh/acorn@7264bc0178e7e6af7cfe02e9e0c6b26ee0e6007f](https://github.com/marijnh/acorn/commit/7264bc0178e7e6af7cfe02e9e0c6b26ee0e6007f). + * **New Feature** + * Optional `es6.blockScopingTDZ` is now completely functional and handles all edgecases. + * `super` in object literals. + * Tail call optimisation. Thanks [@RReverser](https://github.com/RReverser)! + +## 3.4.1 + + * **Bug Fix** + * Fix conflicting `--module-ids` shorthand arg in `$ 6to5`. + * Add require hook options to cache key. + * Fix strict module formatter. + +## 3.4.0 + + * **New Feature** + * Add `commonStandard` module formatter. + * **Bug Fix** + * Fix conflicting `--module-ids` shorthand arg in `$ 6to5`. + * **Internal** + * Lots of internal refactoring with scope tracking and traversal. + * **Polish** + * Don't return `map` in the API result if `sourceMap` was set to `"inline"`. + +## 3.3.12 + + * **Bug Fix** + * Don't override `MemberExpression`s with `core-js` in `selfContained` if a local binding exists. + +## 3.3.11 + + * **Bug Fix** + * Fix the require cache. + +## 3.3.10 + + * **Internal** + * Restructure transformers so they're only ran if the AST contains nodes that they need to worry about. Improves transpilation speed significantly. + * **Bug Fix** + * Fix source maps not tracking end of node locations. + * **Spec Compliancy** + * Use static super references as the home object is actually done at definition time. + * **Polish** + * Force the `es6.destructuring` transformer to be whitelisted when the `es7.objectSpread` transformer is. + * Join sibling string literals when creating JSX. + +## 3.3.9 + + * **Bug Fix** + * Fix super inside of functions. + * Fix super constructor inheritance. + +## 3.3.7 + + * **Bug Fix** + * Add `--use-strict` to valid node flags in `6to5-node`. + * Fix booleans not being properly stripped from the arguments in `6to5-node`. + * Force `.js` extension when writing files to directories with `6to5`. + +## 3.3.5 + + * **Bug Fix** + * Fix block scoping inside of while loops. + * Make module name regex more conservative. Thanks [@johlrich](https://github.com/johlrich)! + * Fix block scoping of constants. + * Fix istanbul interop. + * Make JSX transforming more inline with the official transformer with spaces after non-empty last lines. + * **Polish** + * Make it illegal to export a property called `__esModule`. + +## 3.3.4 + + * **Polish** + * Add istanbul `require` interop. + * **Bug Fix** + * Fix incorrect source map column tracking in specific scenarios. + +## 3.3.3 + + * **Polish** + * Remap top level `this` to `undefined` instead of throwing an error. + * **Bug Fix** + * Run `selfContained` transformer over the regenerator runtime when building `6to5-runtime`. + * Fix `t.isReferenced` not properly allowing `value` nodes. + +## 3.3.1 + + * **Bug Fix** + * Block hoist assignment pattern destructuring. + +## 3.3.0 + + * **Bug Fix** + * Do all transforms before the regenerator transform is ran. + * **New Feature** + * Added back the 2.x optional runtime. + +## 3.2.1 + + * **Bug Fix** + * Fix block scoping transformer rewriting breaks and continues to inner labels. + +## 3.2.0 + + * **Bug Fix** + * Fixed scope tracking for default parameters IIFE. + * Fixed block scoped functions. + * Improved `bin/6to5` path resolution. + * **New Feature** + * You can now trigger super setters in classes. Thanks [@kruppel](https://github.com/kruppel)! + * Add `resolveSourceMap` option. + * Better support and output for block scoping loops with labels. + +## 3.1.1 + + * **Polish** + * Drop `enumerable: false` clause from class method definitions as `enumerable` already defaults to `false`. + * **Bug Fix** + * Properly transform `XJSIdentifier` nodes referencing `this` into a `ThisExpression`. + +## 3.1.0 + + * **Breaking Change** + * [Make class methods unenumerable](https://esdiscuss.org/topic/classes-and-enumerability#content-61). + +## 3.0.16 + + * **Bug Fix** + * Don't ignore dynamic import specifiers. + * **Internal** + * Upgrade `regenerator-6to5`. + * **Polish** + * Use `Object.assign` in place of extends helper if it exists. + * Require individual `lodash` methods. Thanks [@stefanpenner](https://github.com/stefanpenner)! + +## 3.0.15 + + * **Bug Fix** + * Use `debug/node` instead of `debug` to avoid browserify using the browser version that references `window`. + +## 3.0.14 + + * **New Feature** + * Add `--optional` argument to `6to5-node`. + * **Bug Fix** + * Fix bug in `asyncToGenerator` helper where it was incorrectly calling generator iterator functions. + +## 3.0.13 + + * **Bug Fix** + * Fix modules loose mode using `modules` instead of `es6.modules`. + +## 3.0.12 + + * **Internal** + * Add internal debug messages. + * **Bug Fix** + * Add `noScope` option to `traverse.clearProperties`. + +## 3.0.11 + + * **Bug Fix** + * Fix `ast-types` `RestElement` definition. + * Make `es6.forOf` loose mode more versatile and support destructuring. + +## 3.0.10 + + * **Bug Fix** + * In `types.getIds` make sure the `declaration` inside of `ExportDeclaration` is actually a `Declaration`. + +## 3.0.9 + + * **Bug Fix** + * Make `t.isReferenced` more powerful, actually take into consideration all contexts were identifier nodes aren't actually references. + * Don't camelcase underscores when converting a string to a valid identifier. + +## 3.0.8 + + * **Bug Fix** + * Split up default function declaration exports due to regenerator destroying the parent export declaration. + +## 3.0.7 + + * **Internal** + * Upgrade `core-js` to `0.4.9`. + * **Bug Fix** + * Add id to function express scope tracking. + +## 3.0.6 + + * **Bug Fix** + * Fix block scope variable tracking stopping whenever it hits a new scope. + * Fix block scope variable tracking breaking on all block statement scopes that have a for loop parent. + +## 3.0.5 + + * **Internal** + * More reliable default parameter scope. + +## 3.0.4 + + * **Bug Fix** + * Remove traversal stops from block scope tracking. + +## 3.0.3 + + * **Internal** + * Ignore options starting with `_`. + +## 3.0.2 + + * **Internal** + * Add common plugin options to valid options list. + +## 3.0.1 + + * **Internal** + * Downgrade `kexec` as `1.1.0` throws compilation errors. + +## 3.0.0 + + * **Polish** + * Generated code autoindentation. + * Moved global uid registry to a scope registry resulting in nicer uids. + * `this` is now illegal in the top level scope when using the default `useStrict` transformer. + * New `asyncToGenerator` helper that's much more compact. + * Throw errors on unknown options. + * More reliable default parameter scope. + * Helpers are now compact and have no newlines. + * **Internal** + * Rewritten a lot of the internals to much simpler. + * Removed TDZ from default parameters as it was very wonky and unreliable. + * Upgrade `core-js` to `0.4.6`. + * Upgrade `acorn-6to5`. + * JSX support is now on-par with react-tools/esprima. + * Shorthand destructuring. + * **Bug Fix** + * Generators now work flawlessly with any parameter transformers. + * Optional async function transformers should not name their functions. + * Remove `unlink` event watching in `bin/6to5`. + * Fix regenerator variable declarations being incorrectly hoisted breaking scope. + * Transformers that attempted to simplify expressions that had no consequence now take into account whether it's one of the last statements/expressions in the script. + * **New Feature** + * New `selfContained` transformer. + * New `undeclaredVariableCheck` optional transformer. + * Added `--blacklist` and `--whitelist` options to `6to5-node`. + * **Breaking Change** + * Caching is now always enabled for the require hook. It also now no longer caches require resolutions. + * Bare `super();` only works inside of constructors. + * Removed the optional runtime in favor of the `selfContained` transformer. + * This shorthand has been removed from the playground. + * `6to5/polyfill` can now only be required **once**. + * **CLI** + * `--indent` option has been removed. + * `--include-regenerator` option has been removed. + * `--amd-modules-id` option has been removed, use `--module-ids` instead. + * **Options** + * `amdModuleIds` option has been removed, use `moduleIds` instead. + * `includeRegenerator` has been removed. + * `ignoreRegex` fallback has now been dropped from the require hook. `register(/foo/);`, `register({ ignoreRegex: /foo/ })` -> `register({ ignore: /foo/ })`. + * **Modules** + * Module interop now only collapses to `module.exports` when there's a **single** export that's default. + * Imports and exports are now illegal anywhere except the root level by default. Set `modules` to [loose mode](http://6to5.org/docs/usage/loose) to allow them everywhere. + * **Transformers** + * Optional fast transformer backwards compatibility support has been removed. Use [loose mode](https://6to5.org/docs/usage/loose). + * Removed the `coreAliasing` transformer in favor of `selfContained`. + * Renamed transformers: + * `specNoForInOfAssignment` -> `validation.noForInOfAssignment` + * `specSetters` -> `validation.setters` + * `specBlockScopedFunctions` -> `spec.blockScopedFunctions` + * `malletOperator` -> `playground.malletOperator` + * `methodBinding` -> `playground.methodBinding` + * `memoizationOperator` -> `playground.memoizationOperator` + * `objectGetterMemoization` -> `playground.objectGetterMemoization` + * `modules` -> `es6.modules` + * `propertyNameShorthand` -> `es6.properties.shorthand` + * `arrayComprehension` -> `es7.comprehensions` + * `generatorComprehension` -> `es7.comprehensions` + * `arrowFunctions` -> `es6.arrowFunctions` + * `classes` -> `es6.classes` + * `objectSpread` -> `es7.objectSpread` + * `exponentiationOperator` -> `es7.exponentiationOperator` + * `spread` -> `es6.spread` + * `templateLiterals` -> `es6.templateLiterals` + * `propertyMethodAssignment` -> `es6.properties.shorthand` + * `computedPropertyNames` -> `es6.properties.computed` + * `defaultParameters` -> `es6.parameters.default` + * `restParameters` -> `es6.parameters.rest` + * `destructuring` -> `es6.destructuring` + * `forOf` -> `es6.forOf` + * `unicodeRegex` -> `es6.unicodeRegex` + * `abstractReferences` -> `es7.abstractReferences` + * `constants` -> `es6.constants` + * `letScoping` -> `es6.blockScoping` + * `blockScopingTDZ` -> `es6.blockScopingTDZ` + * `generators` -> `regenerator` + * `protoToAssign` -> `spec.protoToAssign` + * `typeofSymbol` -> `spec.typeofSymbol` + * `coreAliasing` -> `selfContained` + * `undefinedToVoid` -> `spec.undefinedToVoid` + * `undeclaredVariableCheck` -> `validation.undeclaredVariableCheck` + * `specPropertyLiterals` -> `minification.propertyLiterals` + * `specMemberExpressionLiterals` -> `minification.memberExpressionLiterals` + +## 2.13.7 + + * **Bug Fix** + * Don't realias variables that are already declared in optional `coreAliasing` transformer. + +## 2.13.6 + + * **Bug Fix** + * Add `NewExpression` as a valid parent for parentheses insertion for `ConditionalExpression`. + +## 2.13.5 + + * **Bug Fix** + * Allow rest parameters to be destructuring patterns. + * **Internal** + * Upgrade `kexec` to `1.1.0`. + +## 2.13.4 + + * **Bug Fix** + * Fix ordering of destructuring and default params. + * Fix loop body scope. + * Fix `for...of` transformation not retaining it's scope. + * Add destructuring assignment support to scope tracking. + * **Polish** + * More reliable newlines for pretty printing variable declarations. + +## 2.13.3 + + * **Internal** + * Add `coverage` and `vendor` to npmignore. + +## 2.13.2 + + * **Bug Fix** + * Fix `super` inside of nested functions. + * **Internal** + * Move let scoping TDZ into a separate transformer until it's more solid. + * Use `process.stdin.write` instead of `console.log` in `bin` to avoid sprintfification. + +## 2.13.1 + + * **New Feature** + * Temporal dead zone for block binding. + +## 2.13.0 + + * **New Feature** + * Block scoped functions. + * Add `--loose all` option. + * Add playground mallet operator thanks to [@jridgewell](https://github.com/jridgewell). + * **Bug Fix** + * Rewrote large parts of the let scoping transformer. Now passes all known tests. + * **Internal** + * Even more optimisations thanks to the awesome [@gaearon](https://github.com/gaearon). + * Upgrade `acorn-6to5`. + * Fixes exponentation operator thanks to [@charliesome](https://github.com/charliesome). + * Fix flow optional parameters with types. + * Upgrade `chokidar` to `0.12.6`. + * Upgrade `commander` to `2.6.0`. + * Upgrade `core-js` to `0.4.5`. + * Upgrade `estraverse` to `1.9.1`. + * Upgrade `jshint` to `2.5.11`. + * Upgrade `regenerator` to `0.8.9`. + * Upgrade `regexpu` to `1.0.0`. + * Upgrade `source-map` to `0.1.43`. + * Upgrade `source-map-support` to `0.2.9`. + * Upgrade `browserify` to `8.1.1`. + * Upgrade `chai` to `1.10.0`. + * Upgrade `istanbul` to `0.3.5`. + * Upgrade `mocha` to `2.1.0`. + * Upgrade `uglify-js` to `2.4.16`. + +## 2.12.6 + + * **Bug Fix** + * Add missing flow type traversal keys. + +## 2.12.5 + + * **Internal** + * Fix incorrect `for...in` loop still causing `ember-script` issues. + +## 2.12.4 + + * **Polish** + * Rest parameters now allocate the array before populating. + * **Internal** + * `for...in` loops have been changed to optimized `for` loops - better performance and no enumeration of protoype keys. + * Parts of the code generator have now been optimized thanks to [gaearon](https://github.com/gaearon). + +## 2.12.3 + + * **Spec Compliancy** + * Optional `typeof` transformer checks for `undefined` before passing it to the helper. + * Class methods are now named. + +## 2.12.2 + + * **Internal** + * Exclude nodes in function parameters and catch clauses from `isReferenced` check. + +## 2.12.1 + + * **Internal** + * Add `.jsx` to list of allowed extensions. + +## 2.12.0 + + * **Bug Fix** + * Support non-string JSX literals. + * **New Feature** + * Loose mode for some transformers that enables non-spec behavior. + * **Internal** + * Uglify `--mangle sort` has been added to the build script, cutting minified scripts in half. + +## 2.11.4 + + * **Internal** + * Make all dependency versions fixed. + +## 2.11.3 + + * **Bug Fix** + * Allow a string to be passed as the `optional` option. + +## 2.11.2 + + * **Bug Fix** + * Support esprima-style catch clause handlers. + * **Polish** + * Don't print a stacktrace for syntax errors in the CLI. + +## 2.11.1 + + * **Bug Fix** + * Remove stray `console.log` outputting debug code. + * Remove `Dict` from `coreAliasing`. + +## 2.11.0 + + * **Bug Fix** + * Fix unnecessary IIFE in default parameters on method calls. + * Add support for supers inside of closures. + * **New Feature** + * Add `--keep-module-id-extensions`/`keepModuleIdExtensions` option to keep extensions in module ids. + * **Polish** + * Special case single argument spread properties in `super` inside classes. + * Don't use a variable declaration for class declaration IFFE. + * Rename `inherits` helper parameters. + * `coreAliasing` transformer now aliases `Promise`, `Set`, `Map` and more. Thanks [@AluisioASG](https://github.com/AluisioASG). + +## 2.10.1 + + * **Internal** + * Upgrade `core-js` to `0.4.4`. + * **New Feature** + * Added `--include-regenerator` option to CLI and `includeRegenerator` option to API that includes the regenerator runtime if necessary. + +## 2.10.0 + + * **New Feature** + * Add `classesFastSuper` optional transformer that doesn't support parent getters and prototype changing. + * Add `forOfFast` transformer that speeds up `for...of` on arrays but produces more code. + * Add `--react-compat` to `bin/6to5`. + * **Spec Compliancy** + * Disallow setters without a single parameter. + * Add `configurable` and `writable` to defined properties. + * Use define instead of assignment for class methods. + * **Polish** + * Fix bin name in `6to5-node --help`. + * Fix shorthand `--whitelist` name in `bin/6to5`. + * **Internal** + * Hot code optimisation of traversal etc thanks to [gaearon](https://github.com/gaearon). + +## 2.9.4 + + * **Bug Fix** + * Support `UpdateExpression`s as `MemberExpression` objects. + +## 2.9.3 + + * **Bug Fix** + * Remove `exportsWildcard` helper in favor of `defaults`. + +## 2.9.2 + + * **Bug Fix** + * Pass `exports` to `exportWildcard` helper to allow for use inside the optional runtime. + +## 2.9.1 + + * **Bug Fix** + * Fix runtime generator breaking the helper inclusion loop. + +## 2.9.0 + + * **Internal** + * Upgrade `acorn-6to5`. + * Now supports destructuring shorthand properties. + +## 2.8.1 + + * **Bug Fix** + * Fix computed accessors on object literals. + +## 2.8.0 + + * **New Feature** + * Add `commonStrict`, `amdStrict` and `umdStrict` module formatters that remove `module.exports` interop assignment. + * Add `--indent` option to the 6to5 CLI. + +## 2.7.4 + + * **Polish** + * Inherit assignments from their declaration in destructuring. + * Properly align multi-declarator variable declarations. + +## 2.7.3 + + * **Polish** + * Indent and add newlines to `React.createElement` calls in `react` transformer. + * Remove `Object.assign` calls and replace it with an `extends` helper. + +## 2.7.1 + + * **New Feature** + * Expose `version` on browser and node API. + * **Internal** + * Upgrade `core-js` to 0.4.1 + +## 2.7.0 + + * **Spec Compliancy** + * Disallow reassignments of imports. + * **New Feature** + * `reactCompat` option to enable pre-v0.12 react components. + +## 2.6.3 + + * **Bug Fix** + * Fix 2.6.0 regression caused by faulty export default from a source handling. + +## 2.6.2 + + * **Bug Fix** + * Fix rest parameter keys when on functions with params. + +## 2.6.1 + + * **Bug Fix** + * Fix rest parameter arguments key. + +## 2.6.0 + + * **Bug Fix** + * Better handling of number literal property keys. + * Handle `NewExpression` paren insertion edegcases better. + * **Internal** + * Fix incorrect AST node `identifier("this")`. + * Better `toIdentifier` method that handles reserved words. + * Upgrade `acorn-6to5`. + * Fix exponentiation operator precedence. + * Fix line terminators after async contextual keywords. + * Add semicolons as class elements inside of a class body. + * Upgrade to `core-js` 4.0.0. + * Upgrade to `regenerator` 0.8.3. + * Fix non-loop labeled statements. + * **New Feature** + * Basic destructuring defaults + * Add `.es` to list of supported extensions. + * Add optional `typeofSymbol` transformer. + * Use a `for` loop for rest parameters instead of `Array.prototype.slice`. + * **Polish** + * Move `"use strict";` to inside module bodies instead of at the top of the file. + * Better handling of dynamic imports. + * **Spec Compliancy** + * Class inheritance now has a `function` or `null` type check. + * Add `interopRequireWildcard` around wildcard imports and exports to handle non-object exports. + +## 2.5.0 + + * Remove `noDuplicateProperties` transformer. + * Better generated UIDs based on nodes. + * Default parameters now use `arguments[i]`, conditionals and variable declarations instead of using long-form if statements. + +## 2.4.10 + + * Upgrade `acorn-6to5`. + +## 2.4.9 + + * Upgrade `acorn-6to5`. + * Add optional `protoToAssign` transformer. + * Fix missing properties from computed property keys. + * Make ES7 comprehensions `let` variables. + +## 2.4.8 + + * Make `require("6to5/register")` work with browserify - [#370](https://github.com/6to5/6to5/pull/370). Thanks [@hughsk](https://github.com/hughsk)! + +## 2.4.7 + + * Upgrade `acorn-6to5`. + +## 2.4.6 + + * Move `coreAliasing` and `undefinedToVoid` transformers down to catch `moduleFormatter` transforms. + +## 2.4.5 + + * Avoid printing comments if they've already been output. + +## 2.4.4 + + * Add `module` type to browser build `'; + } +}; + +}); // module: filters.js + +require.register("inline-tags.js", function(module, exports, require){ + +/*! + * Jade - inline tags + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = [ + 'a' + , 'abbr' + , 'acronym' + , 'b' + , 'br' + , 'code' + , 'em' + , 'font' + , 'i' + , 'img' + , 'ins' + , 'kbd' + , 'map' + , 'samp' + , 'small' + , 'span' + , 'strong' + , 'sub' + , 'sup' +]; +}); // module: inline-tags.js + +require.register("jade.js", function(module, exports, require){ +/*! + * Jade + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Parser = require('./parser') + , Lexer = require('./lexer') + , Compiler = require('./compiler') + , runtime = require('./runtime') + +/** + * Library version. + */ + +exports.version = '0.26.1'; + +/** + * 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); + } +} + +/** + * Compile a `Function` representation of the given jade `str`. + * + * Options: + * + * - `compileDebug` when `false` debugging code is stripped from the compiled template + * - `client` when `true` the helper functions `escape()` etc will reference `jade.escape()` + * for use with the Jade client-side runtime.js + * + * @param {String} str + * @param {Options} options + * @return {Function} + * @api public + */ + +exports.compile = function(str, options){ + var options = options || {} + , client = options.client + , filename = options.filename + ? JSON.stringify(options.filename) + : 'undefined' + , fn; + + if (options.compileDebug !== false) { + fn = [ + 'var __jade = [{ lineno: 1, filename: ' + filename + ' }];' + , 'try {' + , parse(String(str), options) + , '} catch (err) {' + , ' rethrow(err, __jade[0].filename, __jade[0].lineno);' + , '}' + ].join('\n'); + } else { + fn = parse(String(str), options); + } + + if (client) { + fn = 'attrs = attrs || jade.attrs; escape = escape || jade.escape; rethrow = rethrow || jade.rethrow; merge = merge || jade.merge;\n' + fn; + } + + fn = new Function('locals, attrs, escape, rethrow, merge', fn); + + if (client) return fn; + + return function(locals){ + return fn(locals, runtime.attrs, runtime.escape, runtime.rethrow, runtime.merge); + }; +}; + +/** + * 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; + +}); // module: jade.js + +require.register("lexer.js", function(module, exports, require){ + +/*! + * Jade - Lexer + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * 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 `start` / `end` delimiters. + * + * @param {String} start + * @param {String} end + * @return {Number} + * @api private + */ + + indexOfDelimiters: function(start, end){ + var str = this.input + , nstart = 0 + , nend = 0 + , pos = 0; + for (var i = 0, len = str.length; i < len; ++i) { + if (start == str.charAt(i)) { + ++nstart; + } else if (end == str.charAt(i)) { + if (++nend == nstart) { + pos = i; + break; + } + } + } + return pos; + }, + + /** + * 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); + 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() { + var captures; + if (captures = /^#\{(.*?)\}/.exec(this.input)) { + this.consume(captures[0].length); + return this.tok('interpolation', captures[1]); + } + }, + + /** + * 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)) { + if (!/^ *[-\w]+ *=/.test(captures[1])) { + this.consume(captures[0].length); + tok.args = captures[1]; + } + } + + 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 = /^(!?=|-)([^\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[0] === '='; + tok.buffer = flags[0] === '=' || flags[1] === '='; + return tok; + } + }, + + /** + * Attributes. + */ + + attrs: function() { + if ('(' == this.input.charAt(0)) { + var index = this.indexOfDelimiters('(', ')') + , 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(_, expr){ + return quote + " + (" + expr + ") + " + quote; + }); + } + + 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(); + } +}; + +}); // module: lexer.js + +require.register("nodes/attrs.js", function(module, exports, require){ + +/*! + * Jade - nodes - Attrs + * Copyright(c) 2010 TJ Holowaychuk + * 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 = new Node; +Attrs.prototype.constructor = Attrs; + + +/** + * 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; + } + } +}; + +}); // module: nodes/attrs.js + +require.register("nodes/block-comment.js", function(module, exports, require){ + +/*! + * Jade - nodes - BlockComment + * Copyright(c) 2010 TJ Holowaychuk + * 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 = new Node; +BlockComment.prototype.constructor = BlockComment; + +}); // module: nodes/block-comment.js + +require.register("nodes/block.js", function(module, exports, require){ + +/*! + * Jade - nodes - Block + * Copyright(c) 2010 TJ Holowaychuk + * 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 = new Node; +Block.prototype.constructor = Block; + + +/** + * 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(); + } + + 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; +}; + + +}); // module: nodes/block.js + +require.register("nodes/case.js", function(module, exports, require){ + +/*! + * Jade - nodes - Case + * Copyright(c) 2010 TJ Holowaychuk + * 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 = new Node; +Case.prototype.constructor = Case; + + +var When = exports.When = function When(expr, block){ + this.expr = expr; + this.block = block; + this.debug = false; +}; + +/** + * Inherit from `Node`. + */ + +When.prototype = new Node; +When.prototype.constructor = When; + + + +}); // module: nodes/case.js + +require.register("nodes/code.js", function(module, exports, require){ + +/*! + * Jade - nodes - Code + * Copyright(c) 2010 TJ Holowaychuk + * 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 = new Node; +Code.prototype.constructor = Code; + +}); // module: nodes/code.js + +require.register("nodes/comment.js", function(module, exports, require){ + +/*! + * Jade - nodes - Comment + * Copyright(c) 2010 TJ Holowaychuk + * 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 = new Node; +Comment.prototype.constructor = Comment; + +}); // module: nodes/comment.js + +require.register("nodes/doctype.js", function(module, exports, require){ + +/*! + * Jade - nodes - Doctype + * Copyright(c) 2010 TJ Holowaychuk + * 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 = new Node; +Doctype.prototype.constructor = Doctype; + +}); // module: nodes/doctype.js + +require.register("nodes/each.js", function(module, exports, require){ + +/*! + * Jade - nodes - Each + * Copyright(c) 2010 TJ Holowaychuk + * 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 = new Node; +Each.prototype.constructor = Each; + +}); // module: nodes/each.js + +require.register("nodes/filter.js", function(module, exports, require){ + +/*! + * Jade - nodes - Filter + * Copyright(c) 2010 TJ Holowaychuk + * 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; + this.isASTFilter = !block.nodes.every(function(node){ return node.isText }); +}; + +/** + * Inherit from `Node`. + */ + +Filter.prototype = new Node; +Filter.prototype.constructor = Filter; + +}); // module: nodes/filter.js + +require.register("nodes/index.js", function(module, exports, require){ + +/*! + * Jade - nodes + * Copyright(c) 2010 TJ Holowaychuk + * 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'); + +}); // module: nodes/index.js + +require.register("nodes/literal.js", function(module, exports, require){ + +/*! + * Jade - nodes - Literal + * Copyright(c) 2010 TJ Holowaychuk + * 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 + .replace(/\\/g, "\\\\") + .replace(/\n|\r\n/g, "\\n") + .replace(/'/g, "\\'"); +}; + +/** + * Inherit from `Node`. + */ + +Literal.prototype = new Node; +Literal.prototype.constructor = Literal; + + +}); // module: nodes/literal.js + +require.register("nodes/mixin.js", function(module, exports, require){ + +/*! + * Jade - nodes - Mixin + * Copyright(c) 2010 TJ Holowaychuk + * 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 = new Attrs; +Mixin.prototype.constructor = Mixin; + + + +}); // module: nodes/mixin.js + +require.register("nodes/node.js", function(module, exports, require){ + +/*! + * Jade - nodes - Node + * Copyright(c) 2010 TJ Holowaychuk + * 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; +}; + +}); // module: nodes/node.js + +require.register("nodes/tag.js", function(module, exports, require){ + +/*! + * Jade - nodes - Tag + * Copyright(c) 2010 TJ Holowaychuk + * 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 = new Attrs; +Tag.prototype.constructor = Tag; + + +/** + * 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; +}; +}); // module: nodes/tag.js + +require.register("nodes/text.js", function(module, exports, require){ + +/*! + * Jade - nodes - Text + * Copyright(c) 2010 TJ Holowaychuk + * 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 = new Node; +Text.prototype.constructor = Text; + + +/** + * Flag as text. + */ + +Text.prototype.isText = true; +}); // module: nodes/text.js + +require.register("parser.js", function(module, exports, require){ + +/*! + * Jade - Parser + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Lexer = require('./lexer') + , nodes = require('./nodes'); + +/** + * 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; + } + + return block; + }, + + /** + * 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') + , 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 + , 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') + , node = new nodes.Code(tok.val, tok.buffer, tok.escape) + , block + , 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') + , 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') + , node = new nodes.Doctype(tok.val); + node.line = this.line(); + return node; + }, + + /** + * filter attrs? text-block + */ + + parseFilter: function(){ + var block + , tok = this.expect('filter') + , attrs = this.accept('attrs'); + + 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; + }, + + /** + * tag ':' attrs? block + */ + + parseASTFilter: function(){ + var block + , tok = this.expect('tag') + , attrs = this.accept('attrs'); + + this.expect(':'); + block = this.block(); + + 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') + , node = new nodes.Each(tok.code, tok.val, tok.key); + node.line = this.line(); + node.block = this.block(); + return node; + }, + + /** + * 'extends' name + */ + + parseExtends: function(){ + var path = require('path') + , fs = require('fs') + , dirname = path.dirname + , basename = path.basename + , join = path.join; + + if (!this.filename) + throw new Error('the "filename" option is required to extend templates'); + + var path = this.expect('extends').val.trim() + , dir = dirname(this.filename); + + var path = join(dir, path + '.jade') + , str = fs.readFileSync(path, 'utf8') + , parser = new Parser(str, path, this.options); + + parser.blocks = this.blocks; + parser.contexts = this.contexts; + this.extending = parser; + + // TODO: null node + return new nodes.Literal(''); + }, + + /** + * 'block' name block + */ + + parseBlock: function(){ + var block = this.expect('block') + , mode = block.mode + , name = block.val.trim(); + + block = 'indent' == this.peek().type + ? this.block() + : new nodes.Block(new nodes.Literal('')); + + var prev = this.blocks[name]; + + if (prev) { + switch (prev.mode) { + case 'append': + block.nodes = block.nodes.concat(prev.nodes); + prev = block; + break; + case 'prepend': + block.nodes = prev.nodes.concat(block.nodes); + prev = block; + break; + } + } + + block.mode = mode; + return this.blocks[name] = prev || block; + }, + + /** + * include block? + */ + + parseInclude: function(){ + var path = require('path') + , fs = require('fs') + , dirname = path.dirname + , basename = path.basename + , join = path.join; + + var path = this.expect('include').val.trim() + , dir = dirname(this.filename); + + if (!this.filename) + throw new Error('the "filename" option is required to use includes'); + + // no extension + if (!~basename(path).indexOf('.')) { + path += '.jade'; + } + + // non-jade + if ('.jade' != path.substr(-5)) { + var path = join(dir, path) + , str = fs.readFileSync(path, 'utf8'); + return new nodes.Literal(str); + } + + var path = join(dir, path) + , str = fs.readFileSync(path, 'utf8') + , parser = new Parser(str, path, this.options); + parser.blocks = 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') + , name = tok.val + , args = tok.args + , 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') + , name = tok.val + , args = tok.args + , 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; + if (':' == this.lookahead(i).type) { + if ('indent' == this.lookahead(++i).type) { + return this.parseASTFilter(); + } + } + + var tok = this.advance() + , 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; + } +}; + +}); // module: parser.js + +require.register("runtime.js", function(module, exports, require){ + +/*! + * Jade - runtime + * Copyright(c) 2010 TJ Holowaychuk + * 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(/&(?!(\w+|\#\d+);)/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; + + 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; +}; + +}); // module: runtime.js + +require.register("self-closing.js", function(module, exports, require){ + +/*! + * Jade - self closing tags + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = [ + 'meta' + , 'img' + , 'link' + , 'input' + , 'source' + , 'area' + , 'base' + , 'col' + , 'br' + , 'hr' +]; +}); // module: self-closing.js + +require.register("utils.js", function(module, exports, require){ + +/*! + * Jade - utils + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Convert interpolation in the given string to JavaScript. + * + * @param {String} str + * @return {String} + * @api private + */ + +var interpolate = exports.interpolate = function(str){ + return str.replace(/(\\)?([#!]){(.*?)}/g, function(str, escape, flag, code){ + return escape + ? str + : "' + " + + ('!' == flag ? '' : 'escape') + + "((interp = " + code.replace(/\\'/g, "'") + + ") == null ? '' : interp) + '"; + }); +}; + +/** + * Escape single quotes in `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +var escape = exports.escape = function(str) { + return str.replace(/'/g, "\\'"); +}; + +/** + * Interpolate, and escape the given `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +exports.text = function(str){ + return interpolate(escape(str)); +}; +}); // module: utils.js + +window.jade = require("jade"); +})(); diff --git a/node_modules/mocha/node_modules/jade/jade.md b/node_modules/mocha/node_modules/jade/jade.md new file mode 100644 index 0000000..051dc03 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/jade.md @@ -0,0 +1,510 @@ + +# Jade + + The jade template engine for node.js + +## Synopsis + + jade [-h|--help] [-v|--version] [-o|--obj STR] + [-O|--out DIR] [-p|--path PATH] [-P|--pretty] + [-c|--client] [-D|--no-debug] + +## Examples + + translate jade the templates dir + + $ jade templates + + create {foo,bar}.html + + $ jade {foo,bar}.jade + + jade over stdio + + $ jade < my.jade > my.html + + jade over s + + $ echo "h1 Jade!" | jade + + foo, bar dirs rendering to /tmp + + $ jade foo bar --out /tmp + + compile client-side templates without debugging + instrumentation, making the output javascript + very light-weight. This requires runtime.js + in your projects. + + $ jade --client --no-debug < my.jade + +## Tags + + Tags are simply nested via whitespace, closing + tags defined for you. These indents are called "blocks". + + ul + li + a Foo + li + a Bar + + You may have several tags in one "block": + + ul + li + a Foo + a Bar + a Baz + +## Self-closing Tags + + Some tags are flagged as self-closing by default, such + as `meta`, `link`, and so on. To explicitly self-close + a tag simply append the `/` character: + + foo/ + foo(bar='baz')/ + + Would yield: + + + + +## Attributes + + Tag attributes look similar to HTML, however + the values are regular JavaScript, here are + some examples: + + a(href='google.com') Google + a(class='button', href='google.com') Google + + As mentioned the attribute values are just JavaScript, + this means ternary operations and other JavaScript expressions + work just fine: + + body(class=user.authenticated ? 'authenticated' : 'anonymous') + a(href=user.website || 'http://google.com') + + Multiple lines work too: + + input(type='checkbox', + name='agreement', + checked) + + Multiple lines without the comma work fine: + + input(type='checkbox' + name='agreement' + checked) + + Funky whitespace? fine: + + input( + type='checkbox' + name='agreement' + checked) + +## Boolean attributes + + Boolean attributes are mirrored by Jade, and accept + bools, aka _true_ or _false_. When no value is specified + _true_ is assumed. For example: + + input(type="checkbox", checked) + // => "" + + For example if the checkbox was for an agreement, perhaps `user.agreed` + was _true_ the following would also output 'checked="checked"': + + input(type="checkbox", checked=user.agreed) + +## Class attributes + + The _class_ attribute accepts an array of classes, + this can be handy when generated from a javascript + function etc: + + classes = ['foo', 'bar', 'baz'] + a(class=classes) + // => "" + +## Class literal + + Classes may be defined using a ".CLASSNAME" syntax: + + .button + // => "
" + + Or chained: + + .large.button + // => "
" + + The previous defaulted to divs, however you + may also specify the tag type: + + h1.title My Title + // => "

My Title

" + +## Id literal + + Much like the class literal there's an id literal: + + #user-1 + // => "
" + + Again we may specify the tag as well: + + ul#menu + li: a(href='/home') Home + li: a(href='/store') Store + li: a(href='/contact') Contact + + Finally all of these may be used in any combination, + the following are all valid tags: + + a.button#contact(style: 'color: red') Contact + a.button(style: 'color: red')#contact Contact + a(style: 'color: red').button#contact Contact + +## Block expansion + + Jade supports the concept of "block expansion", in which + using a trailing ":" after a tag will inject a block: + + ul + li: a Foo + li: a Bar + li: a Baz + +## Text + + Arbitrary text may follow tags: + + p Welcome to my site + + yields: + +

Welcome to my site

+ +## Pipe text + + Another form of text is "pipe" text. Pipes act + as the text margin for large bodies of text. + + p + | This is a large + | body of text for + | this tag. + | + | Nothing too + | exciting. + + yields: + +

This is a large + body of text for + this tag. + + Nothing too + exciting. +

+ + Using pipes we can also specify regular Jade tags + within the text: + + p + | Click to visit + a(href='http://google.com') Google + | if you want. + +## Text only tags + + As an alternative to pipe text you may add + a trailing "." to indicate that the block + contains nothing but plain-text, no tags: + + p. + This is a large + body of text for + this tag. + + Nothing too + exciting. + + Some tags are text-only by default, for example + _script_, _textarea_, and _style_ tags do not + contain nested HTML so Jade implies the trailing ".": + + script + if (foo) { + bar(); + } + + style + body { + padding: 50px; + font: 14px Helvetica; + } + +## Template script tags + + Sometimes it's useful to define HTML in script + tags using Jade, typically for client-side templates. + + To do this simply give the _script_ tag an arbitrary + _type_ attribute such as _text/x-template_: + + script(type='text/template') + h1 Look! + p Jade still works in here! + +## Interpolation + + Both plain-text and piped-text support interpolation, + which comes in two forms, escapes and non-escaped. The + following will output the _user.name_ in the paragraph + but HTML within it will be escaped to prevent XSS attacks: + + p Welcome #{user.name} + + The following syntax is identical however it will _not_ escape + HTML, and should only be used with strings that you trust: + + p Welcome !{user.name} + +## Inline HTML + + Sometimes constructing small inline snippets of HTML + in Jade can be annoying, luckily we can add plain + HTML as well: + + p Welcome #{user.name} + +## Code + + To buffer output with Jade simply use _=_ at the beginning + of a line or after a tag. This method escapes any HTML + present in the string. + + p= user.description + + To buffer output unescaped use the _!=_ variant, but again + be careful of XSS. + + p!= user.description + + The final way to mess with JavaScript code in Jade is the unbuffered + _-_, which can be used for conditionals, defining variables etc: + + - var user = { description: 'foo bar baz' } + #user + - if (user.description) { + h2 Description + p.description= user.description + - } + + When compiled blocks are wrapped in anonymous functions, so the + following is also valid, without braces: + + - var user = { description: 'foo bar baz' } + #user + - if (user.description) + h2 Description + p.description= user.description + + If you really want you could even use `.forEach()` and others: + + - users.forEach(function(user){ + .user + h2= user.name + p User #{user.name} is #{user.age} years old + - }) + + Taking this further Jade provides some syntax for conditionals, + iteration, switch statements etc. Let's look at those next! + +## Assignment + + Jade's first-class assignment is simple, simply use the _=_ + operator and Jade will _var_ it for you. The following are equivalent: + + - var user = { name: 'tobi' } + user = { name: 'tobi' } + +## Conditionals + + Jade's first-class conditional syntax allows for optional + parenthesis, and you may now omit the leading _-_ otherwise + it's identical, still just regular javascript: + + user = { description: 'foo bar baz' } + #user + if user.description + h2 Description + p.description= user.description + + Jade provides the negated version, _unless_ as well, the following + are equivalent: + + - if (!(user.isAnonymous)) + p You're logged in as #{user.name} + + unless user.isAnonymous + p You're logged in as #{user.name} + +## Iteration + + JavaScript's _for_ loops don't look very declarative, so Jade + also provides its own _for_ loop construct, aliased as _each_: + + for user in users + .user + h2= user.name + p user #{user.name} is #{user.age} year old + + As mentioned _each_ is identical: + + each user in users + .user + h2= user.name + + If necessary the index is available as well: + + for user, i in users + .user(class='user-#{i}') + h2= user.name + + Remember, it's just JavaScript: + + ul#letters + for letter in ['a', 'b', 'c'] + li= letter + +## Mixins + + Mixins provide a way to define jade "functions" which "mix in" + their contents when called. This is useful for abstracting + out large fragments of Jade. + + The simplest possible mixin which accepts no arguments might + look like this: + + mixin hello + p Hello + + You use a mixin by placing `+` before the name: + + +hello + + For something a little more dynamic, mixins can take + arguments, the mixin itself is converted to a javascript + function internally: + + mixin hello(user) + p Hello #{user} + + +hello('Tobi') + + Yields: + +

Hello Tobi

+ + Mixins may optionally take blocks, when a block is passed + its contents becomes the implicit `block` argument. For + example here is a mixin passed a block, and also invoked + without passing a block: + + mixin article(title) + .article + .article-wrapper + h1= title + if block + block + else + p No content provided + + +article('Hello world') + + +article('Hello world') + p This is my + p Amazing article + + yields: + +
+
+

Hello world

+

No content provided

+
+
+ +
+
+

Hello world

+

This is my

+

Amazing article

+
+
+ + Mixins can even take attributes, just like a tag. When + attributes are passed they become the implicit `attributes` + argument. Individual attributes can be accessed just like + normal object properties: + + mixin centered + .centered(class=attributes.class) + block + + +centered.bold Hello world + + +centered.red + p This is my + p Amazing article + + yields: + +
Hello world
+
+

This is my

+

Amazing article

+
+ + If you use `attributes` directly, *all* passed attributes + get used: + + mixin link + a.menu(attributes) + block + + +link.highlight(href='#top') Top + +link#sec1.plain(href='#section1') Section 1 + +link#sec2.plain(href='#section2') Section 2 + + yields: + + Top + Section 1 + Section 2 + + If you pass arguments, they must directly follow the mixin: + + mixin list(arr) + if block + .title + block + ul(attributes) + each item in arr + li= item + + +list(['foo', 'bar', 'baz'])(id='myList', class='bold') + + yields: + +
    +
  • foo
  • +
  • bar
  • +
  • baz
  • +
diff --git a/node_modules/mocha/node_modules/jade/jade.min.js b/node_modules/mocha/node_modules/jade/jade.min.js new file mode 100644 index 0000000..72e4535 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/jade.min.js @@ -0,0 +1,2 @@ +(function(){function require(p){var path=require.resolve(p),mod=require.modules[path];if(!mod)throw new Error('failed to require "'+p+'"');return mod.exports||(mod.exports={},mod.call(mod.exports,mod,mod.exports,require.relative(path))),mod.exports}require.modules={},require.resolve=function(path){var orig=path,reg=path+".js",index=path+"/index.js";return require.modules[reg]&®||require.modules[index]&&index||orig},require.register=function(path,fn){require.modules[path]=fn},require.relative=function(parent){return function(p){if("."!=p.charAt(0))return require(p);var path=parent.split("/"),segs=p.split("/");path.pop();for(var i=0;i",this.doctype=doctype,this.terse="5"==name||"html"==name,this.xml=0==this.doctype.indexOf("1&&!escape&&block.nodes[0].isText&&block.nodes[1].isText&&this.prettyIndent(1,!0);for(var i=0;i0&&!escape&&block.nodes[i].isText&&block.nodes[i-1].isText&&this.prettyIndent(1,!1),this.visit(block.nodes[i]),block.nodes[i+1]&&block.nodes[i].isText&&block.nodes[i+1].isText&&this.buffer("\\n")},visitDoctype:function(doctype){doctype&&(doctype.val||!this.doctype)&&this.setDoctype(doctype.val||"default"),this.doctype&&this.buffer(this.doctype),this.hasCompiledDoctype=!0},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){pp&&this.buf.push("__indent.push('"+Array(this.indents+1).join(" ")+"');");if(block||attrs.length){this.buf.push(name+".call({");if(block){this.buf.push("block: function(){"),this.parentIndents++;var _indents=this.indents;this.indents=0,this.visit(mixin.block),this.indents=_indents,this.parentIndents--,attrs.length?this.buf.push("},"):this.buf.push("}")}if(attrs.length){var val=this.attrs(attrs);val.inherits?this.buf.push("attributes: merge({"+val.buf+"}, attributes), escaped: merge("+val.escaped+", escaped, true)"):this.buf.push("attributes: {"+val.buf+"}, escaped: "+val.escaped)}args?this.buf.push("}, "+args+");"):this.buf.push("});")}else this.buf.push(name+"("+args+");");pp&&this.buf.push("__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("};")},visitTag:function(tag){this.indents++;var name=tag.name,pp=this.pp;tag.buffer&&(name="' + ("+name+") + '"),this.hasCompiledTag||(!this.hasCompiledDoctype&&"html"==name&&this.visitDoctype(),this.hasCompiledTag=!0),pp&&!tag.isInline()&&this.prettyIndent(0,!0),(~selfClosing.indexOf(name)||tag.selfClosing)&&!this.xml?(this.buffer("<"+name),this.visitAttributes(tag.attrs),this.terse?this.buffer(">"):this.buffer("/>")):(tag.attrs.length?(this.buffer("<"+name),tag.attrs.length&&this.visitAttributes(tag.attrs),this.buffer(">")):this.buffer("<"+name+">"),tag.code&&this.visitCode(tag.code),this.escape="pre"==tag.name,this.visit(tag.block),pp&&!tag.isInline()&&"pre"!=tag.name&&!tag.canInline()&&this.prettyIndent(0,!0),this.buffer("")),this.indents--},visitFilter:function(filter){var fn=filters[filter.name];if(!fn)throw filter.isASTFilter?new Error('unknown ast filter "'+filter.name+':"'):new Error('unknown filter ":'+filter.name+'"');if(filter.isASTFilter)this.buf.push(fn(filter.block,this,filter.attrs));else{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(utils.text(fn(text,filter.attrs)))}},visitText:function(text){text=utils.text(text.val.replace(/\\/g,"\\\\")),this.escape&&(text=escape(text)),this.buffer(text)},visitComment:function(comment){if(!comment.buffer)return;this.pp&&this.prettyIndent(1,!0),this.buffer("")},visitBlockComment:function(comment){if(!comment.buffer)return;0==comment.val.trim().indexOf("if")?(this.buffer("")):(this.buffer(""))},visitCode:function(code){if(code.buffer){var val=code.val.trimLeft();this.buf.push("var __val__ = "+val),val='null == __val__ ? "" : __val__',code.escape&&(val="escape("+val+")"),this.buf.push("buf.push("+val+");")}else this.buf.push(code.val);code.block&&(code.buffer||this.buf.push("{"),this.visit(code.block),code.buffer||this.buf.push("}"))},visitEach:function(each){this.buf.push("// iterate "+each.obj+"\n"+";(function(){\n"+" if ('number' == typeof "+each.obj+".length) {\n"+" for (var "+each.key+" = 0, $$l = "+each.obj+".length; "+each.key+" < $$l; "+each.key+"++) {\n"+" var "+each.val+" = "+each.obj+"["+each.key+"];\n"),this.visit(each.block),this.buf.push(" }\n } else {\n for (var "+each.key+" in "+each.obj+") {\n"+" if ("+each.obj+".hasOwnProperty("+each.key+")){"+" var "+each.val+" = "+each.obj+"["+each.key+"];\n"),this.visit(each.block),this.buf.push(" }\n"),this.buf.push(" }\n }\n}).call(this);\n")},visitAttributes:function(attrs){var val=this.attrs(attrs);val.inherits?this.buf.push("buf.push(attrs(merge({ "+val.buf+" }, attributes), merge("+val.escaped+", escaped, true)));"):val.constant?(eval("var buf={"+val.buf+"};"),this.buffer(runtime.attrs(buf,JSON.parse(val.escaped)),!0)):this.buf.push("buf.push(attrs({ "+val.buf+" }, "+val.escaped+"));")},attrs:function(attrs){var buf=[],classes=[],escaped={},constant=attrs.every(function(attr){return isConstant(attr.val)}),inherits=!1;return this.terse&&buf.push("terse: true"),attrs.forEach(function(attr){if(attr.name=="attributes")return inherits=!0;escaped[attr.name]=attr.escaped;if(attr.name=="class")classes.push("("+attr.val+")");else{var pair="'"+attr.name+"':("+attr.val+")";buf.push(pair)}}),classes.length&&(classes=classes.join(" + ' ' + "),buf.push("class: "+classes)),{buf:buf.join(", ").replace("class:",'"class":'),escaped:JSON.stringify(escaped),inherits:inherits,constant:constant}}};function isConstant(val){if(/^ *("([^"\\]*(\\.[^"\\]*)*)"|'([^'\\]*(\\.[^'\\]*)*)'|true|false|null|undefined) *$/i.test(val))return!0;if(!isNaN(Number(val)))return!0;var matches;return(matches=/^ *\[(.*)\] *$/.exec(val))?matches[1].split(",").every(isConstant):!1}function escape(html){return String(html).replace(/&(?!\w+;)/g,"&").replace(//g,">").replace(/"/g,""")}}),require.register("doctypes.js",function(module,exports,require){module.exports={5:"","default":"",xml:'',transitional:'',strict:'',frameset:'',1.1:'',basic:'',mobile:''}}),require.register("filters.js",function(module,exports,require){module.exports={cdata:function(str){return""},sass:function(str){str=str.replace(/\\n/g,"\n");var sass=require("sass").render(str).replace(/\n/g,"\\n");return'"},stylus:function(str,options){var ret;str=str.replace(/\\n/g,"\n");var stylus=require("stylus");return stylus(str,options).render(function(err,css){if(err)throw err;ret=css.replace(/\n/g,"\\n")}),'"},less:function(str){var ret;return str=str.replace(/\\n/g,"\n"),require("less").render(str,function(err,css){if(err)throw err;ret='"}),ret},markdown:function(str){var md;try{md=require("markdown")}catch(err){try{md=require("discount")}catch(err){try{md=require("markdown-js")}catch(err){try{md=require("marked")}catch(err){throw new Error("Cannot find markdown library, install markdown, discount, or marked.")}}}}return str=str.replace(/\\n/g,"\n"),md.parse(str).replace(/\n/g,"\\n").replace(/'/g,"'")},coffeescript:function(str){str=str.replace(/\\n/g,"\n");var js=require("coffee-script").compile(str).replace(/\\/g,"\\\\").replace(/\n/g,"\\n");return'"}}}),require.register("inline-tags.js",function(module,exports,require){module.exports=["a","abbr","acronym","b","br","code","em","font","i","img","ins","kbd","map","samp","small","span","strong","sub","sup"]}),require.register("jade.js",function(module,exports,require){var Parser=require("./parser"),Lexer=require("./lexer"),Compiler=require("./compiler"),runtime=require("./runtime");exports.version="0.26.1",exports.selfClosing=require("./self-closing"),exports.doctypes=require("./doctypes"),exports.filters=require("./filters"),exports.utils=require("./utils"),exports.Compiler=Compiler,exports.Parser=Parser,exports.Lexer=Lexer,exports.nodes=require("./nodes"),exports.runtime=runtime,exports.cache={};function parse(str,options){try{var parser=new Parser(str,options.filename,options),compiler=new(options.compiler||Compiler)(parser.parse(),options),js=compiler.compile();return options.debug&&console.error("\nCompiled Function:\n\n%s",js.replace(/^/gm," ")),"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)}}exports.compile=function(str,options){var options=options||{},client=options.client,filename=options.filename?JSON.stringify(options.filename):"undefined",fn;return options.compileDebug!==!1?fn=["var __jade = [{ lineno: 1, filename: "+filename+" }];","try {",parse(String(str),options),"} catch (err) {"," rethrow(err, __jade[0].filename, __jade[0].lineno);","}"].join("\n"):fn=parse(String(str),options),client&&(fn="attrs = attrs || jade.attrs; escape = escape || jade.escape; rethrow = rethrow || jade.rethrow; merge = merge || jade.merge;\n"+fn),fn=new Function("locals, attrs, escape, rethrow, merge",fn),client?fn:function(locals){return fn(locals,runtime.attrs,runtime.escape,runtime.rethrow,runtime.merge)}},exports.render=function(str,options,fn){"function"==typeof options&&(fn=options,options={});if(options.cache&&!options.filename)return fn(new Error('the "filename" option is required for caching'));try{var path=options.filename,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)}},exports.renderFile=function(path,options,fn){var key=path+":string";"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)}},exports.__express=exports.renderFile}),require.register("lexer.js",function(module,exports,require){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=!1};Lexer.prototype={tok:function(type,val){return{type:type,line:this.lineno,val:val}},consume:function(len){this.input=this.input.substr(len)},scan:function(regexp,type){var captures;if(captures=regexp.exec(this.input))return this.consume(captures[0].length),this.tok(type,captures[1])},defer:function(tok){this.deferredTokens.push(tok)},lookahead:function(n){var fetch=n-this.stash.length;while(fetch-->0)this.stash.push(this.next());return this.stash[--n]},indexOfDelimiters:function(start,end){var str=this.input,nstart=0,nend=0,pos=0;for(var i=0,len=str.length;iindents)this.stash.push(this.tok("outdent")),this.indentStack.shift();tok=this.stash.pop()}else indents&&indents!=this.indentStack[0]?(this.indentStack.unshift(indents),tok=this.tok("indent",indents)):tok=this.tok("newline");return tok}},pipelessText:function(){if(this.pipeless){if("\n"==this.input[0])return;var i=this.input.indexOf("\n");-1==i&&(i=this.input.length);var str=this.input.substr(0,i);return this.consume(str.length),this.tok("text",str)}},colon:function(){return this.scan(/^: */,":")},advance:function(){return this.stashed()||this.next()},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()}}}),require.register("nodes/attrs.js",function(module,exports,require){var Node=require("./node"),Block=require("./block"),Attrs=module.exports=function Attrs(){this.attrs=[]};Attrs.prototype=new Node,Attrs.prototype.constructor=Attrs,Attrs.prototype.setAttribute=function(name,val,escaped){return this.attrs.push({name:name,val:val,escaped:escaped}),this},Attrs.prototype.removeAttribute=function(name){for(var i=0,len=this.attrs.length;i/g,">").replace(/"/g,""")},exports.rethrow=function rethrow(err,filename,lineno){if(!filename)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),context=lines.slice(start,end).map(function(line,i){var curr=i+start+1;return(curr==lineno?" > ":" ")+curr+"| "+line}).join("\n");throw err.path=filename,err.message=(filename||"Jade")+":"+lineno+"\n"+context+"\n\n"+err.message,err}}),require.register("self-closing.js",function(module,exports,require){module.exports=["meta","img","link","input","source","area","base","col","br","hr"]}),require.register("utils.js",function(module,exports,require){var interpolate=exports.interpolate=function(str){return str.replace(/(\\)?([#!]){(.*?)}/g,function(str,escape,flag,code){return escape?str:"' + "+("!"==flag?"":"escape")+"((interp = "+code.replace(/\\'/g,"'")+") == null ? '' : interp) + '"})},escape=exports.escape=function(str){return str.replace(/'/g,"\\'")};exports.text=function(str){return interpolate(escape(str))}}),window.jade=require("jade")})(); \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/lib/compiler.js b/node_modules/mocha/node_modules/jade/lib/compiler.js new file mode 100644 index 0000000..516ac83 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/compiler.js @@ -0,0 +1,642 @@ + +/*! + * Jade - Compiler + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var nodes = require('./nodes') + , filters = require('./filters') + , doctypes = require('./doctypes') + , selfClosing = require('./self-closing') + , runtime = require('./runtime') + , utils = require('./utils'); + +// 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 = ['var interp;']; + if (this.pp) this.buf.push("var __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){ + var doctype = doctypes[(name || 'default').toLowerCase()]; + doctype = doctype || ''; + this.doctype = doctype; + this.terse = '5' == name || 'html' == name; + this.xml = 0 == this.doctype.indexOf(' 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("__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: merge({' + val.buf + + '}, attributes), escaped: 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("__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; + + if (tag.buffer) name = "' + (" + 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('<' + name); + this.visitAttributes(tag.attrs); + this.terse + ? this.buffer('>') + : this.buffer('/>'); + } else { + // Optimize attributes buffering + if (tag.attrs.length) { + this.buffer('<' + name); + if (tag.attrs.length) this.visitAttributes(tag.attrs); + this.buffer('>'); + } else { + this.buffer('<' + name + '>'); + } + 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(''); + } + this.indents--; + }, + + /** + * Visit `filter`, throwing when the filter does not exist. + * + * @param {Filter} filter + * @api public + */ + + visitFilter: function(filter){ + var fn = filters[filter.name]; + + // unknown filter + if (!fn) { + if (filter.isASTFilter) { + throw new Error('unknown ast filter "' + filter.name + ':"'); + } else { + throw new Error('unknown filter ":' + filter.name + '"'); + } + } + + if (filter.isASTFilter) { + this.buf.push(fn(filter.block, this, filter.attrs)); + } else { + 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(utils.text(fn(text, filter.attrs))); + } + }, + + /** + * Visit `text` node. + * + * @param {Text} text + * @api public + */ + + visitText: function(text){ + text = utils.text(text.val.replace(/\\/g, '\\\\')); + if (this.escape) text = escape(text); + this.buffer(text); + }, + + /** + * 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(''); + }, + + /** + * Visit a `BlockComment`. + * + * @param {Comment} comment + * @api public + */ + + visitBlockComment: function(comment){ + if (!comment.buffer) return; + if (0 == comment.val.trim().indexOf('if')) { + this.buffer(''); + } else { + 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(); + this.buf.push('var __val__ = ' + val); + val = 'null == __val__ ? "" : __val__'; + if (code.escape) val = 'escape(' + val + ')'; + this.buf.push("buf.push(" + 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' + + ' if (\'number\' == typeof ' + each.obj + '.length) {\n' + + ' for (var ' + each.key + ' = 0, $$l = ' + each.obj + '.length; ' + each.key + ' < $$l; ' + each.key + '++) {\n' + + ' var ' + each.val + ' = ' + each.obj + '[' + each.key + '];\n'); + + this.visit(each.block); + + this.buf.push('' + + ' }\n' + + ' } else {\n' + + ' for (var ' + each.key + ' in ' + each.obj + ') {\n' + // if browser + // + ' if (' + each.obj + '.hasOwnProperty(' + each.key + ')){' + // end + + ' var ' + each.val + ' = ' + each.obj + '[' + each.key + '];\n'); + + this.visit(each.block); + + // if browser + // this.buf.push(' }\n'); + // end + + this.buf.push(' }\n }\n}).call(this);\n'); + }, + + /** + * Visit `attrs`. + * + * @param {Array} attrs + * @api public + */ + + visitAttributes: function(attrs){ + var val = this.attrs(attrs); + if (val.inherits) { + this.buf.push("buf.push(attrs(merge({ " + val.buf + + " }, attributes), merge(" + val.escaped + ", escaped, true)));"); + } else if (val.constant) { + eval('var buf={' + val.buf + '};'); + this.buffer(runtime.attrs(buf, JSON.parse(val.escaped)), true); + } else { + this.buf.push("buf.push(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(', ').replace('class:', '"class":'), + 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; +} + +/** + * Escape the given string of `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +function escape(html){ + return String(html) + .replace(/&(?!\w+;)/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +} \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/lib/doctypes.js b/node_modules/mocha/node_modules/jade/lib/doctypes.js new file mode 100644 index 0000000..e87ca1e --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/doctypes.js @@ -0,0 +1,18 @@ + +/*! + * Jade - doctypes + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = { + '5': '' + , 'default': '' + , 'xml': '' + , 'transitional': '' + , 'strict': '' + , 'frameset': '' + , '1.1': '' + , 'basic': '' + , 'mobile': '' +}; \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/lib/filters.js b/node_modules/mocha/node_modules/jade/lib/filters.js new file mode 100644 index 0000000..fdb634c --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/filters.js @@ -0,0 +1,97 @@ + +/*! + * Jade - filters + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = { + + /** + * Wrap text with CDATA block. + */ + + cdata: function(str){ + return ''; + }, + + /** + * Transform sass to css, wrapped in style tags. + */ + + sass: function(str){ + str = str.replace(/\\n/g, '\n'); + var sass = require('sass').render(str).replace(/\n/g, '\\n'); + return ''; + }, + + /** + * Transform stylus to css, wrapped in style tags. + */ + + stylus: function(str, options){ + var ret; + str = str.replace(/\\n/g, '\n'); + var stylus = require('stylus'); + stylus(str, options).render(function(err, css){ + if (err) throw err; + ret = css.replace(/\n/g, '\\n'); + }); + return ''; + }, + + /** + * Transform less to css, wrapped in style tags. + */ + + less: function(str){ + var ret; + str = str.replace(/\\n/g, '\n'); + require('less').render(str, function(err, css){ + if (err) throw err; + ret = ''; + }); + return ret; + }, + + /** + * Transform markdown to html. + */ + + markdown: function(str){ + var md; + + // support markdown / discount + try { + md = require('markdown'); + } catch (err){ + try { + md = require('discount'); + } catch (err) { + try { + md = require('markdown-js'); + } catch (err) { + try { + md = require('marked'); + } catch (err) { + throw new + Error('Cannot find markdown library, install markdown, discount, or marked.'); + } + } + } + } + + str = str.replace(/\\n/g, '\n'); + return md.parse(str).replace(/\n/g, '\\n').replace(/'/g,'''); + }, + + /** + * Transform coffeescript to javascript. + */ + + coffeescript: function(str){ + str = str.replace(/\\n/g, '\n'); + var js = require('coffee-script').compile(str).replace(/\\/g, '\\\\').replace(/\n/g, '\\n'); + return ''; + } +}; diff --git a/node_modules/mocha/node_modules/jade/lib/inline-tags.js b/node_modules/mocha/node_modules/jade/lib/inline-tags.js new file mode 100644 index 0000000..491de0b --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/inline-tags.js @@ -0,0 +1,28 @@ + +/*! + * Jade - inline tags + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = [ + 'a' + , 'abbr' + , 'acronym' + , 'b' + , 'br' + , 'code' + , 'em' + , 'font' + , 'i' + , 'img' + , 'ins' + , 'kbd' + , 'map' + , 'samp' + , 'small' + , 'span' + , 'strong' + , 'sub' + , 'sup' +]; \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/lib/jade.js b/node_modules/mocha/node_modules/jade/lib/jade.js new file mode 100644 index 0000000..00f0abb --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/jade.js @@ -0,0 +1,237 @@ +/*! + * Jade + * Copyright(c) 2010 TJ Holowaychuk + * 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.26.3'; + +/** + * 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); + } +} + +/** + * Compile a `Function` representation of the given jade `str`. + * + * Options: + * + * - `compileDebug` when `false` debugging code is stripped from the compiled template + * - `client` when `true` the helper functions `escape()` etc will reference `jade.escape()` + * for use with the Jade client-side runtime.js + * + * @param {String} str + * @param {Options} options + * @return {Function} + * @api public + */ + +exports.compile = function(str, options){ + var options = options || {} + , client = options.client + , filename = options.filename + ? JSON.stringify(options.filename) + : 'undefined' + , fn; + + if (options.compileDebug !== false) { + fn = [ + 'var __jade = [{ lineno: 1, filename: ' + filename + ' }];' + , 'try {' + , parse(String(str), options) + , '} catch (err) {' + , ' rethrow(err, __jade[0].filename, __jade[0].lineno);' + , '}' + ].join('\n'); + } else { + fn = parse(String(str), options); + } + + if (client) { + fn = 'attrs = attrs || jade.attrs; escape = escape || jade.escape; rethrow = rethrow || jade.rethrow; merge = merge || jade.merge;\n' + fn; + } + + fn = new Function('locals, attrs, escape, rethrow, merge', fn); + + if (client) return fn; + + return function(locals){ + return fn(locals, runtime.attrs, runtime.escape, runtime.rethrow, runtime.merge); + }; +}; + +/** + * 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; diff --git a/node_modules/mocha/node_modules/jade/lib/lexer.js b/node_modules/mocha/node_modules/jade/lib/lexer.js new file mode 100644 index 0000000..bca314a --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/lexer.js @@ -0,0 +1,771 @@ + +/*! + * Jade - Lexer + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * 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 `start` / `end` delimiters. + * + * @param {String} start + * @param {String} end + * @return {Number} + * @api private + */ + + indexOfDelimiters: function(start, end){ + var str = this.input + , nstart = 0 + , nend = 0 + , pos = 0; + for (var i = 0, len = str.length; i < len; ++i) { + if (start == str.charAt(i)) { + ++nstart; + } else if (end == str.charAt(i)) { + if (++nend == nstart) { + pos = i; + break; + } + } + } + return pos; + }, + + /** + * 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); + 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() { + var captures; + if (captures = /^#\{(.*?)\}/.exec(this.input)) { + this.consume(captures[0].length); + return this.tok('interpolation', captures[1]); + } + }, + + /** + * 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)) { + if (!/^ *[-\w]+ *=/.test(captures[1])) { + this.consume(captures[0].length); + tok.args = captures[1]; + } + } + + 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 = /^(!?=|-)([^\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[0] === '='; + tok.buffer = flags[0] === '=' || flags[1] === '='; + return tok; + } + }, + + /** + * Attributes. + */ + + attrs: function() { + if ('(' == this.input.charAt(0)) { + var index = this.indexOfDelimiters('(', ')') + , 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(_, expr){ + return quote + " + (" + expr + ") + " + quote; + }); + } + + 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(); + } +}; diff --git a/node_modules/mocha/node_modules/jade/lib/nodes/attrs.js b/node_modules/mocha/node_modules/jade/lib/nodes/attrs.js new file mode 100644 index 0000000..5de9b59 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/nodes/attrs.js @@ -0,0 +1,77 @@ + +/*! + * Jade - nodes - Attrs + * Copyright(c) 2010 TJ Holowaychuk + * 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; + } + } +}; diff --git a/node_modules/mocha/node_modules/jade/lib/nodes/block-comment.js b/node_modules/mocha/node_modules/jade/lib/nodes/block-comment.js new file mode 100644 index 0000000..4f41e4a --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/nodes/block-comment.js @@ -0,0 +1,33 @@ + +/*! + * Jade - nodes - BlockComment + * Copyright(c) 2010 TJ Holowaychuk + * 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; \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/lib/nodes/block.js b/node_modules/mocha/node_modules/jade/lib/nodes/block.js new file mode 100644 index 0000000..bb00a1d --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/nodes/block.js @@ -0,0 +1,121 @@ + +/*! + * Jade - nodes - Block + * Copyright(c) 2010 TJ Holowaychuk + * 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(); + } + + 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; +}; + diff --git a/node_modules/mocha/node_modules/jade/lib/nodes/case.js b/node_modules/mocha/node_modules/jade/lib/nodes/case.js new file mode 100644 index 0000000..08ff033 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/nodes/case.js @@ -0,0 +1,43 @@ + +/*! + * Jade - nodes - Case + * Copyright(c) 2010 TJ Holowaychuk + * 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; + diff --git a/node_modules/mocha/node_modules/jade/lib/nodes/code.js b/node_modules/mocha/node_modules/jade/lib/nodes/code.js new file mode 100644 index 0000000..babc675 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/nodes/code.js @@ -0,0 +1,35 @@ + +/*! + * Jade - nodes - Code + * Copyright(c) 2010 TJ Holowaychuk + * 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; \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/lib/nodes/comment.js b/node_modules/mocha/node_modules/jade/lib/nodes/comment.js new file mode 100644 index 0000000..2e1469e --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/nodes/comment.js @@ -0,0 +1,32 @@ + +/*! + * Jade - nodes - Comment + * Copyright(c) 2010 TJ Holowaychuk + * 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; \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/lib/nodes/doctype.js b/node_modules/mocha/node_modules/jade/lib/nodes/doctype.js new file mode 100644 index 0000000..b8f33e5 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/nodes/doctype.js @@ -0,0 +1,29 @@ + +/*! + * Jade - nodes - Doctype + * Copyright(c) 2010 TJ Holowaychuk + * 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; \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/lib/nodes/each.js b/node_modules/mocha/node_modules/jade/lib/nodes/each.js new file mode 100644 index 0000000..f54101f --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/nodes/each.js @@ -0,0 +1,35 @@ + +/*! + * Jade - nodes - Each + * Copyright(c) 2010 TJ Holowaychuk + * 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; \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/lib/nodes/filter.js b/node_modules/mocha/node_modules/jade/lib/nodes/filter.js new file mode 100644 index 0000000..851a004 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/nodes/filter.js @@ -0,0 +1,35 @@ + +/*! + * Jade - nodes - Filter + * Copyright(c) 2010 TJ Holowaychuk + * 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; + this.isASTFilter = !block.nodes.every(function(node){ return node.isText }); +}; + +/** + * Inherit from `Node`. + */ + +Filter.prototype.__proto__ = Node.prototype; \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/lib/nodes/index.js b/node_modules/mocha/node_modules/jade/lib/nodes/index.js new file mode 100644 index 0000000..386ad2f --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/nodes/index.js @@ -0,0 +1,20 @@ + +/*! + * Jade - nodes + * Copyright(c) 2010 TJ Holowaychuk + * 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'); diff --git a/node_modules/mocha/node_modules/jade/lib/nodes/literal.js b/node_modules/mocha/node_modules/jade/lib/nodes/literal.js new file mode 100644 index 0000000..fde586b --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/nodes/literal.js @@ -0,0 +1,32 @@ + +/*! + * Jade - nodes - Literal + * Copyright(c) 2010 TJ Holowaychuk + * 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 + .replace(/\\/g, "\\\\") + .replace(/\n|\r\n/g, "\\n") + .replace(/'/g, "\\'"); +}; + +/** + * Inherit from `Node`. + */ + +Literal.prototype.__proto__ = Node.prototype; diff --git a/node_modules/mocha/node_modules/jade/lib/nodes/mixin.js b/node_modules/mocha/node_modules/jade/lib/nodes/mixin.js new file mode 100644 index 0000000..8407bc7 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/nodes/mixin.js @@ -0,0 +1,36 @@ + +/*! + * Jade - nodes - Mixin + * Copyright(c) 2010 TJ Holowaychuk + * 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; + diff --git a/node_modules/mocha/node_modules/jade/lib/nodes/node.js b/node_modules/mocha/node_modules/jade/lib/nodes/node.js new file mode 100644 index 0000000..e98f042 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/nodes/node.js @@ -0,0 +1,25 @@ + +/*! + * Jade - nodes - Node + * Copyright(c) 2010 TJ Holowaychuk + * 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; +}; diff --git a/node_modules/mocha/node_modules/jade/lib/nodes/tag.js b/node_modules/mocha/node_modules/jade/lib/nodes/tag.js new file mode 100644 index 0000000..4b6728a --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/nodes/tag.js @@ -0,0 +1,95 @@ + +/*! + * Jade - nodes - Tag + * Copyright(c) 2010 TJ Holowaychuk + * 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; +}; \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/lib/nodes/text.js b/node_modules/mocha/node_modules/jade/lib/nodes/text.js new file mode 100644 index 0000000..3b5dd55 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/nodes/text.js @@ -0,0 +1,36 @@ + +/*! + * Jade - nodes - Text + * Copyright(c) 2010 TJ Holowaychuk + * 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; \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/lib/parser.js b/node_modules/mocha/node_modules/jade/lib/parser.js new file mode 100644 index 0000000..92f2af0 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/parser.js @@ -0,0 +1,710 @@ + +/*! + * Jade - Parser + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var Lexer = require('./lexer') + , nodes = require('./nodes'); + +/** + * 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; + } + + return block; + }, + + /** + * 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') + , 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 + , 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') + , node = new nodes.Code(tok.val, tok.buffer, tok.escape) + , block + , 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') + , 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') + , node = new nodes.Doctype(tok.val); + node.line = this.line(); + return node; + }, + + /** + * filter attrs? text-block + */ + + parseFilter: function(){ + var block + , tok = this.expect('filter') + , attrs = this.accept('attrs'); + + 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; + }, + + /** + * tag ':' attrs? block + */ + + parseASTFilter: function(){ + var block + , tok = this.expect('tag') + , attrs = this.accept('attrs'); + + this.expect(':'); + block = this.block(); + + 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') + , node = new nodes.Each(tok.code, tok.val, tok.key); + node.line = this.line(); + node.block = this.block(); + return node; + }, + + /** + * 'extends' name + */ + + parseExtends: function(){ + var path = require('path') + , fs = require('fs') + , dirname = path.dirname + , basename = path.basename + , join = path.join; + + if (!this.filename) + throw new Error('the "filename" option is required to extend templates'); + + var path = this.expect('extends').val.trim() + , dir = dirname(this.filename); + + var path = join(dir, path + '.jade') + , str = fs.readFileSync(path, 'utf8') + , parser = new Parser(str, path, this.options); + + parser.blocks = this.blocks; + parser.contexts = this.contexts; + this.extending = parser; + + // TODO: null node + return new nodes.Literal(''); + }, + + /** + * 'block' name block + */ + + parseBlock: function(){ + var block = this.expect('block') + , mode = block.mode + , name = block.val.trim(); + + block = 'indent' == this.peek().type + ? this.block() + : new nodes.Block(new nodes.Literal('')); + + var prev = this.blocks[name]; + + if (prev) { + switch (prev.mode) { + case 'append': + block.nodes = block.nodes.concat(prev.nodes); + prev = block; + break; + case 'prepend': + block.nodes = prev.nodes.concat(block.nodes); + prev = block; + break; + } + } + + block.mode = mode; + return this.blocks[name] = prev || block; + }, + + /** + * include block? + */ + + parseInclude: function(){ + var path = require('path') + , fs = require('fs') + , dirname = path.dirname + , basename = path.basename + , join = path.join; + + var path = this.expect('include').val.trim() + , dir = dirname(this.filename); + + if (!this.filename) + throw new Error('the "filename" option is required to use includes'); + + // no extension + if (!~basename(path).indexOf('.')) { + path += '.jade'; + } + + // non-jade + if ('.jade' != path.substr(-5)) { + var path = join(dir, path) + , str = fs.readFileSync(path, 'utf8'); + return new nodes.Literal(str); + } + + var path = join(dir, path) + , str = fs.readFileSync(path, 'utf8') + , parser = new Parser(str, path, this.options); + parser.blocks = 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') + , name = tok.val + , args = tok.args + , 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') + , name = tok.val + , args = tok.args + , 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; + if (':' == this.lookahead(i).type) { + if ('indent' == this.lookahead(++i).type) { + return this.parseASTFilter(); + } + } + + var tok = this.advance() + , 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; + } +}; diff --git a/node_modules/mocha/node_modules/jade/lib/runtime.js b/node_modules/mocha/node_modules/jade/lib/runtime.js new file mode 100644 index 0000000..fb711f5 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/runtime.js @@ -0,0 +1,174 @@ + +/*! + * Jade - runtime + * Copyright(c) 2010 TJ Holowaychuk + * 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(/&(?!(\w+|\#\d+);)/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; + + 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; +}; diff --git a/node_modules/mocha/node_modules/jade/lib/self-closing.js b/node_modules/mocha/node_modules/jade/lib/self-closing.js new file mode 100644 index 0000000..0548771 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/self-closing.js @@ -0,0 +1,19 @@ + +/*! + * Jade - self closing tags + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +module.exports = [ + 'meta' + , 'img' + , 'link' + , 'input' + , 'source' + , 'area' + , 'base' + , 'col' + , 'br' + , 'hr' +]; \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/lib/utils.js b/node_modules/mocha/node_modules/jade/lib/utils.js new file mode 100644 index 0000000..ff46d02 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/lib/utils.js @@ -0,0 +1,49 @@ + +/*! + * Jade - utils + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Convert interpolation in the given string to JavaScript. + * + * @param {String} str + * @return {String} + * @api private + */ + +var interpolate = exports.interpolate = function(str){ + return str.replace(/(\\)?([#!]){(.*?)}/g, function(str, escape, flag, code){ + return escape + ? str + : "' + " + + ('!' == flag ? '' : 'escape') + + "((interp = " + code.replace(/\\'/g, "'") + + ") == null ? '' : interp) + '"; + }); +}; + +/** + * Escape single quotes in `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +var escape = exports.escape = function(str) { + return str.replace(/'/g, "\\'"); +}; + +/** + * Interpolate, and escape the given `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +exports.text = function(str){ + return interpolate(escape(str)); +}; \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/node_modules/commander/.npmignore b/node_modules/mocha/node_modules/jade/node_modules/commander/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/commander/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/mocha/node_modules/jade/node_modules/commander/.travis.yml b/node_modules/mocha/node_modules/jade/node_modules/commander/.travis.yml new file mode 100644 index 0000000..f1d0f13 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/commander/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.4 + - 0.6 diff --git a/node_modules/mocha/node_modules/jade/node_modules/commander/History.md b/node_modules/mocha/node_modules/jade/node_modules/commander/History.md new file mode 100644 index 0000000..4961d2e --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/commander/History.md @@ -0,0 +1,107 @@ + +0.6.1 / 2012-06-01 +================== + + * Added: append (yes or no) on confirmation + * Added: allow node.js v0.7.x + +0.6.0 / 2012-04-10 +================== + + * Added `.prompt(obj, callback)` support. Closes #49 + * Added default support to .choose(). Closes #41 + * Fixed the choice example + +0.5.1 / 2011-12-20 +================== + + * Fixed `password()` for recent nodes. Closes #36 + +0.5.0 / 2011-12-04 +================== + + * Added sub-command option support [itay] + +0.4.3 / 2011-12-04 +================== + + * Fixed custom help ordering. Closes #32 + +0.4.2 / 2011-11-24 +================== + + * Added travis support + * Fixed: line-buffered input automatically trimmed. Closes #31 + +0.4.1 / 2011-11-18 +================== + + * Removed listening for "close" on --help + +0.4.0 / 2011-11-15 +================== + + * Added support for `--`. Closes #24 + +0.3.3 / 2011-11-14 +================== + + * Fixed: wait for close event when writing help info [Jerry Hamlet] + +0.3.2 / 2011-11-01 +================== + + * Fixed long flag definitions with values [felixge] + +0.3.1 / 2011-10-31 +================== + + * Changed `--version` short flag to `-V` from `-v` + * Changed `.version()` so it's configurable [felixge] + +0.3.0 / 2011-10-31 +================== + + * Added support for long flags only. Closes #18 + +0.2.1 / 2011-10-24 +================== + + * "node": ">= 0.4.x < 0.7.0". Closes #20 + +0.2.0 / 2011-09-26 +================== + + * Allow for defaults that are not just boolean. Default peassignment only occurs for --no-*, optional, and required arguments. [Jim Isaacs] + +0.1.0 / 2011-08-24 +================== + + * Added support for custom `--help` output + +0.0.5 / 2011-08-18 +================== + + * Changed: when the user enters nothing prompt for password again + * Fixed issue with passwords beginning with numbers [NuckChorris] + +0.0.4 / 2011-08-15 +================== + + * Fixed `Commander#args` + +0.0.3 / 2011-08-15 +================== + + * Added default option value support + +0.0.2 / 2011-08-15 +================== + + * Added mask support to `Command#password(str[, mask], fn)` + * Added `Command#password(str, fn)` + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/mocha/node_modules/jade/node_modules/commander/Makefile b/node_modules/mocha/node_modules/jade/node_modules/commander/Makefile new file mode 100644 index 0000000..0074625 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/commander/Makefile @@ -0,0 +1,7 @@ + +TESTS = $(shell find test/test.*.js) + +test: + @./test/run $(TESTS) + +.PHONY: test \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/node_modules/commander/Readme.md b/node_modules/mocha/node_modules/jade/node_modules/commander/Readme.md new file mode 100644 index 0000000..b8328c3 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/commander/Readme.md @@ -0,0 +1,262 @@ +# Commander.js + + The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/visionmedia/commander). + + [![Build Status](https://secure.travis-ci.org/visionmedia/commander.js.png)](http://travis-ci.org/visionmedia/commander.js) + +## Installation + + $ npm install commander + +## Option parsing + + Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options. + +```js +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('commander'); + +program + .version('0.0.1') + .option('-p, --peppers', 'Add peppers') + .option('-P, --pineapple', 'Add pineapple') + .option('-b, --bbq', 'Add bbq sauce') + .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble') + .parse(process.argv); + +console.log('you ordered a pizza with:'); +if (program.peppers) console.log(' - peppers'); +if (program.pineapple) console.log(' - pineappe'); +if (program.bbq) console.log(' - bbq'); +console.log(' - %s cheese', program.cheese); +``` + + Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as "--template-engine" are camel-cased, becoming `program.templateEngine` etc. + +## Automated --help + + The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free: + +``` + $ ./examples/pizza --help + + Usage: pizza [options] + + Options: + + -V, --version output the version number + -p, --peppers Add peppers + -P, --pineapple Add pineappe + -b, --bbq Add bbq sauce + -c, --cheese Add the specified type of cheese [marble] + -h, --help output usage information + +``` + +## Coercion + +```js +function range(val) { + return val.split('..').map(Number); +} + +function list(val) { + return val.split(','); +} + +program + .version('0.0.1') + .usage('[options] ') + .option('-i, --integer ', 'An integer argument', parseInt) + .option('-f, --float ', 'A float argument', parseFloat) + .option('-r, --range ..', 'A range', range) + .option('-l, --list ', 'A list', list) + .option('-o, --optional [value]', 'An optional value') + .parse(process.argv); + +console.log(' int: %j', program.integer); +console.log(' float: %j', program.float); +console.log(' optional: %j', program.optional); +program.range = program.range || []; +console.log(' range: %j..%j', program.range[0], program.range[1]); +console.log(' list: %j', program.list); +console.log(' args: %j', program.args); +``` + +## Custom help + + You can display arbitrary `-h, --help` information + by listening for "--help". Commander will automatically + exit once you are done so that the remainder of your program + does not execute causing undesired behaviours, for example + in the following executable "stuff" will not output when + `--help` is used. + +```js +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('../'); + +function list(val) { + return val.split(',').map(Number); +} + +program + .version('0.0.1') + .option('-f, --foo', 'enable some foo') + .option('-b, --bar', 'enable some bar') + .option('-B, --baz', 'enable some baz'); + +// must be before .parse() since +// node's emit() is immediate + +program.on('--help', function(){ + console.log(' Examples:'); + console.log(''); + console.log(' $ custom-help --help'); + console.log(' $ custom-help -h'); + console.log(''); +}); + +program.parse(process.argv); + +console.log('stuff'); +``` + +yielding the following help output: + +``` + +Usage: custom-help [options] + +Options: + + -h, --help output usage information + -V, --version output the version number + -f, --foo enable some foo + -b, --bar enable some bar + -B, --baz enable some baz + +Examples: + + $ custom-help --help + $ custom-help -h + +``` + +## .prompt(msg, fn) + + Single-line prompt: + +```js +program.prompt('name: ', function(name){ + console.log('hi %s', name); +}); +``` + + Multi-line prompt: + +```js +program.prompt('description:', function(name){ + console.log('hi %s', name); +}); +``` + + Coercion: + +```js +program.prompt('Age: ', Number, function(age){ + console.log('age: %j', age); +}); +``` + +```js +program.prompt('Birthdate: ', Date, function(date){ + console.log('date: %s', date); +}); +``` + +## .password(msg[, mask], fn) + +Prompt for password without echoing: + +```js +program.password('Password: ', function(pass){ + console.log('got "%s"', pass); + process.stdin.destroy(); +}); +``` + +Prompt for password with mask char "*": + +```js +program.password('Password: ', '*', function(pass){ + console.log('got "%s"', pass); + process.stdin.destroy(); +}); +``` + +## .confirm(msg, fn) + + Confirm with the given `msg`: + +```js +program.confirm('continue? ', function(ok){ + console.log(' got %j', ok); +}); +``` + +## .choose(list, fn) + + Let the user choose from a `list`: + +```js +var list = ['tobi', 'loki', 'jane', 'manny', 'luna']; + +console.log('Choose the coolest pet:'); +program.choose(list, function(i){ + console.log('you chose %d "%s"', i, list[i]); +}); +``` + +## Links + + - [API documentation](http://visionmedia.github.com/commander.js/) + - [ascii tables](https://github.com/LearnBoost/cli-table) + - [progress bars](https://github.com/visionmedia/node-progress) + - [more progress bars](https://github.com/substack/node-multimeter) + - [examples](https://github.com/visionmedia/commander.js/tree/master/examples) + +## License + +(The MIT License) + +Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/node_modules/commander/index.js b/node_modules/mocha/node_modules/jade/node_modules/commander/index.js new file mode 100644 index 0000000..06ec1e4 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/commander/index.js @@ -0,0 +1,2 @@ + +module.exports = require('./lib/commander'); \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/node_modules/commander/lib/commander.js b/node_modules/mocha/node_modules/jade/node_modules/commander/lib/commander.js new file mode 100644 index 0000000..5ba87eb --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/commander/lib/commander.js @@ -0,0 +1,1026 @@ + +/*! + * commander + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter + , path = require('path') + , tty = require('tty') + , basename = path.basename; + +/** + * Expose the root command. + */ + +exports = module.exports = new Command; + +/** + * Expose `Command`. + */ + +exports.Command = Command; + +/** + * Expose `Option`. + */ + +exports.Option = Option; + +/** + * Initialize a new `Option` with the given `flags` and `description`. + * + * @param {String} flags + * @param {String} description + * @api public + */ + +function Option(flags, description) { + this.flags = flags; + this.required = ~flags.indexOf('<'); + this.optional = ~flags.indexOf('['); + this.bool = !~flags.indexOf('-no-'); + flags = flags.split(/[ ,|]+/); + if (flags.length > 1 && !/^[[<]/.test(flags[1])) this.short = flags.shift(); + this.long = flags.shift(); + this.description = description; +} + +/** + * Return option name. + * + * @return {String} + * @api private + */ + +Option.prototype.name = function(){ + return this.long + .replace('--', '') + .replace('no-', ''); +}; + +/** + * Check if `arg` matches the short or long flag. + * + * @param {String} arg + * @return {Boolean} + * @api private + */ + +Option.prototype.is = function(arg){ + return arg == this.short + || arg == this.long; +}; + +/** + * Initialize a new `Command`. + * + * @param {String} name + * @api public + */ + +function Command(name) { + this.commands = []; + this.options = []; + this.args = []; + this.name = name; +} + +/** + * Inherit from `EventEmitter.prototype`. + */ + +Command.prototype.__proto__ = EventEmitter.prototype; + +/** + * Add command `name`. + * + * The `.action()` callback is invoked when the + * command `name` is specified via __ARGV__, + * and the remaining arguments are applied to the + * function for access. + * + * When the `name` is "*" an un-matched command + * will be passed as the first arg, followed by + * the rest of __ARGV__ remaining. + * + * Examples: + * + * program + * .version('0.0.1') + * .option('-C, --chdir ', 'change the working directory') + * .option('-c, --config ', 'set config path. defaults to ./deploy.conf') + * .option('-T, --no-tests', 'ignore test hook') + * + * program + * .command('setup') + * .description('run remote setup commands') + * .action(function(){ + * console.log('setup'); + * }); + * + * program + * .command('exec ') + * .description('run the given remote command') + * .action(function(cmd){ + * console.log('exec "%s"', cmd); + * }); + * + * program + * .command('*') + * .description('deploy the given env') + * .action(function(env){ + * console.log('deploying "%s"', env); + * }); + * + * program.parse(process.argv); + * + * @param {String} name + * @return {Command} the new command + * @api public + */ + +Command.prototype.command = function(name){ + var args = name.split(/ +/); + var cmd = new Command(args.shift()); + this.commands.push(cmd); + cmd.parseExpectedArgs(args); + cmd.parent = this; + return cmd; +}; + +/** + * Parse expected `args`. + * + * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`. + * + * @param {Array} args + * @return {Command} for chaining + * @api public + */ + +Command.prototype.parseExpectedArgs = function(args){ + if (!args.length) return; + var self = this; + args.forEach(function(arg){ + switch (arg[0]) { + case '<': + self.args.push({ required: true, name: arg.slice(1, -1) }); + break; + case '[': + self.args.push({ required: false, name: arg.slice(1, -1) }); + break; + } + }); + return this; +}; + +/** + * Register callback `fn` for the command. + * + * Examples: + * + * program + * .command('help') + * .description('display verbose help') + * .action(function(){ + * // output help here + * }); + * + * @param {Function} fn + * @return {Command} for chaining + * @api public + */ + +Command.prototype.action = function(fn){ + var self = this; + this.parent.on(this.name, function(args, unknown){ + // Parse any so-far unknown options + unknown = unknown || []; + var parsed = self.parseOptions(unknown); + + // Output help if necessary + outputHelpIfNecessary(self, parsed.unknown); + + // If there are still any unknown options, then we simply + // die, unless someone asked for help, in which case we give it + // to them, and then we die. + if (parsed.unknown.length > 0) { + self.unknownOption(parsed.unknown[0]); + } + + self.args.forEach(function(arg, i){ + if (arg.required && null == args[i]) { + self.missingArgument(arg.name); + } + }); + + // Always append ourselves to the end of the arguments, + // to make sure we match the number of arguments the user + // expects + if (self.args.length) { + args[self.args.length] = self; + } else { + args.push(self); + } + + fn.apply(this, args); + }); + return this; +}; + +/** + * Define option with `flags`, `description` and optional + * coercion `fn`. + * + * The `flags` string should contain both the short and long flags, + * separated by comma, a pipe or space. The following are all valid + * all will output this way when `--help` is used. + * + * "-p, --pepper" + * "-p|--pepper" + * "-p --pepper" + * + * Examples: + * + * // simple boolean defaulting to false + * program.option('-p, --pepper', 'add pepper'); + * + * --pepper + * program.pepper + * // => Boolean + * + * // simple boolean defaulting to false + * program.option('-C, --no-cheese', 'remove cheese'); + * + * program.cheese + * // => true + * + * --no-cheese + * program.cheese + * // => true + * + * // required argument + * program.option('-C, --chdir ', 'change the working directory'); + * + * --chdir /tmp + * program.chdir + * // => "/tmp" + * + * // optional argument + * program.option('-c, --cheese [type]', 'add cheese [marble]'); + * + * @param {String} flags + * @param {String} description + * @param {Function|Mixed} fn or default + * @param {Mixed} defaultValue + * @return {Command} for chaining + * @api public + */ + +Command.prototype.option = function(flags, description, fn, defaultValue){ + var self = this + , option = new Option(flags, description) + , oname = option.name() + , name = camelcase(oname); + + // default as 3rd arg + if ('function' != typeof fn) defaultValue = fn, fn = null; + + // preassign default value only for --no-*, [optional], or + if (false == option.bool || option.optional || option.required) { + // when --no-* we make sure default is true + if (false == option.bool) defaultValue = true; + // preassign only if we have a default + if (undefined !== defaultValue) self[name] = defaultValue; + } + + // register the option + this.options.push(option); + + // when it's passed assign the value + // and conditionally invoke the callback + this.on(oname, function(val){ + // coercion + if (null != val && fn) val = fn(val); + + // unassigned or bool + if ('boolean' == typeof self[name] || 'undefined' == typeof self[name]) { + // if no value, bool true, and we have a default, then use it! + if (null == val) { + self[name] = option.bool + ? defaultValue || true + : false; + } else { + self[name] = val; + } + } else if (null !== val) { + // reassign + self[name] = val; + } + }); + + return this; +}; + +/** + * Parse `argv`, settings options and invoking commands when defined. + * + * @param {Array} argv + * @return {Command} for chaining + * @api public + */ + +Command.prototype.parse = function(argv){ + // store raw args + this.rawArgs = argv; + + // guess name + if (!this.name) this.name = basename(argv[1]); + + // process argv + var parsed = this.parseOptions(this.normalize(argv.slice(2))); + this.args = parsed.args; + return this.parseArgs(this.args, parsed.unknown); +}; + +/** + * Normalize `args`, splitting joined short flags. For example + * the arg "-abc" is equivalent to "-a -b -c". + * + * @param {Array} args + * @return {Array} + * @api private + */ + +Command.prototype.normalize = function(args){ + var ret = [] + , arg; + + for (var i = 0, len = args.length; i < len; ++i) { + arg = args[i]; + if (arg.length > 1 && '-' == arg[0] && '-' != arg[1]) { + arg.slice(1).split('').forEach(function(c){ + ret.push('-' + c); + }); + } else { + ret.push(arg); + } + } + + return ret; +}; + +/** + * Parse command `args`. + * + * When listener(s) are available those + * callbacks are invoked, otherwise the "*" + * event is emitted and those actions are invoked. + * + * @param {Array} args + * @return {Command} for chaining + * @api private + */ + +Command.prototype.parseArgs = function(args, unknown){ + var cmds = this.commands + , len = cmds.length + , name; + + if (args.length) { + name = args[0]; + if (this.listeners(name).length) { + this.emit(args.shift(), args, unknown); + } else { + this.emit('*', args); + } + } else { + outputHelpIfNecessary(this, unknown); + + // If there were no args and we have unknown options, + // then they are extraneous and we need to error. + if (unknown.length > 0) { + this.unknownOption(unknown[0]); + } + } + + return this; +}; + +/** + * Return an option matching `arg` if any. + * + * @param {String} arg + * @return {Option} + * @api private + */ + +Command.prototype.optionFor = function(arg){ + for (var i = 0, len = this.options.length; i < len; ++i) { + if (this.options[i].is(arg)) { + return this.options[i]; + } + } +}; + +/** + * Parse options from `argv` returning `argv` + * void of these options. + * + * @param {Array} argv + * @return {Array} + * @api public + */ + +Command.prototype.parseOptions = function(argv){ + var args = [] + , len = argv.length + , literal + , option + , arg; + + var unknownOptions = []; + + // parse options + for (var i = 0; i < len; ++i) { + arg = argv[i]; + + // literal args after -- + if ('--' == arg) { + literal = true; + continue; + } + + if (literal) { + args.push(arg); + continue; + } + + // find matching Option + option = this.optionFor(arg); + + // option is defined + if (option) { + // requires arg + if (option.required) { + arg = argv[++i]; + if (null == arg) return this.optionMissingArgument(option); + if ('-' == arg[0]) return this.optionMissingArgument(option, arg); + this.emit(option.name(), arg); + // optional arg + } else if (option.optional) { + arg = argv[i+1]; + if (null == arg || '-' == arg[0]) { + arg = null; + } else { + ++i; + } + this.emit(option.name(), arg); + // bool + } else { + this.emit(option.name()); + } + continue; + } + + // looks like an option + if (arg.length > 1 && '-' == arg[0]) { + unknownOptions.push(arg); + + // If the next argument looks like it might be + // an argument for this option, we pass it on. + // If it isn't, then it'll simply be ignored + if (argv[i+1] && '-' != argv[i+1][0]) { + unknownOptions.push(argv[++i]); + } + continue; + } + + // arg + args.push(arg); + } + + return { args: args, unknown: unknownOptions }; +}; + +/** + * Argument `name` is missing. + * + * @param {String} name + * @api private + */ + +Command.prototype.missingArgument = function(name){ + console.error(); + console.error(" error: missing required argument `%s'", name); + console.error(); + process.exit(1); +}; + +/** + * `Option` is missing an argument, but received `flag` or nothing. + * + * @param {String} option + * @param {String} flag + * @api private + */ + +Command.prototype.optionMissingArgument = function(option, flag){ + console.error(); + if (flag) { + console.error(" error: option `%s' argument missing, got `%s'", option.flags, flag); + } else { + console.error(" error: option `%s' argument missing", option.flags); + } + console.error(); + process.exit(1); +}; + +/** + * Unknown option `flag`. + * + * @param {String} flag + * @api private + */ + +Command.prototype.unknownOption = function(flag){ + console.error(); + console.error(" error: unknown option `%s'", flag); + console.error(); + process.exit(1); +}; + +/** + * Set the program version to `str`. + * + * This method auto-registers the "-V, --version" flag + * which will print the version number when passed. + * + * @param {String} str + * @param {String} flags + * @return {Command} for chaining + * @api public + */ + +Command.prototype.version = function(str, flags){ + if (0 == arguments.length) return this._version; + this._version = str; + flags = flags || '-V, --version'; + this.option(flags, 'output the version number'); + this.on('version', function(){ + console.log(str); + process.exit(0); + }); + return this; +}; + +/** + * Set the description `str`. + * + * @param {String} str + * @return {String|Command} + * @api public + */ + +Command.prototype.description = function(str){ + if (0 == arguments.length) return this._description; + this._description = str; + return this; +}; + +/** + * Set / get the command usage `str`. + * + * @param {String} str + * @return {String|Command} + * @api public + */ + +Command.prototype.usage = function(str){ + var args = this.args.map(function(arg){ + return arg.required + ? '<' + arg.name + '>' + : '[' + arg.name + ']'; + }); + + var usage = '[options' + + (this.commands.length ? '] [command' : '') + + ']' + + (this.args.length ? ' ' + args : ''); + if (0 == arguments.length) return this._usage || usage; + this._usage = str; + + return this; +}; + +/** + * Return the largest option length. + * + * @return {Number} + * @api private + */ + +Command.prototype.largestOptionLength = function(){ + return this.options.reduce(function(max, option){ + return Math.max(max, option.flags.length); + }, 0); +}; + +/** + * Return help for options. + * + * @return {String} + * @api private + */ + +Command.prototype.optionHelp = function(){ + var width = this.largestOptionLength(); + + // Prepend the help information + return [pad('-h, --help', width) + ' ' + 'output usage information'] + .concat(this.options.map(function(option){ + return pad(option.flags, width) + + ' ' + option.description; + })) + .join('\n'); +}; + +/** + * Return command help documentation. + * + * @return {String} + * @api private + */ + +Command.prototype.commandHelp = function(){ + if (!this.commands.length) return ''; + return [ + '' + , ' Commands:' + , '' + , this.commands.map(function(cmd){ + var args = cmd.args.map(function(arg){ + return arg.required + ? '<' + arg.name + '>' + : '[' + arg.name + ']'; + }).join(' '); + + return cmd.name + + (cmd.options.length + ? ' [options]' + : '') + ' ' + args + + (cmd.description() + ? '\n' + cmd.description() + : ''); + }).join('\n\n').replace(/^/gm, ' ') + , '' + ].join('\n'); +}; + +/** + * Return program help documentation. + * + * @return {String} + * @api private + */ + +Command.prototype.helpInformation = function(){ + return [ + '' + , ' Usage: ' + this.name + ' ' + this.usage() + , '' + this.commandHelp() + , ' Options:' + , '' + , '' + this.optionHelp().replace(/^/gm, ' ') + , '' + , '' + ].join('\n'); +}; + +/** + * Prompt for a `Number`. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptForNumber = function(str, fn){ + var self = this; + this.promptSingleLine(str, function parseNumber(val){ + val = Number(val); + if (isNaN(val)) return self.promptSingleLine(str + '(must be a number) ', parseNumber); + fn(val); + }); +}; + +/** + * Prompt for a `Date`. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptForDate = function(str, fn){ + var self = this; + this.promptSingleLine(str, function parseDate(val){ + val = new Date(val); + if (isNaN(val.getTime())) return self.promptSingleLine(str + '(must be a date) ', parseDate); + fn(val); + }); +}; + +/** + * Single-line prompt. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptSingleLine = function(str, fn){ + if ('function' == typeof arguments[2]) { + return this['promptFor' + (fn.name || fn)](str, arguments[2]); + } + + process.stdout.write(str); + process.stdin.setEncoding('utf8'); + process.stdin.once('data', function(val){ + fn(val.trim()); + }).resume(); +}; + +/** + * Multi-line prompt. + * + * @param {String} str + * @param {Function} fn + * @api private + */ + +Command.prototype.promptMultiLine = function(str, fn){ + var buf = []; + console.log(str); + process.stdin.setEncoding('utf8'); + process.stdin.on('data', function(val){ + if ('\n' == val || '\r\n' == val) { + process.stdin.removeAllListeners('data'); + fn(buf.join('\n')); + } else { + buf.push(val.trimRight()); + } + }).resume(); +}; + +/** + * Prompt `str` and callback `fn(val)` + * + * Commander supports single-line and multi-line prompts. + * To issue a single-line prompt simply add white-space + * to the end of `str`, something like "name: ", whereas + * for a multi-line prompt omit this "description:". + * + * + * Examples: + * + * program.prompt('Username: ', function(name){ + * console.log('hi %s', name); + * }); + * + * program.prompt('Description:', function(desc){ + * console.log('description was "%s"', desc.trim()); + * }); + * + * @param {String|Object} str + * @param {Function} fn + * @api public + */ + +Command.prototype.prompt = function(str, fn){ + var self = this; + + if ('string' == typeof str) { + if (/ $/.test(str)) return this.promptSingleLine.apply(this, arguments); + this.promptMultiLine(str, fn); + } else { + var keys = Object.keys(str) + , obj = {}; + + function next() { + var key = keys.shift() + , label = str[key]; + + if (!key) return fn(obj); + self.prompt(label, function(val){ + obj[key] = val; + next(); + }); + } + + next(); + } +}; + +/** + * Prompt for password with `str`, `mask` char and callback `fn(val)`. + * + * The mask string defaults to '', aka no output is + * written while typing, you may want to use "*" etc. + * + * Examples: + * + * program.password('Password: ', function(pass){ + * console.log('got "%s"', pass); + * process.stdin.destroy(); + * }); + * + * program.password('Password: ', '*', function(pass){ + * console.log('got "%s"', pass); + * process.stdin.destroy(); + * }); + * + * @param {String} str + * @param {String} mask + * @param {Function} fn + * @api public + */ + +Command.prototype.password = function(str, mask, fn){ + var self = this + , buf = ''; + + // default mask + if ('function' == typeof mask) { + fn = mask; + mask = ''; + } + + process.stdin.resume(); + tty.setRawMode(true); + process.stdout.write(str); + + // keypress + process.stdin.on('keypress', function(c, key){ + if (key && 'enter' == key.name) { + console.log(); + process.stdin.removeAllListeners('keypress'); + tty.setRawMode(false); + if (!buf.trim().length) return self.password(str, mask, fn); + fn(buf); + return; + } + + if (key && key.ctrl && 'c' == key.name) { + console.log('%s', buf); + process.exit(); + } + + process.stdout.write(mask); + buf += c; + }).resume(); +}; + +/** + * Confirmation prompt with `str` and callback `fn(bool)` + * + * Examples: + * + * program.confirm('continue? ', function(ok){ + * console.log(' got %j', ok); + * process.stdin.destroy(); + * }); + * + * @param {String} str + * @param {Function} fn + * @api public + */ + + +Command.prototype.confirm = function(str, fn, verbose){ + var self = this; + this.prompt(str, function(ok){ + if (!ok.trim()) { + if (!verbose) str += '(yes or no) '; + return self.confirm(str, fn, true); + } + fn(parseBool(ok)); + }); +}; + +/** + * Choice prompt with `list` of items and callback `fn(index, item)` + * + * Examples: + * + * var list = ['tobi', 'loki', 'jane', 'manny', 'luna']; + * + * console.log('Choose the coolest pet:'); + * program.choose(list, function(i){ + * console.log('you chose %d "%s"', i, list[i]); + * process.stdin.destroy(); + * }); + * + * @param {Array} list + * @param {Number|Function} index or fn + * @param {Function} fn + * @api public + */ + +Command.prototype.choose = function(list, index, fn){ + var self = this + , hasDefault = 'number' == typeof index; + + if (!hasDefault) { + fn = index; + index = null; + } + + list.forEach(function(item, i){ + if (hasDefault && i == index) { + console.log('* %d) %s', i + 1, item); + } else { + console.log(' %d) %s', i + 1, item); + } + }); + + function again() { + self.prompt(' : ', function(val){ + val = parseInt(val, 10) - 1; + if (hasDefault && isNaN(val)) val = index; + + if (null == list[val]) { + again(); + } else { + fn(val, list[val]); + } + }); + } + + again(); +}; + +/** + * Camel-case the given `flag` + * + * @param {String} flag + * @return {String} + * @api private + */ + +function camelcase(flag) { + return flag.split('-').reduce(function(str, word){ + return str + word[0].toUpperCase() + word.slice(1); + }); +} + +/** + * Parse a boolean `str`. + * + * @param {String} str + * @return {Boolean} + * @api private + */ + +function parseBool(str) { + return /^y|yes|ok|true$/i.test(str); +} + +/** + * Pad `str` to `width`. + * + * @param {String} str + * @param {Number} width + * @return {String} + * @api private + */ + +function pad(str, width) { + var len = Math.max(0, width - str.length); + return str + Array(len + 1).join(' '); +} + +/** + * Output help information if necessary + * + * @param {Command} command to output help for + * @param {Array} array of options to search for -h or --help + * @api private + */ + +function outputHelpIfNecessary(cmd, options) { + options = options || []; + for (var i = 0; i < options.length; i++) { + if (options[i] == '--help' || options[i] == '-h') { + process.stdout.write(cmd.helpInformation()); + cmd.emit('--help'); + process.exit(0); + } + } +} diff --git a/node_modules/mocha/node_modules/jade/node_modules/commander/package.json b/node_modules/mocha/node_modules/jade/node_modules/commander/package.json new file mode 100644 index 0000000..d7795e3 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/commander/package.json @@ -0,0 +1,60 @@ +{ + "name": "commander", + "version": "0.6.1", + "description": "the complete solution for node.js command-line programs", + "keywords": [ + "command", + "option", + "parser", + "prompt", + "stdin" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/commander.js.git" + }, + "dependencies": {}, + "devDependencies": { + "should": ">= 0.0.1" + }, + "scripts": { + "test": "make test" + }, + "main": "index", + "engines": { + "node": ">= 0.4.x" + }, + "_npmUser": { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + }, + "_id": "commander@0.6.1", + "optionalDependencies": {}, + "_engineSupported": true, + "_npmVersion": "1.1.0-3", + "_nodeVersion": "v0.6.12", + "_defaultsLoaded": true, + "dist": { + "shasum": "fa68a14f6a945d54dbbe50d8cdb3320e9e3b1a06", + "tarball": "http://registry.npmjs.org/commander/-/commander-0.6.1.tgz" + }, + "maintainers": [ + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + } + ], + "directories": {}, + "_shasum": "fa68a14f6a945d54dbbe50d8cdb3320e9e3b1a06", + "_resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "_from": "commander@0.6.1", + "bugs": { + "url": "https://github.com/visionmedia/commander.js/issues" + }, + "readme": "ERROR: No README data found!", + "homepage": "https://github.com/visionmedia/commander.js" +} diff --git a/node_modules/mocha/node_modules/jade/node_modules/mkdirp/.gitignore.orig b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/.gitignore.orig new file mode 100644 index 0000000..9303c34 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/.gitignore.orig @@ -0,0 +1,2 @@ +node_modules/ +npm-debug.log \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/node_modules/mkdirp/.gitignore.rej b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/.gitignore.rej new file mode 100644 index 0000000..69244ff --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/.gitignore.rej @@ -0,0 +1,5 @@ +--- /dev/null ++++ .gitignore +@@ -0,0 +1,2 @@ ++node_modules/ ++npm-debug.log \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/node_modules/mkdirp/.npmignore b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/.npmignore new file mode 100644 index 0000000..9303c34 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/.npmignore @@ -0,0 +1,2 @@ +node_modules/ +npm-debug.log \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/node_modules/mkdirp/LICENSE b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/LICENSE new file mode 100644 index 0000000..432d1ae --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/LICENSE @@ -0,0 +1,21 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/mocha/node_modules/jade/node_modules/mkdirp/README.markdown b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/README.markdown new file mode 100644 index 0000000..b4dd75f --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/README.markdown @@ -0,0 +1,54 @@ +mkdirp +====== + +Like `mkdir -p`, but in node.js! + +example +======= + +pow.js +------ + var mkdirp = require('mkdirp'); + + mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') + }); + +Output + pow! + +And now /tmp/foo/bar/baz exists, huzzah! + +methods +======= + +var mkdirp = require('mkdirp'); + +mkdirp(dir, mode, cb) +--------------------- + +Create a new directory and any necessary subdirectories at `dir` with octal +permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +mkdirp.sync(dir, mode) +---------------------- + +Synchronously create a new directory and any necessary subdirectories at `dir` +with octal permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +install +======= + +With [npm](http://npmjs.org) do: + + npm install mkdirp + +license +======= + +MIT/X11 diff --git a/node_modules/mocha/node_modules/jade/node_modules/mkdirp/examples/pow.js b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/examples/pow.js new file mode 100644 index 0000000..e692421 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/examples/pow.js @@ -0,0 +1,6 @@ +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') +}); diff --git a/node_modules/mocha/node_modules/jade/node_modules/mkdirp/examples/pow.js.orig b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/examples/pow.js.orig new file mode 100644 index 0000000..7741462 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/examples/pow.js.orig @@ -0,0 +1,6 @@ +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', 0755, function (err) { + if (err) console.error(err) + else console.log('pow!') +}); diff --git a/node_modules/mocha/node_modules/jade/node_modules/mkdirp/examples/pow.js.rej b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/examples/pow.js.rej new file mode 100644 index 0000000..81e7f43 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/examples/pow.js.rej @@ -0,0 +1,19 @@ +--- examples/pow.js ++++ examples/pow.js +@@ -1,6 +1,15 @@ +-var mkdirp = require('mkdirp').mkdirp; ++var mkdirp = require('../').mkdirp, ++ mkdirpSync = require('../').mkdirpSync; + + mkdirp('/tmp/foo/bar/baz', 0755, function (err) { + if (err) console.error(err) + else console.log('pow!') + }); ++ ++try { ++ mkdirpSync('/tmp/bar/foo/baz', 0755); ++ console.log('double pow!'); ++} ++catch (ex) { ++ console.log(ex); ++} \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/node_modules/mkdirp/index.js b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/index.js new file mode 100644 index 0000000..25f43ad --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/index.js @@ -0,0 +1,79 @@ +var path = require('path'); +var fs = require('fs'); + +module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; + +function mkdirP (p, mode, f) { + if (typeof mode === 'function' || mode === undefined) { + f = mode; + mode = 0777 & (~process.umask()); + } + + var cb = f || function () {}; + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + fs.mkdir(p, mode, function (er) { + if (!er) return cb(); + switch (er.code) { + case 'ENOENT': + mkdirP(path.dirname(p), mode, function (er) { + if (er) cb(er); + else mkdirP(p, mode, cb); + }); + break; + + case 'EEXIST': + fs.stat(p, function (er2, stat) { + // if the stat fails, then that's super weird. + // let the original EEXIST be the failure reason. + if (er2 || !stat.isDirectory()) cb(er) + else cb(); + }); + break; + + default: + cb(er); + break; + } + }); +} + +mkdirP.sync = function sync (p, mode) { + if (mode === undefined) { + mode = 0777 & (~process.umask()); + } + + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + try { + fs.mkdirSync(p, mode) + } + catch (err0) { + switch (err0.code) { + case 'ENOENT' : + var err1 = sync(path.dirname(p), mode) + if (err1) throw err1; + else return sync(p, mode); + break; + + case 'EEXIST' : + var stat; + try { + stat = fs.statSync(p); + } + catch (err1) { + throw err0 + } + if (!stat.isDirectory()) throw err0; + else return null; + break; + default : + throw err0 + break; + } + } + + return null; +}; diff --git a/node_modules/mocha/node_modules/jade/node_modules/mkdirp/package.json b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/package.json new file mode 100644 index 0000000..39708fc --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/package.json @@ -0,0 +1,58 @@ +{ + "name": "mkdirp", + "description": "Recursively mkdir, like `mkdir -p`", + "version": "0.3.0", + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "main": "./index", + "keywords": [ + "mkdir", + "directory" + ], + "repository": { + "type": "git", + "url": "git://github.com/substack/node-mkdirp.git" + }, + "scripts": { + "test": "tap test/*.js" + }, + "devDependencies": { + "tap": "0.0.x" + }, + "license": "MIT/X11", + "engines": { + "node": "*" + }, + "_npmUser": { + "name": "substack", + "email": "mail@substack.net" + }, + "_id": "mkdirp@0.3.0", + "dependencies": {}, + "_engineSupported": true, + "_npmVersion": "1.0.106", + "_nodeVersion": "v0.4.12", + "_defaultsLoaded": true, + "dist": { + "shasum": "1bbf5ab1ba827af23575143490426455f481fe1e", + "tarball": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz" + }, + "maintainers": [ + { + "name": "substack", + "email": "mail@substack.net" + } + ], + "directories": {}, + "_shasum": "1bbf5ab1ba827af23575143490426455f481fe1e", + "_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "_from": "mkdirp@0.3.0", + "bugs": { + "url": "https://github.com/substack/node-mkdirp/issues" + }, + "readme": "ERROR: No README data found!", + "homepage": "https://github.com/substack/node-mkdirp" +} diff --git a/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/chmod.js b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/chmod.js new file mode 100644 index 0000000..520dcb8 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/chmod.js @@ -0,0 +1,38 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +test('chmod-pre', function (t) { + var mode = 0744 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.equal(stat && stat.mode & 0777, mode, 'should be 0744'); + t.end(); + }); + }); +}); + +test('chmod', function (t) { + var mode = 0755 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.end(); + }); + }); +}); diff --git a/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/clobber.js b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/clobber.js new file mode 100644 index 0000000..0eb7099 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/clobber.js @@ -0,0 +1,37 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +// a file in the way +var itw = ps.slice(0, 3).join('/'); + + +test('clobber-pre', function (t) { + console.error("about to write to "+itw) + fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.'); + + fs.stat(itw, function (er, stat) { + t.ifError(er) + t.ok(stat && stat.isFile(), 'should be file') + t.end() + }) +}) + +test('clobber', function (t) { + t.plan(2); + mkdirp(file, 0755, function (err) { + t.ok(err); + t.equal(err.code, 'ENOTDIR'); + t.end(); + }); +}); diff --git a/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/mkdirp.js b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/mkdirp.js new file mode 100644 index 0000000..b07cd70 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/mkdirp.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('woo', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/perm.js b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/perm.js new file mode 100644 index 0000000..23a7abb --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/perm.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('async perm', function (t) { + t.plan(2); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); + +test('async root perm', function (t) { + mkdirp('/tmp', 0755, function (err) { + if (err) t.fail(err); + t.end(); + }); + t.end(); +}); diff --git a/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/perm_sync.js b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/perm_sync.js new file mode 100644 index 0000000..f685f60 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/perm_sync.js @@ -0,0 +1,39 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('sync perm', function (t) { + t.plan(2); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json'; + + mkdirp.sync(file, 0755); + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }); +}); + +test('sync root perm', function (t) { + t.plan(1); + + var file = '/tmp'; + mkdirp.sync(file, 0755); + path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }); +}); diff --git a/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/race.js b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/race.js new file mode 100644 index 0000000..96a0447 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/race.js @@ -0,0 +1,41 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('race', function (t) { + t.plan(4); + var ps = [ '', 'tmp' ]; + + for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); + } + var file = ps.join('/'); + + var res = 2; + mk(file, function () { + if (--res === 0) t.end(); + }); + + mk(file, function () { + if (--res === 0) t.end(); + }); + + function mk (file, cb) { + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + if (cb) cb(); + } + }) + }) + }); + } +}); diff --git a/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/rel.js b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/rel.js new file mode 100644 index 0000000..7985824 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/rel.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('rel', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var cwd = process.cwd(); + process.chdir('/tmp'); + + var file = [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + process.chdir(cwd); + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/sync.js b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/sync.js new file mode 100644 index 0000000..e0e389d --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/sync.js @@ -0,0 +1,27 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('sync', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + var err = mkdirp.sync(file, 0755); + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) +}); diff --git a/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/umask.js b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/umask.js new file mode 100644 index 0000000..64ccafe --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/umask.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('implicit mode from umask', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, function (err) { + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, 0777 & (~process.umask())); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) + }); +}); diff --git a/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/umask_sync.js b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/umask_sync.js new file mode 100644 index 0000000..83cba56 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/node_modules/mkdirp/test/umask_sync.js @@ -0,0 +1,27 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('umask sync modes', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + var err = mkdirp.sync(file); + if (err) t.fail(err); + else path.exists(file, function (ex) { + if (!ex) t.fail('file not created') + else fs.stat(file, function (err, stat) { + if (err) t.fail(err) + else { + t.equal(stat.mode & 0777, (0777 & (~process.umask()))); + t.ok(stat.isDirectory(), 'target not a directory'); + t.end(); + } + }) + }) +}); diff --git a/node_modules/mocha/node_modules/jade/package.json b/node_modules/mocha/node_modules/jade/package.json new file mode 100644 index 0000000..4801886 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/package.json @@ -0,0 +1,61 @@ +{ + "name": "jade", + "description": "Jade template engine", + "version": "0.26.3", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/jade" + }, + "main": "./index.js", + "bin": { + "jade": "./bin/jade" + }, + "man": [ + "./jade.1" + ], + "dependencies": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, + "devDependencies": { + "mocha": "*", + "markdown": "*", + "stylus": "*", + "uubench": "*", + "should": "*", + "less": "*", + "uglify-js": "*" + }, + "component": { + "scripts": { + "jade": "runtime.js" + } + }, + "scripts": { + "prepublish": "npm prune" + }, + "_id": "jade@0.26.3", + "dist": { + "shasum": "8f10d7977d8d79f2f6ff862a81b0513ccb25686c", + "tarball": "http://registry.npmjs.org/jade/-/jade-0.26.3.tgz" + }, + "maintainers": [ + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + } + ], + "directories": {}, + "_shasum": "8f10d7977d8d79f2f6ff862a81b0513ccb25686c", + "_resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "_from": "jade@0.26.3", + "bugs": { + "url": "https://github.com/visionmedia/jade/issues" + }, + "readme": "ERROR: No README data found!", + "homepage": "https://github.com/visionmedia/jade" +} diff --git a/node_modules/mocha/node_modules/jade/runtime.js b/node_modules/mocha/node_modules/jade/runtime.js new file mode 100644 index 0000000..0f54907 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/runtime.js @@ -0,0 +1,179 @@ + +jade = (function(exports){ +/*! + * Jade - runtime + * Copyright(c) 2010 TJ Holowaychuk + * 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(/&(?!(\w+|\#\d+);)/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; + + 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; +}; + + return exports; + +})({}); diff --git a/node_modules/mocha/node_modules/jade/runtime.min.js b/node_modules/mocha/node_modules/jade/runtime.min.js new file mode 100644 index 0000000..1714efb --- /dev/null +++ b/node_modules/mocha/node_modules/jade/runtime.min.js @@ -0,0 +1 @@ +jade=function(exports){Array.isArray||(Array.isArray=function(arr){return"[object Array]"==Object.prototype.toString.call(arr)}),Object.keys||(Object.keys=function(obj){var arr=[];for(var key in obj)obj.hasOwnProperty(key)&&arr.push(key);return arr}),exports.merge=function merge(a,b){var ac=a["class"],bc=b["class"];if(ac||bc)ac=ac||[],bc=bc||[],Array.isArray(ac)||(ac=[ac]),Array.isArray(bc)||(bc=[bc]),ac=ac.filter(nulls),bc=bc.filter(nulls),a["class"]=ac.concat(bc).join(" ");for(var key in b)key!="class"&&(a[key]=b[key]);return a};function nulls(val){return val!=null}return 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/g,">").replace(/"/g,""")},exports.rethrow=function rethrow(err,filename,lineno){if(!filename)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),context=lines.slice(start,end).map(function(line,i){var curr=i+start+1;return(curr==lineno?" > ":" ")+curr+"| "+line}).join("\n");throw err.path=filename,err.message=(filename||"Jade")+":"+lineno+"\n"+context+"\n\n"+err.message,err},exports}({}); \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/test.jade b/node_modules/mocha/node_modules/jade/test.jade new file mode 100644 index 0000000..b3a8988 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/test.jade @@ -0,0 +1,7 @@ +p. + This is a large + body of text for + this tag. + + Nothing too + exciting. \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/testing/head.jade b/node_modules/mocha/node_modules/jade/testing/head.jade new file mode 100644 index 0000000..8515406 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/testing/head.jade @@ -0,0 +1,5 @@ +head + script(src='/jquery.js') + yield + if false + script(src='/jquery.ui.js') diff --git a/node_modules/mocha/node_modules/jade/testing/index.jade b/node_modules/mocha/node_modules/jade/testing/index.jade new file mode 100644 index 0000000..1032c5f --- /dev/null +++ b/node_modules/mocha/node_modules/jade/testing/index.jade @@ -0,0 +1,22 @@ + +tag = 'p' +foo = 'bar' + +#{tag} value +#{tag}(foo='bar') value +#{foo ? 'a' : 'li'}(something) here + +mixin item(icon) + li + if attributes.href + a(attributes) + img.icon(src=icon) + block + else + span(attributes) + img.icon(src=icon) + block + +ul + +item('contact') Contact + +item(href='/contact') Contact diff --git a/node_modules/mocha/node_modules/jade/testing/index.js b/node_modules/mocha/node_modules/jade/testing/index.js new file mode 100644 index 0000000..226e8c0 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/testing/index.js @@ -0,0 +1,11 @@ + +/** + * Module dependencies. + */ + +var jade = require('../'); + +jade.renderFile('testing/index.jade', { pretty: true, debug: true, compileDebug: false }, function(err, str){ + if (err) throw err; + console.log(str); +}); \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/testing/layout.jade b/node_modules/mocha/node_modules/jade/testing/layout.jade new file mode 100644 index 0000000..6923cf1 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/testing/layout.jade @@ -0,0 +1,6 @@ +html + include head + script(src='/caustic.js') + script(src='/app.js') + body + block content \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/testing/user.jade b/node_modules/mocha/node_modules/jade/testing/user.jade new file mode 100644 index 0000000..3c636b7 --- /dev/null +++ b/node_modules/mocha/node_modules/jade/testing/user.jade @@ -0,0 +1,7 @@ +h1 Tobi +p Is a ferret + +ul + li: a foo + li: a bar + li: a baz \ No newline at end of file diff --git a/node_modules/mocha/node_modules/jade/testing/user.js b/node_modules/mocha/node_modules/jade/testing/user.js new file mode 100644 index 0000000..2ecc45e --- /dev/null +++ b/node_modules/mocha/node_modules/jade/testing/user.js @@ -0,0 +1,27 @@ +function anonymous(locals, attrs, escape, rethrow) { +var attrs = jade.attrs, escape = jade.escape, rethrow = jade.rethrow; +var __jade = [{ lineno: 1, filename: "testing/user.jade" }]; +try { +var buf = []; +with (locals || {}) { +var interp; +__jade.unshift({ lineno: 1, filename: __jade[0].filename }); +__jade.unshift({ lineno: 1, filename: __jade[0].filename }); +buf.push('

Tobi'); +__jade.unshift({ lineno: undefined, filename: __jade[0].filename }); +__jade.shift(); +buf.push('

'); +__jade.shift(); +__jade.unshift({ lineno: 2, filename: __jade[0].filename }); +buf.push('

Is a ferret'); +__jade.unshift({ lineno: undefined, filename: __jade[0].filename }); +__jade.shift(); +buf.push('

'); +__jade.shift(); +__jade.shift(); +} +return buf.join(""); +} catch (err) { + rethrow(err, __jade[0].filename, __jade[0].lineno); +} +} \ No newline at end of file diff --git a/node_modules/mocha/node_modules/mkdirp/.npmignore b/node_modules/mocha/node_modules/mkdirp/.npmignore new file mode 100644 index 0000000..9303c34 --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/.npmignore @@ -0,0 +1,2 @@ +node_modules/ +npm-debug.log \ No newline at end of file diff --git a/node_modules/mocha/node_modules/mkdirp/.travis.yml b/node_modules/mocha/node_modules/mkdirp/.travis.yml new file mode 100644 index 0000000..c693a93 --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.6 + - 0.8 + - "0.10" diff --git a/node_modules/mocha/node_modules/mkdirp/LICENSE b/node_modules/mocha/node_modules/mkdirp/LICENSE new file mode 100644 index 0000000..432d1ae --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/LICENSE @@ -0,0 +1,21 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/mocha/node_modules/mkdirp/bin/cmd.js b/node_modules/mocha/node_modules/mkdirp/bin/cmd.js new file mode 100755 index 0000000..d95de15 --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/bin/cmd.js @@ -0,0 +1,33 @@ +#!/usr/bin/env node + +var mkdirp = require('../'); +var minimist = require('minimist'); +var fs = require('fs'); + +var argv = minimist(process.argv.slice(2), { + alias: { m: 'mode', h: 'help' }, + string: [ 'mode' ] +}); +if (argv.help) { + fs.createReadStream(__dirname + '/usage.txt').pipe(process.stdout); + return; +} + +var paths = argv._.slice(); +var mode = argv.mode ? parseInt(argv.mode, 8) : undefined; + +(function next () { + if (paths.length === 0) return; + var p = paths.shift(); + + if (mode === undefined) mkdirp(p, cb) + else mkdirp(p, mode, cb) + + function cb (err) { + if (err) { + console.error(err.message); + process.exit(1); + } + else next(); + } +})(); diff --git a/node_modules/mocha/node_modules/mkdirp/bin/usage.txt b/node_modules/mocha/node_modules/mkdirp/bin/usage.txt new file mode 100644 index 0000000..f952aa2 --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/bin/usage.txt @@ -0,0 +1,12 @@ +usage: mkdirp [DIR1,DIR2..] {OPTIONS} + + Create each supplied directory including any necessary parent directories that + don't yet exist. + + If the directory already exists, do nothing. + +OPTIONS are: + + -m, --mode If a directory needs to be created, set the mode as an octal + permission string. + diff --git a/node_modules/mocha/node_modules/mkdirp/examples/pow.js b/node_modules/mocha/node_modules/mkdirp/examples/pow.js new file mode 100644 index 0000000..e692421 --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/examples/pow.js @@ -0,0 +1,6 @@ +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') +}); diff --git a/node_modules/mocha/node_modules/mkdirp/index.js b/node_modules/mocha/node_modules/mkdirp/index.js new file mode 100644 index 0000000..a1742b2 --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/index.js @@ -0,0 +1,97 @@ +var path = require('path'); +var fs = require('fs'); + +module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; + +function mkdirP (p, opts, f, made) { + if (typeof opts === 'function') { + f = opts; + opts = {}; + } + else if (!opts || typeof opts !== 'object') { + opts = { mode: opts }; + } + + var mode = opts.mode; + var xfs = opts.fs || fs; + + if (mode === undefined) { + mode = 0777 & (~process.umask()); + } + if (!made) made = null; + + var cb = f || function () {}; + p = path.resolve(p); + + xfs.mkdir(p, mode, function (er) { + if (!er) { + made = made || p; + return cb(null, made); + } + switch (er.code) { + case 'ENOENT': + mkdirP(path.dirname(p), opts, function (er, made) { + if (er) cb(er, made); + else mkdirP(p, opts, cb, made); + }); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + xfs.stat(p, function (er2, stat) { + // if the stat fails, then that's super weird. + // let the original error be the failure reason. + if (er2 || !stat.isDirectory()) cb(er, made) + else cb(null, made); + }); + break; + } + }); +} + +mkdirP.sync = function sync (p, opts, made) { + if (!opts || typeof opts !== 'object') { + opts = { mode: opts }; + } + + var mode = opts.mode; + var xfs = opts.fs || fs; + + if (mode === undefined) { + mode = 0777 & (~process.umask()); + } + if (!made) made = null; + + p = path.resolve(p); + + try { + xfs.mkdirSync(p, mode); + made = made || p; + } + catch (err0) { + switch (err0.code) { + case 'ENOENT' : + made = sync(path.dirname(p), opts, made); + sync(p, opts, made); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + var stat; + try { + stat = xfs.statSync(p); + } + catch (err1) { + throw err0; + } + if (!stat.isDirectory()) throw err0; + break; + } + } + + return made; +}; diff --git a/node_modules/mocha/node_modules/mkdirp/package.json b/node_modules/mocha/node_modules/mkdirp/package.json new file mode 100644 index 0000000..a915c51 --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/package.json @@ -0,0 +1,58 @@ +{ + "name": "mkdirp", + "description": "Recursively mkdir, like `mkdir -p`", + "version": "0.5.0", + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "main": "./index", + "keywords": [ + "mkdir", + "directory" + ], + "repository": { + "type": "git", + "url": "https://github.com/substack/node-mkdirp.git" + }, + "scripts": { + "test": "tap test/*.js" + }, + "dependencies": { + "minimist": "0.0.8" + }, + "devDependencies": { + "tap": "~0.4.0", + "mock-fs": "~2.2.0" + }, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/substack/node-mkdirp/issues" + }, + "homepage": "https://github.com/substack/node-mkdirp", + "_id": "mkdirp@0.5.0", + "dist": { + "shasum": "1d73076a6df986cd9344e15e71fcc05a4c9abf12", + "tarball": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz" + }, + "_from": "mkdirp@0.5.0", + "_npmVersion": "1.4.3", + "_npmUser": { + "name": "substack", + "email": "mail@substack.net" + }, + "maintainers": [ + { + "name": "substack", + "email": "mail@substack.net" + } + ], + "directories": {}, + "_shasum": "1d73076a6df986cd9344e15e71fcc05a4c9abf12", + "_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/node_modules/mocha/node_modules/mkdirp/readme.markdown b/node_modules/mocha/node_modules/mkdirp/readme.markdown new file mode 100644 index 0000000..3cc1315 --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/readme.markdown @@ -0,0 +1,100 @@ +# mkdirp + +Like `mkdir -p`, but in node.js! + +[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp) + +# example + +## pow.js + +```js +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') +}); +``` + +Output + +``` +pow! +``` + +And now /tmp/foo/bar/baz exists, huzzah! + +# methods + +```js +var mkdirp = require('mkdirp'); +``` + +## mkdirp(dir, opts, cb) + +Create a new directory and any necessary subdirectories at `dir` with octal +permission string `opts.mode`. If `opts` is a non-object, it will be treated as +the `opts.mode`. + +If `opts.mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +`cb(err, made)` fires with the error or the first directory `made` +that had to be created, if any. + +You can optionally pass in an alternate `fs` implementation by passing in +`opts.fs`. Your implementation should have `opts.fs.mkdir(path, mode, cb)` and +`opts.fs.stat(path, cb)`. + +## mkdirp.sync(dir, opts) + +Synchronously create a new directory and any necessary subdirectories at `dir` +with octal permission string `opts.mode`. If `opts` is a non-object, it will be +treated as the `opts.mode`. + +If `opts.mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +Returns the first directory that had to be created, if any. + +You can optionally pass in an alternate `fs` implementation by passing in +`opts.fs`. Your implementation should have `opts.fs.mkdirSync(path, mode)` and +`opts.fs.statSync(path)`. + +# usage + +This package also ships with a `mkdirp` command. + +``` +usage: mkdirp [DIR1,DIR2..] {OPTIONS} + + Create each supplied directory including any necessary parent directories that + don't yet exist. + + If the directory already exists, do nothing. + +OPTIONS are: + + -m, --mode If a directory needs to be created, set the mode as an octal + permission string. + +``` + +# install + +With [npm](http://npmjs.org) do: + +``` +npm install mkdirp +``` + +to get the library, or + +``` +npm install -g mkdirp +``` + +to get the command. + +# license + +MIT diff --git a/node_modules/mocha/node_modules/mkdirp/test/chmod.js b/node_modules/mocha/node_modules/mkdirp/test/chmod.js new file mode 100644 index 0000000..520dcb8 --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/test/chmod.js @@ -0,0 +1,38 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +test('chmod-pre', function (t) { + var mode = 0744 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.equal(stat && stat.mode & 0777, mode, 'should be 0744'); + t.end(); + }); + }); +}); + +test('chmod', function (t) { + var mode = 0755 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.end(); + }); + }); +}); diff --git a/node_modules/mocha/node_modules/mkdirp/test/clobber.js b/node_modules/mocha/node_modules/mkdirp/test/clobber.js new file mode 100644 index 0000000..0eb7099 --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/test/clobber.js @@ -0,0 +1,37 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +// a file in the way +var itw = ps.slice(0, 3).join('/'); + + +test('clobber-pre', function (t) { + console.error("about to write to "+itw) + fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.'); + + fs.stat(itw, function (er, stat) { + t.ifError(er) + t.ok(stat && stat.isFile(), 'should be file') + t.end() + }) +}) + +test('clobber', function (t) { + t.plan(2); + mkdirp(file, 0755, function (err) { + t.ok(err); + t.equal(err.code, 'ENOTDIR'); + t.end(); + }); +}); diff --git a/node_modules/mocha/node_modules/mkdirp/test/mkdirp.js b/node_modules/mocha/node_modules/mkdirp/test/mkdirp.js new file mode 100644 index 0000000..3b624dd --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/test/mkdirp.js @@ -0,0 +1,26 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var exists = fs.exists || path.exists; +var test = require('tap').test; + +test('woo', function (t) { + t.plan(5); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + t.ifError(err); + exists(file, function (ex) { + t.ok(ex, 'file created'); + fs.stat(file, function (err, stat) { + t.ifError(err); + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + }) + }) + }); +}); diff --git a/node_modules/mocha/node_modules/mkdirp/test/opts_fs.js b/node_modules/mocha/node_modules/mkdirp/test/opts_fs.js new file mode 100644 index 0000000..f1fbeca --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/test/opts_fs.js @@ -0,0 +1,27 @@ +var mkdirp = require('../'); +var path = require('path'); +var test = require('tap').test; +var mockfs = require('mock-fs'); + +test('opts.fs', function (t) { + t.plan(5); + + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/beep/boop/' + [x,y,z].join('/'); + var xfs = mockfs.fs(); + + mkdirp(file, { fs: xfs, mode: 0755 }, function (err) { + t.ifError(err); + xfs.exists(file, function (ex) { + t.ok(ex, 'created file'); + xfs.stat(file, function (err, stat) { + t.ifError(err); + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + }); + }); + }); +}); diff --git a/node_modules/mocha/node_modules/mkdirp/test/opts_fs_sync.js b/node_modules/mocha/node_modules/mkdirp/test/opts_fs_sync.js new file mode 100644 index 0000000..224b506 --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/test/opts_fs_sync.js @@ -0,0 +1,25 @@ +var mkdirp = require('../'); +var path = require('path'); +var test = require('tap').test; +var mockfs = require('mock-fs'); + +test('opts.fs sync', function (t) { + t.plan(4); + + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/beep/boop/' + [x,y,z].join('/'); + var xfs = mockfs.fs(); + + mkdirp.sync(file, { fs: xfs, mode: 0755 }); + xfs.exists(file, function (ex) { + t.ok(ex, 'created file'); + xfs.stat(file, function (err, stat) { + t.ifError(err); + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + }); + }); +}); diff --git a/node_modules/mocha/node_modules/mkdirp/test/perm.js b/node_modules/mocha/node_modules/mkdirp/test/perm.js new file mode 100644 index 0000000..2c97590 --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/test/perm.js @@ -0,0 +1,30 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var exists = fs.exists || path.exists; +var test = require('tap').test; + +test('async perm', function (t) { + t.plan(5); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16); + + mkdirp(file, 0755, function (err) { + t.ifError(err); + exists(file, function (ex) { + t.ok(ex, 'file created'); + fs.stat(file, function (err, stat) { + t.ifError(err); + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + }) + }) + }); +}); + +test('async root perm', function (t) { + mkdirp('/tmp', 0755, function (err) { + if (err) t.fail(err); + t.end(); + }); + t.end(); +}); diff --git a/node_modules/mocha/node_modules/mkdirp/test/perm_sync.js b/node_modules/mocha/node_modules/mkdirp/test/perm_sync.js new file mode 100644 index 0000000..327e54b --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/test/perm_sync.js @@ -0,0 +1,34 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var exists = fs.exists || path.exists; +var test = require('tap').test; + +test('sync perm', function (t) { + t.plan(4); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json'; + + mkdirp.sync(file, 0755); + exists(file, function (ex) { + t.ok(ex, 'file created'); + fs.stat(file, function (err, stat) { + t.ifError(err); + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + }); + }); +}); + +test('sync root perm', function (t) { + t.plan(3); + + var file = '/tmp'; + mkdirp.sync(file, 0755); + exists(file, function (ex) { + t.ok(ex, 'file created'); + fs.stat(file, function (err, stat) { + t.ifError(err); + t.ok(stat.isDirectory(), 'target not a directory'); + }) + }); +}); diff --git a/node_modules/mocha/node_modules/mkdirp/test/race.js b/node_modules/mocha/node_modules/mkdirp/test/race.js new file mode 100644 index 0000000..7c295f4 --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/test/race.js @@ -0,0 +1,40 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var exists = fs.exists || path.exists; +var test = require('tap').test; + +test('race', function (t) { + t.plan(6); + var ps = [ '', 'tmp' ]; + + for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); + } + var file = ps.join('/'); + + var res = 2; + mk(file, function () { + if (--res === 0) t.end(); + }); + + mk(file, function () { + if (--res === 0) t.end(); + }); + + function mk (file, cb) { + mkdirp(file, 0755, function (err) { + t.ifError(err); + exists(file, function (ex) { + t.ok(ex, 'file created'); + fs.stat(file, function (err, stat) { + t.ifError(err); + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + if (cb) cb(); + }); + }) + }); + } +}); diff --git a/node_modules/mocha/node_modules/mkdirp/test/rel.js b/node_modules/mocha/node_modules/mkdirp/test/rel.js new file mode 100644 index 0000000..d1f175c --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/test/rel.js @@ -0,0 +1,30 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var exists = fs.exists || path.exists; +var test = require('tap').test; + +test('rel', function (t) { + t.plan(5); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var cwd = process.cwd(); + process.chdir('/tmp'); + + var file = [x,y,z].join('/'); + + mkdirp(file, 0755, function (err) { + t.ifError(err); + exists(file, function (ex) { + t.ok(ex, 'file created'); + fs.stat(file, function (err, stat) { + t.ifError(err); + process.chdir(cwd); + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + }) + }) + }); +}); diff --git a/node_modules/mocha/node_modules/mkdirp/test/return.js b/node_modules/mocha/node_modules/mkdirp/test/return.js new file mode 100644 index 0000000..bce68e5 --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/test/return.js @@ -0,0 +1,25 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('return value', function (t) { + t.plan(4); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + // should return the first dir created. + // By this point, it would be profoundly surprising if /tmp didn't + // already exist, since every other test makes things in there. + mkdirp(file, function (err, made) { + t.ifError(err); + t.equal(made, '/tmp/' + x); + mkdirp(file, function (err, made) { + t.ifError(err); + t.equal(made, null); + }); + }); +}); diff --git a/node_modules/mocha/node_modules/mkdirp/test/return_sync.js b/node_modules/mocha/node_modules/mkdirp/test/return_sync.js new file mode 100644 index 0000000..7c222d3 --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/test/return_sync.js @@ -0,0 +1,24 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('return value', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + // should return the first dir created. + // By this point, it would be profoundly surprising if /tmp didn't + // already exist, since every other test makes things in there. + // Note that this will throw on failure, which will fail the test. + var made = mkdirp.sync(file); + t.equal(made, '/tmp/' + x); + + // making the same file again should have no effect. + made = mkdirp.sync(file); + t.equal(made, null); +}); diff --git a/node_modules/mocha/node_modules/mkdirp/test/root.js b/node_modules/mocha/node_modules/mkdirp/test/root.js new file mode 100644 index 0000000..97ad7a2 --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/test/root.js @@ -0,0 +1,18 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('root', function (t) { + // '/' on unix, 'c:/' on windows. + var file = path.resolve('/'); + + mkdirp(file, 0755, function (err) { + if (err) throw err + fs.stat(file, function (er, stat) { + if (er) throw er + t.ok(stat.isDirectory(), 'target is a directory'); + t.end(); + }) + }); +}); diff --git a/node_modules/mocha/node_modules/mkdirp/test/sync.js b/node_modules/mocha/node_modules/mkdirp/test/sync.js new file mode 100644 index 0000000..88fa432 --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/test/sync.js @@ -0,0 +1,30 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var exists = fs.exists || path.exists; +var test = require('tap').test; + +test('sync', function (t) { + t.plan(4); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + try { + mkdirp.sync(file, 0755); + } catch (err) { + t.fail(err); + return t.end(); + } + + exists(file, function (ex) { + t.ok(ex, 'file created'); + fs.stat(file, function (err, stat) { + t.ifError(err); + t.equal(stat.mode & 0777, 0755); + t.ok(stat.isDirectory(), 'target not a directory'); + }); + }); +}); diff --git a/node_modules/mocha/node_modules/mkdirp/test/umask.js b/node_modules/mocha/node_modules/mkdirp/test/umask.js new file mode 100644 index 0000000..82c393a --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/test/umask.js @@ -0,0 +1,26 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var exists = fs.exists || path.exists; +var test = require('tap').test; + +test('implicit mode from umask', function (t) { + t.plan(5); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, function (err) { + t.ifError(err); + exists(file, function (ex) { + t.ok(ex, 'file created'); + fs.stat(file, function (err, stat) { + t.ifError(err); + t.equal(stat.mode & 0777, 0777 & (~process.umask())); + t.ok(stat.isDirectory(), 'target not a directory'); + }); + }) + }); +}); diff --git a/node_modules/mocha/node_modules/mkdirp/test/umask_sync.js b/node_modules/mocha/node_modules/mkdirp/test/umask_sync.js new file mode 100644 index 0000000..e537fbe --- /dev/null +++ b/node_modules/mocha/node_modules/mkdirp/test/umask_sync.js @@ -0,0 +1,30 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var exists = fs.exists || path.exists; +var test = require('tap').test; + +test('umask sync modes', function (t) { + t.plan(4); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + try { + mkdirp.sync(file); + } catch (err) { + t.fail(err); + return t.end(); + } + + exists(file, function (ex) { + t.ok(ex, 'file created'); + fs.stat(file, function (err, stat) { + t.ifError(err); + t.equal(stat.mode & 0777, (0777 & (~process.umask()))); + t.ok(stat.isDirectory(), 'target not a directory'); + }); + }); +}); diff --git a/node_modules/mocha/node_modules/supports-color/cli.js b/node_modules/mocha/node_modules/supports-color/cli.js new file mode 100755 index 0000000..e746987 --- /dev/null +++ b/node_modules/mocha/node_modules/supports-color/cli.js @@ -0,0 +1,29 @@ +#!/usr/bin/env node +'use strict'; +var pkg = require('./package.json'); +var supportsColor = require('./'); +var argv = process.argv.slice(2); + +function help() { + console.log([ + '', + ' ' + pkg.description, + '', + ' Usage', + ' supports-color', + '', + ' Exits with code 0 if color is supported and 1 if not' + ].join('\n')); +} + +if (argv.indexOf('--help') !== -1) { + help(); + return; +} + +if (argv.indexOf('--version') !== -1) { + console.log(pkg.version); + return; +} + +process.exit(supportsColor ? 0 : 1); diff --git a/node_modules/mocha/node_modules/supports-color/index.js b/node_modules/mocha/node_modules/supports-color/index.js new file mode 100644 index 0000000..a2b9784 --- /dev/null +++ b/node_modules/mocha/node_modules/supports-color/index.js @@ -0,0 +1,39 @@ +'use strict'; +var argv = process.argv; + +module.exports = (function () { + if (argv.indexOf('--no-color') !== -1 || + argv.indexOf('--no-colors') !== -1 || + argv.indexOf('--color=false') !== -1) { + return false; + } + + if (argv.indexOf('--color') !== -1 || + argv.indexOf('--colors') !== -1 || + argv.indexOf('--color=true') !== -1 || + argv.indexOf('--color=always') !== -1) { + return true; + } + + if (process.stdout && !process.stdout.isTTY) { + return false; + } + + if (process.platform === 'win32') { + return true; + } + + if ('COLORTERM' in process.env) { + return true; + } + + if (process.env.TERM === 'dumb') { + return false; + } + + if (/^screen|^xterm|^vt100|color|ansi|cygwin|linux/i.test(process.env.TERM)) { + return true; + } + + return false; +})(); diff --git a/node_modules/mocha/node_modules/supports-color/license b/node_modules/mocha/node_modules/supports-color/license new file mode 100644 index 0000000..654d0bf --- /dev/null +++ b/node_modules/mocha/node_modules/supports-color/license @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/mocha/node_modules/supports-color/package.json b/node_modules/mocha/node_modules/supports-color/package.json new file mode 100644 index 0000000..eb78419 --- /dev/null +++ b/node_modules/mocha/node_modules/supports-color/package.json @@ -0,0 +1,85 @@ +{ + "name": "supports-color", + "version": "1.2.1", + "description": "Detect whether a terminal supports color", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/sindresorhus/supports-color" + }, + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "http://sindresorhus.com" + }, + "maintainers": [ + { + "name": "sindresorhus", + "email": "sindresorhus@gmail.com" + }, + { + "name": "jbnicolai", + "email": "jappelman@xebia.com" + } + ], + "bin": { + "supports-color": "cli.js" + }, + "engines": { + "node": ">=0.8.0" + }, + "scripts": { + "test": "mocha" + }, + "files": [ + "index.js", + "cli.js" + ], + "keywords": [ + "cli", + "bin", + "color", + "colour", + "colors", + "terminal", + "console", + "cli", + "ansi", + "styles", + "tty", + "rgb", + "256", + "shell", + "xterm", + "command-line", + "support", + "supports", + "capability", + "detect" + ], + "devDependencies": { + "mocha": "*", + "require-uncached": "^1.0.2" + }, + "gitHead": "ffe5e224bd24dc0410787b94e192d240be025aec", + "bugs": { + "url": "https://github.com/sindresorhus/supports-color/issues" + }, + "homepage": "https://github.com/sindresorhus/supports-color", + "_id": "supports-color@1.2.1", + "_shasum": "12ee21507086cd98c1058d9ec0f4ac476b7af3b2", + "_from": "supports-color@>=1.2.0 <1.3.0", + "_npmVersion": "2.1.16", + "_nodeVersion": "0.10.35", + "_npmUser": { + "name": "jbnicolai", + "email": "jappelman@xebia.com" + }, + "dist": { + "shasum": "12ee21507086cd98c1058d9ec0f4ac476b7af3b2", + "tarball": "http://registry.npmjs.org/supports-color/-/supports-color-1.2.1.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.1.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/node_modules/mocha/node_modules/supports-color/readme.md b/node_modules/mocha/node_modules/supports-color/readme.md new file mode 100644 index 0000000..32d4f46 --- /dev/null +++ b/node_modules/mocha/node_modules/supports-color/readme.md @@ -0,0 +1,44 @@ +# supports-color [![Build Status](https://travis-ci.org/sindresorhus/supports-color.svg?branch=master)](https://travis-ci.org/sindresorhus/supports-color) + +> Detect whether a terminal supports color + + +## Install + +```sh +$ npm install --save supports-color +``` + + +## Usage + +```js +var supportsColor = require('supports-color'); + +if (supportsColor) { + console.log('Terminal supports color'); +} +``` + +It obeys the `--color` and `--no-color` CLI flags. + + +## CLI + +```sh +$ npm install --global supports-color +``` + +``` +$ supports-color --help + + Usage + supports-color + + Exits with code 0 if color is supported and 1 if not +``` + + +## License + +MIT © [Sindre Sorhus](http://sindresorhus.com) diff --git a/node_modules/mocha/package.json b/node_modules/mocha/package.json new file mode 100644 index 0000000..f0aae53 --- /dev/null +++ b/node_modules/mocha/package.json @@ -0,0 +1,129 @@ +{ + "name": "mocha", + "version": "2.2.4", + "description": "simple, flexible, fun test framework", + "keywords": [ + "mocha", + "test", + "bdd", + "tdd", + "tap" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "contributors": [ + { + "name": "Joshua Appelman", + "email": "joshua@jbna.nl" + }, + { + "name": "Christoffer Hallas", + "email": "christoffer.hallas@gmail.com" + }, + { + "name": "Christopher Hiller", + "email": "chiller@badwing.com" + }, + { + "name": "Travis Jeffery", + "email": "tj@travisjeffery.com" + }, + { + "name": "Daniel St. Jules", + "email": "danielst.jules@gmail.com" + }, + { + "name": "David da Silva Contín", + "email": "dasilvacontin@gmail.com" + }, + { + "name": "Ariel Mashraki", + "email": "ariel@mashraki.co.il" + }, + { + "name": "Pawel Kozlowski", + "email": "pkozlowski.opensource@gmail.com" + } + ], + "repository": { + "type": "git", + "url": "git://github.com/mochajs/mocha.git" + }, + "maintainers": [ + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + }, + { + "name": "travisjeffery", + "email": "tj@travisjeffery.com" + }, + { + "name": "boneskull", + "email": "chiller@badwing.com" + } + ], + "main": "./index", + "browser": "./mocha.js", + "bin": { + "mocha": "./bin/mocha", + "_mocha": "./bin/_mocha" + }, + "engines": { + "node": ">= 0.8.x" + }, + "scripts": { + "test": "make test-all" + }, + "dependencies": { + "commander": "2.3.0", + "debug": "2.0.0", + "diff": "1.0.8", + "escape-string-regexp": "1.0.2", + "glob": "3.2.3", + "growl": "1.8.1", + "jade": "0.26.3", + "mkdirp": "0.5.0", + "supports-color": "~1.2.0" + }, + "devDependencies": { + "coffee-script": "~1.8.0", + "should": "~4.0.0" + }, + "files": [ + "bin", + "images", + "lib", + "index.js", + "mocha.css", + "mocha.js", + "LICENSE" + ], + "licenses": [ + { + "type": "MIT", + "url": "https://raw.github.com/mochajs/mocha/master/LICENSE" + } + ], + "bugs": { + "url": "https://github.com/mochajs/mocha/issues" + }, + "homepage": "https://github.com/mochajs/mocha", + "_id": "mocha@2.2.4", + "_shasum": "192b0edc0e17e56613bc66e5fc7e81c00413a98d", + "_from": "mocha@*", + "_npmVersion": "1.4.9", + "_npmUser": { + "name": "travisjeffery", + "email": "tj@travisjeffery.com" + }, + "dist": { + "shasum": "192b0edc0e17e56613bc66e5fc7e81c00413a98d", + "tarball": "http://registry.npmjs.org/mocha/-/mocha-2.2.4.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/mocha/-/mocha-2.2.4.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/other/add-binary-debug.js b/other/add-binary-debug.js new file mode 100644 index 0000000..33c68e4 --- /dev/null +++ b/other/add-binary-debug.js @@ -0,0 +1,39 @@ +'use strict'; + +import _ from '../utils'; + +function addBinary(a, b) { + let c = new Array(a.length + 1), + d = new Array(c.length); + + _.debug(`inputs: ${a}, ${b}`); + + for (let i = c.length - 1; i >= 0; i--) { + let sum = i > 0 ? a[i - 1] + b[i - 1] + (d[i] || 0) : d[i] || 0; + + _.debug(`i = ${i} sum = ${sum}`); + + if (sum >= 2) { + d[i - 1] = 1; + c[i] = sum - 2; + _.debug(`sum was >= 2, d[${i - 1}] = 1 c[${i}] = ${sum - 2}`); + } else { + c[i] = sum; + _.debug(`c[${i}] = ${sum}`); + } + } + + return c; +} + +const argumentToArray = (arg) => + arg.split('').map(function(el) { + return parseInt(el, 10); + }); + +let i1 = argumentToArray(_.args[0]), + i2 = argumentToArray(_.args[1]); + +let result = addBinary(i1, i2); + +_.log(result.join('')); diff --git a/other/add-binary.js b/other/add-binary.js new file mode 100644 index 0000000..117835c --- /dev/null +++ b/other/add-binary.js @@ -0,0 +1,33 @@ +'use strict'; + +import _ from '../utils'; + +function addBinary(a, b) { + let c = new Array(a.length+1), + d = new Array(c.length); + + for(let i = c.length-1; i >= 0; i--) { + let sum = i > 0 ? a[i-1] + b[i-1] + (d[i] || 0) : d[i] || 0; + + if(sum >= 2) { + d[i-1] = 1; + c[i] = sum - 2; + } else { + c[i] = sum; + } + } + + return c; +} + +const argumentToArray = (arg) => + arg.split('').map(function(el) { + return parseInt(el, 10); + }); + +let i1 = argumentToArray(_.args[0]), + i2 = argumentToArray(_.args[1]); + +let result = addBinary(i1, i2); + +_.log(result.join('')); \ No newline at end of file diff --git a/other/anagrams.js b/other/anagrams.js new file mode 100644 index 0000000..5a8458d --- /dev/null +++ b/other/anagrams.js @@ -0,0 +1,38 @@ +'use strict'; + +import _ from '../utils'; + +let words = _.args.length ? _.args : ['a gentleman', 'debit card', + 'bad credit', 'elegant man', + 'the eyes', 'they see', + 'mummy', 'my mum', + 'hello', 'lehol']; + +function anagrams(words) { + let pairs = []; + + for(let w of words) { + let matched = pairs.some(a => { + return a[0] === w || a[1] === w; + }); + + if(matched) continue; + let sum = sumAscii(w); + + let other = words.find(a => { + return w !== a && sumAscii(a) === sum; + }); + + if(other) pairs.push([w, other]); + } + + return pairs; +} + +_.log(anagrams(words)); + +function sumAscii(word) { + return word.split('').reduce((a,b) => { + return a + b.charCodeAt(0); + }, 0); +} \ No newline at end of file diff --git a/other/ascii85.js b/other/ascii85.js new file mode 100644 index 0000000..8e9cf77 --- /dev/null +++ b/other/ascii85.js @@ -0,0 +1,67 @@ +String.prototype.toAscii85 = function() { + var str = ''; + + for(var i = 0, len = this.length; i < len; i+=4) { + var bin = ''; + var zeroes = 0; + for(var j = 0; j < 4; j++) { + var char = this[i+j]; + + bin += to8bit(char ? char.charCodeAt(0) : (zeroes++, 0)); + } + + var n = parseInt(bin, 2); + + for(var j = 4; j >= 0; j--) { + var c = Math.floor(n / Math.pow(85, j)); + n -= c*Math.pow(85, j); + str += String.fromCharCode(c + 33); + } + + str = str.slice(0, zeroes > 0 ? -zeroes : undefined); + } + + return '<~' + str.replace(/!{5}/g, 'z') + '~>' +} + +String.prototype.fromAscii85 = function() { + var str = this.slice(2, -2).replace(/z/g, '!!!!!').replace(/\s/g, ''); + var decoded = ''; + + + for(var i = 0, len = str.length; i < len; i+=5) { + var n = 0; + var us = 0; + for(var j = 4; j >= 0; j--) { + var c = str[j+i] || (us++, 'u'), + code = c.charCodeAt(0) - 33; + + n += code * Math.pow(85, Math.abs(j-4)); + } + + var bin = stretch(n.toString(2), 32); + + for(var j = 0; j < 32; j+=8) { + var char = parseInt(bin.slice(j, j+8), 2); + decoded += String.fromCharCode(char); + } + decoded = decoded.slice(0, us > 0 ? -us : undefined); + } + + return decoded; +} + +function to8bit(n) { + var bin = stretch(n.toString(2), 8); + + return bin; +} + +function stretch(s, n) { + var r = s; + while(r.length < n) { + r = '0' + r; + } + + return r; +} \ No newline at end of file diff --git a/other/brainfuck.js b/other/brainfuck.js new file mode 100644 index 0000000..0146e77 --- /dev/null +++ b/other/brainfuck.js @@ -0,0 +1,49 @@ +function brainLuck(code, input) { + var output = '', + data = [], + pointer = 0, + input = input.split(''); + + for(var i = 0, len = code.length; i < len; i++) { + var cmd = code[i]; + + if(cmd === '>') ++pointer; + else if(cmd === '<') --pointer; + else if(cmd === '+') data[pointer] = ((data[pointer] || 0) + 1) % 256; + else if(cmd === '-') data[pointer] = ((data[pointer] || 0) + 255) % 256; + else if(cmd === '.') output += String.fromCharCode(data[pointer] || 0); + else if(cmd === ',') data[pointer] = (input.shift() || '').charCodeAt(0); + else if((cmd === '[' && !data[pointer]) || + (cmd === ']' && data[pointer])) i = matchBracket(code, i); + } + + return output; +} + +function matchBracket(x, index) { + var dir = x[index] === ']' ? -1 : 1, + seek = 0; + + if(dir === -1) { + for(var i = index; i >= 0; i--) { + var char = x[i]; + if (char === ']') seek++; + else if (char === '[') seek--; + + if(seek === 0) return i; + } + } else { + for(var i = index, len = x.length; i < len; i++) { + var char = x[i]; + if (char === '[') seek++; + else if (char === ']') seek--; + + if(seek === 0) return i; + } + } +} + +var result = brainLuck('\ +,>+>>>>++++++++++++++++++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++++<<<<<<[>[>>>>>>+>+<<<<<<<-]>>>>>>>[<<<<<<<+>>>>>>>-]<[>++++++++++[-<-[>>+>+<<<-]>>>[<<<+>>>-]+<[>[-]<[-]]>[<<[>>>+<<<-]>>[-]]<<]>>>[>>+>+<<<-]>>>[<<<+>>>-]+<[>[-]<[-]]>[<<+>>[-]]<<<<<<<]>>>>>[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]++++++++++<[->-<]>++++++++++++++++++++++++++++++++++++++++++++++++.[-]<<<<<<<<<<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<-[>>.>.<<<[-]]<<[>>+>+<<<-]>>>[<<<+>>>-]<<[<+>-]>[<+>-]<<<-]', '\n'); +console.log(result); + diff --git a/other/set-pair-sum-debug.js b/other/set-pair-sum-debug.js new file mode 100644 index 0000000..f8956c7 --- /dev/null +++ b/other/set-pair-sum-debug.js @@ -0,0 +1,32 @@ +'use strict'; + +let _ = require('../utils'), + mergeSort = require('../sort/merge'); + +let args = _.args.numbers(), + set = args.slice(0, -1), + key = args[args.length-1]; + +function findPair(arr, key) { + _.debug(`findPair(arr, ${key})`); + mergeSort(arr, 0, arr.length); + + let i = 0, + j = arr.length-1; + for(let x = 0, len = arr.length-1; x < len; x++) { + let sum = arr[i] + arr[j]; + _.debug(`sum = (arr[${i}]=${arr[i]}) + (arr[${j}]=${arr[j]}) = ${sum}`); + + if(sum === key) return true; + if(sum > key) j--; + if(sum < key) i++; + } + + return false; +} + +if(require.main === module) { + _.log(findPair(set, key)); +} + +module.exports = findPair; diff --git a/other/set-pair-sum.js b/other/set-pair-sum.js new file mode 100644 index 0000000..de95d88 --- /dev/null +++ b/other/set-pair-sum.js @@ -0,0 +1,30 @@ +'use strict'; + +let _ = require('../utils'), + mergeSort = require('../sort/merge'); + +let args = _.args.numbers(), + set = args.slice(0, -1), + key = args[args.length-1]; + +function findPair(arr, x) { + mergeSort(arr, 0, arr.length); + + let i = 0, + j = arr.length-1; + for(let x = 0, len = arr.length/2; x < len; x++) { + let sum = arr[i] + arr[j]; + + if(sum === x) return true; + if(sum > x) j--; + if(sum < x) i++; + } + + return false; +} + +if(require.main === module) { + _.log(findPair(set, key)); +} + +module.exports = findPair; diff --git a/package.json b/package.json new file mode 100644 index 0000000..ac13cd2 --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "name": "harmony-algorithms", + "version": "1.0.0", + "description": "Algorithms and Data Structures implemented in ES6", + "main": "index.js", + "scripts": { + "test": "mocha tests/*.js" + }, + "keywords": [ + "algorithm", + "data-structure", + "harmony", + "es6", + "javascript" + ], + "author": "Mahdi Dibaiee", + "license": "MIT" +} diff --git a/patterns/factory.js b/patterns/factory.js new file mode 100644 index 0000000..56f6526 --- /dev/null +++ b/patterns/factory.js @@ -0,0 +1,60 @@ +'use strict'; + +import _ from '../utils'; + +const AbstractFactory = (function() { + let types = {}; + + return { + get(type, ...args) { + let constructor = types[type]; + + return constructor ? new constructor(...args) : null; + }, + register(type, constructor) { + // We can check if the constructor fulfills the required + // pattern of types registered, for example + if (!constructor.prototype.hi) { + throw new Error('The provided constructor doesn\'t have the required `hi` method'); + } + + types[type] = constructor; + + return AbstractFactory; + } + }; +}()); + +class Boss { + constructor(name) { + this.name = name; + } + + hi() { + return `Hello, ${this.name}`; + } +} + +class Employee extends Boss { + constructor(name, role) { + super(name); + this.role = role; + } +} + +class Invalid { + constructor() { + this.cantRegister = true; + } +} + +AbstractFactory.register('Boss', Boss); +AbstractFactory.register('Employee', Employee); +let boss = AbstractFactory.get('Boss', 'John'); +_.log(boss.hi()); + +try { + AbstractFactory.register('Invalid', Invalid); +} catch (e) { + _.log('Caught error: ', e); +} diff --git a/search/binary-recursive-debug.js b/search/binary-recursive-debug.js new file mode 100644 index 0000000..74bce88 --- /dev/null +++ b/search/binary-recursive-debug.js @@ -0,0 +1,28 @@ +'use strict'; + +import _ from '../utils'; + +let args = _.args.numbers(), + arr = args.slice(0, -1), + key = args[args.length-1]; + +function binarySearch(key, arr, p, q) { + _.debug(`binarySearch(${[key, 'arr', p, q]})`); + + if(q - p < 2) { + if(arr[q] === key) return q; + else if(arr[p] === key) return p; + else return -1; // not found + } + let middle = p + Math.floor((q - p)/2); + _.debug(`arr[${middle}]=${arr[middle]}, key = ${key}`); + if(arr[middle] < key) { + _.debug(`splitting, searching in arr[${Math.floor(q/2)}...${q}]`); + return binarySearch(key, arr, middle, q); + } else { + _.debug(`splitting, searching in arr[${p}...${Math.floor(q/2)}]`); + return binarySearch(key, arr, p, middle); + } +} + +_.log(binarySearch(key, arr, 0, arr.length-1)); diff --git a/search/binary-recursive.js b/search/binary-recursive.js new file mode 100644 index 0000000..a834289 --- /dev/null +++ b/search/binary-recursive.js @@ -0,0 +1,24 @@ +'use strict'; + +import _ from '../utils'; + +let args = _.args.numbers(), + arr = args.slice(0, -1), + key = args[args.length-1]; + +function binarySearch(key, arr, p, q) { + if(q - p < 2) { + if(arr[q] === key) return q; + else if(arr[p] === key) return p; + else return -1; // not found + } + let middle = p + Math.floor((q - p)/2); + if(arr[middle] < key) + return binarySearch(key, arr, middle, q); + else + return binarySearch(key, arr, p, middle); +} + +if(require.main === module) _.log(binarySearch(key, arr, 0, arr.length-1)); + +module.exports = binarySearch; diff --git a/sort/insertion-debug.js b/sort/insertion-debug.js new file mode 100644 index 0000000..9732b8b --- /dev/null +++ b/sort/insertion-debug.js @@ -0,0 +1,23 @@ +'use strict'; + +import _ from '../utils'; + +let arr = _.args.numbers(); + +for(let i = 1, len = arr.length; i < len; i++) { + let key = arr[i]; + let j = i - 1; + _.debug(`on arr[${i}] = ${key}`); + + while(j > -1 && arr[j] > key) { + _.debug(` - a[${j}] = ${arr[j]} > ${key}`); + + arr[j + 1] = arr[j]; + j--; + } + + _.debug(` - moving key = ${key} to arr[${j+1}]`); + arr[j + 1] = key; +} + +_.log(arr.join(' ')); \ No newline at end of file diff --git a/sort/insertion-optimizied-binarySearch-debug.js b/sort/insertion-optimizied-binarySearch-debug.js new file mode 100644 index 0000000..48e0be9 --- /dev/null +++ b/sort/insertion-optimizied-binarySearch-debug.js @@ -0,0 +1,33 @@ +'use strict'; + +let _ = require('../utils'), + binarySearch = require('../search/binary-recursive'); + +let arr = _.args.numbers(); + +for(let i = 1, len = arr.length; i < len; i++) { + let key = arr[i]; + let j = -1, + x = 1; + + _.debug(`at ${key}`); + do { + let end = i - (x-1); + _.debug(` - looking for ${key + x} in ${arr.slice(0, end)}`); + j = binarySearch(key + x++, arr, 0, end); + } while (j === -1 && end > -1); + + if(j === -1) { + _.debug('j not found, continuing'); + continue; + } + + for(let c = i-1; c >= j; c--) { + arr[c+1] = arr[c]; + _.debug(` - arr[${c+1}] = arr[${c}]`); + } + + arr[j] = key; +} + +_.log(arr.join(' ')); \ No newline at end of file diff --git a/sort/insertion-optimizied-binarySearch.js b/sort/insertion-optimizied-binarySearch.js new file mode 100644 index 0000000..360cd91 --- /dev/null +++ b/sort/insertion-optimizied-binarySearch.js @@ -0,0 +1,27 @@ +'use strict'; + +let _ = require('../utils'), + binarySearch = require('../search/binary-recursive'); + +let arr = _.args.numbers(); + +for(let i = 1, len = arr.length; i < len; i++) { + let key = arr[i]; + let j = -1, + x = 1; + + do { + let end = i - (x-1); + j = binarySearch(key + x++, arr, 0, end); + } while (j === -1 && end > -1); + + if(j === -1) continue; + + for(let c = i-1; c >= j; c--) { + arr[c+1] = arr[c]; + } + + arr[j] = key; +} + +_.log(arr.join(' ')); \ No newline at end of file diff --git a/sort/insertion-recursive-debug.js b/sort/insertion-recursive-debug.js new file mode 100644 index 0000000..31c2991 --- /dev/null +++ b/sort/insertion-recursive-debug.js @@ -0,0 +1,27 @@ +'use strict'; + +import _ from '../utils'; + +let arr = _.args.numbers(); + +function insertionSort(arr, n) { + _.debug(`insertionSort(arr, ${n})`); + + if(n > 0) insertionSort(arr, n-1); + + _.debug(`sorting 0...${n}`); + + let o = arr[n], + i = n-1; + while(arr[i] > o) { + arr[i+1] = arr[i]; + _.debug(` - moving arr[${i}] to arr[${i+1}]`); + i--; + } + arr[i+1] = o; + _.debug(` - arr[${i}] set to ${o}`); +} + +insertionSort(arr, arr.length-1); + +_.log(arr.join(' ')); diff --git a/sort/insertion-recursive.js b/sort/insertion-recursive.js new file mode 100644 index 0000000..87713ad --- /dev/null +++ b/sort/insertion-recursive.js @@ -0,0 +1,20 @@ +'use strict'; + +import _ from '../utils'; + +let arr = _.args.numbers(); + +function insertionSort(arr, n) { + if(n > 0) insertionSort(arr, n-1); + let o = arr[n], + i = n-1; + while(arr[i] > o) { + arr[i+1] = arr[i]; + i--; + } + arr[i+1] = o; +} + +insertionSort(arr, arr.length-1); + +_.log(arr.join(' ')); diff --git a/sort/insertion.js b/sort/insertion.js new file mode 100644 index 0000000..28571dd --- /dev/null +++ b/sort/insertion.js @@ -0,0 +1,19 @@ +'use strict'; + +import _ from '../utils'; + +let arr = _.args.numbers(); + +for(let i = 1, len = arr.length; i < len; i++) { + let key = arr[i]; + let j = i - 1; + + while(j > -1 && arr[j] > key) { + arr[j + 1] = arr[j]; + j--; + } + + arr[j + 1] = key; +} + +_.log(arr.join(' ')); \ No newline at end of file diff --git a/sort/merge-debug.js b/sort/merge-debug.js new file mode 100644 index 0000000..a45add4 --- /dev/null +++ b/sort/merge-debug.js @@ -0,0 +1,49 @@ +'use strict'; +import _ from '../utils'; + +let arr = _.args.numbers(); + +mergeSort(arr, 0, arr.length); +_.log(arr.join(' ')); + +function mergeSort(a, p, r) { + if(r - p === 1) return; + + let q = Math.floor((r+p)/2); + _.debug(`mergeSort(${[p, q, r]})`); + + mergeSort(a, p, q); + mergeSort(a, q, r); + merge(a, p, q, r); +} + +function merge(a, p, q, r) { + _.debug(`- merge(${[p, q, r]})`); + + let i = 0, + j = 0; + + let left = a.slice(p, q), + right = a.slice(q, r); + + _.debug(` - left = [${left}]`); + _.debug(` - right = [${right}]`); + + left.push(Infinity); + right.push(Infinity); + + for(let k = p; k < r; k++) { + if(left[i] <= right[j]) { + a[k] = left[i]; + _.debug(` - set a[${k}] = (left[${i}]=${left[i]})`); + + i++; + } else { + a[k] = right[j]; + _.debug(` - set a[${k}] = (right[${j}]=${right[j]})`); + + j++; + } + } + _.debug(`a = [${a}]`); +} diff --git a/sort/merge.js b/sort/merge.js new file mode 100644 index 0000000..0ad4a95 --- /dev/null +++ b/sort/merge.js @@ -0,0 +1,42 @@ +'use strict'; +import _ from '../utils'; + +let arr = _.args.numbers(); + +function mergeSort(a, p, r) { + if(r - p === 1) return; + + let q = Math.floor((r+p)/2); + + mergeSort(a, p, q); + mergeSort(a, q, r); + merge(a, p, q, r); +} + +function merge(a, p, q, r) { + let i = 0, + j = 0; + + let left = a.slice(p, q), + right = a.slice(q, r); + + left.push(Infinity); + right.push(Infinity); + + for(let k = p; k < r; k++) { + if(left[i] <= right[j]) { + a[k] = left[i]; + i++; + } else { + a[k] = right[j]; + j++; + } + } +} + +if (require.main === module) { + mergeSort(arr, 0, arr.length); + _.log(arr.join(' ')); +} + +module.exports = mergeSort; diff --git a/sort/quick.js b/sort/quick.js new file mode 100644 index 0000000..83a3b47 --- /dev/null +++ b/sort/quick.js @@ -0,0 +1,49 @@ +'use strict'; +import _ from '../utils'; + +let arr = _.args.numbers(); + +function quickSort(array, p = 0, r = array.length) { + if (p >= r) return; + + let pivot = partition(array, p, r); + + // pivot is not included + quickSort(array, p, pivot - 1); + quickSort(array, pivot + 1, r); +} + +function partition(array, p, r) { + let q = p; + + // start at p, if any element is bigger than pivot, it will automatically + // be added to RIGHT group as the u increases, + // if it's less than pivot, it will be added to LEFT by swapping it + // with the leftmost element of RIGHT group, and moving RIGHT's starting point + // (q) one point to right + for (let u = p; u < r; u++) { + if (array[u] <= array[r]) { + swap(array, u, q); + + q++; + } + } + + // after finding LEFT and RIGHT groups, move pivot to it's original position + swap(array, r, q); + + return q; +} + +function swap(array, a, b) { + let tmp = array[b]; + array[b] = array[a]; + array[a] = tmp; +} + +if (require.main === module) { + quickSort(arr, 0, arr.length); + _.log(arr.join(' ')); +} + +module.exports = quickSort; diff --git a/sort/selection-debug.js b/sort/selection-debug.js new file mode 100644 index 0000000..f7d02a1 --- /dev/null +++ b/sort/selection-debug.js @@ -0,0 +1,29 @@ +'use strict'; + +import _ from '../utils'; + +let arr = _.args.numbers(); + +for(let i = 0, len = arr.length; i < len-1; i++) { + let min = i; + + _.debug(`on arr[${i}]; min=${arr[min]} minIndex=${min}`); + + for(let j = i+1; j < len; j++) { + _.debug(` - comparing with arr[${j}] = ${arr[j]}`); + + if(arr[j] < arr[min]) { + min = j; + + _.debug(` - found a new minimum; min=${arr[j]} minIndex=${min}`); + } + } + + _.debug(` - swapping arr[${min}]=${arr[min]} with arr[${i}]=${arr[i]}`); + + let tmp = arr[min]; + arr[min] = arr[i]; + arr[i] = tmp; +} + +_.log(arr.join(' ')); diff --git a/sort/selection.js b/sort/selection.js new file mode 100644 index 0000000..ffe97db --- /dev/null +++ b/sort/selection.js @@ -0,0 +1,21 @@ +'use strict'; + +import _ from '../utils'; + +let arr = _.args.numbers(); + +for(let i = 0, len = arr.length; i < len-1; i++) { + let min = i; + + for(let j = i+1; j < len; j++) { + if(arr[j] < arr[min]) { + min = j; + } + } + + let tmp = arr[min]; + arr[min] = arr[i]; + arr[i] = tmp; +} + +_.log(arr.join(' ')); diff --git a/utils.js b/utils.js new file mode 100644 index 0000000..c78e38e --- /dev/null +++ b/utils.js @@ -0,0 +1,23 @@ +'use strict'; + +module.exports.print = process.stdout.write.bind(process.stdout); + +module.exports.log = module.exports.debug = console.log.bind(console); + +module.exports.inspect = object => { + console.dir(object, { + colors: true, + depth: null, + showHidden: false + }); +}; + +module.exports.args = process.argv.slice(2); + +// module.exports.DEBUG = false; + +module.exports.args.numbers = function() { + return module.exports.args.map(function(a) { + return parseInt(a, 10); + }); +};