@helpscout/hsds-react
Version:
React component library for Help Scout's Design System
186 lines (143 loc) • 4.54 kB
JavaScript
exports.__esModule = true;
exports.convertLinksToHTML = exports.escapeHTML = exports.repeat = exports.newlineToHTML = void 0;
var _urls = require("./urls");
var newlineToHTML = function newlineToHTML(string) {
if (!string) {
return '';
}
return string.trim().replace(/\r?\n/g, '<br>');
}; // TODO: Remove, used in Beacon (src/constants/UI.Layers.js)
/**
* Fast way to repeat a string character.
* @param {string} pattern
* @param {number} count
* @returns {string}
*/
exports.newlineToHTML = newlineToHTML;
var repeat = function repeat(pattern, count) {
if (count < 1) return '';
var result = '';
while (count > 1) {
if (count & 1) {
result += pattern;
}
count >>= 1;
if (count <= 0) break;
pattern += pattern;
}
return result + pattern;
}; // Taken from the React escapeTextForBrowser internal utility
exports.repeat = repeat;
var escapeHtmlRegExp = /["'&<>]/;
/**
* Escape HTML special characters in the string for output in the browser.
*
* @param {string} string
* @returns {string}
*/
var escapeHTML = function escapeHTML(string) {
if (!string) {
return '';
}
var match = escapeHtmlRegExp.exec(string);
if (!match) {
return string;
}
var escape;
var html = '';
var index;
var lastIndex = 0;
for (index = match.index; index < string.length; index++) {
switch (string.charCodeAt(index)) {
case 34:
// "
escape = '"';
break;
case 38:
// &
escape = '&';
break;
case 39:
// '
escape = ''';
break;
case 60:
// <
escape = '<';
break;
case 62:
// >
escape = '>';
break;
default:
continue;
}
if (lastIndex !== index) {
html += string.substring(lastIndex, index);
}
lastIndex = index + 1;
html += escape;
}
return lastIndex !== index ? html + string.substring(lastIndex, index) : html;
};
/**
* The string form of a regular expression that would match all of the
* letters, combining marks, and decimal number chars in the unicode character
* set within a URL.
*/
exports.escapeHTML = escapeHTML;
var alphaNumericAndMarksChars = 'a-z0-9\\-+&@#/%=~_';
/**
* Partial regex pattern to match the TLD of a domain.
*
* Maximum length for a TLD is currently 24 characters.
* See: as shown in http://data.iana.org/TLD/tlds-alpha-by-domain.txt
*/
var tldPattern = '[a-z]{2,24}';
/**
* Partial regex pattern to match the domain part of a URL without the subdomain.
*/
var domainPattern = '[a-z0-9-]+\\.' + tldPattern;
/**
* Partial regex pattern to match the path of a URL.
*/
var pathPattern = '(?:[/?#](?:[' + alphaNumericAndMarksChars + "\\(\\)|'$*\\[\\]?!:,.;]*[" + alphaNumericAndMarksChars + "|'$*\\[\\]])?)?)";
/**
* Regex pattern to match a complete URL.
*/
var urlPattern = '(?:(?:(?:https?:\\/\\/(?:[a-z0-9-]+\\.)*)|(?:[a-z0-9-]+\\.)+)?' + domainPattern + pathPattern;
/**
* Regex pattern to match an email address.
*/
var emailPattern = "(?:\\b[a-z0-9._'%+-]+@[a-z0-9.-]+\\." + tldPattern + ')';
/**
* @param {string} string
*
* @returns {string}
*/
var convertLinksToHTML = function convertLinksToHTML(string) {
if (!string) {
return '';
}
return string.split(new RegExp("(" + urlPattern + "|" + emailPattern + ")", 'gi')).reduce(function (accumulator, value, index) {
if (index % 2) {
if (value.match(new RegExp("^" + emailPattern + "$", 'i'))) {
// Matched an email
return accumulator + ("<a href=\"mailto:" + escapeHTML(value) + "\">" + escapeHTML(value) + "</a>");
} // Matched a URL
var url = value;
if (url.match(new RegExp("^" + domainPattern + "$", 'i'))) {
// Only matched a domain name (without subdomain)
// Skip this as it could be the end/start of a sentence without whitespace.
// For example with "Hello Tom.how are you?" we should not match "Tom.how"
return accumulator + url;
} // Add http as the default scheme if needed
url = (0, _urls.normalizeUrl)(url); // Adding target blank and rel noopener for external links
// See: https://developers.google.com/web/tools/lighthouse/audits/noopener
return accumulator + ("<a href=\"" + escapeHTML(url) + "\" target=\"_blank\" rel=\"noopener\">" + escapeHTML(value) + "</a>");
}
return accumulator + escapeHTML(value);
}, '');
};
exports.convertLinksToHTML = convertLinksToHTML;
;