From 42918337e5503c1ec358f485dcd2cc295214b5f9 Mon Sep 17 00:00:00 2001 From: Sean McArthur Date: Tue, 8 Jul 2014 20:43:54 -0700 Subject: [PATCH] return a new function for each getter - defines the getters onto a proto - the function returned has its __proto__ set to our proto fixes #32 --- .jshintrc | 1 + benchmark.js | 5 +++++ index.js | 23 +++++++++++++++++------ test.js | 11 +++++++++++ 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/.jshintrc b/.jshintrc index c511975..3e1760c 100644 --- a/.jshintrc +++ b/.jshintrc @@ -9,6 +9,7 @@ "indent": 4, "newcap": true, "noarg": true, + "proto": true, "quotmark": "single", "undef": true, "unused": "vars", diff --git a/benchmark.js b/benchmark.js index da9ed8d..ce3f2c4 100644 --- a/benchmark.js +++ b/benchmark.js @@ -11,6 +11,11 @@ suite('chalk', function () { chalk.blue.bgRed.bold('the fox jumps over the lazy dog'); }); + var cached = chalk.blue.bgRed.bold; + bench('cached styles', function () { + cached('the fox jumps over the lazy dog'); + }); + bench('nested styles', function () { chalk.red('the fox jumps', chalk.underline.bgBlue('over the lazy dog') + '!'); }); diff --git a/index.js b/index.js index bc19485..b512746 100644 --- a/index.js +++ b/index.js @@ -7,6 +7,17 @@ var supportsColor = require('supports-color'); var defineProps = Object.defineProperties; var chalk = module.exports; +function build(_styles) { + var builder = function builder() { + return applyStyle.apply(builder, arguments); + }; + builder._styles = _styles; + // __proto__ is used because we must return a function, but there is + // no way to create a function with a different prototype. + builder.__proto__ = proto; + return builder; +} + var styles = (function () { var ret = {}; @@ -17,8 +28,7 @@ var styles = (function () { ret[key] = { get: function () { - this._styles.push(key); - return this; + return build(this._styles.concat(key)); } }; }); @@ -26,6 +36,8 @@ var styles = (function () { return ret; })(); +var proto = defineProps(function chalk() {}, styles); + function applyStyle() { // support varags, but simply cast to string in case there's only one arg var str = arguments.length === 1 ? String(arguments[0]) : [].slice.call(arguments).join(' '); @@ -34,7 +46,8 @@ function applyStyle() { return str; } - var nestedStyles = applyStyle._styles; + /*jshint validthis: true*/ + var nestedStyles = this._styles; for (var i = 0; i < nestedStyles.length; i++) { var code = ansiStyles[nestedStyles[i]]; @@ -51,11 +64,9 @@ function init() { var ret = {}; Object.keys(styles).forEach(function (name) { - var style = defineProps(applyStyle, styles); ret[name] = { get: function () { - style._styles = []; - return style[name]; + return build([name]); } }; }); diff --git a/test.js b/test.js index 5d588d4..3e073a6 100644 --- a/test.js +++ b/test.js @@ -32,6 +32,17 @@ describe('chalk', function () { assert.equal(chalk.reset(chalk.red.bgGreen.underline('foo') + 'foo'), '\u001b[0m\u001b[4m\u001b[42m\u001b[31mfoo\u001b[39m\u001b[49m\u001b[24mfoo\u001b[0m'); }); + it('should be able to cache multiple styles', function() { + var red = chalk.red; + var blue = chalk.blue; + var redBold = red.bold; + var blueBold = blue.bold; + + assert.notEqual(red('foo'), blue('foo')); + assert.notEqual(redBold('bar'), blueBold('bar')); + assert.notEqual(blue('baz'), blueBold('baz')); + }); + it('should alias gray to grey', function () { assert.equal(chalk.grey('foo'), '\u001b[90mfoo\u001b[39m'); });