enigma-bbs/core/word_wrap.js

108 lines
2.8 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* jslint node: true */
'use strict';
var assert = require('assert');
var _ = require('lodash');
exports.wordWrapText = wordWrapText;
function wordWrapText(text, options) {
//
// options.*:
// width : word wrap width
// tabHandling : expand (default=expand)
// tabWidth : tab width if tabHandling is 'expand' (default=4)
// tabChar : character to use for tab expansion
//
assert(_.isObject(options), 'Missing options!');
assert(_.isNumber(options.width), 'Missing options.width!');
options.tabHandling = options.tabHandling || 'expand';
if(!_.isNumber(options.tabWidth)) {
options.tabWidth = 4;
}
options.tabChar = options.tabChar || ' ';
//
// Notes
// * Sublime Text 3 for example considers spaces after a word
// part of said word. For example, "word " would be wraped
// in it's entirity.
//
// * Tabs in Sublime Text 3 are also treated as a word, so, e.g.
// "\t" may resolve to " " and must fit within the space.
//
// * If a word is ultimately too long to fit, break it up until it does.
//
// RegExp below is JavaScript '\s' minus the '\t'
//
var re = new RegExp(
'\t|[ \f\n\r\v\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006' +
'\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]', 'g');
var m;
var wordStart = 0;
var results = { wrapped : [ '' ] };
var i = 0;
var word;
var wordLen;
function expandTab(col) {
var remainWidth = options.tabWidth - (col % options.tabWidth);
return new Array(remainWidth).join(options.tabChar);
}
// :TODO: support wrapping pipe code text (e.g. ignore color codes, expand MCI codes)
function addWord() {
word.match(new RegExp('.{0,' + options.width + '}', 'g')).forEach(function wrd(w) {
//wordLen = self.getStringLength(w);
if(results.wrapped[i].length + w.length > options.width) {
//if(results.wrapped[i].length + wordLen > width) {
if(0 === i) {
results.firstWrapRange = { start : wordStart, end : wordStart + w.length };
//results.firstWrapRange = { start : wordStart, end : wordStart + wordLen };
}
results.wrapped[++i] = w;
} else {
results.wrapped[i] += w;
}
});
}
while((m = re.exec(text)) !== null) {
word = text.substring(wordStart, re.lastIndex - 1);
switch(m[0].charAt(0)) {
case ' ' :
word += m[0];
break;
case '\t' :
//
// Expand tab given position
//
// Nice info here: http://c-for-dummies.com/blog/?p=424
//
if('expand' === options.tabHandling) {
word += expandTab(results.wrapped[i].length + word.length) + options.tabChar;
} else {
word += m[0];
}
break;
}
addWord();
wordStart = re.lastIndex + m[0].length - 1;
}
//
// Remainder
//
word = text.substring(wordStart);
addWord();
return results;
}