diff --git a/dev/Common/Utils.js b/dev/Common/Utils.js index b7a5a32d8..2ff896e9e 100644 --- a/dev/Common/Utils.js +++ b/dev/Common/Utils.js @@ -1596,16 +1596,6 @@ 'twitter': false }); -// if ($.fn && $.fn.linkify) -// { -// sHtml = Globals.$div.html(sHtml.replace(/&/ig, 'amp_amp_12345_amp_amp')) -// .linkify() -// .find('.linkified').removeClass('linkified').end() -// .html() -// .replace(/amp_amp_12345_amp_amp/g, '&') -// ; -// } - return sHtml; }; diff --git a/vendors/Autolinker/Autolinker.js b/vendors/Autolinker/Autolinker.js index bfd4af1de..5b91fa54e 100644 --- a/vendors/Autolinker/Autolinker.js +++ b/vendors/Autolinker/Autolinker.js @@ -1,6 +1,6 @@ /*! * Autolinker.js - * 0.11.0 + * 0.11.2 * * Copyright(c) 2014 Gregory Jacobs * MIT Licensed. http://www.opensource.org/licenses/mit-license.php @@ -8,9 +8,8 @@ * https://github.com/gregjacobs/Autolinker.js */ /*global define, module */ -/*jshint undef:true, smarttabs:true */ -// Set up Autolinker appropriately for the environment. ( function( root, factory ) { + if( typeof define === 'function' && define.amd ) { define( factory ); // Define as AMD module if an AMD loader is present (ex: RequireJS). } else if( typeof exports !== 'undefined' ) { @@ -19,7 +18,7 @@ root.Autolinker = factory(); // Finally, define as a browser global if no module loader. } }( this, function() { - + /** * @class Autolinker * @extends Object @@ -54,17 +53,34 @@ * @param {Object} [config] The configuration options for the Autolinker instance, specified in an Object (map). */ var Autolinker = function( cfg ) { - cfg = cfg || {}; - - // Assign the properties of `cfg` onto the Autolinker instance - for( var prop in cfg ) - if( cfg.hasOwnProperty( prop ) ) this[ prop ] = cfg[ prop ]; + Autolinker.Util.assign( this, cfg ); // assign the properties of `cfg` onto the Autolinker instance. Prototype properties will be used for missing configs. }; Autolinker.prototype = { constructor : Autolinker, // fix constructor property + /** + * @cfg {Boolean} urls + * + * `true` if miscellaneous URLs should be automatically linked, `false` if they should not be. + */ + urls : true, + + /** + * @cfg {Boolean} email + * + * `true` if email addresses should be automatically linked, `false` if they should not be. + */ + email : true, + + /** + * @cfg {Boolean} twitter + * + * `true` if Twitter handles ("@example") should be automatically linked, `false` if they should not be. + */ + twitter : true, + /** * @cfg {Boolean} newWindow * @@ -75,7 +91,8 @@ /** * @cfg {Boolean} stripPrefix * - * `true` if 'http://' or 'https://' and/or the 'www.' should be stripped from the beginning of links, `false` otherwise. + * `true` if 'http://' or 'https://' and/or the 'www.' should be stripped from the beginning of URL links' text, + * `false` otherwise. */ stripPrefix : true, @@ -84,33 +101,12 @@ * * A number for how many characters long URLs/emails/twitter handles should be truncated to inside the text of * a link. If the URL/email/twitter is over this number of characters, it will be truncated to this length by - * adding a two period ellipsis ('..') into the middle of the string. + * adding a two period ellipsis ('..') to the end of the string. * * For example: A url like 'http://www.yahoo.com/some/long/path/to/a/file' truncated to 25 characters might look - * something like this: 'http://www...th/to/a/file' + * something like this: 'yahoo.com/some/long/pat..' */ - /** - * @cfg {Boolean} twitter - * - * `true` if Twitter handles ("@example") should be automatically linked, `false` if they should not be. - */ - twitter : true, - - /** - * @cfg {Boolean} email - * - * `true` if email addresses should be automatically linked, `false` if they should not be. - */ - email : true, - - /** - * @cfg {Boolean} urls - * - * `true` if miscellaneous URLs should be automatically linked, `false` if they should not be. - */ - urls : true, - /** * @cfg {String} className * @@ -126,6 +122,45 @@ className : "", + /** + * @private + * @property {RegExp} htmlRegex + * + * The regular expression used to pull out HTML tags from a string. Handles namespaced HTML tags and + * attribute names, as specified by http://www.w3.org/TR/html-markup/syntax.html. + * + * Capturing groups: + * + * 1. If it is an end tag, this group will have the '/'. + * 2. The tag name. + */ + htmlRegex : (function() { + var tagNameRegex = /[0-9a-zA-Z:]+/, + attrNameRegex = /[^\s\0"'>\/=\x01-\x1F\x7F]+/, // the unicode range accounts for excluding control chars, and the delete char + attrValueRegex = /(?:".*?"|'.*?'|[^'"=<>`\s]+)/, // double quoted, single quoted, or unquoted attribute values + nameEqualsValueRegex = attrNameRegex.source + '(?:\\s*=\\s*' + attrValueRegex.source + ')?'; // optional '=[value]' + + return new RegExp( [ + '<(?:!|(/))?', // Beginning of a tag. Either '<' for a start tag, ' tag. The slash or an empty string is Capturing Group 1. + + // The tag name (Capturing Group 2) + '(' + tagNameRegex.source + ')', + + // Zero or more attributes following the tag name + '(?:', + '\\s+', // one or more whitespace chars before an attribute + + // Either: + // A. tag="value", or + // B. "value" alone (for tag. Ex: ) + '(?:', nameEqualsValueRegex, '|', attrValueRegex.source + ')', + ')*', + + '\\s*/?', // any trailing spaces and optional '/' before the closing '>' + '>' + ].join( "" ), 'g' ); + } )(), + /** * @private * @property {RegExp} matcherRegex @@ -212,58 +247,31 @@ /** * @private - * @property {RegExp} protocolRelativeRegex + * @property {RegExp} invalidProtocolRelMatchRegex * - * The regular expression used to find protocol-relative URLs. A protocol-relative URL is, for example, "//yahoo.com" + * The regular expression used to check a potential protocol-relative URL match, coming from the {@link #matcherRegex}. + * A protocol-relative URL is, for example, "//yahoo.com" * - * This regular expression needs to match the character before the '//', in order to determine if we should actually - * autolink a protocol-relative URL. For instance, we want to autolink something like "//google.com", but we - * don't want to autolink something like "abc//google.com" + * This regular expression is used in conjunction with the {@link #matcherRegex}, and checks to see if there is a word character + * before the '//' in order to determine if we should actually autolink a protocol-relative URL. This is needed because there + * is no negative look-behind in JavaScript regular expressions. + * + * For instance, we want to autolink something like "//google.com", but we don't want to autolink something + * like "abc//google.com" */ - protocolRelativeRegex : /(.)?\/\//, + invalidProtocolRelMatchRegex : /^[\w]\/\//, /** * @private - * @property {RegExp} htmlRegex + * @property {RegExp} charBeforeProtocolRelMatchRegex * - * The regular expression used to pull out HTML tags from a string. Handles namespaced HTML tags and - * attribute names, as specified by http://www.w3.org/TR/html-markup/syntax.html. + * The regular expression used to retrieve the character before a protocol-relative URL match. * - * Capturing groups: - * - * 1. If it is an end tag, this group will have the '/'. - * 2. The tag name. + * This is used in conjunction with the {@link #matcherRegex}, which needs to grab the character before a protocol-relative + * '//' due to the lack of a negative look-behind in JavaScript regular expressions. The character before the match is stripped + * from the URL. */ - htmlRegex : (function() { - var tagNameRegex = /[0-9a-zA-Z:]+/, - attrNameRegex = /[^\s\0"'>\/=\x01-\x1F\x7F]+/, // the unicode range accounts for excluding control chars, and the delete char - attrValueRegex = /(?:".*?"|'.*?'|[^'"=<>`\s]+)/; // double quoted, single quoted, or unquoted attribute values - - return new RegExp( [ - '<(/)?', // Beginning of a tag. Either '<' for a start tag, or '' - '>' - ].join( "" ), 'g' ); - } )(), - - /** - * @private - * @property {RegExp} urlPrefixRegex - * - * A regular expression used to remove the 'http://' or 'https://' and/or the 'www.' from URLs. - */ - urlPrefixRegex: /^(https?:\/\/)?(www\.)?/i, + charBeforeProtocolRelMatchRegex : /^(.)?\/\//, /** @@ -282,6 +290,27 @@ }, + /** + * Lazily instantiates and returns the {@link #anchorTagBuilder} instance for this Autolinker instance. + * + * @return {Autolinker.AnchorTagBuilder} + */ + getAnchorTagBuilder : function() { + var anchorTagBuilder = this.anchorTagBuilder; + + if( !anchorTagBuilder ) { + anchorTagBuilder = this.anchorTagBuilder = new Autolinker.AnchorTagBuilder( { + newWindow : this.newWindow, + stripPrefix : this.stripPrefix, + truncate : this.truncate, + className : this.className + } ); + } + + return anchorTagBuilder; + }, + + /** * Processes the given HTML to auto-link URLs/emails/Twitter handles. * @@ -355,35 +384,28 @@ * @return {String} The text with anchor tags auto-filled. */ processTextNode : function( text ) { - var me = this, // for closures - matcherRegex = this.matcherRegex, - enableTwitter = this.twitter, - enableEmailAddresses = this.email, - enableUrls = this.urls; + var me = this, // for closure + invalidProtocolRelMatchRegex = this.invalidProtocolRelMatchRegex, + charBeforeProtocolRelMatchRegex = this.charBeforeProtocolRelMatchRegex, + anchorTagBuilder = this.getAnchorTagBuilder(); - return text.replace( matcherRegex, function( matchStr, $1, $2, $3, $4, $5, $6, $7 ) { + return text.replace( this.matcherRegex, function( matchStr, $1, $2, $3, $4, $5, $6, $7 ) { var twitterMatch = $1, twitterHandlePrefixWhitespaceChar = $2, // The whitespace char before the @ sign in a Twitter handle match. This is needed because of no lookbehinds in JS regexes - twitterHandle = $3, // The actual twitterUser (i.e the word after the @ sign in a Twitter handle match) - emailAddress = $4, // For both determining if it is an email address, and stores the actual email address - urlMatch = $5, // The matched URL string + twitterHandle = $3, // The actual twitterUser (i.e the word after the @ sign in a Twitter handle match) + emailAddressMatch = $4, // For both determining if it is an email address, and stores the actual email address + urlMatch = $5, // The matched URL string protocolRelativeMatch = $6 || $7, // The '//' for a protocol-relative match, with the character that comes before the '//' prefixStr = "", // A string to use to prefix the anchor tag that is created. This is needed for the Twitter handle match - suffixStr = ""; // A string to suffix the anchor tag that is created. This is used if there is a trailing parenthesis that should not be auto-linked. + suffixStr = "", // A string to suffix the anchor tag that is created. This is used if there is a trailing parenthesis that should not be auto-linked. + + match; // Will be an Autolinker.Match object - // Early exits with no replacements for: - // 1) Disabled link types - // 2) URL matches which do not have at least have one period ('.') in the domain name (effectively skipping over - // matches like "abc:def") - // 3) A protocol-relative url match (a URL beginning with '//') whose previous character is a word character - // (effectively skipping over strings like "abc//google.com") - if( - ( twitterMatch && !enableTwitter ) || ( emailAddress && !enableEmailAddresses ) || ( urlMatch && !enableUrls ) || - ( urlMatch && urlMatch.indexOf( '.' ) === -1 ) || // At least one period ('.') must exist in the URL match for us to consider it an actual URL - ( urlMatch && /^[A-Za-z]{3,9}:/.test( urlMatch ) && !/:.*?[A-Za-z]/.test( urlMatch ) ) || // At least one letter character must exist in the domain name after a protocol match. Ex: skip over something like "git:1.0" - ( protocolRelativeMatch && /^[\w]\/\//.test( protocolRelativeMatch ) ) // a protocol-relative match which has a word character in front of it (so we can skip something like "abc//google.com") - ) { + + // Return out with no changes for match types that are disabled (url, email, twitter), or for matches + // that are invalid. + if( !me.isValidMatch( twitterMatch, emailAddressMatch, urlMatch, protocolRelativeMatch ) ) { return matchStr; } @@ -406,60 +428,226 @@ } - var anchorHref = matchStr, // initialize both of these - anchorText = matchStr, // values as the full match - linkType; - - // Process the urls that are found. We need to change URLs like "www.yahoo.com" to "http://www.yahoo.com" (or the browser - // will try to direct the user to "http://current-domain.com/www.yahoo.com"), and we need to prefix 'mailto:' to email addresses. if( twitterMatch ) { - linkType = 'twitter'; prefixStr = twitterHandlePrefixWhitespaceChar; - anchorHref = 'https://twitter.com/' + twitterHandle; - anchorText = '@' + twitterHandle; + match = new Autolinker.TwitterMatch( { twitterHandle: twitterHandle } ); - } else if( emailAddress ) { - linkType = 'email'; - anchorHref = 'mailto:' + emailAddress; - anchorText = emailAddress; + } else if( emailAddressMatch ) { + match = new Autolinker.EmailMatch( { emailAddress: emailAddressMatch } ); } else { // url match - linkType = 'url'; - + // If it's a protocol-relative '//' match, remove the character before the '//' (which the matcherRegex needed + // to match due to the lack of a negative look-behind in JavaScript regular expressions) if( protocolRelativeMatch ) { - // Strip off any protocol-relative '//' from the anchor text (leaving the previous non-word character - // intact, if there is one) - var protocolRelRegex = new RegExp( "^" + me.protocolRelativeRegex.source ), // for this one, we want to only match at the beginning of the string - charBeforeMatch = protocolRelativeMatch.match( protocolRelRegex )[ 1 ] || ""; + var charBeforeMatch = protocolRelativeMatch.match( charBeforeProtocolRelMatchRegex )[ 1 ] || ""; - prefixStr = charBeforeMatch + prefixStr; // re-add the character before the '//' to what will be placed before the tag - anchorHref = anchorHref.replace( protocolRelRegex, "//" ); // remove the char before the match for the href - anchorText = anchorText.replace( protocolRelRegex, "" ); // remove both the char before the match and the '//' for the anchor text - - } else if( !/^[A-Za-z]{3,9}:/i.test( anchorHref ) ) { - // url string doesn't begin with a protocol, assume http:// - anchorHref = 'http://' + anchorHref; + if( charBeforeMatch ) { + prefixStr = charBeforeMatch; // re-add the character before the '//' to what will be placed before the generated tag + matchStr = matchStr.slice( 1 ); + } } + + match = new Autolinker.UrlMatch( { url: matchStr, protocolRelativeMatch: protocolRelativeMatch } ); } - + // wrap the match in an anchor tag - var anchorTag = me.createAnchorTag( linkType, anchorHref, anchorText ); + var anchorTag = anchorTagBuilder.createAnchorTag( match.getType(), match.getAnchorHref(), match.getAnchorText() ); return prefixStr + anchorTag + suffixStr; } ); }, /** - * Generates the actual anchor (<a>) tag to use in place of a source url/email/twitter link. + * Determines if a given match found by {@link #processTextNode} is valid. Will return `false` for: + * + * 1) Disabled link types (i.e. having a Twitter match, but {@link #twitter} matching is disabled) + * 2) URL matches which do not have at least have one period ('.') in the domain name (effectively skipping over + * matches like "abc:def") + * 3) A protocol-relative url match (a URL beginning with '//') whose previous character is a word character + * (effectively skipping over strings like "abc//google.com") + * + * Otherwise, returns `true`. * * @private - * @param {"url"/"email"/"twitter"} linkType The type of link that an anchor tag is being generated for. + * @param {String} twitterMatch The matched Twitter handle, if there was one. Will be empty string if the match is not a + * Twitter match. + * @param {String} emailAddressMatch The matched Email address, if there was one. Will be empty string if the match is not + * an Email address match. + * @param {String} urlMatch The matched URL, if there was one. Will be an empty string if the match is not a URL match. + * @param {String} protocolRelativeMatch The protocol-relative string for a URL match (i.e. '//'), possibly with a preceding + * character (ex, a space, such as: ' //', or a letter, such as: 'a//'). The match is invalid if there is a word character + * preceding the '//'. + * @return {Boolean} `true` if the match given is valid and should be processed, or `false` if the match is invalid and/or + * should just not be processed (such as, if it's a Twitter match, but {@link #twitter} matching is disabled}. + */ + isValidMatch : function( twitterMatch, emailAddressMatch, urlMatch, protocolRelativeMatch ) { + if( + ( twitterMatch && !this.twitter ) || ( emailAddressMatch && !this.email ) || ( urlMatch && !this.urls ) || + ( urlMatch && urlMatch.indexOf( '.' ) === -1 ) || // At least one period ('.') must exist in the URL match for us to consider it an actual URL + ( urlMatch && /^[A-Za-z]{3,9}:/.test( urlMatch ) && !/:.*?[A-Za-z]/.test( urlMatch ) ) || // At least one letter character must exist in the domain name after a protocol match. Ex: skip over something like "git:1.0" + ( protocolRelativeMatch && this.invalidProtocolRelMatchRegex.test( protocolRelativeMatch ) ) // a protocol-relative match which has a word character in front of it (so we can skip something like "abc//google.com") + ) { + return false; + } + + return true; + } + + }; + + + /** + * Automatically links URLs, email addresses, and Twitter handles found in the given chunk of HTML. + * Does not link URLs found within HTML tags. + * + * For instance, if given the text: `You should go to http://www.yahoo.com`, then the result + * will be `You should go to <a href="http://www.yahoo.com">http://www.yahoo.com</a>` + * + * Example: + * + * var linkedText = Autolinker.link( "Go to google.com", { newWindow: false } ); + * // Produces: "Go to google.com" + * + * @static + * @method link + * @param {String} html The HTML text to link URLs within. + * @param {Object} [options] Any of the configuration options for the Autolinker class, specified in an Object (map). + * See the class description for an example call. + * @return {String} The HTML text, with URLs automatically linked + */ + Autolinker.link = function( text, options ) { + var autolinker = new Autolinker( options ); + return autolinker.link( text ); + }; + + /** + * @class Autolinker.Util + * @singleton + * + * A few utility methods for Autolinker. + */ + Autolinker.Util = { + + /** + * @property {Function} abstractMethod + * + * A function object which represents an abstract method. + */ + abstractMethod : function() { throw "abstract"; }, + + + /** + * Assigns (shallow copies) the properties of `src` onto `dest`. + * + * @param {Object} dest The destination object. + * @param {Object} src The source object. + * @return {Object} The destination object. + */ + assign : function( dest, src ) { + for( var prop in src ) { + if( src.hasOwnProperty( prop ) ) { + dest[ prop ] = src[ prop ]; + } + } + + return dest; + }, + + + /** + * Extends `superclass` to create a new subclass, adding the `protoProps` to the new subclass's prototype. + * + * @param {Function} superclass The constructor function for the superclass. + * @param {Object} protoProps The methods/properties to add to the subclass's prototype. This may contain the + * special property `constructor`, which will be used as the new subclass's constructor function. + * @return {Function} The new subclass function. + */ + extend : function( superclass, protoProps ) { + var superclassProto = superclass.prototype; + + var F = function() {}; + F.prototype = superclassProto; + + var subclass; + if( protoProps.hasOwnProperty( 'constructor' ) ) { + subclass = protoProps.constructor; + } else { + subclass = function() { superclassProto.constructor.apply( this, arguments ); }; + } + + var subclassProto = subclass.prototype = new F(); // set up prototype chain + subclassProto.constructor = subclass; // fix constructor property + subclassProto.superclass = superclassProto; + + delete protoProps.constructor; // don't re-assign constructor property to the prototype, since a new function may have been created (`subclass`), which is now already there + Autolinker.Util.assign( subclassProto, protoProps ); + + return subclass; + } + + }; + /** + * @private + * @class Autolinker.AnchorTagBuilder + * @extends Object + * + * Builds the anchor (<a>) tags for the Autolinker utility when a match is found. + */ + Autolinker.AnchorTagBuilder = Autolinker.Util.extend( Object, { + + /** + * @cfg {Boolean} newWindow + * + * See {@link Autolinker#newWindow} for details. + */ + + /** + * @cfg {Boolean} stripPrefix + * + * See {@link Autolinker#stripPrefix} for details. + */ + + /** + * @cfg {Number} truncate + * + * See {@link Autolinker#truncate} for details. + */ + + /** + * @cfg {String} className + * + * See {@link Autolinker#className} for details. + */ + + + /** + * @private + * @property {RegExp} urlPrefixRegex + * + * A regular expression used to remove the 'http://' or 'https://' and/or the 'www.' from URLs. + */ + urlPrefixRegex: /^(https?:\/\/)?(www\.)?/i, + + + /** + * @constructor + * @param {Object} [cfg] The configuration options for the AnchorTagBuilder instance, specified in an Object (map). + */ + constructor : function( cfg ) { + Autolinker.Util.assign( this, cfg ); + }, + + + /** + * Generates the actual anchor (<a>) tag to use in place of a source url/email/twitter link. + * + * @param {"url"/"email"/"twitter"} matchType The type of match that an anchor tag is being generated for. * @param {String} anchorHref The href for the anchor tag. * @param {String} anchorText The anchor tag's text (i.e. what will be displayed). * @return {String} The full HTML for the anchor tag. */ - createAnchorTag : function( linkType, anchorHref, anchorText ) { - var attributesStr = this.createAnchorAttrsStr( linkType, anchorHref ); + createAnchorTag : function( matchType, anchorHref, anchorText ) { + var attributesStr = this.createAnchorAttrsStr( matchType, anchorHref ); anchorText = this.processAnchorText( anchorText ); return '' + anchorText + ''; @@ -470,14 +658,14 @@ * Creates the string which will be the HTML attributes for the anchor (<a>) tag being generated. * * @private - * @param {"url"/"email"/"twitter"} linkType The type of link that an anchor tag is being generated for. + * @param {"url"/"email"/"twitter"} matchType The type of match that an anchor tag is being generated for. * @param {String} href The href for the anchor tag. * @return {String} The anchor tag's attribute. Ex: `href="http://google.com" class="myLink myLink-url" target="_blank"` */ - createAnchorAttrsStr : function( linkType, anchorHref ) { + createAnchorAttrsStr : function( matchType, anchorHref ) { var attrs = [ 'href="' + anchorHref + '"' ]; // we'll always have the `href` attribute - var cssClass = this.createCssClass( linkType ); + var cssClass = this.createCssClass( matchType ); if( cssClass ) { attrs.push( 'class="' + cssClass + '"' ); } @@ -490,21 +678,21 @@ /** - * Creates the CSS class that will be used for a given anchor tag, based on the `linkType` and the {@link #className} + * Creates the CSS class that will be used for a given anchor tag, based on the `matchType` and the {@link #className} * config. * * @private - * @param {"url"/"email"/"twitter"} linkType The type of link that an anchor tag is being generated for. + * @param {"url"/"email"/"twitter"} matchType The type of match that an anchor tag is being generated for. * @return {String} The CSS class string for the link. Example return: "myLink myLink-url". If no {@link #className} * was configured, returns an empty string. */ - createCssClass : function( linkType ) { + createCssClass : function( matchType ) { var className = this.className; if( !className ) return ""; else - return className + " " + className + "-" + linkType; // ex: "myLink myLink-url", "myLink myLink-email", or "myLink myLink-twitter" + return className + " " + className + "-" + matchType; // ex: "myLink myLink-url", "myLink myLink-email", or "myLink myLink-twitter" }, @@ -541,7 +729,7 @@ /** - * Removes any trailing slash from the given `anchorText`, in prepration for the text to be displayed. + * Removes any trailing slash from the given `anchorText`, in preparation for the text to be displayed. * * @private * @param {String} anchorText The text of the anchor that is being generated, for which to remove any trailing @@ -573,35 +761,260 @@ } return anchorText; } - - }; - - + + } ); /** - * Automatically links URLs, email addresses, and Twitter handles found in the given chunk of HTML. - * Does not link URLs found within HTML tags. + * @private + * @abstract + * @class Autolinker.Match * - * For instance, if given the text: `You should go to http://www.yahoo.com`, then the result - * will be `You should go to <a href="http://www.yahoo.com">http://www.yahoo.com</a>` - * - * Example: - * - * var linkedText = Autolinker.link( "Go to google.com", { newWindow: false } ); - * // Produces: "Go to google.com" - * - * @static - * @method link - * @param {String} html The HTML text to link URLs within. - * @param {Object} [options] Any of the configuration options for the Autolinker class, specified in an Object (map). - * See the class description for an example call. - * @return {String} The HTML text, with URLs automatically linked + * Represents a match found in an input string which should be Autolinked. */ - Autolinker.link = function( text, options ) { - var autolinker = new Autolinker( options ); - return autolinker.link( text ); - }; + Autolinker.Match = Autolinker.Util.extend( Object, { + + /** + * @constructor + * @param {Object} cfg The configuration properties for the Match instance, specified in an Object (map). + */ + constructor : function( cfg ) { + Autolinker.Util.assign( this, cfg ); + }, + + + /** + * Returns a string name for the type of match that this class represents. + * + * @abstract + * @return {String} + */ + getType : Autolinker.Util.abstractMethod, + + + /** + * Returns the anchor href that should be generated for the match. + * + * @abstract + * @return {String} + */ + getAnchorHref : Autolinker.Util.abstractMethod, + + + /** + * Returns the anchor text that should be generated for the match. + * + * @abstract + * @return {String} + */ + getAnchorText : Autolinker.Util.abstractMethod + + } ); + /** + * @private + * @class Autolinker.EmailMatch + * + * Represents a Email match found in an input string which should be Autolinked. + */ + Autolinker.EmailMatch = Autolinker.Util.extend( Autolinker.Match, { + + /** + * @cfg {String} emailAddress (required) + * + * The email address that was matched. + */ + + + /** + * Returns a string name for the type of match that this class represents. + * + * @return {String} + */ + getType : function() { + return 'email'; + }, + + + /** + * Returns the email address that was matched. + * + * @return {String} + */ + getEmailAddress : function() { + return this.emailAddress; + }, + + + /** + * Returns the anchor href that should be generated for the match. + * + * @return {String} + */ + getAnchorHref : function() { + return 'mailto:' + this.emailAddress; + }, + + + /** + * Returns the anchor text that should be generated for the match. + * + * @return {String} + */ + getAnchorText : function() { + return this.emailAddress; + } + + } ); + /** + * @private + * @class Autolinker.TwitterMatch + * + * Represents a Twitter match found in an input string which should be Autolinked. + */ + Autolinker.TwitterMatch = Autolinker.Util.extend( Autolinker.Match, { + + /** + * @cfg {String} twitterHandle (required) + * + * The Twitter handle that was matched. + */ + + + /** + * Returns the type of match that this class represents. + * + * @return {String} + */ + getType : function() { + return 'twitter'; + }, + + + /** + * Returns a string name for the type of match that this class represents. + * + * @return {String} + */ + getTwitterHandle : function() { + return this.twitterHandle; + }, + + + /** + * Returns the anchor href that should be generated for the match. + * + * @return {String} + */ + getAnchorHref : function() { + return 'https://twitter.com/' + this.twitterHandle; + }, + + + /** + * Returns the anchor text that should be generated for the match. + * + * @return {String} + */ + getAnchorText : function() { + return '@' + this.twitterHandle; + } + + } ); + /** + * @private + * @class Autolinker.TwitterMatch + * + * Represents a Url match found in an input string which should be Autolinked. + */ + Autolinker.UrlMatch = Autolinker.Util.extend( Autolinker.Match, { + + /** + * @cfg {String} url (required) + * + * The url that was matched. + */ + + /** + * @cfg {Boolean} protocolRelativeMatch (required) + * + * `true` if the URL is a protocol-relative match. A protocol-relative match is a URL that starts with '//', + * and will be either http:// or https:// based on the protocol that the site is loaded under. + */ + + + /** + * @private + * @property {RegExp} protocolRelativeRegex + * + * The regular expression used to remove the protocol-relative '//' from the {@link #url} string, for purposes + * of {@link #getAnchorText}. A protocol-relative URL is, for example, "//yahoo.com" + */ + protocolRelativeRegex : /^\/\//, + + /** + * @protected + * @property {RegExp} checkForProtocolRegex + * + * A regular expression used to check if the {@link #url} is missing a protocol (in which case, 'http://' + * will be added). + */ + checkForProtocolRegex: /^[A-Za-z]{3,9}:/, + + + /** + * Returns a string name for the type of match that this class represents. + * + * @return {String} + */ + getType : function() { + return 'url'; + }, + + + /** + * Returns the url that was matched, assuming the protocol to be 'http://' if the match + * was missing a protocol. + * + * @return {String} + */ + getUrl : function() { + var url = this.url; + + // if the url string doesn't begin with a protocol, assume http:// + if( !this.protocolRelativeMatch && !this.checkForProtocolRegex.test( url ) ) { + url = this.url = 'http://' + url; + } + + return url; + }, + + + /** + * Returns the anchor href that should be generated for the match. + * + * @return {String} + */ + getAnchorHref : function() { + return this.getUrl(); + }, + + + /** + * Returns the anchor text that should be generated for the match. + * + * @return {String} + */ + getAnchorText : function() { + var url = this.getUrl(); + + if( this.protocolRelativeMatch ) { + // Strip off any protocol-relative '//' from the anchor text + url = url.replace( this.protocolRelativeRegex, '' ); + } + + return url; + } + + } ); - return Autolinker; - -} ) ); + +} ) ); \ No newline at end of file diff --git a/vendors/Autolinker/Autolinker.min.js b/vendors/Autolinker/Autolinker.min.js index ea375d19b..6b0a97c63 100644 --- a/vendors/Autolinker/Autolinker.min.js +++ b/vendors/Autolinker/Autolinker.min.js @@ -1,10 +1,10 @@ /*! * Autolinker.js - * 0.11.0 + * 0.11.2 * * Copyright(c) 2014 Gregory Jacobs * MIT Licensed. http://www.opensource.org/licenses/mit-license.php * * https://github.com/gregjacobs/Autolinker.js */ -!function(a,b){"function"==typeof define&&define.amd?define(b):"undefined"!=typeof exports?module.exports=b():a.Autolinker=b()}(this,function(){var a=function(a){a=a||{};for(var b in a)a.hasOwnProperty(b)&&(this[b]=a[b])};return a.prototype={constructor:a,newWindow:!0,stripPrefix:!0,twitter:!0,email:!0,urls:!0,className:"",matcherRegex:function(){var a=/(^|[^\w])@(\w{1,15})/,b=/(?:[\-;:&=\+\$,\w\.]+@)/,c=/(?:[A-Za-z]{3,9}:(?:\/\/)?)/,d=/(?:www\.)/,e=/[A-Za-z0-9\.\-]*[A-Za-z0-9\-]/,f=/\.(?:international|construction|contractors|enterprises|photography|productions|foundation|immobilien|industries|management|properties|technology|christmas|community|directory|education|equipment|institute|marketing|solutions|vacations|bargains|boutique|builders|catering|cleaning|clothing|computer|democrat|diamonds|graphics|holdings|lighting|partners|plumbing|supplies|training|ventures|academy|careers|company|cruises|domains|exposed|flights|florist|gallery|guitars|holiday|kitchen|neustar|okinawa|recipes|rentals|reviews|shiksha|singles|support|systems|agency|berlin|camera|center|coffee|condos|dating|estate|events|expert|futbol|kaufen|luxury|maison|monash|museum|nagoya|photos|repair|report|social|supply|tattoo|tienda|travel|viajes|villas|vision|voting|voyage|actor|build|cards|cheap|codes|dance|email|glass|house|mango|ninja|parts|photo|shoes|solar|today|tokyo|tools|watch|works|aero|arpa|asia|best|bike|blue|buzz|camp|club|cool|coop|farm|fish|gift|guru|info|jobs|kiwi|kred|land|limo|link|menu|mobi|moda|name|pics|pink|post|qpon|rich|ruhr|sexy|tips|vote|voto|wang|wien|wiki|zone|bar|bid|biz|cab|cat|ceo|com|edu|gov|int|kim|mil|net|onl|org|pro|pub|red|tel|uno|wed|xxx|xyz|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cw|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|za|zm|zw)\b/,g=/(?:[\-A-Za-z0-9+&@#\/%?=~_()|!:,.;]*[\-A-Za-z0-9+&@#\/%=~_()|])?/;return new RegExp(["(",a.source,")","|","(",b.source,e.source,f.source,")","|","(","(?:","(?:",c.source,e.source,")","|","(?:","(.?//)?",d.source,e.source,")","|","(?:","(.?//)?",e.source,f.source,")",")",g.source,")"].join(""),"gi")}(),protocolRelativeRegex:/(.)?\/\//,htmlRegex:function(){var a=/[0-9a-zA-Z:]+/,b=/[^\s\0"'>\/=\x01-\x1F\x7F]+/,c=/(?:".*?"|'.*?'|[^'"=<>`\s]+)/;return new RegExp(["<(/)?","("+a.source+")","(?:","\\s+",b.source,"(?:\\s*=\\s*"+c.source+")?",")*","\\s*",">"].join(""),"g")}(),urlPrefixRegex:/^(https?:\/\/)?(www\.)?/i,link:function(a){return this.processHtml(a)},processHtml:function(a){for(var b,c,d=this.htmlRegex,e=0,f=0,g=[];null!==(b=d.exec(a));){var h=b[0],i=b[2],j=!!b[1];c=a.substring(e,b.index),e=b.index+h.length,"a"===i?j?(f=Math.max(f-1,0),0===f&&g.push(c)):(f++,g.push(this.processTextNode(c))):g.push(0===f?this.processTextNode(c):c),g.push(h)}if(ex&&(a=a.substr(0,a.length-1),t=")")}var z,A=a,B=a;if(m)z="twitter",s=n,A="https://twitter.com/"+o,B="@"+o;else if(p)z="email",A="mailto:"+p,B=p;else if(z="url",r){var C=new RegExp("^"+b.protocolRelativeRegex.source),D=r.match(C)[1]||"";s=D+s,A=A.replace(C,"//"),B=B.replace(C,"")}else/^[A-Za-z]{3,9}:/i.test(A)||(A="http://"+A);var E=b.createAnchorTag(z,A,B);return s+E+t})},createAnchorTag:function(a,b,c){var d=this.createAnchorAttrsStr(a,b);return c=this.processAnchorText(c),""+c+""},createAnchorAttrsStr:function(a,b){var c=['href="'+b+'"'],d=this.createCssClass(a);return d&&c.push('class="'+d+'"'),this.newWindow&&c.push('target="_blank"'),c.join(" ")},createCssClass:function(a){var b=this.className;return b?b+" "+b+"-"+a:""},processAnchorText:function(a){return this.stripPrefix&&(a=this.stripUrlPrefix(a)),a=this.removeTrailingSlash(a),a=this.doTruncate(a)},stripUrlPrefix:function(a){return a.replace(this.urlPrefixRegex,"")},removeTrailingSlash:function(a){return"/"===a.charAt(a.length-1)&&(a=a.slice(0,-1)),a},doTruncate:function(a){var b=this.truncate;return b&&a.length>b&&(a=a.substring(0,b-2)+".."),a}},a.link=function(b,c){var d=new a(c);return d.link(b)},a}); \ No newline at end of file +!function(a,b){"function"==typeof define&&define.amd?define(b):"undefined"!=typeof exports?module.exports=b():a.Autolinker=b()}(this,function(){var a=function(b){a.Util.assign(this,b)};return a.prototype={constructor:a,urls:!0,email:!0,twitter:!0,newWindow:!0,stripPrefix:!0,className:"",htmlRegex:function(){var a=/[0-9a-zA-Z:]+/,b=/[^\s\0"'>\/=\x01-\x1F\x7F]+/,c=/(?:".*?"|'.*?'|[^'"=<>`\s]+)/,d=b.source+"(?:\\s*=\\s*"+c.source+")?";return new RegExp(["<(?:!|(/))?","("+a.source+")","(?:","\\s+","(?:",d,"|",c.source+")",")*","\\s*/?",">"].join(""),"g")}(),matcherRegex:function(){var a=/(^|[^\w])@(\w{1,15})/,b=/(?:[\-;:&=\+\$,\w\.]+@)/,c=/(?:[A-Za-z]{3,9}:(?:\/\/)?)/,d=/(?:www\.)/,e=/[A-Za-z0-9\.\-]*[A-Za-z0-9\-]/,f=/\.(?:international|construction|contractors|enterprises|photography|productions|foundation|immobilien|industries|management|properties|technology|christmas|community|directory|education|equipment|institute|marketing|solutions|vacations|bargains|boutique|builders|catering|cleaning|clothing|computer|democrat|diamonds|graphics|holdings|lighting|partners|plumbing|supplies|training|ventures|academy|careers|company|cruises|domains|exposed|flights|florist|gallery|guitars|holiday|kitchen|neustar|okinawa|recipes|rentals|reviews|shiksha|singles|support|systems|agency|berlin|camera|center|coffee|condos|dating|estate|events|expert|futbol|kaufen|luxury|maison|monash|museum|nagoya|photos|repair|report|social|supply|tattoo|tienda|travel|viajes|villas|vision|voting|voyage|actor|build|cards|cheap|codes|dance|email|glass|house|mango|ninja|parts|photo|shoes|solar|today|tokyo|tools|watch|works|aero|arpa|asia|best|bike|blue|buzz|camp|club|cool|coop|farm|fish|gift|guru|info|jobs|kiwi|kred|land|limo|link|menu|mobi|moda|name|pics|pink|post|qpon|rich|ruhr|sexy|tips|vote|voto|wang|wien|wiki|zone|bar|bid|biz|cab|cat|ceo|com|edu|gov|int|kim|mil|net|onl|org|pro|pub|red|tel|uno|wed|xxx|xyz|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cw|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|za|zm|zw)\b/,g=/(?:[\-A-Za-z0-9+&@#\/%?=~_()|!:,.;]*[\-A-Za-z0-9+&@#\/%=~_()|])?/;return new RegExp(["(",a.source,")","|","(",b.source,e.source,f.source,")","|","(","(?:","(?:",c.source,e.source,")","|","(?:","(.?//)?",d.source,e.source,")","|","(?:","(.?//)?",e.source,f.source,")",")",g.source,")"].join(""),"gi")}(),invalidProtocolRelMatchRegex:/^[\w]\/\//,charBeforeProtocolRelMatchRegex:/^(.)?\/\//,link:function(a){return this.processHtml(a)},getAnchorTagBuilder:function(){var b=this.anchorTagBuilder;return b||(b=this.anchorTagBuilder=new a.AnchorTagBuilder({newWindow:this.newWindow,stripPrefix:this.stripPrefix,truncate:this.truncate,className:this.className})),b},processHtml:function(a){for(var b,c,d=this.htmlRegex,e=0,f=0,g=[];null!==(b=d.exec(a));){var h=b[0],i=b[2],j=!!b[1];c=a.substring(e,b.index),e=b.index+h.length,"a"===i?j?(f=Math.max(f-1,0),0===f&&g.push(c)):(f++,g.push(this.processTextNode(c))):g.push(0===f?this.processTextNode(c):c),g.push(h)}if(ey&&(b=b.substr(0,b.length-1),u=")")}if(n)t=o,m=new a.TwitterMatch({twitterHandle:p});else if(q)m=new a.EmailMatch({emailAddress:q});else{if(s){var A=s.match(d)[1]||"";A&&(t=A,b=b.slice(1))}m=new a.UrlMatch({url:b,protocolRelativeMatch:s})}var B=e.createAnchorTag(m.getType(),m.getAnchorHref(),m.getAnchorText());return t+B+u})},isValidMatch:function(a,b,c,d){return a&&!this.twitter||b&&!this.email||c&&!this.urls||c&&-1===c.indexOf(".")||c&&/^[A-Za-z]{3,9}:/.test(c)&&!/:.*?[A-Za-z]/.test(c)||d&&this.invalidProtocolRelMatchRegex.test(d)?!1:!0}},a.link=function(b,c){var d=new a(c);return d.link(b)},a.Util={abstractMethod:function(){throw"abstract"},assign:function(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a},extend:function(b,c){var d=b.prototype,e=function(){};e.prototype=d;var f;f=c.hasOwnProperty("constructor")?c.constructor:function(){d.constructor.apply(this,arguments)};var g=f.prototype=new e;return g.constructor=f,g.superclass=d,delete c.constructor,a.Util.assign(g,c),f}},a.AnchorTagBuilder=a.Util.extend(Object,{urlPrefixRegex:/^(https?:\/\/)?(www\.)?/i,constructor:function(b){a.Util.assign(this,b)},createAnchorTag:function(a,b,c){var d=this.createAnchorAttrsStr(a,b);return c=this.processAnchorText(c),""+c+""},createAnchorAttrsStr:function(a,b){var c=['href="'+b+'"'],d=this.createCssClass(a);return d&&c.push('class="'+d+'"'),this.newWindow&&c.push('target="_blank"'),c.join(" ")},createCssClass:function(a){var b=this.className;return b?b+" "+b+"-"+a:""},processAnchorText:function(a){return this.stripPrefix&&(a=this.stripUrlPrefix(a)),a=this.removeTrailingSlash(a),a=this.doTruncate(a)},stripUrlPrefix:function(a){return a.replace(this.urlPrefixRegex,"")},removeTrailingSlash:function(a){return"/"===a.charAt(a.length-1)&&(a=a.slice(0,-1)),a},doTruncate:function(a){var b=this.truncate;return b&&a.length>b&&(a=a.substring(0,b-2)+".."),a}}),a.Match=a.Util.extend(Object,{constructor:function(b){a.Util.assign(this,b)},getType:a.Util.abstractMethod,getAnchorHref:a.Util.abstractMethod,getAnchorText:a.Util.abstractMethod}),a.EmailMatch=a.Util.extend(a.Match,{getType:function(){return"email"},getEmailAddress:function(){return this.emailAddress},getAnchorHref:function(){return"mailto:"+this.emailAddress},getAnchorText:function(){return this.emailAddress}}),a.TwitterMatch=a.Util.extend(a.Match,{getType:function(){return"twitter"},getTwitterHandle:function(){return this.twitterHandle},getAnchorHref:function(){return"https://twitter.com/"+this.twitterHandle},getAnchorText:function(){return"@"+this.twitterHandle}}),a.UrlMatch=a.Util.extend(a.Match,{protocolRelativeRegex:/^\/\//,checkForProtocolRegex:/^[A-Za-z]{3,9}:/,getType:function(){return"url"},getUrl:function(){var a=this.url;return this.protocolRelativeMatch||this.checkForProtocolRegex.test(a)||(a=this.url="http://"+a),a},getAnchorHref:function(){return this.getUrl()},getAnchorText:function(){var a=this.getUrl();return this.protocolRelativeMatch&&(a=a.replace(this.protocolRelativeRegex,"")),a}}),a}); \ No newline at end of file diff --git a/vendors/jquery-linkify/jquery.linkify.js b/vendors/jquery-linkify/jquery.linkify.js deleted file mode 100644 index b825f6445..000000000 --- a/vendors/jquery-linkify/jquery.linkify.js +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Linkify - v1.1.6 - * Find URLs in plain text and return HTML for discovered links. - * https://github.com/HitSend/jQuery-linkify/ - * - * Made by SoapBox Innovations, Inc. - * Under MIT License - */ -!function($, window, document) { - "use strict"; - function Linkified(element, options) { - this._defaults = defaults, this.element = element, this.setOptions(options), this.init(); - } - var defaults = { - tagName: "a", - newLine: "\n", - target: "_blank", - linkClass: null, - linkClasses: [], - linkAttributes: null - }; - Linkified.prototype = { - constructor: Linkified, - init: function() { - 1 === this.element.nodeType ? Linkified.linkifyNode.call(this, this.element) : this.element = Linkified.linkify.call(this, this.element.toString()); - }, - setOptions: function(options) { - this.settings = Linkified.extendSettings(options, this.settings); - }, - toString: function() { - return this.element.toString(); - } - }, Linkified.extendSettings = function(options, settings) { - var prop; - settings = settings || {}; - for (prop in defaults) settings[prop] || (settings[prop] = defaults[prop]); - for (prop in options) settings[prop] = options[prop]; - return settings; - }, Linkified.linkMatch = new RegExp([ "(", '\\s|[^a-zA-Z0-9.\\+_\\/"\\>\\-]|^', ")(?:", "(", "[a-zA-Z0-9\\+_\\-]+", "(?:", "\\.[a-zA-Z0-9\\+_\\-]+", ")*@", ")?(", "http:\\/\\/|https:\\/\\/|ftp:\\/\\/", ")?(", "(?:(?:[a-zA-Z0-9][a-zA-Z0-9_%\\-_+]*\\.)+)", ")(", "(?:com|ca|co|edu|gov|net|org|dev|biz|cat|int|pro|tel|mil|aero|asia|coop|info|jobs|mobi|museum|name|post|travel|local|[a-z]{2})", ")(", "(?::\\d{1,5})", ")?(", "(?:", "[\\/|\\?]", "(?:", "[\\-a-zA-Z0-9_%#*&+=~!?,;:.\\/]*", ")*", ")", "[\\-\\/a-zA-Z0-9_%#*&+=~]", "|", "\\/?", ")?", ")(", '[^a-zA-Z0-9\\+_\\/"\\<\\-]|$', ")" ].join(""), "g"), - Linkified.emailLinkMatch = /(<[a-z]+ href=\")(http:\/\/)([a-zA-Z0-9\+_\-]+(?:\.[a-zA-Z0-9\+_\-]+)*@)/g, - Linkified.linkify = function(text, options) { - var attr, settings, linkClasses, linkReplace = []; - this.constructor === Linkified && this.settings ? (settings = this.settings, options && (settings = Linkified.extendSettings(options, settings))) : settings = Linkified.extendSettings(options), - linkClasses = settings.linkClass ? settings.linkClass.split(/\s+/) : [], linkClasses.push.apply(linkClasses, settings.linkClasses), - text = text.replace(/$2$3$4$5$6$7$8"), text = text.replace(Linkified.linkMatch, linkReplace.join(" ")), - text = text.replace(Linkified.emailLinkMatch, "$1mailto:$3"), text = text.replace(/(\s){2}/g, "$1"), - text = text.replace(/\n/g, settings.newLine); - }, Linkified.linkifyNode = function(node) { - var children, childNode, childCount, dummyElement, i; - if (node && "object" == typeof node && 1 === node.nodeType && "a" !== node.tagName.toLowerCase() && !/[^\s]linkified[\s$]/.test(node.className)) { - for (children = [], dummyElement = Linkified._dummyElement || document.createElement("div"), - childNode = node.firstChild, childCount = node.childElementCount; childNode; ) { - if (3 === childNode.nodeType) { - for (;dummyElement.firstChild; ) dummyElement.removeChild(dummyElement.firstChild); - for (dummyElement.innerHTML = Linkified.linkify.call(this, childNode.textContent || childNode.innerText || childNode.nodeValue), - children.push.apply(children, dummyElement.childNodes); dummyElement.firstChild; ) dummyElement.removeChild(dummyElement.firstChild); - } else 1 === childNode.nodeType ? children.push(Linkified.linkifyNode(childNode)) : children.push(childNode); - childNode = childNode.nextSibling; - } - for (;node.firstChild; ) node.removeChild(node.firstChild); - for (i = 0; i < children.length; i++) node.appendChild(children[i]); - } - return node; - }, Linkified._dummyElement = document.createElement("div"), $.fn.linkify = function(options) { - return this.each(function() { - var linkified; - (linkified = $.data(this, "plugin-linkify")) ? (linkified.setOptions(options), linkified.init()) : $.data(this, "plugin-linkify", new Linkified(this, options)); - }); - }, $.fn.linkify.Constructor = Linkified, $(window).on("load", function() { - $("[data-linkify]").each(function() { - var $target, $this = $(this), target = $this.attr("data-linkify"), options = { - tagName: $this.attr("data-linkify-tagname"), - newLine: $this.attr("data-linkify-newline"), - target: $this.attr("data-linkify-target"), - linkClass: $this.attr("data-linkify-linkclass") - }; - for (var option in options) "undefined" == typeof options[option] && delete options[option]; - $target = "this" === target ? $this : $this.find(target), $target.linkify(options); - }); - }), $("body").on("click", ".linkified", function() { - var $link = $(this), url = $link.attr("href"), isEmail = /^mailto:/i.test(url), target = $link.attr("target"); - return isEmail ? window.location.href = url : window.open(url, target), !1; - }); -}(jQuery, window, document); \ No newline at end of file diff --git a/vendors/jquery-linkify/jquery.linkify.min.js b/vendors/jquery-linkify/jquery.linkify.min.js deleted file mode 100644 index 512141310..000000000 --- a/vendors/jquery-linkify/jquery.linkify.min.js +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Linkify - v1.1.6 - * Find URLs in plain text and return HTML for discovered links. - * https://github.com/HitSend/jQuery-linkify/ - * - * Made by SoapBox Innovations, Inc. - * Under MIT License - */ -!function(a,b,c){"use strict";function d(a,b){this._defaults=e,this.element=a,this.setOptions(b),this.init()}var e={tagName:"a",newLine:"\n",target:"_blank",linkClass:null,linkClasses:[],linkAttributes:null};d.prototype={constructor:d,init:function(){1===this.element.nodeType?d.linkifyNode.call(this,this.element):this.element=d.linkify.call(this,this.element.toString())},setOptions:function(a){this.settings=d.extendSettings(a,this.settings)},toString:function(){return this.element.toString()}},d.extendSettings=function(a,b){var c;b=b||{};for(c in e)b[c]||(b[c]=e[c]);for(c in a)b[c]=a[c];return b},d.linkMatch=new RegExp(["(",'\\s|[^a-zA-Z0-9.\\+_\\/"\\>\\-]|^',")(?:","(","[a-zA-Z0-9\\+_\\-]+","(?:","\\.[a-zA-Z0-9\\+_\\-]+",")*@",")?(","http:\\/\\/|https:\\/\\/|ftp:\\/\\/",")?(","(?:(?:[a-zA-Z0-9][a-zA-Z0-9_%\\-_+]*\\.)+)",")(","(?:com|ca|co|edu|gov|net|org|dev|biz|cat|int|pro|tel|mil|aero|asia|coop|info|jobs|mobi|museum|name|post|travel|local|[a-z]{2})",")(","(?::\\d{1,5})",")?(","(?:","[\\/|\\?]","(?:","[\\-a-zA-Z0-9_%#*&+=~!?,;:.\\/]*",")*",")","[\\-\\/a-zA-Z0-9_%#*&+=~]","|","\\/?",")?",")(",'[^a-zA-Z0-9\\+_\\/"\\<\\-]|$',")"].join(""),"g"),d.emailLinkMatch=/(<[a-z]+ href=\")(http:\/\/)([a-zA-Z0-9\+_\-]+(?:\.[a-zA-Z0-9\+_\-]+)*@)/g,d.linkify=function(a,b){var c,e,f,g=[];this.constructor===d&&this.settings?(e=this.settings,b&&(e=d.extendSettings(b,e))):e=d.extendSettings(b),f=e.linkClass?e.linkClass.split(/\s+/):[],f.push.apply(f,e.linkClasses),a=a.replace(/$2$3$4$5$6$7$8"),a=a.replace(d.linkMatch,g.join(" ")),a=a.replace(d.emailLinkMatch,"$1mailto:$3"),a=a.replace(/(\s){2}/g,"$1"),a=a.replace(/\n/g,e.newLine)},d.linkifyNode=function(a){var b,e,f,g,h;if(a&&"object"==typeof a&&1===a.nodeType&&"a"!==a.tagName.toLowerCase()&&!/[^\s]linkified[\s$]/.test(a.className)){for(b=[],g=d._dummyElement||c.createElement("div"),e=a.firstChild,f=a.childElementCount;e;){if(3===e.nodeType){for(;g.firstChild;)g.removeChild(g.firstChild);for(g.innerHTML=d.linkify.call(this,e.textContent||e.innerText||e.nodeValue),b.push.apply(b,g.childNodes);g.firstChild;)g.removeChild(g.firstChild)}else 1===e.nodeType?b.push(d.linkifyNode(e)):b.push(e);e=e.nextSibling}for(;a.firstChild;)a.removeChild(a.firstChild);for(h=0;h