The most compact and readable string clamping/truncation approach (in JS)

At least, the best I've created so far!

There are many ways to limit the size of a given piece of content - a process usually called truncation or clamping. CSS Tricks has a bunch of interesting approaches and there are tons of libraries out there to do it, from lodash.truncate to React-specific components to thousands of others.

I started doing this with the naive str.slice(0, maxLength) + "...", but that will add ellipsis even to text that is smaller than maxLength.

Adding a if (str.length < maxLength) return str conditional is a good step, but then you'll find some words are truncated in hal...

Frustrating, right?

To fix this, I created this crazy complex function that would increase the truncated string until it found a whitespace, at which point it'd return to ensure only whole words were displayed. It worked across many projects for over a year, but felt kinda yucky.

Now that I'm a little more comfortable with RegEx I figured that there must be a better way. The answer came through the power of String.prototype.search():

export function truncate(str: string, maxLength: number) {
  if (str.length < maxLength) {
  	return str;
  }
  
  // To prevent truncating in the middle of words, let's get
  // the position of the first whitespace after the truncation
  const firstWhitespaceAfterTruncation = str.slice(maxLength).search(/\s/) + maxLength;
  
  return str.slice(0, firstWhitespaceAfterTruncation) + '...';
}

11 lines of code including comments and tons of whitespace! I'll definitely drag this around all of my projects - hope it's useful to you :)

PS: technically I'm not respecting the maxLength in this code, but I'm okay with the small deviation this brings.

If you must have maxLength as the absolute maximum length of strings, you could use String.matchAll() to check the index of the last whitespace right before the original target truncation, and use that as the value for str.slice(0, truncationTarget) 😉