@budibase/handlebars-helpers
Version:
More than 130 Handlebars helpers in ~20 categories. Helpers can be used with Assemble, Generate, Verb, Ghost, gulp-handlebars, grunt-handlebars, consolidate, or any node.js/Handlebars project.
834 lines (753 loc) • 19.2 kB
JavaScript
'use strict';
var util = {
isString: require('./utils/isString'),
isObject: require('./utils/isObject'),
options: require('./utils/options')
};
var utils = require('./utils');
var helpers = module.exports;
let lorem = require('./lorem.js');
/**
* Append the specified `suffix` to the given string.
*
* ```handlebars
* <!-- given that 'item.stem' is 'foo' -->
* {{append item.stem '.html'}}
* <!-- results in: 'foo.html' -->
* ```
* @param {String} `str`
* @param {String} `suffix`
* @return {String}
* @api public
* @example {{append 'index' '.html'}} -> index.html
*/
helpers.append = function(str, suffix) {
if (typeof str === 'string' && typeof suffix === 'string') {
return str + suffix;
}
return str;
};
/**
* camelCase the characters in the given `string`.
*
* ```handlebars
* {{camelcase 'foo bar baz'}};
* <!-- results in: 'fooBarBaz' -->
* ```
* @param {String} `string` The string to camelcase.
* @return {String}
* @api public
* @example {{camelcase 'foo bar baz'}} -> fooBarBaz
*/
helpers.camelcase = function(str) {
if (typeof(str) !== 'string') return '';
return utils.changecase(str, function(ch) {
return ch.toUpperCase();
});
};
/**
* Capitalize the first word in a sentence.
*
* ```handlebars
* {{capitalize 'foo bar baz'}}
* <!-- results in: 'Foo bar baz' -->
* ```
* @param {String} `str`
* @return {String}
* @api public
* @example {{capitalize 'foo bar baz'}} -> Foo bar baz
*/
helpers.capitalize = function(str) {
if (typeof(str) !== 'string') return '';
return str.charAt(0).toUpperCase() + str.slice(1);
};
/**
* Capitalize all words in a string.
*
* ```handlebars
* {{capitalizeAll 'foo bar baz'}}
* <!-- results in: 'Foo Bar Baz' -->
* ```
* @param {String} `str`
* @return {String}
* @api public
* @example {{ capitalizeAll 'foo bar baz'}} -> Foo Bar Baz
*/
helpers.capitalizeAll = function(str) {
if (typeof(str) !== 'string') return '';
if (util.isString(str)) {
return str.replace(/\w\S*/g, function(word) {
return helpers.capitalize(word);
});
}
};
/**
* Center a string using non-breaking spaces
*
* @param {String} `str`
* @param {String} `spaces`
* @return {String}
* @api public
* @example {{ center 'test' 1}} -> ' test '
*/
helpers.center = function(str, spaces) {
if (typeof(str) !== 'string') return '';
var space = '';
var i = 0;
while (i < spaces) {
space += ' ';
i++;
}
return space + str + space;
};
/**
* Like trim, but removes both extraneous whitespace **and
* non-word characters** from the beginning and end of a string.
*
* ```handlebars
* {{chop '_ABC_'}}
* <!-- results in: 'ABC' -->
*
* {{chop '-ABC-'}}
* <!-- results in: 'ABC' -->
*
* {{chop ' ABC '}}
* <!-- results in: 'ABC' -->
* ```
* @param {String} `string` The string to chop.
* @return {String}
* @api public
* @example {{ chop ' ABC '}} -> ABC
*/
helpers.chop = function(str) {
if (typeof(str) !== 'string') return '';
return utils.chop(str);
};
/**
* dash-case the characters in `string`. Replaces non-word
* characters and periods with hyphens.
*
* ```handlebars
* {{dashcase 'a-b-c d_e'}}
* <!-- results in: 'a-b-c-d-e' -->
* ```
* @param {String} `string`
* @return {String}
* @api public
* @example {{dashcase 'a-b-c d_e'}} -> a-b-c-d-e
*/
helpers.dashcase = function(str) {
if (typeof(str) !== 'string') return '';
return utils.changecase(str, function(ch) {
return '-' + ch;
});
};
/**
* dot.case the characters in `string`.
*
* ```handlebars
* {{dotcase 'a-b-c d_e'}}
* <!-- results in: 'a.b.c.d.e' -->
* ```
* @param {String} `string`
* @return {String}
* @api public
* @example {{dotcase 'a-b-c d_e'}} -> a.b.c.d.e
*/
helpers.dotcase = function(str) {
if (typeof(str) !== 'string') return '';
return utils.changecase(str, function(ch) {
return '.' + ch;
});
};
/**
* Lowercase all of the characters in the given string. Alias for [lowercase](#lowercase).
*
* ```handlebars
* {{downcase 'aBcDeF'}}
* <!-- results in: 'abcdef' -->
* ```
* @param {String} `string`
* @return {String}
* @alias lowercase
* @api public
* @example {{downcase 'aBcDeF'}} -> abcdef
*/
helpers.downcase = function() {
return helpers.lowercase.apply(this, arguments);
};
/**
* Truncates a string to the specified `length`, and appends
* it with an elipsis, `…`.
*
* ```handlebars
* {{ellipsis (sanitize '<span>foo bar baz</span>'), 7}}
* <!-- results in: 'foo bar…' -->
* {{ellipsis 'foo bar baz', 7}}
* <!-- results in: 'foo bar…' -->
* ```
* @param {String} `str`
* @param {Number} `length` The desired length of the returned string.
* @return {String} The truncated string.
* @api public
* @example {{ellipsis 'foo bar baz' 7}} -> foo bar…
*/
helpers.ellipsis = function(str, limit) {
if (util.isString(str)) {
if (str.length <= limit) {
return str;
}
return helpers.truncate(str, limit) + '…';
}
};
/**
* Replace spaces in a string with hyphens.
*
* ```handlebars
* {{hyphenate 'foo bar baz qux'}}
* <!-- results in: 'foo-bar-baz-qux' -->
* ```
* @param {String} `str`
* @return {String}
* @api public
* @example {{hyphenate 'foo bar baz qux'}} -> foo-bar-baz-qux
*/
helpers.hyphenate = function(str) {
if (typeof(str) !== 'string') return '';
return str.split(' ').join('-');
};
/**
* Return true if `value` is a string.
*
* ```handlebars
* {{isString 'foo'}}
* <!-- results in: 'true' -->
* ```
* @param {String} `value`
* @return {Boolean}
* @api public
* @example {{isString 'foo'}} -> true
*/
helpers.isString = function(value) {
return typeof value === 'string';
};
/**
* Lowercase all characters in the given string.
*
* ```handlebars
* {{lowercase 'Foo BAR baZ'}}
* <!-- results in: 'foo bar baz' -->
* ```
* @param {String} `str`
* @return {String}
* @api public
* @example {{lowercase 'Foo BAR baZ'}} -> foo bar baz
*/
helpers.lowercase = function(str) {
if (util.isObject(str) && str.fn) {
return str.fn(this).toLowerCase();
}
if (typeof(str) !== 'string') return '';
return str.toLowerCase();
};
/**
* Return the number of occurrences of `substring` within the
* given `string`.
*
* ```handlebars
* {{occurrences 'foo bar foo bar baz' 'foo'}}
* <!-- results in: 2 -->
* ```
* @param {String} `str`
* @param {String} `substring`
* @return {Number} Number of occurrences
* @api public
* @example {{occurrences 'foo bar foo bar baz' 'foo'}} -> 2
*/
helpers.occurrences = function(str, substring) {
if (typeof(str) !== 'string') return '';
var len = substring.length;
var pos = 0;
var n = 0;
while ((pos = str.indexOf(substring, pos)) > -1) {
n++;
pos += len;
}
return n;
};
/**
* PascalCase the characters in `string`.
*
* ```handlebars
* {{pascalcase 'foo bar baz'}}
* <!-- results in: 'FooBarBaz' -->
* ```
* @param {String} `string`
* @return {String}
* @api public
* @example {{pascalcase 'foo bar baz'}} -> FooBarBaz
*/
helpers.pascalcase = function(str) {
if (typeof(str) !== 'string') return '';
str = utils.changecase(str, function(ch) {
return ch.toUpperCase();
});
return str.charAt(0).toUpperCase() + str.slice(1);
};
/**
* path/case the characters in `string`.
*
* ```handlebars
* {{pathcase 'a-b-c d_e'}}
* <!-- results in: 'a/b/c/d/e' -->
* ```
* @param {String} `string`
* @return {String}
* @api public
* @example {{pathcase 'a-b-c d_e'}} -> a/b/c/d/e
*/
helpers.pathcase = function(str) {
if (typeof(str) !== 'string') return '';
return utils.changecase(str, function(ch) {
return '/' + ch;
});
};
/**
* Replace spaces in the given string with pluses.
*
* ```handlebars
* {{plusify 'foo bar baz'}}
* <!-- results in: 'foo+bar+baz' -->
* ```
* @param {String} `str` The input string
* @return {String} Input string with spaces replaced by plus signs
* @source Stephen Way <https://github.com/stephenway>
* @api public
* @example {{plusify 'foo bar baz'}} -> foo+bar+baz
*/
helpers.plusify = function(str, ch) {
if (typeof(str) !== 'string') return '';
if (!util.isString(ch)) ch = ' ';
return str.split(ch).join('+');
};
/**
* Prepends the given `string` with the specified `prefix`.
*
* ```handlebars
* <!-- given that 'val' is 'bar' -->
* {{prepend val 'foo-'}}
* <!-- results in: 'foo-bar' -->
* ```
* @param {String} `str`
* @param {String} `prefix`
* @return {String}
* @api public
* @example {{prepend 'bar' 'foo-'}} -> foo-bar
*/
helpers.prepend = function(str, prefix) {
return typeof str === 'string' && typeof prefix === 'string'
? (prefix + str)
: str;
};
/**
* Render a block without processing mustache templates inside the block.
*
* ```handlebars
* {{{{raw}}}}
* {{foo}}
* {{{{/raw}}}}
* <!-- results in: '{{foo}}' -->
* ```
*
* @param {Object} `options`
* @return {String}
* @block
* @api public
* @example {{{{raw}}}}{{foo}}{{{{/raw}}}} -> \{{foo}}
*/
helpers.raw = function(options) {
var str = options.fn();
var opts = util.options(this, options);
if (opts.escape !== false) {
var idx = 0;
while (((idx = str.indexOf('{{', idx)) !== -1)) {
if (str[idx - 1] !== '\\') {
str = str.slice(0, idx) + '\\' + str.slice(idx);
}
idx += 3;
}
}
return str;
};
/**
* Remove all occurrences of `substring` from the given `str`.
*
* ```handlebars
* {{remove 'a b a b a b' 'a '}}
* <!-- results in: 'b b b' -->
* ```
* @param {String} `str`
* @param {String} `substring`
* @return {String}
* @api public
* @example {{remove 'a b a b a b' 'a '}} -> b b b
*/
helpers.remove = function(str, ch) {
if (typeof(str) !== 'string') return '';
if (!util.isString(ch)) return str;
return str.split(ch).join('');
};
/**
* Remove the first occurrence of `substring` from the given `str`.
*
* ```handlebars
* {{remove 'a b a b a b' 'a'}}
* <!-- results in: ' b a b a b' -->
* ```
* @param {String} `str`
* @param {String} `substring`
* @return {String}
* @api public
* @example {{removeFirst 'a b a b a b' 'a'}} -> ' b a b a b'
*/
helpers.removeFirst = function(str, ch) {
if (typeof(str) !== 'string') return '';
if (!util.isString(ch)) return str;
return str.replace(ch, '');
};
/**
* Replace all occurrences of substring `a` with substring `b`.
*
* ```handlebars
* {{replace 'a b a b a b' 'a' 'z'}}
* <!-- results in: 'z b z b z b' -->
* ```
* @param {String} `str`
* @param {String} `a`
* @param {String} `b`
* @return {String}
* @api public
* @example {{replace 'a b a b a b' 'a' 'z'}} -> z b z b z b
*/
helpers.replace = function(str, a, b) {
if (typeof(str) !== 'string') return '';
if (!util.isString(a)) return str;
if (!util.isString(b)) b = '';
return str.split(a).join(b);
};
/**
* Replace the first occurrence of substring `a` with substring `b`.
*
* ```handlebars
* {{replace 'a b a b a b' 'a' 'z'}}
* <!-- results in: 'z b a b a b' -->
* ```
* @param {String} `str`
* @param {String} `a`
* @param {String} `b`
* @return {String}
* @api public
* @example {{replaceFirst 'a b a b a b' 'a' 'z'}} -> z b a b a b
*/
helpers.replaceFirst = function(str, a, b) {
if (typeof(str) !== 'string') return '';
if (!util.isString(a)) return str;
if (!util.isString(b)) b = '';
return str.replace(a, b);
};
/**
* Reverse a string.
*
* ```handlebars
* {{reverse 'abcde'}}
* <!-- results in: 'edcba' -->
* ```
* @param {String} `str`
* @return {String}
* @api public
* @example {{reverse 'abcde'}} -> edcba
*/
helpers.reverse = require('./array').reverse;
/**
* Sentence case the given string
*
* ```handlebars
* {{sentence 'hello world. goodbye world.'}}
* <!-- results in: 'Hello world. Goodbye world.' -->
* ```
* @param {String} `str`
* @return {String}
* @api public
* @example {{sentence 'hello world. goodbye world.'}} -> Hello world. Goodbye world.
*/
helpers.sentence = function(str) {
if (typeof(str) !== 'string') return '';
return str.replace(/((?:\S[^\.\?\!]*)[\.\?\!]*)/g, function(txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
};
/**
* snake_case the characters in the given `string`.
*
* ```handlebars
* {{snakecase 'a-b-c d_e'}}
* <!-- results in: 'a_b_c_d_e' -->
* ```
* @param {String} `string`
* @return {String}
* @api public
* @example {{snakecase 'a-b-c d_e'}} -> a_b_c_d_e
*/
helpers.snakecase = function(str) {
if (typeof(str) !== 'string') return '';
return utils.changecase(str, function(ch) {
return '_' + ch;
});
};
/**
* Split `string` by the given `character`.
*
* ```handlebars
* {{split 'a,b,c' ','}}
* <!-- results in: ['a', 'b', 'c'] -->
* ```
* @param {String} `string` The string to split.
* @return {String} `character` Default is an empty string.
* @api public
* @example {{split 'a,b,c'}} -> ['a', 'b', 'c']
*/
helpers.split = function(str, ch) {
if (typeof(str) !== 'string') return '';
if (!util.isString(ch)) ch = ',';
return str.split(ch);
};
/**
* Tests whether a string begins with the given prefix.
*
* ```handlebars
* {{#startsWith 'Goodbye' 'Hello, world!'}}
* Whoops
* {{else}}
* Bro, do you even hello world?
* {{/startsWith}}
* ```
* @contributor Dan Fox <http://github.com/iamdanfox>
* @param {String} `prefix`
* @param {String} `testString`
* @param {String} `options`
* @return {String}
* @block
* @api public
* @example {{#startsWith 'Goodbye' 'Hello, world!'}}Yep{{else}}Nope{{/startsWith}} -> Nope
*/
helpers.startsWith = function(prefix, str, options) {
var args = [].slice.call(arguments);
options = args.pop();
if (util.isString(str) && str.indexOf(prefix) === 0) {
return options.fn(this);
}
if (typeof options.inverse === 'function') {
return options.inverse(this);
}
return '';
};
/**
* Title case the given string.
*
* ```handlebars
* {{titleize 'this is title case'}}
* <!-- results in: 'This Is Title Case' -->
* ```
* @param {String} `str`
* @return {String}
* @api public
* @example {{titleize 'this is title case' }} -> This Is Title Case
*/
helpers.titleize = function(str) {
if (typeof(str) !== 'string') return '';
var title = str.replace(/[- _]+/g, ' ');
var words = title.split(' ');
var len = words.length;
var res = [];
var i = 0;
while (len--) {
var word = words[i++];
res.push(exports.capitalize(word));
}
return res.join(' ');
};
/**
* Removes extraneous whitespace from the beginning and end
* of a string.
*
* ```handlebars
* {{trim ' ABC '}}
* <!-- results in: 'ABC' -->
* ```
* @param {String} `string` The string to trim.
* @return {String}
* @api public
* @example {{trim ' ABC ' }} -> ABC
*/
helpers.trim = function(str) {
return typeof str === 'string' ? str.trim() : '';
};
/**
* Removes extraneous whitespace from the beginning of a string.
*
* ```handlebars
* {{trim ' ABC '}}
* <!-- results in: 'ABC ' -->
* ```
* @param {String} `string` The string to trim.
* @return {String}
* @api public
* @example {{trimLeft ' ABC ' }} -> 'ABC '
*/
helpers.trimLeft = function(str) {
if (util.isString(str)) {
return str.replace(/^\s+/, '');
}
};
/**
* Removes extraneous whitespace from the end of a string.
*
* ```handlebars
* {{trimRight ' ABC '}}
* <!-- results in: ' ABC' -->
* ```
* @param {String} `string` The string to trim.
* @return {String}
* @api public
* @example {{trimRight ' ABC ' }} -> ' ABC'
*/
helpers.trimRight = function(str) {
if (util.isString(str)) {
return str.replace(/\s+$/, '');
}
};
/**
* Truncate a string to the specified `length`. Also see [ellipsis](#ellipsis).
*
* ```handlebars
* truncate('foo bar baz', 7);
* <!-- results in: 'foo bar' -->
* truncate(sanitize('<span>foo bar baz</span>', 7));
* <!-- results in: 'foo bar' -->
* ```
* @param {String} `str`
* @param {Number} `limit` The desired length of the returned string.
* @param {String} `suffix` Optionally supply a string to use as a suffix to
* denote when the string has been truncated. Otherwise an ellipsis (`…`) will be used.
* @return {String} The truncated string.
* @api public
* @example {{truncate 'foo bar baz' 7 }} -> foo bar
*/
helpers.truncate = function(str, limit, suffix) {
if (util.isString(str)) {
if (typeof suffix !== 'string') {
suffix = '';
}
if (str.length > limit) {
return str.slice(0, limit - suffix.length) + suffix;
}
return str;
}
};
/**
* Truncate a string to have the specified number of words.
* Also see [truncate](#truncate).
*
* ```handlebars
* truncateWords('foo bar baz', 1);
* <!-- results in: 'foo…' -->
* truncateWords('foo bar baz', 2);
* <!-- results in: 'foo bar…' -->
* truncateWords('foo bar baz', 3);
* <!-- results in: 'foo bar baz' -->
* ```
* @param {String} `str`
* @param {Number} `limit` The desired length of the returned string.
* @param {String} `suffix` Optionally supply a string to use as a suffix to
* denote when the string has been truncated.
* @return {String} The truncated string.
* @api public
* @example {{truncateWords 'foo bar baz' 1 }} -> foo…
*/
helpers.truncateWords = function(str, count, suffix) {
if (util.isString(str) && !isNaN(count)) {
if (typeof suffix !== 'string') {
suffix = '…';
}
var num = Number(count);
var arr = str.split(/[ \t]/);
if (num >= arr.length) {
return str;
}
arr = arr.slice(0, num);
var val = arr.join(' ').trim();
return val + suffix;
}
};
/**
* Uppercase all of the characters in the given string. Alias for [uppercase](#uppercase).
*
* ```handlebars
* {{upcase 'aBcDeF'}}
* <!-- results in: 'ABCDEF' -->
* ```
* @param {String} `string`
* @return {String}
* @alias uppercase
* @api public
* @example {{upcase 'aBcDef'}} -> ABCDEF
*/
helpers.upcase = function() {
return helpers.uppercase.apply(this, arguments);
};
/**
* Uppercase all of the characters in the given string. If used as a
* block helper it will uppercase the entire block. This helper
* does not support inverse blocks.
*
* ```handlebars
* {{uppercase 'aBcDeF'}}
* <!-- results in: 'ABCDEF' -->
* ```
* @related capitalize capitalizeAll
* @param {String} `str` The string to uppercase
* @param {Object} `options` Handlebars options object
* @return {String}
* @block
* @inline
* @api public
* @example {{uppercase 'aBcDef'}} -> ABCDEF
*/
helpers.uppercase = function(str) {
if (util.isObject(str) && str.fn) {
return str.fn(this).toUpperCase();
}
if (typeof(str) !== 'string') return '';
return str.toUpperCase();
};
/**
* Takes a number and returns that many charaters of Lorem Ipsum
*
* ```handlebars
* {{lorem 11}}
* <!-- results in: 'Lorem Ipsum' -->
* ```
* @param {Number} `[num=11]`
* @return {String}
* @block
* @inline
* @api public
* @example {{lorem 11}} -> Lorem ipsum
*/
helpers.lorem = function(num) {
// Sad Path - Not a number, or not greater than 1, or not truthy
if (isNaN(num) || num < 1 || !num) {
num = 11;
}
return lorem.substring(0, num);
};