Function that returns words in string not exceeding max number of characters I'm trying to create a robust function that receives a string -- typically a paragraph or two -- and the max number of characters in the output. One condition is to make sure that we return full words and never cut one in half.

Here's the code I have and I feel it needs to be improved. This is normal ES2015/ES6 with no additional libraries.

export const shortenTextToSpecifiedNumberOfCharacters = (input, numberOfCharacters) =&gt; {

    if (!input) return "";
    else if (input.length &lt;= numberOfCharacters) return input;

    for (var i = numberOfCharacters; i &gt; 0; i--) {
        if (input[i] == ' ') {
            return input.slice(0, i) + ' ...';
        }
    }

}
You code can end up falling out of the loop and implicitly returning undefined if there are no spaces within the first numberOfCharacters characters in the input string.  You might want to add an explicit return statement at the end of the function to handle that case.

Also, in your loop you only test for spaces, not for newlines, tabs or other whitespace characters.  You could simply add tests for those into your if statement, like this:

if (input[i] == ' ' || input[i] == '\t' || input[i] == '\r' || input[i] == '\n') {


but it would be shorter and cleaner to use either indexOf():

if (" \t\r\n".indexOf(input[i]) &gt;= 0) {


or a regexp test:

if (/\s/.test(input[i])) {


You may also wish to ensure that input[i-1] is not a whitespace character.  You could do it like this:

const spaces = " \t\r\n";
for (var i = numberOfCharacters; i &gt; 1; i--) {
    if (spaces.indexOf(input[i]) &gt;= 0 &amp;&amp; spaces.indexOf(input[i-1]) &lt; 0) {
        return input.slice(0, i) + ' ...';
    }
}


or, using a regexp, like this:

for (var i = numberOfCharacters; i &gt; 1; i--) {
    if (/\S\s/.test(input.slice(i-1, i+1))) {
        return input.slice(0, i) + ' ...';
    }
}


Also note that the output of your function may be up to 4 characters (the length of the " ..." suffix) longer than the specified length limit.  If that's not what you want, you may wish to change your for loop to:

for (var i = numberOfCharacters - 4; i &gt; 1; i--) {