diff --git a/.npmignore b/.npmignore index e0f6eb0..fdc151e 100644 --- a/.npmignore +++ b/.npmignore @@ -1,8 +1,8 @@ +*.sh +*.yml .* benchmark -bower_components bower.json -*.yml -compile +bower_components img test diff --git a/README.md b/README.md index b22c1bf..0b1319d 100644 --- a/README.md +++ b/README.md @@ -1,49 +1,73 @@ -# fast-format [![Circle CI](https://circleci.com/gh/knowledgecode/fast-format.svg?style=shield)](https://circleci.com/gh/knowledgecode/fast-format) -This is a simplified version of Node.js `util.format()`. This supports only `%s` placeholder, but faster than that. This will be the best solution if you need speed rather than complex formatting. +# fast-format +[![Circle CI](https://circleci.com/gh/knowledgecode/fast-format.svg?style=shield)](https://circleci.com/gh/knowledgecode/fast-format) + +This is a string formatter like `util.format()` method in Node.js, supports just only `%s` placeholder but accordingly faster than that. It will be one of the best solution if need a speed rather than complex formatting. ## Usage -Same as Node.js `util.format()`. +Same as `util.format()` method. ```js format(formatString[, ...]) ``` +If use one formatting repeatedly, recommended to compile the `formatString` in advance. +```js +format.compile(formatString) +``` + ## Example ```js -var s = format('%s, %s!', 'Hello', 'world'); +let s = format('%s, %s!', 'Hello', 'world'); console.log(s); // => 'Hello, world!' ``` +```js +let f = format.compile('%s, %s!'); +let s1 = f('Hello', 'world'); +console.log(s1); // => 'Hello, world!' +let s2 = f('Howdy', 'World'); +console.log(s2); // => 'Howdy, World!' +``` ## Benchmark ```js -var i, len, s = Date.now(); -for (i = 0, len = 10000000; i < len; i++) { +// Bench 1 +let s = Date.now(); +for (let i = 0, len = 100000000; i < len; i++) { format('i = %s, len = %s', i, len); } console.log(Date.now() - s); ``` +```js +// Bench 2 +let s = Date.now(); +let f = format.compile('i = %s, len = %s'); +for (let i = 0, len = 100000000; i < len; i++) { + f(i, len); +} +console.log(Date.now() - s); +``` -*environment1: MacBook Air Early 2015 + Node.js v0.12.5* +*environment1: Core i7 2.2GHz + Node.js v6.9.5* - + -| module | time | -|-------------|-------------| -| fast-format | 2,072 msec | -| util.format | 11,571 msec | -| sprintf-js | 19,438 msec | +| module | time | bench | +|-------------|-------------|:-----:| +| fast-format | 12,388 msec | 2 | +| fast-format | 22,039 msec | 1 | +| util.format | 28,659 msec | 1 | --- -*environment2: Core i7 2.5GHz Windows 8.1 Pro + Internet Explorer 11* +*environment2: Core i7 2.2GHz + Google Chrome 56.0.2924.87* - + -| module | time | -|-------------|-------------| -| fast-format | 25,302 msec | -| util.format | 40,550 msec | -| sprintf-js | 58,133 msec | +| module | time | bench | +|-------------|-------------|:-----:| +| fast-format | 12,898 msec | 2 | +| fast-format | 22,705 msec | 1 | +| util.format | 99,103 msec | 1 | -[sprintf-js](https://github.com/alexei/sprintf.js) is a JavaScript sprintf implementation for the browser and Node.js. It is slow but might not be inevitable because a high functional module. +The `util.format()` method was converted with `Browserify` to run on the browser. ## Installation ### via npm @@ -51,14 +75,18 @@ console.log(Date.now() - s); npm install fast-format --save ``` -### via bower +### via Bower ```sh bower install fast-format ``` +### directly (in case of the browser) +``` html + +``` + ## Browser Support -Chrome, Firefox, Safari, Opera, and Internet Explorer 6+ +Google Chrome, Firefox, Safari, Opera, Microsoft Edge and IE 6+ ## License MIT - diff --git a/bower.json b/bower.json index f6a6df7..8428f5d 100644 --- a/bower.json +++ b/bower.json @@ -1,12 +1,12 @@ { "name": "fast-format", "main": "fast-format.min.js", - "version": "0.1.1", + "version": "0.2.0", "homepage": "https://github.com/knowledgecode/fast-format", "authors": [ "knowledgecode " ], - "description": "A simplified version of Node.js util.format()", + "description": "A fast, simple string formatter like util.format() method in Node.js", "moduleType": [ "amd", "globals", @@ -15,11 +15,11 @@ "ignore": [ "**/.*", "bower_components", - "compile", "img", "node_modules", "test", "*.json", + "*.sh", "*.yml" ], "keywords": [ diff --git a/circle.yml b/circle.yml index 31badd0..e9bdad1 100644 --- a/circle.yml +++ b/circle.yml @@ -1,3 +1,3 @@ machine: node: - version: 0.12.0 + version: 6.1.0 diff --git a/compile b/compile.sh similarity index 61% rename from compile rename to compile.sh index 0a32904..df312cb 100755 --- a/compile +++ b/compile.sh @@ -1,9 +1,9 @@ #!/bin/sh -eu -url="http://closure-compiler.appspot.com/compile" +url="https://closure-compiler.appspot.com/compile" dir=`dirname $0` -input="${dir}/fast-format.js" -output="${dir}/fast-format.min.js" +input=${dir}/$1 +output=${dir}/$2 js_code=`cat $input` curl --silent \ diff --git a/fast-format.js b/fast-format.js index 6aa9576..80f8b00 100644 --- a/fast-format.js +++ b/fast-format.js @@ -1,17 +1,41 @@ /** - * @preserve fast-format.js (C) 2015 KNOWLEDGECODE | MIT + * @preserve fast-format.js (C) KNOWLEDGECODE | MIT */ (function (global) { 'use strict'; var f = function (format) { - var i, len, argc = arguments.length, v = (format + '').split('%s'), r = argc ? v[0] : ''; - for (i = 1, len = v.length, argc--; i < len; i++) { - r += (i > argc ? '%s' : arguments[i]) + v[i]; + var argc = arguments.length, v = (argc ? format + '' : '').split('%s'), i = 1, len = v.length, r = v[0]; + if (argc > len) { + argc = len; + } + while (i < argc) { + r += arguments[i] + v[i++]; + } + while (i < len) { + r += '%s' + v[i++]; } return r; }; + f.compile = function (format) { + var v = (arguments.length ? format + '' : '').split('%s'), len = v.length; + return function () { + var i = 0, argc = arguments.length, r = v[0]; + if (argc > len - 1) { + argc = len - 1; + } + while (i < argc) { + r += arguments[i] + v[++i]; + } + i++; + while (i < len) { + r += '%s' + v[i++]; + } + return r; + }; + }; + if (typeof module === 'object' && typeof module.exports === 'object') { module.exports = f; } else if (typeof global.define === 'function' && global.define.amd) { diff --git a/fast-format.min.js b/fast-format.min.js index 502b958..ecdbab7 100644 --- a/fast-format.min.js +++ b/fast-format.min.js @@ -1,4 +1,5 @@ /* - fast-format.js (C) 2015 KNOWLEDGECODE | MIT + fast-format.js (C) KNOWLEDGECODE | MIT */ -(function(a){var c=function(a){var b,c,d=arguments.length,e=(a+"").split("%s"),f=d?e[0]:"";b=1;c=e.length;for(d--;bd?"%s":arguments[b])+e[b];return f};"object"===typeof module&&"object"===typeof module.exports?module.exports=c:"function"===typeof a.define&&a.define.amd?a.define([],function(){return c}):a.format=c})(this); +(function(a){var f=function(a){var c=arguments.length,d=(c?a+"":"").split("%s"),b=1,g=d.length,e=d[0];for(c>g&&(c=g);bd-1&&(a=d-1);b - - - + + + - - fast-format - util.format - sprintf-js + + fast-format + + compile + fast-format + util.format - + 0 - 15,000 - 30,000 - 45,000 - 60,000 + 7,500 + 15,000 + 22,500 + 30,000 [msec] diff --git a/img/graph2.svg b/img/graph2.svg index 9f55bef..67b4864 100644 --- a/img/graph2.svg +++ b/img/graph2.svg @@ -30,22 +30,23 @@ - - - + + + - - fast-format - util.format - + browserify - sprintf-js + + fast-format + + compile + fast-format + util.format + + browserify - + 0 - 15,000 - 30,000 - 45,000 - 60,000 + 25,000 + 50,000 + 75,000 + 100,000 [msec] diff --git a/package.json b/package.json index 6e8ce74..2c14da1 100644 --- a/package.json +++ b/package.json @@ -1,19 +1,19 @@ { "name": "fast-format", - "version": "0.1.1", - "description": "A simplified version of Node.js util.format()", + "version": "0.2.0", + "description": "A fast, simple string formatter like util.format() method in Node.js", "main": "fast-format.js", "directories": { "test": "test" }, "devDependencies": { "expect.js": "^0.3.1", - "mocha": "^2.2.5", - "mocha-phantomjs": "^3.5.3" + "mocha": "^2.5.3", + "mocha-phantomjs": "^4.1.0" }, "scripts": { "test": "mocha test/test.js && mocha-phantomjs test/test.html", - "compile": "./compile" + "compile": "./compile.sh fast-format.js fast-format.min.js" }, "keywords": [ "fast", diff --git a/test/test.js b/test/test.js index eaecaa7..76074a5 100644 --- a/test/test.js +++ b/test/test.js @@ -73,5 +73,95 @@ }); }); -}(this)); + describe('format.compile', function () { + it('1 replace', function () { + var f = format.compile('%s'); + expect(f('hello')).to.eql('hello'); + }); + it('2 insert', function () { + var f = format.compile('%shello'); + expect(f('hello')).to.eql('hellohello'); + }); + it('3 append', function () { + var f = format.compile('hello%s'); + expect(f('hello')).to.eql('hellohello'); + }); + it('4 insert2', function () { + var f = format.compile('hello%shello'); + expect(f('hello')).to.eql('hellohellohello'); + }); + it('5 join', function () { + var f = format.compile('%s%s'); + expect(f('he', 'llo')).to.eql('hello'); + }); + it('6 replace2', function () { + var f = format.compile(' %s %s '); + expect(f('he', 'llo')).to.eql(' he llo '); + }); + it('7 %s', function () { + var f = format.compile('%s'); + expect(f('%s')).to.eql('%s'); + }); + it('8 number', function () { + var f = format.compile('%s'); + expect(f(100)).to.eql('100'); + }); + it('9 boolean', function () { + var f = format.compile('%s'); + expect(f(true)).to.eql('true'); + }); + it('10 date', function () { + var f = format.compile('%s'); + expect(f(new Date(2015, 5, 28))).to.contain('Sun Jun 28 2015 00:00:00'); + }); + it('11 array', function () { + var f = format.compile('%s'); + expect(f([1, 2, 3])).to.eql('1,2,3'); + }); + it('12 object', function () { + var f = format.compile('%s'); + expect(f({ key: 'value' })).to.eql('[object Object]'); + }); + it('13 NaN', function () { + var f = format.compile('%s'); + expect(f(NaN)).to.eql('NaN'); + }); + it('14 function', function () { + var f = format.compile('%s'); + expect(f(function () {})).to.eql('function () {}'); + }); + it('15 null', function () { + var f = format.compile('%s'); + expect(f(null)).to.eql('null'); + }); + it('16 undefined', function () { + var f = format.compile('%s'); + expect(f(undefined)).to.eql('undefined'); + }); + it('17 excess', function () { + var f = format.compile('%s %s %s %s'); + expect(f('1', '2', '3', '4', '5')).to.eql('1 2 3 4'); + }); + it('18 deficiency', function () { + var f = format.compile('%s %s %s %s'); + expect(f('1', '2', '3')).to.eql('1 2 3 %s'); + }); + it('19 no values', function () { + var f = format.compile('%s %s %s %s'); + expect(f()).to.eql('%s %s %s %s'); + }); + it('20 %', function () { + var f = format.compile('%'); + expect(f()).to.eql('%'); + }); + it('21 empty', function () { + var f = format.compile(); + expect(f()).to.eql(''); + }); + it('22 not supported', function () { + var f = format.compile('%d, %j'); + expect(f(10, { key: 'value' })).to.eql('%d, %j'); + }); + }); +}(this));