matches.forEach(function(m) { // Linkify the trimmed URL linkifyUrl(m[0][1], trimUrl(m[0][0])); }); /** * Linkify given URL at given position * * @param {number} tagPos URL's position in the text * @param {string} url URL */ function linkifyUrl(tagPos, url) { // Create a zero-width end tag right after the URL var endPos = tagPos + url.length, endTag = addEndTag(config.tagName, endPos, 0); // If the URL starts with "www." we prepend "http://" if (url[3] === '.') { url = 'http://' + url; } // Create a zero-width start tag right before the URL, with a slightly worse priority to // allow specialized plugins to use the URL instead var startTag = addStartTag(config.tagName, tagPos, 0, 1); startTag.setAttribute(config.attrName, url); // Pair the tags together startTag.pairWith(endTag); // Protect the tag's content from partial replacements with a low priority tag var contentTag = addVerbatim(tagPos, endPos - tagPos, 1000); startTag.cascadeInvalidationTo(contentTag); } /** * Remove trailing punctuation from given URL * * We remove most ASCII non-letters from the end of the string. * Exceptions: * - dashes and underscores, (base64 IDs could end with one) * - equal signs, (because of "foo?bar=") * - plus signs, (used by some file share services to force download) * - trailing slashes, * - closing parentheses. (they are balanced separately) * * @param {string} url Original URL * @return {string} Trimmed URL */ function trimUrl(url) { return url.replace(/(?:(?![-=+)\/_])[\s!-.:-@[-`{-~])+$/, ''); }