Skip to content

Instantly share code, notes, and snippets.

@larzconwell
Created June 19, 2012 00:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save larzconwell/2951662 to your computer and use it in GitHub Desktop.
Save larzconwell/2951662 to your computer and use it in GitHub Desktop.
/*
* Truncate(string<String>, options<Object>, callback[Function])
*
* Truncates a given `string` after a specified `length` if `string` is longer than
* `length`. The last characters will be replaced with an `omission` for a total length not
* exceeding `length`. If `callback` is given it will fire if `string` is truncated.
*
* Options:
* length <Integer> Length the output string will be(default: 30)
* omission <String> Replace last letters with an omission(default: '...')
* ellipsis <String> Alias for omission
* seperator <String>/<RegExp> Break the truncated text at the nearest `seperator`
*
* Warnings:
* Please be aware that truncating HTML tags or entities may result in malformed HTML returned
*
* Examples:
* truncate('Once upon a time in a world', { length: 10 })
* => 'Once upo...'
*
* truncate('Once upon a time in a world', { length: 20, omission: '...(continued)' })
* => 'Once u...(continued)'
*
* truncate('Once upon a time in a world', { length: 15, seperator: ' ' })
* => 'Once upon a...'
* Normal Output: => 'Once upon a ...'
*/
exports.truncate = {
name: 'truncate',
action: function(string, options, callback) {
if(!string) return;
options = options || {};
// Set `options` defaults
options.length = options.length || 30;
options.omission = options.omission || options.ellipsis || '...';
if(typeof options.escape === 'undefined') options.escape = true;
var stringLen = string.length
, stringLenWithOmission = options.length - options.omission.length
, last;
// Set the index to stop at for `string`
if(options.seperator) {
if(options.seperator instanceof RegExp) {
// If `options.seperator` is a regex search
if(options.seperator.global) {
options.seperator = options.seperator;
} else {
var ignoreCase = options.seperator.ignoreCase ? 'i' : ''
, multiLine = options.seperator.multiLine ? 'm' : '';
options.seperator = new RegExp(options.seperator.source, 'g' + ignoreCase + multiLine);
}
var stringToWorkWith = string.substring(0, stringLenWithOmission + 1)
, lastIndexOf = -1
, nextStop = 0
, result;
while((result = options.seperator.exec(stringToWorkWith)) !== null) {
lastIndexOf = result.index;
options.seperator.lastIndex = ++nextStop;
}
last = lastIndexOf;
} else {
last = string.lastIndexOf(options.seperator, stringLenWithOmission);
}
// If the above couldn't be found, they'll default to -1 so, we need to just set
// - it as `stringLenWithOmission`
if(last === -1) last = stringLenWithOmission;
} else last = stringLenWithOmission;
if(stringLen < options.length) return string;
return string.substring(0, last) + options.omission;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment