--- /dev/null
+/*
+colors.js
+
+Copyright (c) 2010
+
+Marak Squires
+Alexis Sellier (cloudhead)
+
+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.
+
+*/
+
+var isHeadless = false;
+
+if (typeof module !== 'undefined') {
+ isHeadless = true;
+}
+
+if (!isHeadless) {
+ var exports = {};
+ var module = {};
+ var colors = exports;
+ exports.mode = "browser";
+} else {
+ exports.mode = "console";
+}
+
+//
+// Prototypes the string object to have additional method calls that add terminal colors
+//
+var addProperty = function (color, func) {
+ exports[color] = function (str) {
+ return func.apply(str);
+ };
+ String.prototype.__defineGetter__(color, func);
+};
+
+function stylize(str, style) {
+
+ var styles;
+
+ if (exports.mode === 'console') {
+ styles = {
+ //styles
+ 'bold' : ['\x1B[1m', '\x1B[22m'],
+ 'italic' : ['\x1B[3m', '\x1B[23m'],
+ 'underline' : ['\x1B[4m', '\x1B[24m'],
+ 'inverse' : ['\x1B[7m', '\x1B[27m'],
+ 'strikethrough' : ['\x1B[9m', '\x1B[29m'],
+ //text colors
+ //grayscale
+ 'white' : ['\x1B[37m', '\x1B[39m'],
+ 'grey' : ['\x1B[90m', '\x1B[39m'],
+ 'black' : ['\x1B[30m', '\x1B[39m'],
+ //colors
+ 'blue' : ['\x1B[34m', '\x1B[39m'],
+ 'cyan' : ['\x1B[36m', '\x1B[39m'],
+ 'green' : ['\x1B[32m', '\x1B[39m'],
+ 'magenta' : ['\x1B[35m', '\x1B[39m'],
+ 'red' : ['\x1B[31m', '\x1B[39m'],
+ 'yellow' : ['\x1B[33m', '\x1B[39m'],
+ //background colors
+ //grayscale
+ 'whiteBG' : ['\x1B[47m', '\x1B[49m'],
+ 'greyBG' : ['\x1B[49;5;8m', '\x1B[49m'],
+ 'blackBG' : ['\x1B[40m', '\x1B[49m'],
+ //colors
+ 'blueBG' : ['\x1B[44m', '\x1B[49m'],
+ 'cyanBG' : ['\x1B[46m', '\x1B[49m'],
+ 'greenBG' : ['\x1B[42m', '\x1B[49m'],
+ 'magentaBG' : ['\x1B[45m', '\x1B[49m'],
+ 'redBG' : ['\x1B[41m', '\x1B[49m'],
+ 'yellowBG' : ['\x1B[43m', '\x1B[49m']
+ };
+ } else if (exports.mode === 'browser') {
+ styles = {
+ //styles
+ 'bold' : ['<b>', '</b>'],
+ 'italic' : ['<i>', '</i>'],
+ 'underline' : ['<u>', '</u>'],
+ 'inverse' : ['<span style="background-color:black;color:white;">', '</span>'],
+ 'strikethrough' : ['<del>', '</del>'],
+ //text colors
+ //grayscale
+ 'white' : ['<span style="color:white;">', '</span>'],
+ 'grey' : ['<span style="color:gray;">', '</span>'],
+ 'black' : ['<span style="color:black;">', '</span>'],
+ //colors
+ 'blue' : ['<span style="color:blue;">', '</span>'],
+ 'cyan' : ['<span style="color:cyan;">', '</span>'],
+ 'green' : ['<span style="color:green;">', '</span>'],
+ 'magenta' : ['<span style="color:magenta;">', '</span>'],
+ 'red' : ['<span style="color:red;">', '</span>'],
+ 'yellow' : ['<span style="color:yellow;">', '</span>'],
+ //background colors
+ //grayscale
+ 'whiteBG' : ['<span style="background-color:white;">', '</span>'],
+ 'greyBG' : ['<span style="background-color:gray;">', '</span>'],
+ 'blackBG' : ['<span style="background-color:black;">', '</span>'],
+ //colors
+ 'blueBG' : ['<span style="background-color:blue;">', '</span>'],
+ 'cyanBG' : ['<span style="background-color:cyan;">', '</span>'],
+ 'greenBG' : ['<span style="background-color:green;">', '</span>'],
+ 'magentaBG' : ['<span style="background-color:magenta;">', '</span>'],
+ 'redBG' : ['<span style="background-color:red;">', '</span>'],
+ 'yellowBG' : ['<span style="background-color:yellow;">', '</span>']
+ };
+ } else if (exports.mode === 'none') {
+ return str + '';
+ } else {
+ console.log('unsupported mode, try "browser", "console" or "none"');
+ }
+ return styles[style][0] + str + styles[style][1];
+}
+
+function applyTheme(theme) {
+
+ //
+ // Remark: This is a list of methods that exist
+ // on String that you should not overwrite.
+ //
+ var stringPrototypeBlacklist = [
+ '__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', 'charAt', 'constructor',
+ 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf', 'charCodeAt',
+ 'indexOf', 'lastIndexof', 'length', 'localeCompare', 'match', 'replace', 'search', 'slice', 'split', 'substring',
+ 'toLocaleLowerCase', 'toLocaleUpperCase', 'toLowerCase', 'toUpperCase', 'trim', 'trimLeft', 'trimRight'
+ ];
+
+ Object.keys(theme).forEach(function (prop) {
+ if (stringPrototypeBlacklist.indexOf(prop) !== -1) {
+ console.log('warn: '.red + ('String.prototype' + prop).magenta + ' is probably something you don\'t want to override. Ignoring style name');
+ }
+ else {
+ if (typeof(theme[prop]) === 'string') {
+ addProperty(prop, function () {
+ return exports[theme[prop]](this);
+ });
+ }
+ else {
+ addProperty(prop, function () {
+ var ret = this;
+ for (var t = 0; t < theme[prop].length; t++) {
+ ret = exports[theme[prop][t]](ret);
+ }
+ return ret;
+ });
+ }
+ }
+ });
+}
+
+
+//
+// Iterate through all default styles and colors
+//
+var x = ['bold', 'underline', 'strikethrough', 'italic', 'inverse', 'grey', 'black', 'yellow', 'red', 'green', 'blue', 'white', 'cyan', 'magenta', 'greyBG', 'blackBG', 'yellowBG', 'redBG', 'greenBG', 'blueBG', 'whiteBG', 'cyanBG', 'magentaBG'];
+x.forEach(function (style) {
+
+ // __defineGetter__ at the least works in more browsers
+ // http://robertnyman.com/javascript/javascript-getters-setters.html
+ // Object.defineProperty only works in Chrome
+ addProperty(style, function () {
+ return stylize(this, style);
+ });
+});
+
+function sequencer(map) {
+ return function () {
+ if (!isHeadless) {
+ return this.replace(/( )/, '$1');
+ }
+ var exploded = this.split(""), i = 0;
+ exploded = exploded.map(map);
+ return exploded.join("");
+ };
+}
+
+var rainbowMap = (function () {
+ var rainbowColors = ['red', 'yellow', 'green', 'blue', 'magenta']; //RoY G BiV
+ return function (letter, i, exploded) {
+ if (letter === " ") {
+ return letter;
+ } else {
+ return stylize(letter, rainbowColors[i++ % rainbowColors.length]);
+ }
+ };
+})();
+
+exports.themes = {};
+
+exports.addSequencer = function (name, map) {
+ addProperty(name, sequencer(map));
+};
+
+exports.addSequencer('rainbow', rainbowMap);
+exports.addSequencer('zebra', function (letter, i, exploded) {
+ return i % 2 === 0 ? letter : letter.inverse;
+});
+
+exports.setTheme = function (theme) {
+ if (typeof theme === 'string') {
+ try {
+ exports.themes[theme] = require(theme);
+ applyTheme(exports.themes[theme]);
+ return exports.themes[theme];
+ } catch (err) {
+ console.log(err);
+ return err;
+ }
+ } else {
+ applyTheme(theme);
+ }
+};
+
+
+addProperty('stripColors', function () {
+ return ("" + this).replace(/\x1B\[\d+m/g, '');
+});
+
+// please no
+function zalgo(text, options) {
+ var soul = {
+ "up" : [
+ '̍', '̎', '̄', '̅',
+ '̿', '̑', '̆', '̐',
+ '͒', '͗', '͑', '̇',
+ '̈', '̊', '͂', '̓',
+ '̈', '͊', '͋', '͌',
+ '̃', '̂', '̌', '͐',
+ '̀', '́', '̋', '̏',
+ '̒', '̓', '̔', '̽',
+ '̉', 'ͣ', 'ͤ', 'ͥ',
+ 'ͦ', 'ͧ', 'ͨ', 'ͩ',
+ 'ͪ', 'ͫ', 'ͬ', 'ͭ',
+ 'ͮ', 'ͯ', '̾', '͛',
+ '͆', '̚'
+ ],
+ "down" : [
+ '̖', '̗', '̘', '̙',
+ '̜', '̝', '̞', '̟',
+ '̠', '̤', '̥', '̦',
+ '̩', '̪', '̫', '̬',
+ '̭', '̮', '̯', '̰',
+ '̱', '̲', '̳', '̹',
+ '̺', '̻', '̼', 'ͅ',
+ '͇', '͈', '͉', '͍',
+ '͎', '͓', '͔', '͕',
+ '͖', '͙', '͚', '̣'
+ ],
+ "mid" : [
+ '̕', '̛', '̀', '́',
+ '͘', '̡', '̢', '̧',
+ '̨', '̴', '̵', '̶',
+ '͜', '͝', '͞',
+ '͟', '͠', '͢', '̸',
+ '̷', '͡', ' ҉'
+ ]
+ },
+ all = [].concat(soul.up, soul.down, soul.mid),
+ zalgo = {};
+
+ function randomNumber(range) {
+ var r = Math.floor(Math.random() * range);
+ return r;
+ }
+
+ function is_char(character) {
+ var bool = false;
+ all.filter(function (i) {
+ bool = (i === character);
+ });
+ return bool;
+ }
+
+ function heComes(text, options) {
+ var result = '', counts, l;
+ options = options || {};
+ options["up"] = options["up"] || true;
+ options["mid"] = options["mid"] || true;
+ options["down"] = options["down"] || true;
+ options["size"] = options["size"] || "maxi";
+ text = text.split('');
+ for (l in text) {
+ if (is_char(l)) {
+ continue;
+ }
+ result = result + text[l];
+ counts = {"up" : 0, "down" : 0, "mid" : 0};
+ switch (options.size) {
+ case 'mini':
+ counts.up = randomNumber(8);
+ counts.min = randomNumber(2);
+ counts.down = randomNumber(8);
+ break;
+ case 'maxi':
+ counts.up = randomNumber(16) + 3;
+ counts.min = randomNumber(4) + 1;
+ counts.down = randomNumber(64) + 3;
+ break;
+ default:
+ counts.up = randomNumber(8) + 1;
+ counts.mid = randomNumber(6) / 2;
+ counts.down = randomNumber(8) + 1;
+ break;
+ }
+
+ var arr = ["up", "mid", "down"];
+ for (var d in arr) {
+ var index = arr[d];
+ for (var i = 0 ; i <= counts[index]; i++) {
+ if (options[index]) {
+ result = result + soul[index][randomNumber(soul[index].length)];
+ }
+ }
+ }
+ }
+ return result;
+ }
+ return heComes(text);
+}
+
+
+// don't summon zalgo
+addProperty('zalgo', function () {
+ return zalgo(this);
+});