I'm trying to evenly balance text over multiple lines using only JavaScript and without caring about the complexity of font sizes.
Given an input string and the maximum1 amount of characters in each line, how can I evenly balance2 the text over the minimum amount of lines?
I'm using an up-to-date version of Google Chrome and legacy browser support isn't important to my question.
Below is my attempt without trying to balance the text (which I want but I don't know how to go about doing it).
It might be possible to remove one or both of the replace()
methods by changing the RegExp's string in the match()
method.
const stringInputsAndExpectedArrayOutputs = [
['', ['']],
[' ', ['']],
[' ', ['']],
['.', ['.']],
['The ', ['The']],
['The quick\nbrown fox', ['The quick brown', 'fox']],
['Thequickbrownfox jumpsoverthelazydog.', ['Thequickbrownfox', 'jumpsoverthelazydog.']],
[' The quick brown fox jumps over the lazy dog. ', ['The quick brown', 'fox jumps over', 'the lazy dog.']],
['The quick brown fox jumps over the lazy dog.', ['The quick brown', 'fox jumps over', 'the lazy dog.']]
];
const maximumCharactersPerLine = 15;
const distributeTextOverLines = ((stringInput, maximumCharactersPerLine) => {
let arrayOutput = stringInput.replace(/[\r\n ]+$/g, '').replace(/[\r\n ]{2,}|[\r\n]/g, ' ');
arrayOutput = arrayOutput.match(new RegExp(`(?! )(?:.{1,${maximumCharactersPerLine}}|[^ ]+)(?= |$)`, 'g')) || [''];
return arrayOutput;
});
for (const [stringInput, expectedArrayOutput] of stringInputsAndExpectedArrayOutputs) {
const arrayOutput = distributeTextOverLines(stringInput, maximumCharactersPerLine);
const arrayOutputDifferentThanExpected = !(arrayOutput.length === expectedArrayOutput.length && arrayOutput.every((value, index) => value === expectedArrayOutput[index]));
if (arrayOutputDifferentThanExpected) {
console.log('array output:');
console.log(arrayOutput);
console.log('expected array output:');
console.log(expectedArrayOutput);
continue;
}
const stringOutput = arrayOutput.join('\n');
console.log('string output:');
console.log(stringOutput);
}
.as-console-wrapper {
max-height: 100% !important;
top: 0;
}
1 If a word is longer than the maximum limit then the line must contain the whole word overflowing it.
2 Distribute the text in a way so that each line has as similar amount of characters as the other ones have as possible which makes the width of all the lines together as small as possible.