Split text into equal length strings keeping words intact
Here's how to fix the original code:
Add the following after line 40:
in_text = false;
The in_text
flag is used by the code to determine if the current position is in regular text. However, it was not clearing the flag when it entered a region of formatting markup. This was the cause care of the main issue described in the question with the ultra-short line.
Change the if statement at line 76/77 to:
if (is_space() && ((formatting && in_text) || !formatting || (line[j] === '[' && line[j+1] === '['))) {
This takes care of a lesser problem where line breaks were not happening on spaces between regular text and formatted text.
Working fiddle here: https://jsfiddle.net/2w10xp3m/1/
I think I've solved the problem using a much simpler approach. First break up all words, then re-assemble the lines while keeping track of the current format. See JsFiddle.
JavaScript
$.terminal.split_equal = function(str, length, words) {
var result = [],
currentFormat = null,
currentLine = '',
currentLineLengthWithoutFormatting = 0;
// 1. Split words on
words = str.split(/ /g);
// 2. Re-assemble lines while keeping track of current formats
words.forEach(function(word) {
// Keep track of current format
var format = word.match(/^\[\[([^\]]+)\]/g),
wordWithFormatting, wordLength;
if (format !== null && format[0]) {
currentFormat = format[0];
word = word.slice(format[0].length);
}
// Apply current format to each word separatly
wordLength = word.length;
wordWithFormatting = (currentFormat || '') + word;
if (currentFormat) {
if (word.indexOf(']') !== -1) {
wordLength--;
currentFormat = null;
} else {
wordWithFormatting += ']';
}
}
// Assemble line
if (currentLineLengthWithoutFormatting + wordLength <= length) {
// Word still fits on current line
if (currentLineLengthWithoutFormatting > 0) {
currentLine += ' ';
currentLineLengthWithoutFormatting++;
}
} else {
// Need to start new line
result.push(currentLine);
currentLine = '';
currentLineLengthWithoutFormatting = 0;
}
currentLine += wordWithFormatting;
currentLineLengthWithoutFormatting += wordLength;
});
if (currentLineLengthWithoutFormatting > 0)
result.push(currentLine);
return result;
};