From e124d1750d3a9401f04ebbace93faa2c8e0f43dc Mon Sep 17 00:00:00 2001 From: nitreo Date: Wed, 7 May 2014 18:17:38 +0200 Subject: [PATCH 1/4] ranking example added --- lib/services/parser.js | 2 +- lib/services/rcon.js | 2 +- lib/services/templator.js | 12 + mods/commands/advanced_command.js | 8 + mods/ranks/index.js | 118 ++ .../kag_mods/RulesScripts/RankMessage.as | 14 + node_modules/.bin/dot-compile | 1 + node_modules/.bin/dot-compile-server | 1 + node_modules/.bin/dottojs | 1 + node_modules/.bin/minstache | 1 + node_modules/dot/LICENSE-DOT.txt | 24 + node_modules/dot/README.md | 72 ++ node_modules/dot/benchmarks/compileBench.js | 110 ++ node_modules/dot/benchmarks/genspeed.html | 22 + node_modules/dot/benchmarks/index.html | 22 + node_modules/dot/benchmarks/jslitmus.js | 628 ++++++++++ node_modules/dot/benchmarks/templatesBench.js | 138 +++ node_modules/dot/benchmarks/templating/doT.js | 135 +++ node_modules/dot/benchmarks/templating/doU.js | 56 + node_modules/dot/bin/dot-packer | 52 + node_modules/dot/doT.js | 135 +++ node_modules/dot/doT.min.js | 7 + node_modules/dot/doU.js | 56 + node_modules/dot/examples/advancedsnippet.txt | 119 ++ node_modules/dot/examples/browsersample.html | 54 + node_modules/dot/examples/customdoT.js | 19 + node_modules/dot/examples/snippet.txt | 13 + .../dot/examples/views/multidef.def.jst | 13 + node_modules/dot/examples/views/one.def | 2 + node_modules/dot/examples/views/two.dot.jst | 17 + node_modules/dot/examples/withdoT.js | 21 + node_modules/dot/index.js | 143 +++ node_modules/dot/package.json | 45 + node_modules/dot/test/testdoT.js | 30 + node_modules/minstache/.npmignore | 4 + node_modules/minstache/History.md | 11 + node_modules/minstache/Makefile | 7 + node_modules/minstache/Readme.md | 72 ++ node_modules/minstache/bin/minstache | 28 + node_modules/minstache/component.json | 7 + node_modules/minstache/index.js | 149 +++ .../node_modules/commander/.npmignore | 4 + .../node_modules/commander/.travis.yml | 4 + .../node_modules/commander/History.md | 135 +++ .../minstache/node_modules/commander/Makefile | 7 + .../node_modules/commander/Readme.md | 262 ++++ .../minstache/node_modules/commander/index.js | 2 + .../node_modules/commander/lib/commander.js | 1053 +++++++++++++++++ .../commander/node_modules/keypress/README.md | 101 ++ .../commander/node_modules/keypress/index.js | 346 ++++++ .../node_modules/keypress/package.json | 32 + .../commander/node_modules/keypress/test.js | 28 + .../node_modules/commander/package.json | 45 + node_modules/minstache/package.json | 33 + pg.js | 28 + 55 files changed, 4449 insertions(+), 2 deletions(-) create mode 100644 lib/services/templator.js create mode 100644 mods/commands/advanced_command.js create mode 100644 mods/ranks/index.js create mode 100644 mods/ranks/kag_mods/RulesScripts/RankMessage.as create mode 120000 node_modules/.bin/dot-compile create mode 120000 node_modules/.bin/dot-compile-server create mode 120000 node_modules/.bin/dottojs create mode 120000 node_modules/.bin/minstache create mode 100644 node_modules/dot/LICENSE-DOT.txt create mode 100644 node_modules/dot/README.md create mode 100644 node_modules/dot/benchmarks/compileBench.js create mode 100644 node_modules/dot/benchmarks/genspeed.html create mode 100644 node_modules/dot/benchmarks/index.html create mode 100644 node_modules/dot/benchmarks/jslitmus.js create mode 100644 node_modules/dot/benchmarks/templatesBench.js create mode 100644 node_modules/dot/benchmarks/templating/doT.js create mode 100644 node_modules/dot/benchmarks/templating/doU.js create mode 100755 node_modules/dot/bin/dot-packer create mode 100644 node_modules/dot/doT.js create mode 100644 node_modules/dot/doT.min.js create mode 100644 node_modules/dot/doU.js create mode 100644 node_modules/dot/examples/advancedsnippet.txt create mode 100644 node_modules/dot/examples/browsersample.html create mode 100644 node_modules/dot/examples/customdoT.js create mode 100644 node_modules/dot/examples/snippet.txt create mode 100644 node_modules/dot/examples/views/multidef.def.jst create mode 100644 node_modules/dot/examples/views/one.def create mode 100644 node_modules/dot/examples/views/two.dot.jst create mode 100644 node_modules/dot/examples/withdoT.js create mode 100644 node_modules/dot/index.js create mode 100644 node_modules/dot/package.json create mode 100644 node_modules/dot/test/testdoT.js create mode 100644 node_modules/minstache/.npmignore create mode 100644 node_modules/minstache/History.md create mode 100644 node_modules/minstache/Makefile create mode 100644 node_modules/minstache/Readme.md create mode 100755 node_modules/minstache/bin/minstache create mode 100644 node_modules/minstache/component.json create mode 100644 node_modules/minstache/index.js create mode 100644 node_modules/minstache/node_modules/commander/.npmignore create mode 100644 node_modules/minstache/node_modules/commander/.travis.yml create mode 100644 node_modules/minstache/node_modules/commander/History.md create mode 100644 node_modules/minstache/node_modules/commander/Makefile create mode 100644 node_modules/minstache/node_modules/commander/Readme.md create mode 100644 node_modules/minstache/node_modules/commander/index.js create mode 100644 node_modules/minstache/node_modules/commander/lib/commander.js create mode 100644 node_modules/minstache/node_modules/commander/node_modules/keypress/README.md create mode 100644 node_modules/minstache/node_modules/commander/node_modules/keypress/index.js create mode 100644 node_modules/minstache/node_modules/commander/node_modules/keypress/package.json create mode 100644 node_modules/minstache/node_modules/commander/node_modules/keypress/test.js create mode 100644 node_modules/minstache/node_modules/commander/package.json create mode 100644 node_modules/minstache/package.json create mode 100644 pg.js diff --git a/lib/services/parser.js b/lib/services/parser.js index 1327257..0ab9e2a 100644 --- a/lib/services/parser.js +++ b/lib/services/parser.js @@ -20,9 +20,9 @@ var xRegExp = require('xregexp').XRegExp; function Parser() { var expressionMap = {}; - var onceExpressionMap = {}; var composites = []; var onceComposites = []; + var onceExpressionMap = {}; /** * Every time parsed input matches given regular expression, diff --git a/lib/services/rcon.js b/lib/services/rcon.js index fa04c09..9878473 100644 --- a/lib/services/rcon.js +++ b/lib/services/rcon.js @@ -31,7 +31,7 @@ function RconConnection(ip, port, password, limit) { var connected = false; var authorized = false; var lineQueue = []; - var wasConnected = false;a + var wasConnected = false; var data = ""; var sIntId; diff --git a/lib/services/templator.js b/lib/services/templator.js new file mode 100644 index 0000000..e6f1053 --- /dev/null +++ b/lib/services/templator.js @@ -0,0 +1,12 @@ +var jazz = require('jazz'); + +var template = '/msg "{arg}"'; + +var compTemplate = jazz.compile(template,function(){ + +}); + +compTemplate.eval({arg:"Hello world!"},function(res){ + console.log(res); +}); + diff --git a/mods/commands/advanced_command.js b/mods/commands/advanced_command.js new file mode 100644 index 0000000..1f7c418 --- /dev/null +++ b/mods/commands/advanced_command.js @@ -0,0 +1,8 @@ +var dot = require('dot'); + +var ban = dot.template('' + + 'CBitStream@ stream;' + + '{{ for(var key in it) { }}'+ + 'Key: {{=key}} Value = {{=it[key]}}\n'+ + '{{ } }}' + + 'SendCommandOnlyServer(getRules().getCommandID(),)'); diff --git a/mods/ranks/index.js b/mods/ranks/index.js new file mode 100644 index 0000000..9699573 --- /dev/null +++ b/mods/ranks/index.js @@ -0,0 +1,118 @@ +var db; +var dbName = "ranking"; + + +//When we load the mod, we want it to load our database. +//This is done using async function Dao.getDatastore +Dao.getDatastore(dbName, function (err, datastore) { + if (err) throw new err; + //once db is loaded - we assign it global variable + db = datastore; +}); + + +/* GAME EVENTS HOOKS */ +//hook up to "player_killed" event from "stats" mod +GameEvents.on("player_killed", function (victim, killer) { + //If we have a victim + if (victim) { + //Find a player with such a login + getRankedPlayer(victim, function (err,rankedPlayer) { + //Increase deaths and update points + rankedPlayer.deaths++; + rankedPlayer.points = rankedPlayer.kills / (rankedPlayer.deaths + 1); // points calculation formula + //Save it + saveRankedPlayer(rankedPlayer); + }) + } + //Same as with victim + if (killer) { + getRankedPlayer(killer, function (err,rankedPlayer) { + rankedPlayer.kills++; + rankedPlayer.points = rankedPlayer.kills / (rankedPlayer.deaths + 1); // points calculation formula + saveRankedPlayer(rankedPlayer,function(){ + }); + }) + } +}) + +//hook up to chat_command from "chat" mod +GameEvents.on("chat_command", function (player, cmd, args, argl) { + if(cmd != "rank") return; + + //If no argument - display current player + if(!args[0]) + showPlayerRank(player,player); + //If argument is "top" then display top + else if(args[0] == "top") showTop(player); + //Else display player with name equal to argument + else showPlayerRank(player,args[0]); + + //Set up timeout to clear the window + setTimeout(function(){ + RCON.send(compileMessage(player,"")); // Clear the screen with an empty message + },10000); + + +}); + +/* HELPER METHODS */ + +//Async function to get a player +function getRankedPlayer(login, cb) { + if (!db) return; + db.findOne({login: login}, function (err, player) { + //If no player with this name found, we create one + if (!player) + player = new RankedPlayer(login); + + if(cb) cb(err, player); + }); +} + +//Async function to save the player. check NeDB documentation for details. +function saveRankedPlayer(player, cb) { + if(!db) return; + cb = cb || function(){}; + //upsert:true means: + //If no player with such login is found, + //create a new object in the db with those values and give it _id + db.update({login: player.login}, player, {upsert: true}, cb); +} + +//Ranked player scheme +function RankedPlayer(login) { + this.login = login; + this.kills = 0; + this.deaths = 0; + this.points = 0; +} + +//Compile code to sync the message to player +function compileMessage(player, message) { + return "CRules@ rules = getRules();" + + 'CPlayer@ player = getPlayerByUsername("' + player + '");' + + 'if(player is null) return;' + + 'rules.set_string("rank_message","' + message + '");' + + 'rules.SyncToPlayer("rank_message",player);'; +} + +function showPlayerRank(requester,targetPlayer){ + getRankedPlayer(targetPlayer,function(err,rankedPlayer){ + if(err) console.log(err.message); + var message = targetPlayer+" has:\\n" + + "Kills: "+ rankedPlayer.kills + "\\n" + + "Deaths: "+ rankedPlayer.deaths + "\\n" + + "Points: "+rankedPlayer.points; + RCON.send(compileMessage(requester,message)); + }); +} + +function showTop(requester){ + db.find().sort({ points: -1 }).limit(10).exec(function (err, topPlayers) { + var topStr=""; + for (var i = 0; i < topPlayers.length; i++) + topStr += (i + 1) + ". " + topPlayers[i].login + " with " + topPlayers[i].points + " points\\n"; + RCON.send(compileMessage(requester,topStr)); + }); +} \ No newline at end of file diff --git a/mods/ranks/kag_mods/RulesScripts/RankMessage.as b/mods/ranks/kag_mods/RulesScripts/RankMessage.as new file mode 100644 index 0000000..260159f --- /dev/null +++ b/mods/ranks/kag_mods/RulesScripts/RankMessage.as @@ -0,0 +1,14 @@ +const string rankMsgTag = "rank_message"; + +void onRender( CRules@ this ) +{ + if (g_videorecording) + return; + + string text; + text = this.get_string(rankMsgTag); + if (text.size() > 0) + { + GUI::DrawText( text, Vec2f(20,20), Vec2f(300,200), color_black, false, false, true ); + } +} \ No newline at end of file diff --git a/node_modules/.bin/dot-compile b/node_modules/.bin/dot-compile new file mode 120000 index 0000000..1ef9760 --- /dev/null +++ b/node_modules/.bin/dot-compile @@ -0,0 +1 @@ +../doT/bin/dot-compile \ No newline at end of file diff --git a/node_modules/.bin/dot-compile-server b/node_modules/.bin/dot-compile-server new file mode 120000 index 0000000..c2f0d32 --- /dev/null +++ b/node_modules/.bin/dot-compile-server @@ -0,0 +1 @@ +../doT/bin/dot-compile-server \ No newline at end of file diff --git a/node_modules/.bin/dottojs b/node_modules/.bin/dottojs new file mode 120000 index 0000000..321b2c4 --- /dev/null +++ b/node_modules/.bin/dottojs @@ -0,0 +1 @@ +../dot/bin/dot-packer \ No newline at end of file diff --git a/node_modules/.bin/minstache b/node_modules/.bin/minstache new file mode 120000 index 0000000..7cff8dd --- /dev/null +++ b/node_modules/.bin/minstache @@ -0,0 +1 @@ +../minstache/bin/minstache \ No newline at end of file diff --git a/node_modules/dot/LICENSE-DOT.txt b/node_modules/dot/LICENSE-DOT.txt new file mode 100644 index 0000000..5b36cb8 --- /dev/null +++ b/node_modules/dot/LICENSE-DOT.txt @@ -0,0 +1,24 @@ + +Copyright (c) 2011 Laura Doktorova + +Software includes portions from jQote2 Copyright (c) 2010 aefxx, +http://aefxx.com/ licensed under the MIT 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/dot/README.md b/node_modules/dot/README.md new file mode 100644 index 0000000..7f171ee --- /dev/null +++ b/node_modules/dot/README.md @@ -0,0 +1,72 @@ +Created in search of the fastest and concise JavaScript templating function with emphasis on performance under V8 and nodejs. It shows great performance for both nodejs and browsers. + +doT.js is fast, small and has no dependencies. + +## Features + custom delimiters + runtime evaluation + runtime interpolation + compile-time evaluation + partials support + conditionals support + array iterators + encoding + control whitespace - strip or preserve + streaming friendly + use it as logic-less or with logic, it is up to you + +## Docs, live playground and samples + +http://olado.github.com/doT (todo: update docs with new features added in version 1.0.0) + +## New in version 1.0.0 + +####Added parameters support in partials + + {{##def.macro:param: +
{{=param.foo}}
+ #}} + + {{#def.macro:myvariable}} + +####Node module now supports auto-compilation of dot templates from specified path + + var dots = require("dot").process({ path: "./views"}); + +This will compile .def, .dot, .jst files found under the specified path. +Details + * It ignores sub-directories. + * Template files can have multiple extensions at the same time. + * Files with .def extension can be included in other files via {{#def.name}} + * Files with .dot extension are compiled into functions with the same name and + can be accessed as renderer.filename + * Files with .jst extension are compiled into .js files. Produced .js file can be + loaded as a commonJS, AMD module, or just installed into a global variable (default is set to window.render) + * All inline defines defined in the .jst file are + compiled into separate functions and are available via _render.filename.definename + + Basic usage: + ``` + var dots = require("dot").process({path: "./views"}); + dots.mytemplate({foo:"hello world"}); + ``` + The above snippet will: + * Compile all templates in views folder (.dot, .def, .jst) + * Place .js files compiled from .jst templates into the same folder + These files can be used with require, i.e. require("./views/mytemplate") + * Return an object with functions compiled from .dot templates as its properties + * Render mytemplate template + +####CLI tool to compile dot templates into js files + + ./bin/dot-packer -s examples/views -d out/views + +## Notes + doU.js is here only so that legacy external tests do not break. Use doT.js. + doT.js with doT.templateSettings.append=false provides the same performance as doU.js. + +## Author +Laura Doktorova @olado + +## License +doT is licensed under the MIT License. (See LICENSE-DOT) diff --git a/node_modules/dot/benchmarks/compileBench.js b/node_modules/dot/benchmarks/compileBench.js new file mode 100644 index 0000000..82c5d54 --- /dev/null +++ b/node_modules/dot/benchmarks/compileBench.js @@ -0,0 +1,110 @@ +(function() { + var jslitmus, _, doU, doT, + data = { f1: 1, f2: 2, f3: 3, f4: "http://bebedo.com/laura"}, + snippet = "

Just static text

\ +

Here is a simple {{=it.f1}}

\ +
test {{=it.f2}}\ +
{{=it.f3}}
\ +
{{!it.f4}}
\ +
"; + + if (typeof module !== 'undefined' && module.exports) { + runTests(); + } else { + window.onload = runTestsInBrowser; + } + + function testsetup(snippet) { + + jslitmus.test('doU.js', function() { + doU.template(snippet); + }); + + jslitmus.test('doU.js - looping', function(count) { + while (count--) { + doU.template(snippet); + } + }); + + jslitmus.test('doT.js - using this', function() { + doT.template(snippet); + }); + + jslitmus.test('doT.js - using this - looping', function(count) { + while (count--) { + doT.template(snippet); + } + }); + } + + function runTests() { + //var util = require('util'); + jslitmus = require('./jslitmus.js'); + doU = require('./templating/doU.js'); + doT = require('./templating/doT.js'); + var passOne = 0; + console.log("*** Compilation speed test"); + console.log("*** Small template length: " + snippet.length); + testsetup(snippet); + // Log the test results + jslitmus.on('complete', function(test) { + //console.log(util.inspect(process.memoryUsage())); + console.log(test.toString()); + }); + // 'all_complete' fires when all tests have finished. + jslitmus.on('all_complete', function() { + switch (passOne) { + case 0: + passOne++; + for(var i=0; i<5; i++) { snippet += snippet; } + console.log("*** Medium template length: " + snippet.length); + break; + case 1: + passOne++; + for(var i=0; i<3; i++) { snippet += snippet; } + console.log("*** Large template length: " + snippet.length); + break; + default: + return; + } + + jslitmus.clearAll(); + testsetup(snippet); + jslitmus.runAll(); + }); + // Run it! + jslitmus.runAll(); + } + + function runTestsInBrowser() { + jslitmus = window.jslitmus;doU = window.doU;doT = window.doT; + + var resultTmpl = doT.template("

Template length : {{=it.size}}

"); + var currentSet = document.getElementById('small'); + testsetup(snippet); + // 'complete' fires for each test when it finishes. + jslitmus.on('complete', function(test) { + // Output test results + currentSet.innerHTML += test + '
'; + }); + // 'all_complete' fires when all tests have finished. + jslitmus.on('all_complete', function() { + // Get the results image URL + var url = jslitmus.getGoogleChart(); + if (currentSet.id === 'small') { + currentSet.innerHTML += resultTmpl({size: snippet.length, url: url}); + setTimeout(function() { + jslitmus.clearAll(); + currentSet = document.getElementById('large'); + for(var i=0; i<8; i++) { snippet += snippet; } + testsetup(snippet); + jslitmus.runAll(); + }, 10); + } else { + currentSet.innerHTML += resultTmpl({size: snippet.length, url: url}); + } + }); + // Run it! + jslitmus.runAll(); + } +})(); diff --git a/node_modules/dot/benchmarks/genspeed.html b/node_modules/dot/benchmarks/genspeed.html new file mode 100644 index 0000000..5e3fb8f --- /dev/null +++ b/node_modules/dot/benchmarks/genspeed.html @@ -0,0 +1,22 @@ + + + + + +Templating Test Suite + + + + + + + + + +

Comparing doU.js and doT.js compilation speed

+

Small template

+

Large template

+ + + diff --git a/node_modules/dot/benchmarks/index.html b/node_modules/dot/benchmarks/index.html new file mode 100644 index 0000000..5956eff --- /dev/null +++ b/node_modules/dot/benchmarks/index.html @@ -0,0 +1,22 @@ + + + + + +Templating Test Suite + + + + + + + + + +

Comparing doU.js and doT.js

+

Small template

+

Large template

+ + + diff --git a/node_modules/dot/benchmarks/jslitmus.js b/node_modules/dot/benchmarks/jslitmus.js new file mode 100644 index 0000000..8031338 --- /dev/null +++ b/node_modules/dot/benchmarks/jslitmus.js @@ -0,0 +1,628 @@ +// jslitmus.js +// +// Copyright (c) 2010, Robert Kieffer, http://broofa.com +// Available under MIT license (http://en.wikipedia.org/wiki/MIT_License) + +(function() { + var root = this; + + // + // Platform detect + // + + var platform = (function() { + // Platform info object + var p = { + name: null, + version: null, + os: null, + description: 'unknown platform', + toString: function() {return this.description;} + }; + + if (root.navigator) { + var ua = navigator.userAgent; + + // Detect OS + var oses = 'Windows|iPhone OS|(?:Intel |PPC )?Mac OS X|Linux'; + p.os = new RegExp('((' + oses + ') +[^ \);]*)').test(ua) ? RegExp.$1.replace(/_/g, '.') : null; + + // Detect expected names + p.name = /(Chrome|MSIE|Safari|Opera|Firefox|Minefield)/.test(ua) ? RegExp.$1 : null; + + // Detect version + if (p.name == 'Opera') { + p.version = opera.name; + } else if (p.name) { + var vre = new RegExp('(Version|' + p.name + ')[ \/]([^ ;]*)'); + p.version = vre.test(ua) ? RegExp.$2 : null; + } + } else if (root.process && process.platform) { + // Support node.js (see http://nodejs.org) + p.name = 'node'; + p.version = process.version; + p.os = process.platform; + } + + // Set the description + var d = []; + if (p.name) d.push(p.name); + if (p.version) d.push(' ' + p.version); + if (p.os) d.push(' on ' + p.os); + if (d.length) p.description = d.join(''); + + return p; + })(); + + // + // Context-specific initialization + // + + var sys = null, querystring = null; + if (platform.name == 'node') { + util = require('util'); + querystring = require('querystring'); + } + + // + // Misc convenience methods + // + + function log(msg) { + if (typeof(console) != 'undefined') { + console.log(msg); + } else if (sys) { + util.log(msg); + } + } + + // nil function + function nilf(x) { + return x; + } + + // Copy properties + function extend(dst, src) { + for (var k in src) { + dst[k] = src[k]; + } + return dst; + } + + // Array: apply f to each item in a + function forEach(a, f) { + for (var i = 0, il = (a && a.length); i < il; i++) { + var o = a[i]; + f(o, i); + } + } + + // Array: return array of all results of f(item) + function map(a, f) { + var o, res = []; + for (var i = 0, il = (a && a.length); i < il; i++) { + var o = a[i]; + res.push(f(o, i)); + } + return res; + } + + // Array: filter out items for which f(item) is falsy + function filter(a, f) { + var o, res = []; + for (var i = 0, il = (a && a.length); i < il; i++) { + var o = a[i]; + if (f(o, i)) res.push(o); + } + return res; + } + + // Array: IE doesn't have indexOf in some cases + function indexOf(a, o) { + if (a.indexOf) return a.indexOf(o); + for (var i = 0, l = a.length; i < l; i++) if (a[i] === o) return i; + return -1; + } + + // Enhanced escape() + function escape2(s) { + s = s.replace(/,/g, '\\,'); + s = querystring ? querystring.escape(s) : escape(s); + s = s.replace(/\+/g, '%2b'); + s = s.replace(/ /g, '+'); + return s; + } + + // join(), for objects. Creates url query param-style strings by default + function join(o, delimit1, delimit2) { + var asQuery = !delimit1 && !delimit2; + if (asQuery) { + delimit1 = '&'; + delimit2 = '='; + } + + var pairs = []; + for (var key in o) { + var value = o[key]; + if (asQuery) value = escape2(value); + pairs.push(key + delimit2 + o[key]); + } + return pairs.join(delimit1); + } + + // split(), for object strings. Parses url query param strings by default + function split(s, delimit1, delimit2) { + var asQuery = !delimit1 && !delimit2; + if (asQuery) { + s = s.replace(/.*[?#]/, ''); + delimit1 = '&'; + delimit2 = '='; + } + + if (match) { + var o = query.split(delimit1); + for (var i = 0; i < o.length; i++) { + var pair = o[i].split(new RegExp(delimit2 + '+')); + var key = pair.shift(); + var value = (asQuery && pair.length > 1) ? pair.join(delimit2) : pair[0]; + o[key] = value; + } + } + + return o; + } + + // Round x to d significant digits + function sig(x, d) { + var exp = Math.ceil(Math.log(Math.abs(x))/Math.log(10)), + f = Math.pow(10, exp-d); + return Math.round(x/f)*f; + } + + // Convert x to a readable string version + function humanize(x, sd) { + var ax = Math.abs(x), res; + sd = sd | 4; // significant digits + if (ax == Infinity) { + res = ax > 0 ? 'Infinity' : '-Infinity'; + } else if (ax > 1e9) { + res = sig(x/1e9, sd) + 'G'; + } else if (ax > 1e6) { + res = sig(x/1e6, sd) + 'M'; + } else if (ax > 1e3) { + res = sig(x/1e3, sd) + 'k'; + } else if (ax > .01) { + res = sig(x, sd); + } else if (ax > 1e-3) { + res = sig(x/1e-3, sd) + 'm'; + } else if (ax > 1e-6) { + res = sig(x/1e-6, sd) + '\u00b5'; // Greek mu + } else if (ax > 1e-9) { + res = sig(x/1e-9, sd) + 'n'; + } else { + res = x ? sig(x, sd) : 0; + } + // Turn values like "1.1000000000005" -> "1.1" + res = (res + '').replace(/0{5,}\d*/, ''); + + return res; + } + + // Node.js-inspired event emitter API, with some enhancements. + function EventEmitter() { + var ee = this; + var listeners = {}; + extend(ee, { + on: function(e, f) { + if (!listeners[e]) listeners[e] = []; + listeners[e].push(f); + }, + removeListener: function(e, f) { + listeners[e] = filter(listeners[e], function(l) { + return l != f; + }); + }, + removeAllListeners: function(e) { + listeners[e] = []; + }, + emit: function(e) { + var args = Array.prototype.slice.call(arguments, 1); + forEach([].concat(listeners[e], listeners['*']), function(l) { + ee._emitting = e; + if (l) l.apply(ee, args); + }); + delete ee._emitting; + } + }); + } + + // + // Test class + // + + /** + * Test manages a single test (created with JSLitmus.test()) + */ + function Test(name, f) { + var test = this; + + // Test instances get EventEmitter API + EventEmitter.call(test); + + if (!f) throw new Error('Undefined test function'); + if (!/function[^\(]*\(([^,\)]*)/.test(f)) { + throw new Error('"' + name + '" test: Invalid test function'); + } + + // If the test function takes an argument, we assume it does the iteration + // for us + var isLoop = !!RegExp.$1; + + /** + * Reset test state + */ + function reset() { + delete test.count; + delete test.time; + delete test.running; + test.emit('reset', test); + return test; + } + + function clone() { + var test = extend(new Test(name, f), test); + return test.reset(); + } + + /** + * Run the test n times, and use the best results + */ + function bestOf(n) { + var best = null; + while (n--) { + var t = clone(); + t.run(null, true); + if (!best || t.period < best.period) { + best = t; + } + } + extend(test, best); + } + + /** + * Start running a test. Default is to run the test asynchronously (via + * setTimeout). Can be made synchronous by passing true for 2nd param + */ + function run(count, synchronous) { + count = count || test.INIT_COUNT; + test.running = true; + + if (synchronous) { + _run(count, synchronous); + } else { + setTimeout(function() { + _run(count); + }, 1); + } + return test; + } + + /** + * Run, for real + */ + function _run(count, noTimeout) { + + try { + var start, f = test.f, now, i = count; + + // Start the timer + start = new Date(); + + // Run the test code + test.count = count; + test.time = 0; + test.period = 0; + + test.emit('start', test); + + if (isLoop) { + // Test code does it's own iteration + f(count); + } else { + // Do the iteration ourselves + while (i--) f(); + } + + // Get time test took (in secs) + test.time = Math.max(1,new Date() - start)/1000; + + // Store iteration count and per-operation time taken + test.count = count; + test.period = test.time/count; + + // Do we need to keep running? + test.running = test.time < test.MIN_TIME; + + // Publish results + test.emit('results', test); + + // Set up for another run, if needed + if (test.running) { + // Use an iteration count that will (we hope) get us close to the + // MAX_COUNT time. + var x = test.MIN_TIME/test.time; + var pow = Math.pow(2, Math.max(1, Math.ceil(Math.log(x)/Math.log(2)))); + count *= pow; + if (count > test.MAX_COUNT) { + throw new Error('Max count exceeded. If this test uses a looping function, make sure the iteration loop is working properly.'); + } + + if (noTimeout) { + _run(count, noTimeout); + } else { + run(count); + } + } else { + test.emit('complete', test); + } + } catch (err) { + log(err); + // Exceptions are caught and displayed in the test UI + test.emit('error', err); + } + + return test; + } + + /** + * Get the number of operations per second for this test. + * + * @param normalize if true, iteration loop overhead taken into account. + * Note that normalized tests may return Infinity if the + * test time is of the same order as the calibration time. + */ + function getHz(normalize) { + var p = test.period; + + // Adjust period based on the calibration test time + if (normalize) { + var cal = test.isLoop ? Test.LOOP_CAL : Test.NOLOOP_CAL; + if (!cal.period) { + // Run calibration if needed + cal.MIN_TIME = .3; + cal.bestOf(3); + } + + // Subtract off calibration time. In theory this should never be + // negative, but in practice the calibration times are affected by a + // variety of factors so just clip to zero and let users test for + // getHz() == Infinity + p = Math.max(0, p - cal.period); + } + + return sig(1/p, 4); + } + + // Set properties that are specific to this instance + extend(test, { + // Test name + name: name, + + // Test function + f: f, + + // True if the test function does it's own looping (i.e. takes an arg) + isLoop: isLoop, + + clone: clone, + run: run, + bestOf: bestOf, + getHz: getHz, + reset: reset + }); + + // IE7 doesn't do 'toString' or 'toValue' in object enumerations, so set + // it explicitely here. + test.toString = function() { + if (this.time) { + return this.name + ', f = ' + + humanize(this.getHz()) + 'hz (' + + humanize(this.count) + '/' + humanize(this.time) + 'secs)'; + } else { + return this.name + ', count = ' + humanize(this.count); + } + }; + }; + + // Set static properties + extend(Test, { + LOOP_CAL: new Test('loop cal', function(count) {while (count--) {}}), + NOLOOP_CAL: new Test('noloop cal', nilf) + }); + + // Set default property values + extend(Test.prototype, { + // Initial number of iterations + INIT_COUNT: 10, + + // Max iterations allowed (used to detect bad looping functions) + MAX_COUNT: 1e9, + + // Minimum time test should take to get valid results (secs) + MIN_TIME: 1.0 + }); + + // + // jslitmus + // + + // Set up jslitmus context + var jslitmus; + if (platform.name == 'node') { + jslitmus = exports; + } else { + jslitmus = root.jslitmus = {}; + } + + var tests = [], // test store (all tests added w/ jslitmus.test()) + queue = [], // test queue (to be run) + currentTest; // currently runnning test + + // jslitmus gets EventEmitter API + EventEmitter.call(jslitmus); + + /** + * Create a new test + */ + function test(name, f) { + // Create the Test object + var test = new Test(name, f); + tests.push(test); + + // Run the next test if this one finished + test.on('*', function() { + // Forward test events to jslitmus listeners + var args = Array.prototype.slice.call(arguments); + args.unshift(test._emitting); + jslitmus.emit.apply(jslitmus, args); + + // Auto-run the next test + if (test._emitting == 'complete') { + currentTest = null; + _nextTest(); + } + }); + + jslitmus.emit('added', test); + + return test; + } + + /** + * Add all tests to the run queue + */ + function runAll(e) { + forEach(tests, _queueTest); + } + + /** + * Remove all tests from the run queue. The current test has to finish on + * it's own though + */ + function stop() { + while (queue.length) { + var test = queue.shift(); + } + } + + /** + * Run the next test in the run queue + */ + function _nextTest() { + if (!currentTest) { + var test = queue.shift(); + if (test) { + currentTest = test; + test.run(); + } else { + jslitmus.emit('all_complete'); + } + } + } + + /** + * Add a test to the run queue + */ + function _queueTest(test) { + if (indexOf(queue, test) >= 0) return; + queue.push(test); + _nextTest(); + } + + function clearAll() { + tests = []; + } + + /** + * Generate a Google Chart URL that shows the data for all tests + */ + function getGoogleChart(normalize) { + var chart_title = [ + 'Operations/second on ' + platform.name, + '(' + platform.version + ' / ' + platform.os + ')' + ]; + + var n = tests.length, markers = [], data = []; + var d, min = 0, max = -1e10; + + // Gather test data + + var markers = map(tests, function(test, i) { + if (test.count) { + var hz = test.getHz(); + var v = hz != Infinity ? hz : 0; + data.push(v); + var label = test.name + '(' + humanize(hz)+ ')'; + var marker = 't' + escape2(label) + ',000000,0,' + i + ',10'; + max = Math.max(v, max); + + return marker; + } + }); + + if (markers.length <= 0) return null; + + // Build labels + var labels = [humanize(min), humanize(max)]; + + var w = 250, bw = 15; + var bs = 5; + var h = markers.length*(bw + bs) + 30 + chart_title.length*20; + + var params = { + chtt: escape(chart_title.join('|')), + chts: '000000,10', + cht: 'bhg', // chart type + chd: 't:' + data.join(','), // data set + chds: min + ',' + max, // max/min of data + chxt: 'x', // label axes + chxl: '0:|' + labels.join('|'), // labels + chsp: '0,1', + chm: markers.join('|'), // test names + chbh: [bw, 0, bs].join(','), // bar widths + // chf: 'bg,lg,0,eeeeee,0,eeeeee,.5,ffffff,1', // gradient + chs: w + 'x' + h + }; + + var url = 'http://chart.apis.google.com/chart?' + join(params); + + return url; + } + + // Public API + extend(jslitmus, { + Test: Test, + platform: platform, + test: test, + runAll: runAll, + getGoogleChart: getGoogleChart, + clearAll: clearAll + }); + + // Expose code goodness we've got here, since it's useful, but do so in a way + // that doesn't commit us to supporting it in future versions. + jslitmus.unsupported = { + nilf: nilf, + log: log, + extend: extend, + forEach: forEach, + filter: filter, + map: map, + indexOf: indexOf, + escape2: escape2, + join: join, + split: split, + sig: sig, + humanize: humanize + }; +})(); diff --git a/node_modules/dot/benchmarks/templatesBench.js b/node_modules/dot/benchmarks/templatesBench.js new file mode 100644 index 0000000..b346a89 --- /dev/null +++ b/node_modules/dot/benchmarks/templatesBench.js @@ -0,0 +1,138 @@ +(function() { + var jslitmus, _, doU, doT, + data = { f1: 1, f2: 2, f3: 3, f4: "http://bebedo.com/laura"}, + snippet = "

Just static text

\ +

Here is a simple {{=it.f1}}

\ +
test {{=it.f2}}\ +
{{=it.f3}}
\ +
{{!it.f4}}
\ +
"; + + if (typeof module !== 'undefined' && module.exports) { + runTests(); + } else { + window.onload = runTestsInBrowser; + } + + function testsetup(snippet) { + // doU with 'it' + var doUCompiled = doU.template(snippet); + // doT with 'it' + var doTCompiledParam = doT.template(snippet); + // doT with 'this' + var doTCompiled = doT.template(snippet.replace(/=it\./g, '=this.').replace(/{{!it\./g, '{{!this.')); + // doT with 'it' and append = false + doT.templateSettings.append = false; + var doTCompiledNoAppend = doT.template(snippet); + + jslitmus.test('doU.js', function() { + doUCompiled(data); + }); + + jslitmus.test('doU.js - looping', function(count) { + while (count--) { + doUCompiled(data); + } + }); + + jslitmus.test('doT.js - using this', function() { + doTCompiled.call(data); + }); + + jslitmus.test('doT.js - using this - looping', function(count) { + while (count--) { + doTCompiled.call(data); + } + }); + + jslitmus.test('doT.js - using it', function() { + doTCompiledParam(data); + }); + + jslitmus.test('doT.js - using it - looping', function(count) { + while (count--) { + doTCompiledParam(data); + } + }); + + jslitmus.test('doT.js - append off', function() { + doTCompiledNoAppend(data); + }); + + jslitmus.test('doT.js - append off - looping', function(count) { + while (count--) { + doTCompiledNoAppend(data); + } + }); +} + + function runTests() { + //var util = require('util'); + jslitmus = require('./jslitmus.js'); + doU = require('./templating/doU.js'); + doT = require('./templating/doT.js'); + var passOne = 0; + console.log("*** Small template length: " + snippet.length); + testsetup(snippet); + // Log the test results + jslitmus.on('complete', function(test) { + //console.log(util.inspect(process.memoryUsage())); + console.log(test.toString()); + }); + // 'all_complete' fires when all tests have finished. + jslitmus.on('all_complete', function() { + switch (passOne) { + case 0: + passOne++; + for(var i=0; i<5; i++) { snippet += snippet; } + console.log("*** Medium template length: " + snippet.length); + break; + case 1: + passOne++; + for(var i=0; i<3; i++) { snippet += snippet; } + console.log("*** Large template length: " + snippet.length); + break; + default: + return; + } + + jslitmus.clearAll(); + testsetup(snippet); + jslitmus.runAll(); + }); + // Run it! + jslitmus.runAll(); + } + + function runTestsInBrowser() { + jslitmus = window.jslitmus;doU = window.doU;doT = window.doT; + + var resultTmpl = doT.template("

Template length : {{=it.size}}

"); + var currentSet = document.getElementById('small'); + testsetup(snippet); + // 'complete' fires for each test when it finishes. + jslitmus.on('complete', function(test) { + // Output test results + currentSet.innerHTML += test + '
'; + }); + // 'all_complete' fires when all tests have finished. + jslitmus.on('all_complete', function() { + // Get the results image URL + var url = jslitmus.getGoogleChart(); + if (currentSet.id === 'small') { + currentSet.innerHTML += resultTmpl({size: snippet.length, url: url}); + setTimeout(function() { + jslitmus.clearAll(); + currentSet = document.getElementById('large'); + for(var i=0; i<8; i++) { snippet += snippet; } + testsetup(snippet); + jslitmus.runAll(); + }, 10); + } else { + currentSet.innerHTML += resultTmpl({size: snippet.length, url: url}); + } + }); + // Run it! + jslitmus.runAll(); + } +})(); diff --git a/node_modules/dot/benchmarks/templating/doT.js b/node_modules/dot/benchmarks/templating/doT.js new file mode 100644 index 0000000..3b82453 --- /dev/null +++ b/node_modules/dot/benchmarks/templating/doT.js @@ -0,0 +1,135 @@ +// doT.js +// 2011, Laura Doktorova, https://github.com/olado/doT +// Licensed under the MIT license. + +(function() { + "use strict"; + + var doT = { + version: '1.0.1', + templateSettings: { + evaluate: /\{\{([\s\S]+?(\}?)+)\}\}/g, + interpolate: /\{\{=([\s\S]+?)\}\}/g, + encode: /\{\{!([\s\S]+?)\}\}/g, + use: /\{\{#([\s\S]+?)\}\}/g, + useParams: /(^|[^\w$])def(?:\.|\[[\'\"])([\w$\.]+)(?:[\'\"]\])?\s*\:\s*([\w$\.]+|\"[^\"]+\"|\'[^\']+\'|\{[^\}]+\})/g, + define: /\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g, + defineParams:/^\s*([\w$]+):([\s\S]+)/, + conditional: /\{\{\?(\?)?\s*([\s\S]*?)\s*\}\}/g, + iterate: /\{\{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/g, + varname: 'it', + strip: true, + append: true, + selfcontained: false + }, + template: undefined, //fn, compile template + compile: undefined //fn, for express + }; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = doT; + } else if (typeof define === 'function' && define.amd) { + define(function(){return doT;}); + } else { + (function(){ return this || (0,eval)('this'); }()).doT = doT; + } + + function encodeHTMLSource() { + var encodeHTMLRules = { "&": "&", "<": "<", ">": ">", '"': '"', "'": ''', "/": '/' }, + matchHTML = /&(?!#?\w+;)|<|>|"|'|\//g; + return function() { + return this ? this.replace(matchHTML, function(m) {return encodeHTMLRules[m] || m;}) : this; + }; + } + String.prototype.encodeHTML = encodeHTMLSource(); + + var startend = { + append: { start: "'+(", end: ")+'", endencode: "||'').toString().encodeHTML()+'" }, + split: { start: "';out+=(", end: ");out+='", endencode: "||'').toString().encodeHTML();out+='"} + }, skip = /$^/; + + function resolveDefs(c, block, def) { + return ((typeof block === 'string') ? block : block.toString()) + .replace(c.define || skip, function(m, code, assign, value) { + if (code.indexOf('def.') === 0) { + code = code.substring(4); + } + if (!(code in def)) { + if (assign === ':') { + if (c.defineParams) value.replace(c.defineParams, function(m, param, v) { + def[code] = {arg: param, text: v}; + }); + if (!(code in def)) def[code]= value; + } else { + new Function("def", "def['"+code+"']=" + value)(def); + } + } + return ''; + }) + .replace(c.use || skip, function(m, code) { + if (c.useParams) code = code.replace(c.useParams, function(m, s, d, param) { + if (def[d] && def[d].arg && param) { + var rw = (d+":"+param).replace(/'|\\/g, '_'); + def.__exp = def.__exp || {}; + def.__exp[rw] = def[d].text.replace(new RegExp("(^|[^\\w$])" + def[d].arg + "([^\\w$])", "g"), "$1" + param + "$2"); + return s + "def.__exp['"+rw+"']"; + } + }); + var v = new Function("def", "return " + code)(def); + return v ? resolveDefs(c, v, def) : v; + }); + } + + function unescape(code) { + return code.replace(/\\('|\\)/g, "$1").replace(/[\r\t\n]/g, ' '); + } + + doT.template = function(tmpl, c, def) { + c = c || doT.templateSettings; + var cse = c.append ? startend.append : startend.split, needhtmlencode, sid = 0, indv, + str = (c.use || c.define) ? resolveDefs(c, tmpl, def || {}) : tmpl; + + str = ("var out='" + (c.strip ? str.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g,' ') + .replace(/\r|\n|\t|\/\*[\s\S]*?\*\//g,''): str) + .replace(/'|\\/g, '\\$&') + .replace(c.interpolate || skip, function(m, code) { + return cse.start + unescape(code) + cse.end; + }) + .replace(c.encode || skip, function(m, code) { + needhtmlencode = true; + return cse.start + unescape(code) + cse.endencode; + }) + .replace(c.conditional || skip, function(m, elsecase, code) { + return elsecase ? + (code ? "';}else if(" + unescape(code) + "){out+='" : "';}else{out+='") : + (code ? "';if(" + unescape(code) + "){out+='" : "';}out+='"); + }) + .replace(c.iterate || skip, function(m, iterate, vname, iname) { + if (!iterate) return "';} } out+='"; + sid+=1; indv=iname || "i"+sid; iterate=unescape(iterate); + return "';var arr"+sid+"="+iterate+";if(arr"+sid+"){var "+vname+","+indv+"=-1,l"+sid+"=arr"+sid+".length-1;while("+indv+"\s*|[\r\n\t]|(\/\*[\s\S]*?\*\/)/g, '') + .split(tb).join(te +'\x1b') + .split(te); + + for (m=0,l=arr.length; m < l; m++) { + str += arr[m].charAt(0) !== '\x1b' ? + "out+='" + arr[m].replace(/(\\|["'])/g, '\\$1') + "'" : (arr[m].charAt(1) === '=' ? + ';out+=(' + arr[m].substr(2) + ');' : (arr[m].charAt(1) === '!' ? + ';out+=(' + arr[m].substr(2) + ").toString().replace(/&(?!\\w+;)/g, '&').split('<').join('<').split('>').join('>').split('" + '"' + "').join('"').split(" + '"' + "'" + '"' + ").join(''').split('/').join('/');" : ';' + arr[m].substr(1))); + } + + str = ('var out="";'+str+';return out;') + .split("out+='';").join('') + .split('var out="";out+=').join('var out='); + + try { + return new Function(conf.varname, str); + } catch (e) { + if (typeof console !== 'undefined') console.log("Could not create a template function: " + str); + throw e; + } + }; +}()); diff --git a/node_modules/dot/bin/dot-packer b/node_modules/dot/bin/dot-packer new file mode 100755 index 0000000..cf31582 --- /dev/null +++ b/node_modules/dot/bin/dot-packer @@ -0,0 +1,52 @@ +#!/usr/bin/env node +/* Continuation of https://github.com/Katahdin/dot-packer */ + +var program = require('commander'), + dot = require('../'); + +program + .version('0.0.1') + .usage('dottojs') + .option('-s, --source [value]', 'source folder/file path') + .option('-d, --dest [value]', 'destination folder') + .option('-g, --global [value]', 'the global variable to install the templates in',"window.render") + .option('-p, --package [value]', 'if specified, package all templates from destination folder into specified file') + .parse(process.argv); + +if (program.dest) mkdirordie(program.dest); +if (program.package) { + var li = program.package.lastIndexOf('/'); + if (li>0) mkdirordie(program.package.substring(0, li)); +} + +function mkdirordie(path) { + require("mkdirp")(path, function (err) { + if (err) { + console.error(err); + process.exit(1); + } + }); +} + +var render = dot.process({ + path: program.source, + destination: program.dest, + global: program.global + }); + +if (program.package) { + console.log("Packaging all files into " + program.package); + var fs = require("fs"); + var files = []; + var dest = program.dest || './'; + if (dest[dest.length-1] !== '/') dest += '/'; + var sources = fs.readdirSync(dest); + for(k = 0; k < sources.length; k++) { + name = sources[k]; + if (/\.js$/.test(name)) { + files.push(dest + name); + } + } + var result = require("uglify-js").minify(files); + fs.writeFileSync(program.package, result.code); +} diff --git a/node_modules/dot/doT.js b/node_modules/dot/doT.js new file mode 100644 index 0000000..3b82453 --- /dev/null +++ b/node_modules/dot/doT.js @@ -0,0 +1,135 @@ +// doT.js +// 2011, Laura Doktorova, https://github.com/olado/doT +// Licensed under the MIT license. + +(function() { + "use strict"; + + var doT = { + version: '1.0.1', + templateSettings: { + evaluate: /\{\{([\s\S]+?(\}?)+)\}\}/g, + interpolate: /\{\{=([\s\S]+?)\}\}/g, + encode: /\{\{!([\s\S]+?)\}\}/g, + use: /\{\{#([\s\S]+?)\}\}/g, + useParams: /(^|[^\w$])def(?:\.|\[[\'\"])([\w$\.]+)(?:[\'\"]\])?\s*\:\s*([\w$\.]+|\"[^\"]+\"|\'[^\']+\'|\{[^\}]+\})/g, + define: /\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g, + defineParams:/^\s*([\w$]+):([\s\S]+)/, + conditional: /\{\{\?(\?)?\s*([\s\S]*?)\s*\}\}/g, + iterate: /\{\{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/g, + varname: 'it', + strip: true, + append: true, + selfcontained: false + }, + template: undefined, //fn, compile template + compile: undefined //fn, for express + }; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = doT; + } else if (typeof define === 'function' && define.amd) { + define(function(){return doT;}); + } else { + (function(){ return this || (0,eval)('this'); }()).doT = doT; + } + + function encodeHTMLSource() { + var encodeHTMLRules = { "&": "&", "<": "<", ">": ">", '"': '"', "'": ''', "/": '/' }, + matchHTML = /&(?!#?\w+;)|<|>|"|'|\//g; + return function() { + return this ? this.replace(matchHTML, function(m) {return encodeHTMLRules[m] || m;}) : this; + }; + } + String.prototype.encodeHTML = encodeHTMLSource(); + + var startend = { + append: { start: "'+(", end: ")+'", endencode: "||'').toString().encodeHTML()+'" }, + split: { start: "';out+=(", end: ");out+='", endencode: "||'').toString().encodeHTML();out+='"} + }, skip = /$^/; + + function resolveDefs(c, block, def) { + return ((typeof block === 'string') ? block : block.toString()) + .replace(c.define || skip, function(m, code, assign, value) { + if (code.indexOf('def.') === 0) { + code = code.substring(4); + } + if (!(code in def)) { + if (assign === ':') { + if (c.defineParams) value.replace(c.defineParams, function(m, param, v) { + def[code] = {arg: param, text: v}; + }); + if (!(code in def)) def[code]= value; + } else { + new Function("def", "def['"+code+"']=" + value)(def); + } + } + return ''; + }) + .replace(c.use || skip, function(m, code) { + if (c.useParams) code = code.replace(c.useParams, function(m, s, d, param) { + if (def[d] && def[d].arg && param) { + var rw = (d+":"+param).replace(/'|\\/g, '_'); + def.__exp = def.__exp || {}; + def.__exp[rw] = def[d].text.replace(new RegExp("(^|[^\\w$])" + def[d].arg + "([^\\w$])", "g"), "$1" + param + "$2"); + return s + "def.__exp['"+rw+"']"; + } + }); + var v = new Function("def", "return " + code)(def); + return v ? resolveDefs(c, v, def) : v; + }); + } + + function unescape(code) { + return code.replace(/\\('|\\)/g, "$1").replace(/[\r\t\n]/g, ' '); + } + + doT.template = function(tmpl, c, def) { + c = c || doT.templateSettings; + var cse = c.append ? startend.append : startend.split, needhtmlencode, sid = 0, indv, + str = (c.use || c.define) ? resolveDefs(c, tmpl, def || {}) : tmpl; + + str = ("var out='" + (c.strip ? str.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g,' ') + .replace(/\r|\n|\t|\/\*[\s\S]*?\*\//g,''): str) + .replace(/'|\\/g, '\\$&') + .replace(c.interpolate || skip, function(m, code) { + return cse.start + unescape(code) + cse.end; + }) + .replace(c.encode || skip, function(m, code) { + needhtmlencode = true; + return cse.start + unescape(code) + cse.endencode; + }) + .replace(c.conditional || skip, function(m, elsecase, code) { + return elsecase ? + (code ? "';}else if(" + unescape(code) + "){out+='" : "';}else{out+='") : + (code ? "';if(" + unescape(code) + "){out+='" : "';}out+='"); + }) + .replace(c.iterate || skip, function(m, iterate, vname, iname) { + if (!iterate) return "';} } out+='"; + sid+=1; indv=iname || "i"+sid; iterate=unescape(iterate); + return "';var arr"+sid+"="+iterate+";if(arr"+sid+"){var "+vname+","+indv+"=-1,l"+sid+"=arr"+sid+".length-1;while("+indv+"":">",'"':""","'":"'","/":"/"},b=/&(?!#?\w+;)|<|>|"|'|\//g;return function(){return this?this.replace(b,function(c){return a[c]||c}):this}}function p(a,b,c){return(typeof b==="string"?b:b.toString()).replace(a.define||i,function(l,e,f,g){if(e.indexOf("def.")===0)e=e.substring(4);if(!(e in c))if(f===":"){a.defineParams&&g.replace(a.defineParams,function(n,h,d){c[e]={arg:h,text:d}});e in c||(c[e]=g)}else(new Function("def","def['"+ +e+"']="+g))(c);return""}).replace(a.use||i,function(l,e){if(a.useParams)e=e.replace(a.useParams,function(g,n,h,d){if(c[h]&&c[h].arg&&d){g=(h+":"+d).replace(/'|\\/g,"_");c.__exp=c.__exp||{};c.__exp[g]=c[h].text.replace(RegExp("(^|[^\\w$])"+c[h].arg+"([^\\w$])","g"),"$1"+d+"$2");return n+"def.__exp['"+g+"']"}});var f=(new Function("def","return "+e))(c);return f?p(a,f,c):f})}function m(a){return a.replace(/\\('|\\)/g,"$1").replace(/[\r\t\n]/g," ")}var j={version:"1.0.1",templateSettings:{evaluate:/\{\{([\s\S]+?(\}?)+)\}\}/g, +interpolate:/\{\{=([\s\S]+?)\}\}/g,encode:/\{\{!([\s\S]+?)\}\}/g,use:/\{\{#([\s\S]+?)\}\}/g,useParams:/(^|[^\w$])def(?:\.|\[[\'\"])([\w$\.]+)(?:[\'\"]\])?\s*\:\s*([\w$\.]+|\"[^\"]+\"|\'[^\']+\'|\{[^\}]+\})/g,define:/\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g,defineParams:/^\s*([\w$]+):([\s\S]+)/,conditional:/\{\{\?(\?)?\s*([\s\S]*?)\s*\}\}/g,iterate:/\{\{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/g,varname:"it",strip:true,append:true,selfcontained:false},template:undefined, +compile:undefined};if(typeof module!=="undefined"&&module.exports)module.exports=j;else if(typeof define==="function"&&define.amd)define(function(){return j});else(function(){return this||(0,eval)("this")})().doT=j;String.prototype.encodeHTML=o();var q={append:{start:"'+(",end:")+'",endencode:"||'').toString().encodeHTML()+'"},split:{start:"';out+=(",end:");out+='",endencode:"||'').toString().encodeHTML();out+='"}},i=/$^/;j.template=function(a,b,c){b=b||j.templateSettings;var l=b.append?q.append: +q.split,e,f=0,g;a=b.use||b.define?p(b,a,c||{}):a;a=("var out='"+(b.strip?a.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g," ").replace(/\r|\n|\t|\/\*[\s\S]*?\*\//g,""):a).replace(/'|\\/g,"\\$&").replace(b.interpolate||i,function(h,d){return l.start+m(d)+l.end}).replace(b.encode||i,function(h,d){e=true;return l.start+m(d)+l.endencode}).replace(b.conditional||i,function(h,d,k){return d?k?"';}else if("+m(k)+"){out+='":"';}else{out+='":k?"';if("+m(k)+"){out+='":"';}out+='"}).replace(b.iterate||i,function(h, +d,k,r){if(!d)return"';} } out+='";f+=1;g=r||"i"+f;d=m(d);return"';var arr"+f+"="+d+";if(arr"+f+"){var "+k+","+g+"=-1,l"+f+"=arr"+f+".length-1;while("+g+"\s*|[\r\n\t]|(\/\*[\s\S]*?\*\/)/g, '') + .split(tb).join(te +'\x1b') + .split(te); + + for (m=0,l=arr.length; m < l; m++) { + str += arr[m].charAt(0) !== '\x1b' ? + "out+='" + arr[m].replace(/(\\|["'])/g, '\\$1') + "'" : (arr[m].charAt(1) === '=' ? + ';out+=(' + arr[m].substr(2) + ');' : (arr[m].charAt(1) === '!' ? + ';out+=(' + arr[m].substr(2) + ").toString().replace(/&(?!\\w+;)/g, '&').split('<').join('<').split('>').join('>').split('" + '"' + "').join('"').split(" + '"' + "'" + '"' + ").join(''').split('/').join('/');" : ';' + arr[m].substr(1))); + } + + str = ('var out="";'+str+';return out;') + .split("out+='';").join('') + .split('var out="";out+=').join('var out='); + + try { + return new Function(conf.varname, str); + } catch (e) { + if (typeof console !== 'undefined') console.log("Could not create a template function: " + str); + throw e; + } + }; +}()); diff --git a/node_modules/dot/examples/advancedsnippet.txt b/node_modules/dot/examples/advancedsnippet.txt new file mode 100644 index 0000000..fe735e1 --- /dev/null +++ b/node_modules/dot/examples/advancedsnippet.txt @@ -0,0 +1,119 @@ +Advanced templating: illustrates defines and includes. + +Include external snippet defined in a variable: +{{#def.externalsnippet}} + +Load external template from a file: +{{#def.loadfile('/snippet.txt')}} + +Load external template from a file and cache in a variable: +{{#def['snippet.txt'] || (def['snippet.txt'] = def.loadfile('/snippet.txt'))}} + +Use cached file again: +{{#def['snippet.txt']}} + +Here is a def block that will be used later. This snippet can be referenced from external templates too: +{{##def.snippet1: + Some snippet that will be included {{#def.a}} later {{=it.f1}} +#}} + +First use of snippet1: +{{#def.snippet1}} + +Second use of snippet1: +{{#def.snippet1}} + +Include snippet1 if true: +{{# true && def.snippet1 }} + +Runtime and Compile time evaluation used together: +{{= it.f3 + {{#def.a + def.b}} }} + +Include xyz or insert 'not found': +{{#def.xyz || 'not found'}} + +Set xyz to 1 and exclude result from output: +{{##def.xyz=1#}} is identical to {{#(def.xyz=1) && ""}} + +Compare xyz to 1, show 'xyz is not 1' if false: +{{#def.xyz === 1 || 'xyz is not 1'}} + +{{ if ({{#!def.abc}}) { }} + {{#def.abc}} is falsy +{{ } }} + +{{ if ({{#def.xyz === 1}}) { }} + if(true) block +{{ } }} + +{{##def.fntest = function() { + return "Function test worked!"; +} +#}} + +{{#def.fntest()}} + +Conditionals: +{{? !it.altEmail }} +

