Skip to content

Instantly share code, notes, and snippets.

@stedman
Last active December 3, 2019 21:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stedman/b49c280f4a200a1d75b72ffb4c066dd6 to your computer and use it in GitHub Desktop.
Save stedman/b49c280f4a200a1d75b72ffb4c066dd6 to your computer and use it in GitHub Desktop.
Insert optional HTML content break points to improve word wrap appearance.
/**
* HTML content doesn't always break where we want it to--especially when long,
* unbroken strings are present. If we want HTML to optionally break at certain
* pre-determined points, we add <wbr> (word break oppportunity) tags.
*
* This utility adds <wbr> tags after a specified content length and character.
*
* For example, given the following string:
* https://github.com/stedman/long-hash/raw/file-name.js
* ...if we want to gracefully break after 30 characters and a forward slash (/),
* the HTML would need to look like:
* https://github.com/stedman/long-hash/<wbr>raw/<wbr>file-name.js
*
* Reference: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/wbr
*
* @param {String} content Raw content to insert <wbr> into.
* @param {Object} options
* @param {Number} [options.cutLength=30] Length of content allowed before inserting <wbr>.
* @param {String} [options.cutChar='/'] Character(s) to insert <wbr> after.
*
* @return {String} Content with <wbr> tags added.
*/
function breakSoftly(_content, _options) {
let content = _content || '';
const options = _options || {};
const cutLength = options.cutLength || 30;
const cutChar = options.cutChar || '/';
// Exit if content isn't long enough.
if (content.length <= cutLength) {
return content.trim();
}
// Use the cutLength as the loop starting point.
let index = cutLength;
// Loop over the character matches until none remain.
while ((index = content.indexOf(cutChar, index + 1)) !== -1) {
const lookbehind = content[index - 1];
const lookahead = content[index + 1];
// If there's a left bracket (the start of an HTML element), skip this replacement.
// If there's a leading or trailing space, skip replacement -- browsers already break on spaces.
if (lookbehind !== '<' && lookbehind !== ' ' && lookahead !== ' ') {
// Splice content together:
// 1) from the start to the point where the cutChar was found
// 2) the cutChar and inserted <wbr> tag
// 3) the rest of the original content following the cutChar
content = content.substring(0, index) + cutChar + '<wbr>' + content.substring(index + 1);
}
}
return content.trim();
}
@stedman
Copy link
Author

stedman commented Dec 3, 2019

FWIW, the original regex replace took about twice as long to run as the while loop.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment