├── .travis.yml ├── .gitignore ├── index.js ├── lib ├── urlify.js ├── subtract.js ├── calendar.js ├── encodeURIComponent.js ├── title-case.js ├── capitalize.js ├── possessive.js ├── number.js ├── paragraphify.js ├── join.js ├── abbr-count.js ├── indefinite-article.js ├── if-lt.js ├── if-gt.js ├── firstof.js ├── not-eq.js ├── repeat.js ├── eq.js ├── chr-gt.js ├── chr-lt.js ├── neither.js ├── either.js ├── each-reverse.js ├── each-key.js ├── each-limit.js ├── iter.js ├── truncate.js ├── input-select.js └── pack-it.js ├── test ├── subtract.js ├── urlify.js ├── join.js ├── title-case.js ├── bin │ ├── hash.js │ └── build.js ├── calendar.js ├── capitalize.js ├── possessive.js ├── paragraphify.js ├── abbr-count.js ├── indefinite-article.js ├── repeat.js ├── each-reverse.js ├── firstof.js ├── eq.js ├── not-eq.js ├── each-limit.js ├── either.js ├── neither.js ├── each-key.js ├── pack-it.js ├── number.js ├── if-gt.js ├── if-lt.js ├── chr-lt.js ├── chr-gt.js ├── iter.js ├── truncate.js └── input-select.js ├── makefile ├── bin ├── hash.js └── build.js ├── package.json ├── LICENSE.md ├── register.js └── README.md /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 0.6 4 | - 0.8 5 | - 0.10 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /* MacOS */ 2 | .DS_Store 3 | 4 | /* NPM */ 5 | /node_modules 6 | npm* 7 | 8 | /* Other */ 9 | .notes.txt -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var helpers = require('require-all')({ 2 | 'dirname': __dirname + '/lib', 3 | 'filter': /(.+)\.js$/ 4 | }); 5 | 6 | module.exports = helpers; 7 | -------------------------------------------------------------------------------- /lib/urlify.js: -------------------------------------------------------------------------------- 1 | module.exports = function urlify (string) { 2 | if (!string) return ''; 3 | return string.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9\-]/g, ''); 4 | }; 5 | -------------------------------------------------------------------------------- /lib/subtract.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Reduces a number by given amount 3 | * {{subtract a.length 2}} 4 | */ 5 | module.exports = function subtract (object, reducer) { 6 | return object - reducer; 7 | }; 8 | -------------------------------------------------------------------------------- /lib/calendar.js: -------------------------------------------------------------------------------- 1 | var moment = require('moment'); 2 | 3 | module.exports = function calendar (timestamp) { 4 | var time = moment.utc(timestamp); 5 | return '' + time.format('MMM DD, YYYY') + ''; 6 | } 7 | -------------------------------------------------------------------------------- /lib/encodeURIComponent.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Proxy for the native js `encodeURIComponent`. 3 | * 4 | * @param {string} str 5 | */ 6 | module.exports = function encodeURIComponentHelper (str) { 7 | return encodeURIComponent(str); 8 | }; 9 | -------------------------------------------------------------------------------- /test/subtract.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var subtract = require('../lib/subtract'); 4 | 5 | test('subtract', function (t) { 6 | t.plan(1); 7 | 8 | t.equals(subtract(10, 5), 5, 'should be 5'); 9 | }); 10 | -------------------------------------------------------------------------------- /test/urlify.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var urlify = require('../lib/urlify'); 4 | 5 | test('urlify', function (t) { 6 | t.plan(1); 7 | 8 | t.equals(urlify('Beep Boop'), 'beep-boop', 'urlified'); 9 | }); 10 | -------------------------------------------------------------------------------- /lib/title-case.js: -------------------------------------------------------------------------------- 1 | module.exports = function titleCase (str) { 2 | if (typeof str === 'undefined') return ''; 3 | 4 | return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}); 5 | }; 6 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | build: 2 | node ./bin/build.js 3 | 4 | hash: 5 | node ./bin/hash.js 6 | 7 | browserify: 8 | browserify -x ../../node_modules/lodash -x ../../node_modules/handlebars-runtime -x ../pack-it -r ./register.js > ./helpers.bundled.js 9 | -------------------------------------------------------------------------------- /test/join.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var join = require('../lib/join'); 4 | 5 | test('non array', function (t) { 6 | t.plan(1); 7 | 8 | t.equal(join(false), '', 'should return empty string for non arrays'); 9 | }); 10 | -------------------------------------------------------------------------------- /lib/capitalize.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Capitalizes a word 3 | * {{capitalize lowercase.word}} 4 | * 5 | * @param {string} word 6 | */ 7 | module.exports = function capitalize (word) { 8 | return word.charAt(0).toUpperCase() + word.slice(1); 9 | }; 10 | -------------------------------------------------------------------------------- /test/title-case.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var titleCase = require('../lib/title-case'); 4 | 5 | test('title case', function (t) { 6 | t.plan(1); 7 | 8 | t.equals(titleCase('beep boop'), 'Beep Boop', 'title case works'); 9 | }); 10 | -------------------------------------------------------------------------------- /lib/possessive.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Someone -> Someone's 3 | * Alexis -> Alexis' 4 | * {{posessive maker.name}} 5 | * 6 | @ @param {string} str 7 | */ 8 | module.exports = function possessive (str) { 9 | return str + (str.charAt(str.length - 1) === 's' ? '\'' : '\'s'); 10 | }; 11 | -------------------------------------------------------------------------------- /lib/number.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Pretty prints a number with commas. 3 | * See: http://stackoverflow.com/a/2901298/147471 4 | * 5 | * @param {number} number 6 | */ 7 | module.exports = function number (value) { 8 | return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); 9 | }; 10 | -------------------------------------------------------------------------------- /bin/hash.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | 3 | var helpersPath = './lib'; 4 | 5 | fs.readdir(helpersPath, function componentsDir (err, files) { 6 | files.forEach(function (file) { 7 | console.log('\'' + file.replace('.js', '') + '\': require(\'./lib/' + file + '\'),'); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/bin/hash.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | 3 | var helpersPath = './helpers'; 4 | 5 | fs.readdir(helpersPath, function componentsDir (err, files) { 6 | files.forEach(function (file) { 7 | console.log('\'' + file.replace('.js', '') + '\': require(\'./helpers/' + file + '\'),'); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /lib/paragraphify.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Replaces line breaks with paragraphs 3 | * 4 | * @param {string} str 5 | */ 6 | module.exports = function paragraphify (str) { 7 | return '
' + str 8 | .replace(/^\s\s/, '') 9 | .replace(/\s*\s$/, '') 10 | .replace(/(\r?\n)+/, '
') + '
'; 11 | }; 12 | -------------------------------------------------------------------------------- /bin/build.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | 3 | var helpersPath = './lib'; 4 | 5 | fs.readdir(helpersPath, function componentsDir (err, files) { 6 | files.forEach(function (file) { 7 | console.log('Handlebars.registerHelper(\'' + file.replace('.js', '') + '\', require(\'./lib/' + file + '\'));'); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/calendar.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var calendar = require('../lib/calendar.js'); 4 | var date = '2013-10-09T21:43:33.396Z'; 5 | 6 | test('calendar', function (t) { 7 | t.plan(1); 8 | 9 | t.equal(calendar(date), 'Oct 09, 2013', 'should be the correct date'); 10 | }); -------------------------------------------------------------------------------- /lib/join.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Joins an array by a delimiter. 3 | * {{join array ","}} 4 | * 5 | * @param {array} array 6 | @ @param {string} delimiter 7 | */ 8 | module.exports = function join (array, delimiter) { 9 | return typeof array.join === 'function' ? array.join((typeof delimiter === 'string') ? delimiter : ',') : ''; 10 | }; 11 | -------------------------------------------------------------------------------- /lib/abbr-count.js: -------------------------------------------------------------------------------- 1 | module.exports = function abbrCount (val) { 2 | var count = parseInt(val, 10); 3 | var countString = val + ''; 4 | var symbol = ''; 5 | 6 | if (count >= 1000) { 7 | symbol = 'k+'; 8 | return countString.substring(0, 1) + symbol; 9 | } 10 | 11 | return countString; 12 | }; 13 | -------------------------------------------------------------------------------- /test/bin/build.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | 3 | var helpersPath = './helpers'; 4 | 5 | fs.readdir(helpersPath, function componentsDir (err, files) { 6 | files.forEach(function (file) { 7 | console.log('Handlebars.registerHelper(\'' + file.replace('.js', '') + '\', require(\'./helpers/' + file + '\'));'); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/capitalize.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var capitalize = require('../lib/capitalize'); 4 | 5 | test('capitalize', function (t) { 6 | t.plan(2); 7 | 8 | t.equals(capitalize('bleep'), 'Bleep', 'should capitalize'); 9 | t.equals(capitalize('bleep bloop'), 'Bleep bloop', 'should capitalize first word only'); 10 | }); 11 | -------------------------------------------------------------------------------- /lib/indefinite-article.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Oceanographer -> 'an' 3 | * Maker -> 'a' 4 | * Aquarium -> 'an' 5 | * 6 | * @param {string} str 7 | */ 8 | module.exports = function indefiniteArticle (str) { 9 | if (!str || !str.length) return 'a'; 10 | return (['a','e','i','o','u'].indexOf(str.charAt(0).toLowerCase()) === -1) ? 'a' : 'an'; 11 | }; 12 | -------------------------------------------------------------------------------- /test/possessive.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var possessive = require('../lib/possessive'); 4 | 5 | test('possessive', function (t) { 6 | t.plan(2); 7 | 8 | t.equal(possessive('Beep'), 'Beep\'s', 'beep should add \'s at end'); 9 | t.equal(possessive('Boops'), 'Boops\'', 'boops should add \' before trailing s'); 10 | }); 11 | -------------------------------------------------------------------------------- /lib/if-lt.js: -------------------------------------------------------------------------------- 1 | /** 2 | * If Less-Than Helper. Renders the block none of the first 3 | * argument is less than the second. 4 | * 5 | * {{#if-lt a 5}} content {{/if-lt}} 6 | */ 7 | module.exports = function ifLt (a, b) { 8 | var options = arguments[arguments.length - 1]; 9 | if (a < b) { return options.fn(this); } 10 | else { return options.inverse(this); } 11 | }; 12 | -------------------------------------------------------------------------------- /lib/if-gt.js: -------------------------------------------------------------------------------- 1 | /** 2 | * If Greater-Than Helper. Renders the block none of the first 3 | * argument is greater than the second. 4 | * 5 | * {{#if-lt a 5}} content {{/if-lt}} 6 | */ 7 | module.exports = function ifGt (a, b) { 8 | var options = arguments[arguments.length - 1]; 9 | if (a > b) { return options.fn(this); } 10 | else { return options.inverse(this); } 11 | }; 12 | -------------------------------------------------------------------------------- /lib/firstof.js: -------------------------------------------------------------------------------- 1 | // Will return the first turthy value. 2 | // Handy for setting default values. 3 | module.exports = function firstof () { 4 | // Use everything, but the options object 5 | var valuesLength = arguments.length - 1; 6 | 7 | for (var i = 0; i < valuesLength; i++) { 8 | var value = arguments[i]; 9 | if (value) return value; 10 | } 11 | 12 | return ''; 13 | }; 14 | -------------------------------------------------------------------------------- /lib/not-eq.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Inverse of of #eq block helper. 3 | * {{#not-eq a b}} content {{/not-eq}} 4 | * 5 | * @param {object} obj3 6 | * @param {object} obj2 7 | * @param {object} options 8 | */ 9 | module.exports = function notEqual (obj1, obj2, options) { 10 | if (obj1 !== obj2) { 11 | return options.fn(this); 12 | } else { 13 | return options.inverse(this); 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /lib/repeat.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Repeats a block `n` times. 3 | * {{#repeat 5}} Hello! {{/repeat}} 4 | * 5 | * @param {number} n 6 | */ 7 | module.exports = function repeat (n) { 8 | var options = arguments[arguments.length - 1], ret = ''; 9 | if (typeof n === 'string') n = parseInt(n, 10); 10 | for (var i = 0; i < n; i++) { 11 | ret += options.fn(this); 12 | } 13 | return ret; 14 | }; 15 | -------------------------------------------------------------------------------- /test/paragraphify.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var paragraphify = require('../lib/paragraphify'); 4 | 5 | test('paragraphify', function (t) { 6 | t.plan(1); 7 | 8 | var testStr = 'Line1\n' + 'Line2\n' + 'Line3'; 9 | var expected = 'Line1
Line2\nLine3
'; 10 | var result = paragraphify(testStr); 11 | 12 | t.equals(result, expected, 'should create 2 paragraphs'); 13 | }); 14 | -------------------------------------------------------------------------------- /test/abbr-count.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var abbrCount = require('../lib/abbr-count'); 4 | 5 | test('less than 1000', function (t) { 6 | t.plan(1); 7 | 8 | t.equals(abbrCount(999), '999', 'value should remain uncahnged'); 9 | }); 10 | 11 | test('greater than 1000', function (t) { 12 | t.plan(1); 13 | 14 | t.equals(abbrCount(2000), '2k+', 'should abbreviate and append symbol'); 15 | }); 16 | -------------------------------------------------------------------------------- /lib/eq.js: -------------------------------------------------------------------------------- 1 | /** 2 | * If equality block helper. Renders the block if `obj1` equals `obj2` (strict). 3 | * {{#eq a b}} content {{/eq}} 4 | * 5 | * @param {object} obj1 6 | * @param {object} obj2 7 | * @param {object} options 8 | */ 9 | module.exports = function eq (obj1, obj2, options) { 10 | if (obj1 === obj2) { 11 | return options.fn(this); 12 | } else { 13 | return options.inverse(this); 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /lib/chr-gt.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Conditional for determining if the character length of a string 3 | * is greater than the provided max value. 4 | * {{#chr-gt someString 10}}...{{/chr-gt}} 5 | * 6 | * @param {string} Any string. 7 | * @param {int} The max number of characters. 8 | */ 9 | 10 | module.exports = function chrGt (str, length, options) { 11 | if (str.length > length) { 12 | return options.fn(this); 13 | } else { 14 | return options.inverse(this); 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /lib/chr-lt.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Conditional for determining if the character length of a string 3 | * is less than the provided min value. 4 | * {{#chr-lt someString 10}}...{{/chr-lt}} 5 | * 6 | * @param {string} Any string. 7 | * @param {int} The min number of characters. 8 | */ 9 | 10 | module.exports = function chrLt (str, length, options) { 11 | if (str.length < length) { 12 | return options.fn(this); 13 | } else { 14 | return options.inverse(this); 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /lib/neither.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Neither Helper. Renders the block if all arguments have 3 | * a falsey value. 4 | * 5 | * {{#neither a b c}} content {{/neither}} 6 | */ 7 | module.exports = function neither () { 8 | var options = arguments[arguments.length - 1]; 9 | 10 | for (var i = 0; i < arguments.length - 1; i++) { 11 | if (typeof arguments[i] !== 'undefined' && !arguments[i]) { 12 | return options.fn(this); 13 | } 14 | } 15 | return options.inverse(this); 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /lib/either.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Either Helper. Renders the block if any one of the 3 | * arguments has a truthy value. 4 | * 5 | * {{#either a b c}} content {{/either}} 6 | */ 7 | module.exports = function either () { 8 | var options = arguments[arguments.length - 1]; 9 | 10 | for (var i = 0; i < arguments.length - 1; i++) { 11 | if (typeof arguments[i] !== 'undefined' && arguments[i]) { 12 | return options.fn(this); 13 | } 14 | } 15 | return options.inverse(this); 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /test/indefinite-article.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var idefiniteArticle = require('../lib/indefinite-article'); 4 | 5 | test('an', function (t) { 6 | t.plan(2); 7 | 8 | t.equal(idefiniteArticle('Oceanographer'), 'an', 'should be an'); 9 | t.equal(idefiniteArticle('Aquarium'), 'an', 'should be an'); 10 | }); 11 | 12 | test('a', function (t) { 13 | t.plan(2); 14 | 15 | t.equal(idefiniteArticle('Maker'), 'a', 'should be a'); 16 | t.equal(idefiniteArticle('Poop'), 'a', 'should be a'); 17 | }); 18 | -------------------------------------------------------------------------------- /test/repeat.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var repeat = require('../lib/repeat'); 4 | 5 | test('repeat', function (t) { 6 | t.plan(1); 7 | 8 | var callCount = 0; 9 | 10 | var subject = 'hey'; 11 | var expected = 'heyheyheyheyheyheyhey'; 12 | 13 | var result = repeat(7, { 14 | 'fn': function repeatCallback (scope) { 15 | callCount++; 16 | 17 | return subject; 18 | } 19 | }); 20 | 21 | t.equals(expected, result, 'there should be 7 heys'); 22 | }); 23 | -------------------------------------------------------------------------------- /test/each-reverse.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var eachReverse = require('../lib/each-reverse'); 4 | 5 | test('each limit', function (t) { 6 | t.plan(2); 7 | 8 | var callCount = 0; 9 | 10 | var obj = ['bleep', 'bloop']; 11 | var reverse = ['bloop', 'bleep']; 12 | 13 | eachReverse(obj, 1, { 14 | 'fn': function eachReverseCallback (scope) { 15 | t.equals(scope, reverse[callCount], 'should match reverse array item'); 16 | 17 | callCount++; 18 | } 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /test/firstof.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var firstof = require('../lib/firstof'); 4 | 5 | // Stub out the options object passed to all helpers 6 | var stub = {}; 7 | 8 | test('firstof', function (t) { 9 | t.plan(3); 10 | 11 | t.equals(firstof(null, null, 'test', 'test2', stub), 'test', 'should return third position "test"'); 12 | t.equals(firstof('test', null, null, 'test2', stub), 'test', 'should return first position "test"'); 13 | t.equals(firstof(null, null, 'test', stub), 'test', 'should return last position "test"'); 14 | }); 15 | -------------------------------------------------------------------------------- /test/eq.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var eq = require('../lib/eq'); 4 | 5 | test('equal arguments', function (t) { 6 | t.plan(1); 7 | 8 | eq(true, true, { 9 | 'fn': function trueCallback () { 10 | t.ok(true, 'truthy callback was called'); 11 | } 12 | }); 13 | }); 14 | 15 | test('NOT equal arguments', function (t) { 16 | t.plan(1); 17 | 18 | eq(true, false, { 19 | 'inverse': function trueCallback () { 20 | t.ok(true, 'falsey callback was called'); 21 | } 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /lib/each-reverse.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Each Helper (in reverse). 3 | * 4 | * {{#each-reverse items 3}} 5 | * {{/each-reverse}} 6 | * 7 | * @param {array} context 8 | */ 9 | module.exports = function eachReverse (context) { 10 | var options = arguments[arguments.length - 1]; 11 | var ret = ''; 12 | 13 | if (context && context.length > 0) { 14 | for (var i = context.length - 1; i >= 0; i--) { 15 | ret += options.fn(context[i]); 16 | } 17 | } else { 18 | ret = options.inverse(this); 19 | } 20 | 21 | return ret; 22 | }; 23 | -------------------------------------------------------------------------------- /test/not-eq.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var notEq = require('../lib/not-eq'); 4 | 5 | test('not equal arguments', function (t) { 6 | t.plan(1); 7 | 8 | notEq(true, true, { 9 | 'inverse': function trueCallback () { 10 | t.ok(true, 'falsey callback was called'); 11 | } 12 | }); 13 | }); 14 | 15 | test('NOT equal arguments', function (t) { 16 | t.plan(1); 17 | 18 | notEq(true, false, { 19 | 'fn': function trueCallback () { 20 | t.ok(true, 'truthy callback was called'); 21 | } 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /lib/each-key.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Object Iteration Helper (w/key extraction). 3 | * 4 | * {{#each-key object}} 5 | * Key: {{this.key}} Value: {{this.value}} 6 | * {{/each-key}} 7 | * 8 | * @param {object} object 9 | */ 10 | module.exports = function eachKey (object) { 11 | var options = arguments[arguments.length - 1]; 12 | var ret = ''; 13 | for (var key in object) { 14 | if (object.hasOwnProperty(key)) { 15 | ret += options.fn({ 16 | key: key, 17 | value: object[key] 18 | }); 19 | } 20 | } 21 | return ret; 22 | }; 23 | -------------------------------------------------------------------------------- /test/each-limit.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var eachLimit = require('../lib/each-limit'); 4 | 5 | test('each limit', function (t) { 6 | t.plan(1); 7 | 8 | var callCount = 0; 9 | 10 | var obj = ['bleep', 'bloop']; 11 | 12 | eachLimit(obj, 1, { 13 | 'fn': function eachLimitCallback (scope) { 14 | if (callCount > 1) { 15 | t.notOk(true, 'This should have iterated once'); 16 | } 17 | 18 | t.equals(scope, obj[callCount], 'should match first array item'); 19 | 20 | callCount++; 21 | } 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/either.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var either = require('../lib/either'); 4 | 5 | test('with a truthy argument', function (t) { 6 | t.plan(1); 7 | 8 | either(false, true, false, { 9 | 'fn': function trueCallback () { 10 | t.ok(true, 'truthy callback was called'); 11 | } 12 | }); 13 | }); 14 | 15 | test('with no truthy arguments', function (t) { 16 | t.plan(1); 17 | 18 | either(false, false, false, { 19 | 'inverse': function trueCallback () { 20 | t.ok(true, 'falsey callback was called'); 21 | } 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/neither.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var neither = require('../lib/neither'); 4 | 5 | test('with a falsey arguments', function (t) { 6 | t.plan(1); 7 | 8 | neither(true, false, true, { 9 | 'fn': function trueCallback () { 10 | t.ok(true, 'truthy callback was called'); 11 | } 12 | }); 13 | }); 14 | 15 | test('with no falsey arguments', function (t) { 16 | t.plan(1); 17 | 18 | neither(true, true, true, { 19 | 'inverse': function trueCallback () { 20 | t.ok(true, 'falsey callback was called'); 21 | } 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /lib/each-limit.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Each Helper (w/limit). 3 | * 4 | * {{#each-limit items 3}} 5 | * {{/each-limit}} 6 | * 7 | * @param {array} context 8 | * @param {number} limit 9 | */ 10 | module.exports = function eachLimit (context, limit) { 11 | var options = arguments[arguments.length - 1]; 12 | var ret = ''; 13 | 14 | if (context && context.length > 0) { 15 | var max = Math.min(context.length, limit); 16 | for (var i = 0; i < max; i++) { 17 | ret += options.fn(context[i]); 18 | } 19 | } else { 20 | ret = options.inverse(this); 21 | } 22 | 23 | return ret; 24 | }; 25 | -------------------------------------------------------------------------------- /lib/iter.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | 3 | /** 4 | * Adds the current index and next index to iteration scope. 5 | * 6 | * {{#iter items}} 7 | * {{/iter}} 8 | * 9 | * @param {array} context 10 | */ 11 | module.exports = function iter (context, options) { 12 | var fn = options.fn, inverse = options.inverse; 13 | var ret = ""; 14 | 15 | if (context && context.length > 0) { 16 | for (var i = 0, j = context.length; i < j; i++) { 17 | ret = ret + fn(_.extend({}, context[i], { i: i, iPlus1: i + 1 })); 18 | } 19 | } else { 20 | ret = inverse(this); 21 | } 22 | return ret; 23 | }; 24 | -------------------------------------------------------------------------------- /lib/truncate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Truncates string to first 10 characters and appends an ellipses. 3 | * Can override truncate length and appending string. 4 | * 5 | * {{truncate someLongString}} 6 | * 7 | * @param {string} subject 8 | * @param {number} truncation amount (how many characters to print) 9 | * @param {string} string to append (can provide empty string to remove everything) 10 | */ 11 | module.exports = function capitalize (str, length, append) { 12 | str = str || ''; 13 | length = length || 10; 14 | append = typeof append === 'undefined' ? '…' : append; 15 | 16 | if (str.length === length) return str; 17 | 18 | return str.substring(0, length).replace(/\s+$|\.+$/, '') + append; 19 | }; 20 | -------------------------------------------------------------------------------- /test/each-key.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var eachKey = require('../lib/each-key'); 4 | 5 | test('each item calls callback with `key` `value` in scope', function (t) { 6 | t.plan(4); 7 | 8 | var callCount = 0; 9 | 10 | var obj = { 11 | 'bleep': 'bloop', 12 | 'zip': 'zap' 13 | }; 14 | 15 | eachKey(obj, { 16 | 'fn': function eachKeyCallback (scope) { 17 | t.ok(obj.hasOwnProperty(scope.key), scope.key + ' key exist in original object'); 18 | t.equal(obj[scope.key], scope.value, scope.key + ' value matches original object'); 19 | 20 | if (callCount === 2) return t.end(); 21 | callCount++; 22 | } 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /test/pack-it.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var packIt = require('../lib/pack-it'); 4 | 5 | test('iteration scope', function (t) { 6 | t.plan(6); 7 | 8 | var callCount = 1; // start at 1 since the first item is skipped in pack-it 9 | 10 | var obj = [ 11 | 'bleep', 12 | 'bloop', 13 | 'zip', 14 | 'zap' 15 | ]; 16 | 17 | packIt(obj, { 18 | 'fn': function packItCallback (scope) { 19 | t.equals(scope.content, obj[callCount], callCount + ' content is correct'); 20 | t.type(scope.size, 'number', ' size is number'); 21 | 22 | if (callCount === 3) return t.end(); 23 | callCount++; 24 | } 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /test/number.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var number = require('../lib/number'); 4 | 5 | test('hundreds', function (t) { 6 | t.plan(1); 7 | 8 | t.equal(number(100), '100', 'should be the same'); 9 | }); 10 | 11 | test('thousands', function (t) { 12 | t.plan(1); 13 | 14 | t.equal(number(1000), '1,000', 'should add a comma at thousands place'); 15 | }); 16 | 17 | test('tens of thousands', function (t) { 18 | t.plan(1); 19 | 20 | t.equal(number(10000), '10,000', 'should add a comma at ten-thounsands place'); 21 | }); 22 | 23 | test('hudreds of thousands', function (t) { 24 | t.plan(1); 25 | 26 | t.equal(number(100000), '100,000', 'should add a comma at hundred-thounsands place'); 27 | }); 28 | -------------------------------------------------------------------------------- /test/if-gt.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var ifGt = require('../lib/if-gt'); 4 | 5 | test('obj1 gt obj2', function (t) { 6 | t.plan(1); 7 | 8 | ifGt(10, 5, { 9 | 'fn': function trueCallback () { 10 | t.ok(true, 'truthy callback was called'); 11 | } 12 | }); 13 | }); 14 | 15 | test('obj1 lt obj2', function (t) { 16 | t.plan(1); 17 | 18 | ifGt(5, 10, { 19 | 'inverse': function trueCallback () { 20 | t.ok(true, 'falsey callback was called'); 21 | } 22 | }); 23 | }); 24 | 25 | test('obj1 eq obj2', function (t) { 26 | t.plan(1); 27 | 28 | ifGt(5, 5, { 29 | 'inverse': function trueCallback () { 30 | t.ok(true, 'falsey callback was called'); 31 | } 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /test/if-lt.js: -------------------------------------------------------------------------------- 1 | var test = require('tap').test; 2 | 3 | var ifLt = require('../lib/if-lt'); 4 | 5 | test('obj1 lt obj2', function (t) { 6 | t.plan(1); 7 | 8 | ifLt(5, 10, { 9 | 'fn': function trueCallback () { 10 | t.ok(true, 'truthy callback was called'); 11 | } 12 | }); 13 | }); 14 | 15 | test('obj1 gt obj2', function (t) { 16 | t.plan(1); 17 | 18 | ifLt(10, 5, { 19 | 'inverse': function trueCallback () { 20 | t.ok(true, 'falsey callback was called'); 21 | } 22 | }); 23 | }); 24 | 25 | test('obj1 eq obj2', function (t) { 26 | t.plan(1); 27 | 28 | ifLt(5, 5, { 29 | 'inverse': function trueCallback () { 30 | t.ok(true, 'falsey callback was called'); 31 | } 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /lib/input-select.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Builds a