+ second email: {{= it.altEmail }} +

+{{?? true }} + else case worked +{{?}} + +Array iterators +{{~ it.farray :p }} +

{{=p.farray}}

+ {{~ p.farray :value:i }} +

{{=i}}: {{=value}}

+ {{~ value :w }} +

{{=w}}

+ {{~}} + {{~}} +{{~}} + +{{~ ["apple", "banana", "orange"] :k}} + {{=k}} +{{~}} + +{{~ (function(){ return [1,2,3]})() :k}} + {{=k}} +{{~}} + +{{ function children(it) { }} + +{{?it.Nodes.length}} +
    + {{~ it.Nodes :p}} +
  • + {{=p.title}} + {{children(p);}} +
  • + {{~}} +
+{{?}} + +{{ } }} + +{{ children( {Nodes:[ {title:"1.1", Nodes:[ {title:"1.1.1", Nodes:[]}, {title:"1.1.2", Nodes:[]}] }, { title:"1.2", Nodes:[]}, { title:"1.3", Nodes:[]}], title:"1" } ); }} + + +{{##def.block:param: +
{{=param}}
+#}} + +{{##def.block1:param: +
{{=param.a}}
+#}} + + +{{#(def.block:'text' || '') + def.block:5}} + +{{#def.block:it.f3 || ''}} + +{{#def.block:"lala tralala" || ''}} + +{{#def.block1:{a:1, b:2} || ''}} + +The end diff --git a/node_modules/dot/examples/browsersample.html b/node_modules/dot/examples/browsersample.html new file mode 100644 index 0000000..2feb3a3 --- /dev/null +++ b/node_modules/dot/examples/browsersample.html @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + +
+
+ + + + + diff --git a/node_modules/dot/examples/customdoT.js b/node_modules/dot/examples/customdoT.js new file mode 100644 index 0000000..2131084 --- /dev/null +++ b/node_modules/dot/examples/customdoT.js @@ -0,0 +1,19 @@ +(function() { + var doT = require('../doT.js'), + data = { f1: 1, f2: 2, f3: 3}, + snippet = '

Just static text

Here is a simple case

Next we will use a JavaScript block:
'; + + doT.templateSettings = { + evaluate : /\<\?([\s\S]+?)\?\>/g, + interpolate : /\<\?=([\s\S]+?)\?\>/g, + varname : 'it', + strip: true + }; + + + + var doTCompiled = doT.template(snippet); + + console.log("Generated function: \n" + doTCompiled.toString()); + console.log("Result of calling with " + JSON.stringify(data) + " :\n" + doTCompiled(data)); +}()); diff --git a/node_modules/dot/examples/snippet.txt b/node_modules/dot/examples/snippet.txt new file mode 100644 index 0000000..8e2ca9a --- /dev/null +++ b/node_modules/dot/examples/snippet.txt @@ -0,0 +1,13 @@ +Core templating + +

Just static text

+

Interpolation {{=it.f1 + it.f3}}

+
JavaScript block evaluation +{{ for(var i=0; i < it.f2; i++) { + console.log("Pass\t" + i); +}} +
{{=it.f3}}
+{{ } }} +
+
Encoding {{!''}}
+ diff --git a/node_modules/dot/examples/views/multidef.def.jst b/node_modules/dot/examples/views/multidef.def.jst new file mode 100644 index 0000000..0ba7338 --- /dev/null +++ b/node_modules/dot/examples/views/multidef.def.jst @@ -0,0 +1,13 @@ +{{##def.template1: +
{{=it.bar}}
+ /* Including one.def file here */ + {{#def.one}} +#}} + +{{##def.template2:param: +
{{=param.bar}}
+
+
+#}} + + diff --git a/node_modules/dot/examples/views/one.def b/node_modules/dot/examples/views/one.def new file mode 100644 index 0000000..c13cf1b --- /dev/null +++ b/node_modules/dot/examples/views/one.def @@ -0,0 +1,2 @@ +/* This file can be inserted into other files */ +
{{=it.foo}}
diff --git a/node_modules/dot/examples/views/two.dot.jst b/node_modules/dot/examples/views/two.dot.jst new file mode 100644 index 0000000..1c9daae --- /dev/null +++ b/node_modules/dot/examples/views/two.dot.jst @@ -0,0 +1,17 @@ +/* Including multidef file */ +{{#def.multidef}} + +
+ /* Including one.def file */ + {{#def.one}} + + /* Using sub-define from multidef */ + {{#def.template2:{bar:"hello", class:"hidden"} }} + + /* Using sub-define from multidef */ + {{ var data = {bar:"world", class:"visible"}; }} + {{#def.template2:data}} +
+ + + diff --git a/node_modules/dot/examples/withdoT.js b/node_modules/dot/examples/withdoT.js new file mode 100644 index 0000000..5eea573 --- /dev/null +++ b/node_modules/dot/examples/withdoT.js @@ -0,0 +1,21 @@ +(function() { + var doT = require('../doT.js'), + fs = require('fs'), + data = { f1: 1, f2: 2, f3: 3, altEmail: "conditional works", farray:[{farray:[1,2,3,[11,22,33]],person:{name:'Ell',age:23}},{farray:{how:'really'}}, {farray:[5,6,7,8]}]}, + defs = { a: 100, b: 200}; + + defs.loadfile = function(path) { + return fs.readFileSync(process.argv[1].replace(/\/[^\/]*$/,path)); + }; + defs.externalsnippet = defs.loadfile('/snippet.txt'); + + fs.readFile(process.argv[1].replace(/\/[^\/]*$/,'/advancedsnippet.txt'), function (err, snippet) { + if (err) { + console.log("Error reading advancedsnippet.txt " + err); + } else { + var doTCompiled = doT.template(snippet.toString(), undefined, defs); + console.log("Generated function: \n" + doTCompiled.toString()); + console.log("Result of calling with " + JSON.stringify(data) + " :\n" + doTCompiled(data)); + } + }); +}()); diff --git a/node_modules/dot/index.js b/node_modules/dot/index.js new file mode 100644 index 0000000..ac624ae --- /dev/null +++ b/node_modules/dot/index.js @@ -0,0 +1,143 @@ +/* doT + auto-compilation of doT templates + * + * 2012, Laura Doktorova, https://github.com/olado/doT + * Licensed under the MIT license + * + * Compiles .def, .dot, .jst files found under the specified path. + * It ignores sub-directories. + * Template files can have multiple extensions at the same time. + * Files with .def extension can be included in other files via {{#def.name}} + * Files with .dot extension are compiled into functions with the same name and + * can be accessed as renderer.filename + * Files with .jst extension are compiled into .js files. Produced .js file can be + * loaded as a commonJS, AMD module, or just installed into a global variable + * (default is set to window.render). + * All inline defines defined in the .jst file are + * compiled into separate functions and are available via _render.filename.definename + * + * Basic usage: + * var dots = require("dot").process({path: "./views"}); + * dots.mytemplate({foo:"hello world"}); + * + * The above snippet will: + * 1. Compile all templates in views folder (.dot, .def, .jst) + * 2. Place .js files compiled from .jst templates into the same folder. + * These files can be used with require, i.e. require("./views/mytemplate"). + * 3. Return an object with functions compiled from .dot templates as its properties. + * 4. Render mytemplate template. + */ + +var fs = require("fs"), + doT = module.exports = require("./doT"); + +doT.process = function(options) { + //path, destination, global, rendermodule, templateSettings + return new InstallDots(options).compileAll(); +}; + +function InstallDots(o) { + this.__path = o.path || "./"; + if (this.__path[this.__path.length-1] !== '/') this.__path += '/'; + this.__destination = o.destination || this.__path; + if (this.__destination[this.__destination.length-1] !== '/') this.__destination += '/'; + this.__global = o.global || "window.render"; + this.__rendermodule = o.rendermodule || {}; + this.__settings = o.templateSettings ? copy(o.templateSettings, copy(doT.templateSettings)) : undefined; + this.__includes = {}; +} + +InstallDots.prototype.compileToFile = function(path, template, def) { + def = def || {}; + var modulename = path.substring(path.lastIndexOf("/")+1, path.lastIndexOf(".")) + , defs = copy(this.__includes, copy(def)) + , settings = this.__settings || doT.templateSettings + , compileoptions = copy(settings) + , defaultcompiled = doT.template(template, settings, defs) + , exports = [] + , compiled = "" + , fn; + + for (var property in defs) { + if (defs[property] !== def[property] && defs[property] !== this.__includes[property]) { + fn = undefined; + if (typeof defs[property] === 'string') { + fn = doT.template(defs[property], settings, defs); + } else if (typeof defs[property] === 'function') { + fn = defs[property]; + } else if (defs[property].arg) { + compileoptions.varname = defs[property].arg; + fn = doT.template(defs[property].text, compileoptions, defs); + } + if (fn) { + compiled += fn.toString().replace('anonymous', property); + exports.push(property); + } + } + } + compiled += defaultcompiled.toString().replace('anonymous', modulename); + fs.writeFileSync(path, "(function(){" + compiled + + "var itself=" + modulename + ";" + + addexports(exports) + + "if(typeof module!=='undefined' && module.exports) module.exports=itself;else if(typeof define==='function')define(function(){return itself;});else {" + + this.__global + "=" + this.__global + "||{};" + this.__global + "['" + modulename + "']=itself;}}());"); +}; + +function addexports(exports) { + for (var ret ='', i=0; i< exports.length; i++) { + ret += "itself." + exports[i]+ "=" + exports[i]+";"; + } + return ret; +} + +function copy(o, to) { + to = to || {}; + for (var property in o) { + to[property] = o[property]; + } + return to; +} + +function readdata(path) { + var data = fs.readFileSync(path); + if (data) return data.toString(); + console.log("problems with " + path); +} + +InstallDots.prototype.compilePath = function(path) { + var data = readdata(path); + if (data) { + return doT.template(data, + this.__settings || doT.templateSettings, + copy(this.__includes)); + } +}; + +InstallDots.prototype.compileAll = function() { + console.log("Compiling all doT templates..."); + + var defFolder = this.__path, + sources = fs.readdirSync(defFolder), + k, l, name; + + for( k = 0, l = sources.length; k < l; k++) { + name = sources[k]; + if (/\.def(\.dot|\.jst)?$/.test(name)) { + console.log("Loaded def " + name); + this.__includes[name.substring(0, name.indexOf('.'))] = readdata(defFolder + name); + } + } + + for( k = 0, l = sources.length; k < l; k++) { + name = sources[k]; + if (/\.dot(\.def|\.jst)?$/.test(name)) { + console.log("Compiling " + name + " to function"); + this.__rendermodule[name.substring(0, name.indexOf('.'))] = this.compilePath(defFolder + name); + } + if (/\.jst(\.dot|\.def)?$/.test(name)) { + console.log("Compiling " + name + " to file"); + this.compileToFile(this.__destination + name.substring(0, name.indexOf('.')) + '.js', + readdata(defFolder + name)); + } + } + return this.__rendermodule; +}; diff --git a/node_modules/dot/package.json b/node_modules/dot/package.json new file mode 100644 index 0000000..e7ef0e1 --- /dev/null +++ b/node_modules/dot/package.json @@ -0,0 +1,45 @@ +{ + "name": "dot", + "description": "Concise and fast javascript templating compatible with nodejs and other javascript environments", + "keywords": [ + "template", + "fast", + "simple", + "templating" + ], + "version": "1.0.2", + "main": "index", + "bin": { + "dottojs": "./bin/dot-packer" + }, + "homepage": "http://github.com/olado/doT", + "repository": { + "type": "git", + "url": "git://github.com/olado/doT.git" + }, + "author": { + "name": "Laura Doktorova", + "email": "ldoktorova@gmail.com" + }, + "engines": [ + "node >=0.2.6" + ], + "scripts": { + "test": "mocha" + }, + "dependencies": {}, + "devDependencies": { + "commander": "*", + "uglify-js": "*", + "mkdirp": "*", + "mocha": "*", + "jshint": "*" + }, + "readme": "Created in search of the fastest and concise JavaScript templating function with emphasis on performance under V8 and nodejs. It shows great performance for both nodejs and browsers.\n\ndoT.js is fast, small and has no dependencies.\n\n## Features\n custom delimiters\n runtime evaluation\n runtime interpolation\n compile-time evaluation\n partials support\n conditionals support\n array iterators\n encoding\n control whitespace - strip or preserve\n streaming friendly\n use it as logic-less or with logic, it is up to you\n\n## Docs, live playground and samples\n\nhttp://olado.github.com/doT (todo: update docs with new features added in version 1.0.0)\n\n## New in version 1.0.0\n\n####Added parameters support in partials\n\n\t{{##def.macro:param:\n\t\t
{{=param.foo}}
\n\t#}}\n\n\t{{#def.macro:myvariable}}\n\n####Node module now supports auto-compilation of dot templates from specified path\n\n\tvar dots = require(\"dot\").process({ path: \"./views\"});\n\nThis will compile .def, .dot, .jst files found under the specified path.\nDetails\n * It ignores sub-directories.\n * Template files can have multiple extensions at the same time.\n * Files with .def extension can be included in other files via {{#def.name}}\n * Files with .dot extension are compiled into functions with the same name and\n can be accessed as renderer.filename\n * Files with .jst extension are compiled into .js files. Produced .js file can be\n loaded as a commonJS, AMD module, or just installed into a global variable (default is set to window.render)\n * All inline defines defined in the .jst file are\n compiled into separate functions and are available via _render.filename.definename\n \n Basic usage:\n ```\n var dots = require(\"dot\").process({path: \"./views\"});\n dots.mytemplate({foo:\"hello world\"});\n ```\n The above snippet will:\n\t* Compile all templates in views folder (.dot, .def, .jst)\n \t* Place .js files compiled from .jst templates into the same folder\n \t These files can be used with require, i.e. require(\"./views/mytemplate\")\n \t* Return an object with functions compiled from .dot templates as its properties\n \t* Render mytemplate template\n \n####CLI tool to compile dot templates into js files\n\n\t./bin/dot-packer -s examples/views -d out/views\n\n## Notes\n doU.js is here only so that legacy external tests do not break. Use doT.js.\n doT.js with doT.templateSettings.append=false provides the same performance as doU.js.\n\n## Author\nLaura Doktorova @olado\n\n## License\ndoT is licensed under the MIT License. (See LICENSE-DOT)\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/olado/doT/issues" + }, + "_id": "dot@1.0.2", + "_from": "dot@" +} diff --git a/node_modules/dot/test/testdoT.js b/node_modules/dot/test/testdoT.js new file mode 100644 index 0000000..2a4ad28 --- /dev/null +++ b/node_modules/dot/test/testdoT.js @@ -0,0 +1,30 @@ +var assert = require("assert"), doT = require("../doT"); + +describe('doT', function(){ + var basictemplate = "
{{!it.foo}}
", + basiccompiled = doT.template(basictemplate), + definestemplate = "{{##def.tmp:
{{!it.foo}}
#}}{{#def.tmp}}", + definescompiled = doT.template(definestemplate); + + describe('#template()', function(){ + it('should return a function', function(){ + assert.equal("function", typeof basiccompiled); + }); + }); + + describe('#()', function(){ + it('should render the template', function(){ + assert.equal("
http
", basiccompiled({foo:"http"})); + assert.equal("
http://abc.com
", basiccompiled({foo:"http://abc.com"})); + assert.equal("
", basiccompiled({})); + }); + }); + + describe('defines', function(){ + it('should render define', function(){ + assert.equal("
http
", definescompiled({foo:"http"})); + assert.equal("
http://abc.com
", definescompiled({foo:"http://abc.com"})); + assert.equal("
", definescompiled({})); + }); + }); +}); diff --git a/node_modules/minstache/.npmignore b/node_modules/minstache/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/minstache/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/minstache/History.md b/node_modules/minstache/History.md new file mode 100644 index 0000000..b7addb8 --- /dev/null +++ b/node_modules/minstache/History.md @@ -0,0 +1,11 @@ + +1.1.0 / 2013-07-04 +================== + + * add unescaped property support + * remove support for single braces + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/minstache/Makefile b/node_modules/minstache/Makefile new file mode 100644 index 0000000..4e9c8d3 --- /dev/null +++ b/node_modules/minstache/Makefile @@ -0,0 +1,7 @@ + +test: + @./node_modules/.bin/mocha \ + --require should \ + --reporter spec + +.PHONY: test \ No newline at end of file diff --git a/node_modules/minstache/Readme.md b/node_modules/minstache/Readme.md new file mode 100644 index 0000000..6a9f847 --- /dev/null +++ b/node_modules/minstache/Readme.md @@ -0,0 +1,72 @@ + +# minstache + + Mini mustache template engine. + +## Installation + + $ npm install minstache + $ component install visionmedia/minstache + +## minstache(1) + + The `minstache(1)` executable can compile a file to a valid + stand-alone commonjs module for you, there's no need to have minstache + as a dependency: + + hello.mustache: + +``` +Hello {{name}}! {{^authenticated}}login{{/authenticated}} +``` + + convert it: + +``` +$ minstache < hello.mustache > hello.js +``` + + hello.js: + +```js +module.exports = function anonymous(obj) { + + function escape(html) { + return String(html) + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(//g, '>'); + }; + + function section(obj, prop, negate, str) { + var val = obj[prop]; + if ('function' == typeof val) return val.call(obj, str); + if (negate) val = !val; + if (val) return str; + return ''; + }; + + return "Hello " + escape(obj.name) + "! " + section(obj, "authenticated", true, "login") + "\n" +} +``` + +## API + +### minstache(string, [obj]) + + Compile and render the given mustache `string` with optional context `obj`. + +### minstache.compile(string) + + Compile the mustache `string` to a stand-alone `Function` accepting a context `obj`. + +## Divergence + + Partials are not supported, this lib is meant to be a small template engine solution for stand-alone [component](http://github.com/component) templates. If your template takes "partials" then pass other rendered strings to it. If you need a full-blown mustache solution Hogan.js is still great. + + Minstache uses `{{!name}}` for unescaped properties. + +## License + + MIT diff --git a/node_modules/minstache/bin/minstache b/node_modules/minstache/bin/minstache new file mode 100755 index 0000000..d68b1fc --- /dev/null +++ b/node_modules/minstache/bin/minstache @@ -0,0 +1,28 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('commander') + , mm = require('..'); + +// options + +program + .usage('< template > js') + .version(require('../package.json').version) + .parse(process.argv); + +// read stdin + +var str = ''; +process.stdin.setEncoding('utf8'); +process.stdin.on('data', function(chunk){ str += chunk; }); +process.stdin.on('end', done); +process.stdin.resume(); + +function done() { + var fn = mm.compile(str).toString(); + process.stdout.write('module.exports = ' + fn); +} \ No newline at end of file diff --git a/node_modules/minstache/component.json b/node_modules/minstache/component.json new file mode 100644 index 0000000..9a71629 --- /dev/null +++ b/node_modules/minstache/component.json @@ -0,0 +1,7 @@ +{ + "name": "minstache", + "version": "1.1.0", + "description": "Mini mustache template engine", + "keywords": ["mustache", "template", "engine"], + "scripts": ["index.js"] +} diff --git a/node_modules/minstache/index.js b/node_modules/minstache/index.js new file mode 100644 index 0000000..0ba8f94 --- /dev/null +++ b/node_modules/minstache/index.js @@ -0,0 +1,149 @@ + +/** + * Expose `render()`.` + */ + +exports = module.exports = render; + +/** + * Expose `compile()`. + */ + +exports.compile = compile; + +/** + * Render the given mustache `str` with `obj`. + * + * @param {String} str + * @param {Object} obj + * @return {String} + * @api public + */ + +function render(str, obj) { + obj = obj || {}; + var fn = compile(str); + return fn(obj); +} + +/** + * Compile the given `str` to a `Function`. + * + * @param {String} str + * @return {Function} + * @api public + */ + +function compile(str) { + var js = []; + var toks = parse(str); + var tok; + + for (var i = 0; i < toks.length; ++i) { + tok = toks[i]; + if (i % 2 == 0) { + js.push('"' + tok.replace(/"/g, '\\"') + '"'); + } else { + switch (tok[0]) { + case '/': + tok = tok.slice(1); + js.push(') + '); + break; + case '^': + tok = tok.slice(1); + assertProperty(tok); + js.push(' + section(obj, "' + tok + '", true, '); + break; + case '#': + tok = tok.slice(1); + assertProperty(tok); + js.push(' + section(obj, "' + tok + '", false, '); + break; + case '!': + tok = tok.slice(1); + assertProperty(tok); + js.push(' + obj.' + tok + ' + '); + break; + default: + assertProperty(tok); + js.push(' + escape(obj.' + tok + ') + '); + } + } + } + + js = '\n' + + indent(escape.toString()) + ';\n\n' + + indent(section.toString()) + ';\n\n' + + ' return ' + js.join('').replace(/\n/g, '\\n'); + + return new Function('obj', js); +} + +/** + * Assert that `prop` is a valid property. + * + * @param {String} prop + * @api private + */ + +function assertProperty(prop) { + if (!prop.match(/^[\w.]+$/)) throw new Error('invalid property "' + prop + '"'); +} + +/** + * Parse `str`. + * + * @param {String} str + * @return {Array} + * @api private + */ + +function parse(str) { + return str.split(/\{\{|\}\}/); +} + +/** + * Indent `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +function indent(str) { + return str.replace(/^/gm, ' '); +} + +/** + * Section handler. + * + * @param {Object} context obj + * @param {String} prop + * @param {String} str + * @param {Boolean} negate + * @api private + */ + +function section(obj, prop, negate, str) { + var val = obj[prop]; + if ('function' == typeof val) return val.call(obj, str); + if (negate) val = !val; + if (val) return str; + return ''; +} + +/** + * Escape the given `html`. + * + * @param {String} html + * @return {String} + * @api private + */ + +function escape(html) { + return String(html) + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(//g, '>'); +} diff --git a/node_modules/minstache/node_modules/commander/.npmignore b/node_modules/minstache/node_modules/commander/.npmignore new file mode 100644 index 0000000..f1250e5 --- /dev/null +++ b/node_modules/minstache/node_modules/commander/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/node_modules/minstache/node_modules/commander/.travis.yml b/node_modules/minstache/node_modules/commander/.travis.yml new file mode 100644 index 0000000..f1d0f13 --- /dev/null +++ b/node_modules/minstache/node_modules/commander/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.4 + - 0.6 diff --git a/node_modules/minstache/node_modules/commander/History.md b/node_modules/minstache/node_modules/commander/History.md new file mode 100644 index 0000000..15847b2 --- /dev/null +++ b/node_modules/minstache/node_modules/commander/History.md @@ -0,0 +1,135 @@ + +1.0.4 / 2012-09-03 +================== + + * add `outputHelp()` method. + +1.0.3 / 2012-08-30 +================== + + * remove invalid .version() defaulting + +1.0.2 / 2012-08-24 +================== + + * add `--foo=bar` support [arv] + * fix password on node 0.8.8. Make backward compatible with 0.6 [focusaurus] + +1.0.1 / 2012-08-03 +================== + + * fix issue #56 + * fix tty.setRawMode(mode) was moved to tty.ReadStream#setRawMode() (i.e. process.stdin.setRawMode()) + +1.0.0 / 2012-07-05 +================== + + * add support for optional option descriptions + * add defaulting of `.version()` to package.json's version + +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/minstache/node_modules/commander/Makefile b/node_modules/minstache/node_modules/commander/Makefile new file mode 100644 index 0000000..0074625 --- /dev/null +++ b/node_modules/minstache/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/minstache/node_modules/commander/Readme.md b/node_modules/minstache/node_modules/commander/Readme.md new file mode 100644 index 0000000..b8328c3 --- /dev/null +++ b/node_modules/minstache/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/minstache/node_modules/commander/index.js b/node_modules/minstache/node_modules/commander/index.js new file mode 100644 index 0000000..06ec1e4 --- /dev/null +++ b/node_modules/minstache/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/minstache/node_modules/commander/lib/commander.js b/node_modules/minstache/node_modules/commander/lib/commander.js new file mode 100644 index 0000000..cfe5eb0 --- /dev/null +++ b/node_modules/minstache/node_modules/commander/lib/commander.js @@ -0,0 +1,1053 @@ +/*! + * commander + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter + , path = require('path') + , keypress = require('keypress') + , 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]); + } + + // Leftover arguments need to be pushed back. Fixes issue #56 + if (parsed.args.length) args = parsed.args.concat(args); + + 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". + * This also normalizes equal sign and splits "--abc=def" into "--abc def". + * + * @param {Array} args + * @return {Array} + * @api private + */ + +Command.prototype.normalize = function(args){ + var ret = [] + , arg + , index; + + 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 if (/^--/.test(arg) && ~(index = arg.indexOf('='))) { + ret.push(arg.slice(0, index), arg.slice(index + 1)); + } 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 = ''; + } + + keypress(process.stdin); + + function setRawMode(mode) { + if (process.stdin.setRawMode) { + process.stdin.setRawMode(mode); + } else { + tty.setRawMode(mode); + } + }; + setRawMode(true); + process.stdout.write(str); + + // keypress + process.stdin.on('keypress', function(c, key){ + if (key && 'enter' == key.name) { + console.log(); + process.stdin.pause(); + process.stdin.removeAllListeners('keypress'); + 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(); +}; + + +/** + * Output help information for this command + * + * @api public + */ + +Command.prototype.outputHelp = function(){ + process.stdout.write(this.helpInformation()); + this.emit('--help'); +}; + +/** + * 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') { + cmd.outputHelp(); + process.exit(0); + } + } +} diff --git a/node_modules/minstache/node_modules/commander/node_modules/keypress/README.md b/node_modules/minstache/node_modules/commander/node_modules/keypress/README.md new file mode 100644 index 0000000..a768e8f --- /dev/null +++ b/node_modules/minstache/node_modules/commander/node_modules/keypress/README.md @@ -0,0 +1,101 @@ +keypress +======== +### Make any Node ReadableStream emit "keypress" events + + +Previous to Node `v0.8.x`, there was an undocumented `"keypress"` event that +`process.stdin` would emit when it was a TTY. Some people discovered this hidden +gem, and started using it in their own code. + +Now in Node `v0.8.x`, this `"keypress"` event does not get emitted by default, +but rather only when it is being used in conjuction with the `readline` (or by +extension, the `repl`) module. + +This module is the exact logic from the node `v0.8.x` releases ripped out into its +own module. + +__Bonus:__ Now with mouse support! + +Installation +------------ + +Install with `npm`: + +``` bash +$ npm install keypress +``` + +Or add it to the `"dependencies"` section of your _package.json_ file. + + +Example +------- + +#### Listening for "keypress" events + +``` js +var keypress = require('keypress'); + +// make `process.stdin` begin emitting "keypress" events +keypress(process.stdin); + +// listen for the "keypress" event +process.stdin.on('keypress', function (ch, key) { + console.log('got "keypress"', key); + if (key && key.ctrl && key.name == 'c') { + process.stdin.pause(); + } +}); + +process.stdin.setRawMode(true); +process.stdin.resume(); +``` + +#### Listening for "mousepress" events + +``` js +var keypress = require('keypress'); + +// make `process.stdin` begin emitting "mousepress" (and "keypress") events +keypress(process.stdin); + +// you must enable the mouse events before they will begin firing +keypress.enableMouse(process.stdout); + +process.stdin.on('mousepress', function (info) { + console.log('got "mousepress" event at %d x %d', info.x, info.y); +}); + +process.on('exit', function () { + // disable mouse on exit, so that the state + // is back to normal for the terminal + keypress.disableMouse(process.stdout); +}); +``` + + +License +------- + +(The MIT License) + +Copyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net> + +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/minstache/node_modules/commander/node_modules/keypress/index.js b/node_modules/minstache/node_modules/commander/node_modules/keypress/index.js new file mode 100644 index 0000000..c2ba488 --- /dev/null +++ b/node_modules/minstache/node_modules/commander/node_modules/keypress/index.js @@ -0,0 +1,346 @@ + +/** + * This module offers the internal "keypress" functionality from node-core's + * `readline` module, for your own programs and modules to use. + * + * Usage: + * + * require('keypress')(process.stdin); + * + * process.stdin.on('keypress', function (ch, key) { + * console.log(ch, key); + * if (key.ctrl && key.name == 'c') { + * process.stdin.pause(); + * } + * }); + * proces.stdin.resume(); + */ +var exports = module.exports = keypress; + +exports.enableMouse = function (stream) { + stream.write('\x1b' +'[?1000h') +} + +exports.disableMouse = function (stream) { + stream.write('\x1b' +'[?1000l') +} + + +/** + * accepts a readable Stream instance and makes it emit "keypress" events + */ + +function keypress(stream) { + if (isEmittingKeypress(stream)) return; + stream._emitKeypress = true; + + function onData(b) { + if (stream.listeners('keypress').length > 0) { + emitKey(stream, b); + } else { + // Nobody's watching anyway + stream.removeListener('data', onData); + stream.on('newListener', onNewListener); + } + } + + function onNewListener(event) { + if (event == 'keypress') { + stream.on('data', onData); + stream.removeListener('newListener', onNewListener); + } + } + + if (stream.listeners('keypress').length > 0) { + stream.on('data', onData); + } else { + stream.on('newListener', onNewListener); + } +} + +/** + * Returns `true` if the stream is already emitting "keypress" events. + * `false` otherwise. + */ + +function isEmittingKeypress(stream) { + var rtn = stream._emitKeypress; + if (!rtn) { + // hack: check for the v0.6.x "data" event + stream.listeners('data').forEach(function (l) { + if (l.name == 'onData' && /emitKey/.test(l.toString())) { + rtn = true; + stream._emitKeypress = true; + } + }); + } + if (!rtn) { + // hack: check for the v0.6.x "newListener" event + stream.listeners('newListener').forEach(function (l) { + if (l.name == 'onNewListener' && /keypress/.test(l.toString())) { + rtn = true; + stream._emitKeypress = true; + } + }); + } + return rtn; +} + + +/* + Some patterns seen in terminal key escape codes, derived from combos seen + at http://www.midnight-commander.org/browser/lib/tty/key.c + + ESC letter + ESC [ letter + ESC [ modifier letter + ESC [ 1 ; modifier letter + ESC [ num char + ESC [ num ; modifier char + ESC O letter + ESC O modifier letter + ESC O 1 ; modifier letter + ESC N letter + ESC [ [ num ; modifier char + ESC [ [ 1 ; modifier letter + ESC ESC [ num char + ESC ESC O letter + + - char is usually ~ but $ and ^ also happen with rxvt + - modifier is 1 + + (shift * 1) + + (left_alt * 2) + + (ctrl * 4) + + (right_alt * 8) + - two leading ESCs apparently mean the same as one leading ESC +*/ + +// Regexes used for ansi escape code splitting +var metaKeyCodeRe = /^(?:\x1b)([a-zA-Z0-9])$/; +var functionKeyCodeRe = + /^(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/; + +function emitKey(stream, s) { + var ch, + key = { + name: undefined, + ctrl: false, + meta: false, + shift: false + }, + parts; + + if (Buffer.isBuffer(s)) { + if (s[0] > 127 && s[1] === undefined) { + s[0] -= 128; + s = '\x1b' + s.toString(stream.encoding || 'utf-8'); + } else { + s = s.toString(stream.encoding || 'utf-8'); + } + } + + key.sequence = s; + + if (s === '\r' || s === '\n') { + // enter + key.name = 'enter'; + + } else if (s === '\t') { + // tab + key.name = 'tab'; + + } else if (s === '\b' || s === '\x7f' || + s === '\x1b\x7f' || s === '\x1b\b') { + // backspace or ctrl+h + key.name = 'backspace'; + key.meta = (s.charAt(0) === '\x1b'); + + } else if (s === '\x1b' || s === '\x1b\x1b') { + // escape key + key.name = 'escape'; + key.meta = (s.length === 2); + + } else if (s === ' ' || s === '\x1b ') { + key.name = 'space'; + key.meta = (s.length === 2); + + } else if (s <= '\x1a') { + // ctrl+letter + key.name = String.fromCharCode(s.charCodeAt(0) + 'a'.charCodeAt(0) - 1); + key.ctrl = true; + + } else if (s.length === 1 && s >= 'a' && s <= 'z') { + // lowercase letter + key.name = s; + + } else if (s.length === 1 && s >= 'A' && s <= 'Z') { + // shift+letter + key.name = s.toLowerCase(); + key.shift = true; + + } else if (parts = metaKeyCodeRe.exec(s)) { + // meta+character key + key.name = parts[1].toLowerCase(); + key.meta = true; + key.shift = /^[A-Z]$/.test(parts[1]); + + } else if (parts = functionKeyCodeRe.exec(s)) { + // ansi escape sequence + + // reassemble the key code leaving out leading \x1b's, + // the modifier key bitflag and any meaningless "1;" sequence + var code = (parts[1] || '') + (parts[2] || '') + + (parts[4] || '') + (parts[6] || ''), + modifier = (parts[3] || parts[5] || 1) - 1; + + // Parse the key modifier + key.ctrl = !!(modifier & 4); + key.meta = !!(modifier & 10); + key.shift = !!(modifier & 1); + key.code = code; + + // Parse the key itself + switch (code) { + /* xterm/gnome ESC O letter */ + case 'OP': key.name = 'f1'; break; + case 'OQ': key.name = 'f2'; break; + case 'OR': key.name = 'f3'; break; + case 'OS': key.name = 'f4'; break; + + /* xterm/rxvt ESC [ number ~ */ + case '[11~': key.name = 'f1'; break; + case '[12~': key.name = 'f2'; break; + case '[13~': key.name = 'f3'; break; + case '[14~': key.name = 'f4'; break; + + /* from Cygwin and used in libuv */ + case '[[A': key.name = 'f1'; break; + case '[[B': key.name = 'f2'; break; + case '[[C': key.name = 'f3'; break; + case '[[D': key.name = 'f4'; break; + case '[[E': key.name = 'f5'; break; + + /* common */ + case '[15~': key.name = 'f5'; break; + case '[17~': key.name = 'f6'; break; + case '[18~': key.name = 'f7'; break; + case '[19~': key.name = 'f8'; break; + case '[20~': key.name = 'f9'; break; + case '[21~': key.name = 'f10'; break; + case '[23~': key.name = 'f11'; break; + case '[24~': key.name = 'f12'; break; + + /* xterm ESC [ letter */ + case '[A': key.name = 'up'; break; + case '[B': key.name = 'down'; break; + case '[C': key.name = 'right'; break; + case '[D': key.name = 'left'; break; + case '[E': key.name = 'clear'; break; + case '[F': key.name = 'end'; break; + case '[H': key.name = 'home'; break; + + /* xterm/gnome ESC O letter */ + case 'OA': key.name = 'up'; break; + case 'OB': key.name = 'down'; break; + case 'OC': key.name = 'right'; break; + case 'OD': key.name = 'left'; break; + case 'OE': key.name = 'clear'; break; + case 'OF': key.name = 'end'; break; + case 'OH': key.name = 'home'; break; + + /* xterm/rxvt ESC [ number ~ */ + case '[1~': key.name = 'home'; break; + case '[2~': key.name = 'insert'; break; + case '[3~': key.name = 'delete'; break; + case '[4~': key.name = 'end'; break; + case '[5~': key.name = 'pageup'; break; + case '[6~': key.name = 'pagedown'; break; + + /* putty */ + case '[[5~': key.name = 'pageup'; break; + case '[[6~': key.name = 'pagedown'; break; + + /* rxvt */ + case '[7~': key.name = 'home'; break; + case '[8~': key.name = 'end'; break; + + /* rxvt keys with modifiers */ + case '[a': key.name = 'up'; key.shift = true; break; + case '[b': key.name = 'down'; key.shift = true; break; + case '[c': key.name = 'right'; key.shift = true; break; + case '[d': key.name = 'left'; key.shift = true; break; + case '[e': key.name = 'clear'; key.shift = true; break; + + case '[2$': key.name = 'insert'; key.shift = true; break; + case '[3$': key.name = 'delete'; key.shift = true; break; + case '[5$': key.name = 'pageup'; key.shift = true; break; + case '[6$': key.name = 'pagedown'; key.shift = true; break; + case '[7$': key.name = 'home'; key.shift = true; break; + case '[8$': key.name = 'end'; key.shift = true; break; + + case 'Oa': key.name = 'up'; key.ctrl = true; break; + case 'Ob': key.name = 'down'; key.ctrl = true; break; + case 'Oc': key.name = 'right'; key.ctrl = true; break; + case 'Od': key.name = 'left'; key.ctrl = true; break; + case 'Oe': key.name = 'clear'; key.ctrl = true; break; + + case '[2^': key.name = 'insert'; key.ctrl = true; break; + case '[3^': key.name = 'delete'; key.ctrl = true; break; + case '[5^': key.name = 'pageup'; key.ctrl = true; break; + case '[6^': key.name = 'pagedown'; key.ctrl = true; break; + case '[7^': key.name = 'home'; key.ctrl = true; break; + case '[8^': key.name = 'end'; key.ctrl = true; break; + + /* misc. */ + case '[Z': key.name = 'tab'; key.shift = true; break; + default: key.name = 'undefined'; break; + + } + } else if (s.length > 1 && s[0] !== '\x1b') { + // Got a longer-than-one string of characters. + // Probably a paste, since it wasn't a control sequence. + Array.prototype.forEach.call(s, function(c) { + emitKey(stream, c); + }); + return; + } + + if (key.code == '[M') { + key.name = 'mouse'; + var s = key.sequence; + var b = s.charCodeAt(3); + key.x = s.charCodeAt(4) - 040; + key.y = s.charCodeAt(5) - 040; + + key.scroll = 0; + + key.ctrl = !!(1<<4 & b); + key.meta = !!(1<<3 & b); + key.shift = !!(1<<2 & b); + + key.release = (3 & b) === 3; + + if (1<<6 & b) { //scroll + key.scroll = 1 & b ? 1 : -1; + } + + if (!key.release && !key.scroll) { + key.button = b & 3; + } + } + + // Don't emit a key if no name was found + if (key.name === undefined) { + key = undefined; + } + + if (s.length === 1) { + ch = s; + } + + if (key && key.name == 'mouse') { + stream.emit('mousepress', key) + } else if (key || ch) { + stream.emit('keypress', ch, key); + } +} diff --git a/node_modules/minstache/node_modules/commander/node_modules/keypress/package.json b/node_modules/minstache/node_modules/commander/node_modules/keypress/package.json new file mode 100644 index 0000000..c546205 --- /dev/null +++ b/node_modules/minstache/node_modules/commander/node_modules/keypress/package.json @@ -0,0 +1,32 @@ +{ + "name": "keypress", + "version": "0.1.0", + "description": "Make any Node ReadableStream emit \"keypress\" events", + "author": { + "name": "Nathan Rajlich", + "email": "nathan@tootallnate.net", + "url": "http://tootallnate.net" + }, + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git://github.com/TooTallNate/keypress.git" + }, + "keywords": [ + "keypress", + "readline", + "core" + ], + "license": "MIT", + "readme": "keypress\n========\n### Make any Node ReadableStream emit \"keypress\" events\n\n\nPrevious to Node `v0.8.x`, there was an undocumented `\"keypress\"` event that\n`process.stdin` would emit when it was a TTY. Some people discovered this hidden\ngem, and started using it in their own code.\n\nNow in Node `v0.8.x`, this `\"keypress\"` event does not get emitted by default,\nbut rather only when it is being used in conjuction with the `readline` (or by\nextension, the `repl`) module.\n\nThis module is the exact logic from the node `v0.8.x` releases ripped out into its\nown module.\n\n__Bonus:__ Now with mouse support!\n\nInstallation\n------------\n\nInstall with `npm`:\n\n``` bash\n$ npm install keypress\n```\n\nOr add it to the `\"dependencies\"` section of your _package.json_ file.\n\n\nExample\n-------\n\n#### Listening for \"keypress\" events\n\n``` js\nvar keypress = require('keypress');\n\n// make `process.stdin` begin emitting \"keypress\" events\nkeypress(process.stdin);\n\n// listen for the \"keypress\" event\nprocess.stdin.on('keypress', function (ch, key) {\n console.log('got \"keypress\"', key);\n if (key && key.ctrl && key.name == 'c') {\n process.stdin.pause();\n }\n});\n\nprocess.stdin.setRawMode(true);\nprocess.stdin.resume();\n```\n\n#### Listening for \"mousepress\" events\n\n``` js\nvar keypress = require('keypress');\n\n// make `process.stdin` begin emitting \"mousepress\" (and \"keypress\") events\nkeypress(process.stdin);\n\n// you must enable the mouse events before they will begin firing\nkeypress.enableMouse(process.stdout);\n\nprocess.stdin.on('mousepress', function (info) {\n console.log('got \"mousepress\" event at %d x %d', info.x, info.y);\n});\n\nprocess.on('exit', function () {\n // disable mouse on exit, so that the state\n // is back to normal for the terminal\n keypress.disableMouse(process.stdout);\n});\n```\n\n\nLicense\n-------\n\n(The MIT License)\n\nCopyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/TooTallNate/keypress/issues" + }, + "homepage": "https://github.com/TooTallNate/keypress", + "_id": "keypress@0.1.0", + "_from": "keypress@0.1.x" +} diff --git a/node_modules/minstache/node_modules/commander/node_modules/keypress/test.js b/node_modules/minstache/node_modules/commander/node_modules/keypress/test.js new file mode 100644 index 0000000..c3f61d7 --- /dev/null +++ b/node_modules/minstache/node_modules/commander/node_modules/keypress/test.js @@ -0,0 +1,28 @@ + +var keypress = require('./') +keypress(process.stdin) + +if (process.stdin.setRawMode) + process.stdin.setRawMode(true) +else + require('tty').setRawMode(true) + +process.stdin.on('keypress', function (c, key) { + console.log(0, c, key) + if (key && key.ctrl && key.name == 'c') { + process.stdin.pause() + } +}) +process.stdin.on('mousepress', function (mouse) { + console.log(mouse) +}) + +keypress.enableMouse(process.stdout) +process.on('exit', function () { + //disable mouse on exit, so that the state is back to normal + //for the terminal. + keypress.disableMouse(process.stdout) +}) + +process.stdin.resume() + diff --git a/node_modules/minstache/node_modules/commander/package.json b/node_modules/minstache/node_modules/commander/package.json new file mode 100644 index 0000000..ba140e8 --- /dev/null +++ b/node_modules/minstache/node_modules/commander/package.json @@ -0,0 +1,45 @@ +{ + "name": "commander", + "version": "1.0.4", + "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": "https://github.com/visionmedia/commander.js.git" + }, + "dependencies": { + "keypress": "0.1.x" + }, + "devDependencies": { + "should": ">= 0.0.1" + }, + "scripts": { + "test": "make test" + }, + "main": "index", + "engines": { + "node": ">= 0.6.x" + }, + "readme": "# Commander.js\n\n The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/visionmedia/commander).\n\n [![Build Status](https://secure.travis-ci.org/visionmedia/commander.js.png)](http://travis-ci.org/visionmedia/commander.js)\n\n## Installation\n\n $ npm install commander\n\n## Option parsing\n\n 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.\n\n```js\n#!/usr/bin/env node\n\n/**\n * Module dependencies.\n */\n\nvar program = require('commander');\n\nprogram\n .version('0.0.1')\n .option('-p, --peppers', 'Add peppers')\n .option('-P, --pineapple', 'Add pineapple')\n .option('-b, --bbq', 'Add bbq sauce')\n .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble')\n .parse(process.argv);\n\nconsole.log('you ordered a pizza with:');\nif (program.peppers) console.log(' - peppers');\nif (program.pineapple) console.log(' - pineappe');\nif (program.bbq) console.log(' - bbq');\nconsole.log(' - %s cheese', program.cheese);\n```\n\n 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.\n\n## Automated --help\n\n The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free:\n\n``` \n $ ./examples/pizza --help\n\n Usage: pizza [options]\n\n Options:\n\n -V, --version output the version number\n -p, --peppers Add peppers\n -P, --pineapple Add pineappe\n -b, --bbq Add bbq sauce\n -c, --cheese Add the specified type of cheese [marble]\n -h, --help output usage information\n\n```\n\n## Coercion\n\n```js\nfunction range(val) {\n return val.split('..').map(Number);\n}\n\nfunction list(val) {\n return val.split(',');\n}\n\nprogram\n .version('0.0.1')\n .usage('[options] ')\n .option('-i, --integer ', 'An integer argument', parseInt)\n .option('-f, --float ', 'A float argument', parseFloat)\n .option('-r, --range ..', 'A range', range)\n .option('-l, --list ', 'A list', list)\n .option('-o, --optional [value]', 'An optional value')\n .parse(process.argv);\n\nconsole.log(' int: %j', program.integer);\nconsole.log(' float: %j', program.float);\nconsole.log(' optional: %j', program.optional);\nprogram.range = program.range || [];\nconsole.log(' range: %j..%j', program.range[0], program.range[1]);\nconsole.log(' list: %j', program.list);\nconsole.log(' args: %j', program.args);\n```\n\n## Custom help\n\n You can display arbitrary `-h, --help` information\n by listening for \"--help\". Commander will automatically\n exit once you are done so that the remainder of your program\n does not execute causing undesired behaviours, for example\n in the following executable \"stuff\" will not output when\n `--help` is used.\n\n```js\n#!/usr/bin/env node\n\n/**\n * Module dependencies.\n */\n\nvar program = require('../');\n\nfunction list(val) {\n return val.split(',').map(Number);\n}\n\nprogram\n .version('0.0.1')\n .option('-f, --foo', 'enable some foo')\n .option('-b, --bar', 'enable some bar')\n .option('-B, --baz', 'enable some baz');\n\n// must be before .parse() since\n// node's emit() is immediate\n\nprogram.on('--help', function(){\n console.log(' Examples:');\n console.log('');\n console.log(' $ custom-help --help');\n console.log(' $ custom-help -h');\n console.log('');\n});\n\nprogram.parse(process.argv);\n\nconsole.log('stuff');\n```\n\nyielding the following help output:\n\n```\n\nUsage: custom-help [options]\n\nOptions:\n\n -h, --help output usage information\n -V, --version output the version number\n -f, --foo enable some foo\n -b, --bar enable some bar\n -B, --baz enable some baz\n\nExamples:\n\n $ custom-help --help\n $ custom-help -h\n\n```\n\n## .prompt(msg, fn)\n\n Single-line prompt:\n\n```js\nprogram.prompt('name: ', function(name){\n console.log('hi %s', name);\n});\n```\n\n Multi-line prompt:\n\n```js\nprogram.prompt('description:', function(name){\n console.log('hi %s', name);\n});\n```\n\n Coercion:\n\n```js\nprogram.prompt('Age: ', Number, function(age){\n console.log('age: %j', age);\n});\n```\n\n```js\nprogram.prompt('Birthdate: ', Date, function(date){\n console.log('date: %s', date);\n});\n```\n\n## .password(msg[, mask], fn)\n\nPrompt for password without echoing:\n\n```js\nprogram.password('Password: ', function(pass){\n console.log('got \"%s\"', pass);\n process.stdin.destroy();\n});\n```\n\nPrompt for password with mask char \"*\":\n\n```js\nprogram.password('Password: ', '*', function(pass){\n console.log('got \"%s\"', pass);\n process.stdin.destroy();\n});\n```\n\n## .confirm(msg, fn)\n\n Confirm with the given `msg`:\n\n```js\nprogram.confirm('continue? ', function(ok){\n console.log(' got %j', ok);\n});\n```\n\n## .choose(list, fn)\n\n Let the user choose from a `list`:\n\n```js\nvar list = ['tobi', 'loki', 'jane', 'manny', 'luna'];\n\nconsole.log('Choose the coolest pet:');\nprogram.choose(list, function(i){\n console.log('you chose %d \"%s\"', i, list[i]);\n});\n```\n\n## Links\n\n - [API documentation](http://visionmedia.github.com/commander.js/)\n - [ascii tables](https://github.com/LearnBoost/cli-table)\n - [progress bars](https://github.com/visionmedia/node-progress)\n - [more progress bars](https://github.com/substack/node-multimeter)\n - [examples](https://github.com/visionmedia/commander.js/tree/master/examples)\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", + "readmeFilename": "Readme.md", + "bugs": { + "url": "https://github.com/visionmedia/commander.js/issues" + }, + "homepage": "https://github.com/visionmedia/commander.js", + "_id": "commander@1.0.4", + "dist": { + "shasum": "80244c63741c7c89eaf13ef21c5b9c035c46d0a5" + }, + "_from": "commander@1.0.4", + "_resolved": "https://registry.npmjs.org/commander/-/commander-1.0.4.tgz" +} diff --git a/node_modules/minstache/package.json b/node_modules/minstache/package.json new file mode 100644 index 0000000..35bba1b --- /dev/null +++ b/node_modules/minstache/package.json @@ -0,0 +1,33 @@ +{ + "name": "minstache", + "version": "1.1.0", + "description": "Mini mustache template engine", + "keywords": [ + "mustache", + "template", + "engine" + ], + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "dependencies": { + "commander": "1.0.4" + }, + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "bin": { + "minstache": "bin/minstache" + }, + "main": "index", + "readme": "\n# minstache\n\n Mini mustache template engine.\n\n## Installation\n\n $ npm install minstache\n $ component install visionmedia/minstache\n\n## minstache(1)\n\n The `minstache(1)` executable can compile a file to a valid\n stand-alone commonjs module for you, there's no need to have minstache\n as a dependency:\n\n hello.mustache:\n\n```\nHello {{name}}! {{^authenticated}}login{{/authenticated}}\n```\n\n convert it:\n\n```\n$ minstache < hello.mustache > hello.js\n```\n\n hello.js:\n\n```js\nmodule.exports = function anonymous(obj) {\n\n function escape(html) {\n return String(html)\n .replace(/&/g, '&')\n .replace(/\"/g, '"')\n .replace(//g, '>');\n };\n\n function section(obj, prop, negate, str) {\n var val = obj[prop];\n if ('function' == typeof val) return val.call(obj, str);\n if (negate) val = !val;\n if (val) return str;\n return '';\n };\n\n return \"Hello \" + escape(obj.name) + \"! \" + section(obj, \"authenticated\", true, \"login\") + \"\\n\"\n}\n```\n\n## API\n\n### minstache(string, [obj])\n\n Compile and render the given mustache `string` with optional context `obj`.\n\n### minstache.compile(string)\n\n Compile the mustache `string` to a stand-alone `Function` accepting a context `obj`.\n\n## Divergence\n\n Partials are not supported, this lib is meant to be a small template engine solution for stand-alone [component](http://github.com/component) templates. If your template takes \"partials\" then pass other rendered strings to it. If you need a full-blown mustache solution Hogan.js is still great.\n\n Minstache uses `{{!name}}` for unescaped properties.\n\n## License\n\n MIT\n", + "readmeFilename": "Readme.md", + "_id": "minstache@1.1.0", + "dist": { + "shasum": "12bd3a63cc055cba3a59d7925c3982a5c5f463f4" + }, + "_from": "minstache@", + "_resolved": "https://registry.npmjs.org/minstache/-/minstache-1.1.0.tgz" +} diff --git a/pg.js b/pg.js new file mode 100644 index 0000000..f33b4ef --- /dev/null +++ b/pg.js @@ -0,0 +1,28 @@ +var dot = require('dot'); + +dot.templateSettings = { + evaluate: /\{\{([\s\S]+?)\}\}/g, + interpolate: /\{\{=([\s\S]+?)\}\}/g, + encode: /\{\{!([\s\S]+?)\}\}/g, + use: /\{\{#([\s\S]+?)\}\}/g, + define: /\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g, + conditional: /\{\{\?(\?)?\s*([\s\S]*?)\s*\}\}/g, + iterate: /\{\{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/g, + varname: 'it', + strip: false, + append: true, + selfcontained: false +}; + +var ban = dot.template('' + + 'CBitStream@ = @CBitStream;' + + '{{ for(var key in it) { }}'+ + 'Key: {{=key}} Value = {{=it[key]}}\n'+ + '{{ } }}' + + 'SendCommandOnlyServer(1,)'); + +console.log(ban({ + str : 3, + agi : 5, + lvl : 8 +} )); \ No newline at end of file From c5d913522fd31324856716cf3841cfb638f09ecb Mon Sep 17 00:00:00 2001 From: nitreo Date: Fri, 9 May 2014 17:22:17 +0200 Subject: [PATCH 2/4] reps+players --- mods/players/index.js | 158 +++++++++++++++++++++++------------------- mods/repl/index.js | 12 ++++ 2 files changed, 100 insertions(+), 70 deletions(-) create mode 100644 mods/repl/index.js diff --git a/mods/players/index.js b/mods/players/index.js index f252dc3..7b17a78 100644 --- a/mods/players/index.js +++ b/mods/players/index.js @@ -15,79 +15,17 @@ Parser.onRegex( "[\\s]+" + "\\(hwid\\s(? [\\d]+)", function (player,id,ip,hwid) { - //If player is here, wr should update instead of creating a new object - var playerObject = { - login: player, - id: id, - ip: ip, - hwid: hwid, - - /** - * Description - * @method kick - * @return - */ - kick : function(){ - Commands.kick(this.id); - }, - /** - * Description - * @method ban - * @param {} time - * @return - */ - ban : function(time){ - Commands.ban(this.id,time); - }, - /** - * Description - * @method mute - * @param {} time - * @return - */ - mute : function(time){ - Commands.mute(this.id); - }, - /** - * Description - * @method freeze - * @return - */ - freeze : function(){ - Commands.freeze(this.id); - }, - /** - * Description - * @method unfreeze - * @return - */ - unfreeze : function(){ - Commands.unfreeze(this.id); - }, - /** - * Description - * @method unban - * @return - */ - unban : function(){ - Commands.unban(this.id); - }, - /** - * Description - * @method unmute - * @return - */ - unmute : function(){ - Commands.unmute(this.id); - } - }; if(!players[player]){ - players[player] = playerObject; - GameEvents.emit('player_connect',player,playerObject); + players[player] = new PlayerObject(player,id,ip,hwid); + GameEvents.emit('player_connect',player,players[player]); + } else { + players[player].login = player; + players[player].id= id; + players[player].ip= ip; + players[player].hwid= hwid; } - players[player] = playerObject; - GameEvents.emit('player_update',player, playerObject); + GameEvents.emit('player_update',player, players[player]); } ); @@ -112,4 +50,84 @@ Parser.onRegex( } ); +Parser.onRegex( + "^(? [\\w-]+)" + + "[\\s]+ changed \\s team \\s from" + + "(? [\\d]+)" + + "\\s to" + + "(? [\\d]+)", + function (player,oldteam,newteam) { + players[player].team = newteam; + GameEvents.emit('player_changed_team',player,oldteam,newteam); + } +); + + +var PlayerObject = function PlayerObject(login,id,ip,hwid){ + this.login = login, + this.id = id, + this.ip = ip, + this.hwid = hwid, + this.team = 255; + /** + * Description + * @method kick + * @return + */ + this.kick = function(){ + Commands.kick(this.id); + }, + /** + * Description + * @method ban + * @param {} time + * @return + */ + this.ban = function(time){ + Commands.ban(this.id,time); + }, + /** + * Description + * @method mute + * @param {} time + * @return + */ + this.mute = function(time){ + Commands.mute(this.id); + }, + /** + * Description + * @method freeze + * @return + */ + this.freeze = function(){ + Commands.freeze(this.id); + }, + /** + * Description + * @method unfreeze + * @return + */ + this.unfreeze = function(){ + Commands.unfreeze(this.id); + }, + /** + * Description + * @method unban + * @return + */ + this.unban = function(){ + Commands.unban(this.id); + }, + /** + * Description + * @method unmute + * @return + */ + this.unmute = function(){ + Commands.unmute(this.id); + } +}; + + global.Players = players; \ No newline at end of file diff --git a/mods/repl/index.js b/mods/repl/index.js new file mode 100644 index 0000000..491e26a --- /dev/null +++ b/mods/repl/index.js @@ -0,0 +1,12 @@ +GameEvents.on("connect",function(){ + var repl = require('repl'); + var replServer = repl.start({ + prompt: " > ", + input: process.stdin, + output: process.stdout, + useGlobal: true + }); + replServer.on('exit', function() { + console.log("Bye!"); + }); +}) \ No newline at end of file From 1e8ef3363cdac7f5751479556e95c767b5db5b69 Mon Sep 17 00:00:00 2001 From: nitreo Date: Fri, 9 May 2014 18:02:39 +0200 Subject: [PATCH 3/4] team regex hotfix --- mods/players/index.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/mods/players/index.js b/mods/players/index.js index 7b17a78..4d5a779 100644 --- a/mods/players/index.js +++ b/mods/players/index.js @@ -52,17 +52,16 @@ Parser.onRegex( Parser.onRegex( "^(? [\\w-]+)" + - "[\\s]+ changed \\s team \\s from" + + "[\\s]+changed[\\s]+team[\\s]+from[\\s]+" + "(? [\\d]+)" + - "\\s to" + - "(? [\\d]+)", + "[\\s]+to[\\s]+" + + "(? [\\d]+) .*", function (player,oldteam,newteam) { players[player].team = newteam; GameEvents.emit('player_changed_team',player,oldteam,newteam); } ); - var PlayerObject = function PlayerObject(login,id,ip,hwid){ this.login = login, this.id = id, From f6e27e1ec52891f5afc6ac3bad0d4e7fb0006e13 Mon Sep 17 00:00:00 2001 From: nitreo Date: Fri, 9 May 2014 19:12:33 +0200 Subject: [PATCH 4/4] Ugly hotfix for initial team parsing --- kscript2.sh | 2 +- lib/services/parser.js | 1 - mods/players/index.js | 32 +++++++++++++++++++++++++++++++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/kscript2.sh b/kscript2.sh index d5b3272..06276ab 100755 --- a/kscript2.sh +++ b/kscript2.sh @@ -1,2 +1,2 @@ -#!/bin/bash + #!/bin/bash ./node/bin/node app.js $@ \ No newline at end of file diff --git a/lib/services/parser.js b/lib/services/parser.js index 0ab9e2a..c945dd9 100644 --- a/lib/services/parser.js +++ b/lib/services/parser.js @@ -168,7 +168,6 @@ function Parser() { for (var prop in content) { if (!typeof prop == 'object' || !content.hasOwnProperty(prop)) delete content[prop]; } - console.dir(content); composite.results = composite.results || []; composite.results.push(content); } diff --git a/mods/players/index.js b/mods/players/index.js index 4d5a779..2713785 100644 --- a/mods/players/index.js +++ b/mods/players/index.js @@ -1,8 +1,9 @@ var players = {}; var playerCount = 0; - +var teamsInitialized = false; GameEvents.on("connect",function(){ RCON.send("/players"); + }) Parser.onRegex( @@ -26,9 +27,38 @@ Parser.onRegex( players[player].hwid= hwid; } GameEvents.emit('player_update',player, players[player]); + + if(!teamsInitialized){ + setTimeout(function(){ + RCON.send('print("LISTING TEAMS");'); + + for(var p in players){ + //Ultra shit. + RCON.send('print("'+ p +' : "+getPlayerByUsername("'+ p+'").getTeamNum());'); + } + RCON.send('print("END LISTING TEAMS");'); + + },1000); + teamsInitialized = true; + } + } ); +Parser.onComposition({ + start:"^LISTING[\\s]TEAMS", + content:"(? [\\w-]+) [\\s]+ : [\\s]+(? [\\d]+)", + end:"^END[\\s]LISTING[\\s]TEAMS" + +},function(pairs){ + console.log('got pairs'); + for (var i = 0; i < pairs.length; i++) { + var obj = pairs[i]; + players[obj.player].team = obj.team + console.log(players[obj.player].login +" is set to "+obj.team); + } +}) + Parser.onRegex( "^(?:\\*\\s)?" + "(? [\\w-]+)" +