mirror of
				https://github.com/tooot-app/app
				synced 2025-06-05 22:19:13 +02:00 
			
		
		
		
	Temporary use local autolinker
https://github.com/gregjacobs/Autolinker.js/pull/240/ https://github.com/gregjacobs/Autolinker.js/issues/130
This commit is contained in:
		
							
								
								
									
										120
									
								
								src/modules/autolinker/anchor-tag-builder.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								src/modules/autolinker/anchor-tag-builder.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,120 @@ | ||||
| import { Match } from "./match/match"; | ||||
| import { HtmlTag } from "./html-tag"; | ||||
| import { TruncateConfigObj } from "./autolinker"; | ||||
| /** | ||||
|  * @protected | ||||
|  * @class Autolinker.AnchorTagBuilder | ||||
|  * @extends Object | ||||
|  * | ||||
|  * Builds anchor (<a>) tags for the Autolinker utility when a match is | ||||
|  * found. | ||||
|  * | ||||
|  * Normally this class is instantiated, configured, and used internally by an | ||||
|  * {@link Autolinker} instance, but may actually be used indirectly in a | ||||
|  * {@link Autolinker#replaceFn replaceFn} to create {@link Autolinker.HtmlTag HtmlTag} | ||||
|  * instances which may be modified before returning from the | ||||
|  * {@link Autolinker#replaceFn replaceFn}. For example: | ||||
|  * | ||||
|  *     var html = Autolinker.link( "Test google.com", { | ||||
|  *         replaceFn : function( match ) { | ||||
|  *             var tag = match.buildTag();  // returns an {@link Autolinker.HtmlTag} instance | ||||
|  *             tag.setAttr( 'rel', 'nofollow' ); | ||||
|  * | ||||
|  *             return tag; | ||||
|  *         } | ||||
|  *     } ); | ||||
|  * | ||||
|  *     // generated html: | ||||
|  *     //   Test <a href="http://google.com" target="_blank" rel="nofollow">google.com</a> | ||||
|  */ | ||||
| export declare class AnchorTagBuilder { | ||||
|     /** | ||||
|      * @cfg {Boolean} newWindow | ||||
|      * @inheritdoc Autolinker#newWindow | ||||
|      */ | ||||
|     private readonly newWindow; | ||||
|     /** | ||||
|      * @cfg {Object} truncate | ||||
|      * @inheritdoc Autolinker#truncate | ||||
|      */ | ||||
|     private readonly truncate; | ||||
|     /** | ||||
|      * @cfg {String} className | ||||
|      * @inheritdoc Autolinker#className | ||||
|      */ | ||||
|     private readonly className; | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} [cfg] The configuration options for the AnchorTagBuilder instance, specified in an Object (map). | ||||
|      */ | ||||
|     constructor(cfg?: AnchorTagBuilderCfg); | ||||
|     /** | ||||
|      * Generates the actual anchor (<a>) tag to use in place of the | ||||
|      * matched text, via its `match` object. | ||||
|      * | ||||
|      * @param {Autolinker.match.Match} match The Match instance to generate an | ||||
|      *   anchor tag from. | ||||
|      * @return {Autolinker.HtmlTag} The HtmlTag instance for the anchor tag. | ||||
|      */ | ||||
|     build(match: Match): HtmlTag; | ||||
|     /** | ||||
|      * Creates the Object (map) of the HTML attributes for the anchor (<a>) | ||||
|      *   tag being generated. | ||||
|      * | ||||
|      * @protected | ||||
|      * @param {Autolinker.match.Match} match The Match instance to generate an | ||||
|      *   anchor tag from. | ||||
|      * @return {Object} A key/value Object (map) of the anchor tag's attributes. | ||||
|      */ | ||||
|     protected createAttrs(match: Match): { | ||||
|         [attrName: string]: string; | ||||
|     }; | ||||
|     /** | ||||
|      * Creates the CSS class that will be used for a given anchor tag, based on | ||||
|      * the `matchType` and the {@link #className} config. | ||||
|      * | ||||
|      * Example returns: | ||||
|      * | ||||
|      * - ""                                      // no {@link #className} | ||||
|      * - "myLink myLink-url"                     // url match | ||||
|      * - "myLink myLink-email"                   // email match | ||||
|      * - "myLink myLink-phone"                   // phone match | ||||
|      * - "myLink myLink-hashtag"                 // hashtag match | ||||
|      * - "myLink myLink-mention myLink-twitter"  // mention match with Twitter service | ||||
|      * | ||||
|      * @protected | ||||
|      * @param {Autolinker.match.Match} match The Match instance to generate an | ||||
|      *   anchor tag from. | ||||
|      * @return {String} The CSS class string for the link. Example return: | ||||
|      *   "myLink myLink-url". If no {@link #className} was configured, returns | ||||
|      *   an empty string. | ||||
|      */ | ||||
|     protected createCssClass(match: Match): string; | ||||
|     /** | ||||
|      * Processes the `anchorText` by truncating the text according to the | ||||
|      * {@link #truncate} config. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {String} anchorText The anchor tag's text (i.e. what will be | ||||
|      *   displayed). | ||||
|      * @return {String} The processed `anchorText`. | ||||
|      */ | ||||
|     private processAnchorText; | ||||
|     /** | ||||
|      * Performs the truncation of the `anchorText` based on the {@link #truncate} | ||||
|      * option. If the `anchorText` is longer than the length specified by the | ||||
|      * {@link #truncate} option, the truncation is performed based on the | ||||
|      * `location` property. See {@link #truncate} for details. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {String} anchorText The anchor tag's text (i.e. what will be | ||||
|      *   displayed). | ||||
|      * @return {String} The truncated anchor text. | ||||
|      */ | ||||
|     private doTruncate; | ||||
| } | ||||
| export interface AnchorTagBuilderCfg { | ||||
|     newWindow?: boolean; | ||||
|     truncate?: TruncateConfigObj; | ||||
|     className?: string; | ||||
| } | ||||
							
								
								
									
										176
									
								
								src/modules/autolinker/anchor-tag-builder.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								src/modules/autolinker/anchor-tag-builder.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,176 @@ | ||||
| import { HtmlTag } from "./html-tag"; | ||||
| import { truncateSmart } from "./truncate/truncate-smart"; | ||||
| import { truncateMiddle } from "./truncate/truncate-middle"; | ||||
| import { truncateEnd } from "./truncate/truncate-end"; | ||||
| /** | ||||
|  * @protected | ||||
|  * @class Autolinker.AnchorTagBuilder | ||||
|  * @extends Object | ||||
|  * | ||||
|  * Builds anchor (<a>) tags for the Autolinker utility when a match is | ||||
|  * found. | ||||
|  * | ||||
|  * Normally this class is instantiated, configured, and used internally by an | ||||
|  * {@link Autolinker} instance, but may actually be used indirectly in a | ||||
|  * {@link Autolinker#replaceFn replaceFn} to create {@link Autolinker.HtmlTag HtmlTag} | ||||
|  * instances which may be modified before returning from the | ||||
|  * {@link Autolinker#replaceFn replaceFn}. For example: | ||||
|  * | ||||
|  *     var html = Autolinker.link( "Test google.com", { | ||||
|  *         replaceFn : function( match ) { | ||||
|  *             var tag = match.buildTag();  // returns an {@link Autolinker.HtmlTag} instance | ||||
|  *             tag.setAttr( 'rel', 'nofollow' ); | ||||
|  * | ||||
|  *             return tag; | ||||
|  *         } | ||||
|  *     } ); | ||||
|  * | ||||
|  *     // generated html: | ||||
|  *     //   Test <a href="http://google.com" target="_blank" rel="nofollow">google.com</a> | ||||
|  */ | ||||
| var AnchorTagBuilder = /** @class */ (function () { | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} [cfg] The configuration options for the AnchorTagBuilder instance, specified in an Object (map). | ||||
|      */ | ||||
|     function AnchorTagBuilder(cfg) { | ||||
|         if (cfg === void 0) { cfg = {}; } | ||||
|         /** | ||||
|          * @cfg {Boolean} newWindow | ||||
|          * @inheritdoc Autolinker#newWindow | ||||
|          */ | ||||
|         this.newWindow = false; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {Object} truncate | ||||
|          * @inheritdoc Autolinker#truncate | ||||
|          */ | ||||
|         this.truncate = {}; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {String} className | ||||
|          * @inheritdoc Autolinker#className | ||||
|          */ | ||||
|         this.className = ''; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         this.newWindow = cfg.newWindow || false; | ||||
|         this.truncate = cfg.truncate || {}; | ||||
|         this.className = cfg.className || ''; | ||||
|     } | ||||
|     /** | ||||
|      * Generates the actual anchor (<a>) tag to use in place of the | ||||
|      * matched text, via its `match` object. | ||||
|      * | ||||
|      * @param {Autolinker.match.Match} match The Match instance to generate an | ||||
|      *   anchor tag from. | ||||
|      * @return {Autolinker.HtmlTag} The HtmlTag instance for the anchor tag. | ||||
|      */ | ||||
|     AnchorTagBuilder.prototype.build = function (match) { | ||||
|         return new HtmlTag({ | ||||
|             tagName: 'a', | ||||
|             attrs: this.createAttrs(match), | ||||
|             innerHtml: this.processAnchorText(match.getAnchorText()) | ||||
|         }); | ||||
|     }; | ||||
|     /** | ||||
|      * Creates the Object (map) of the HTML attributes for the anchor (<a>) | ||||
|      *   tag being generated. | ||||
|      * | ||||
|      * @protected | ||||
|      * @param {Autolinker.match.Match} match The Match instance to generate an | ||||
|      *   anchor tag from. | ||||
|      * @return {Object} A key/value Object (map) of the anchor tag's attributes. | ||||
|      */ | ||||
|     AnchorTagBuilder.prototype.createAttrs = function (match) { | ||||
|         var attrs = { | ||||
|             'href': match.getAnchorHref() // we'll always have the `href` attribute | ||||
|         }; | ||||
|         var cssClass = this.createCssClass(match); | ||||
|         if (cssClass) { | ||||
|             attrs['class'] = cssClass; | ||||
|         } | ||||
|         if (this.newWindow) { | ||||
|             attrs['target'] = "_blank"; | ||||
|             attrs['rel'] = "noopener noreferrer"; // Issue #149. See https://mathiasbynens.github.io/rel-noopener/ | ||||
|         } | ||||
|         if (this.truncate) { | ||||
|             if (this.truncate.length && this.truncate.length < match.getAnchorText().length) { | ||||
|                 attrs['title'] = match.getAnchorHref(); | ||||
|             } | ||||
|         } | ||||
|         return attrs; | ||||
|     }; | ||||
|     /** | ||||
|      * Creates the CSS class that will be used for a given anchor tag, based on | ||||
|      * the `matchType` and the {@link #className} config. | ||||
|      * | ||||
|      * Example returns: | ||||
|      * | ||||
|      * - ""                                      // no {@link #className} | ||||
|      * - "myLink myLink-url"                     // url match | ||||
|      * - "myLink myLink-email"                   // email match | ||||
|      * - "myLink myLink-phone"                   // phone match | ||||
|      * - "myLink myLink-hashtag"                 // hashtag match | ||||
|      * - "myLink myLink-mention myLink-twitter"  // mention match with Twitter service | ||||
|      * | ||||
|      * @protected | ||||
|      * @param {Autolinker.match.Match} match The Match instance to generate an | ||||
|      *   anchor tag from. | ||||
|      * @return {String} The CSS class string for the link. Example return: | ||||
|      *   "myLink myLink-url". If no {@link #className} was configured, returns | ||||
|      *   an empty string. | ||||
|      */ | ||||
|     AnchorTagBuilder.prototype.createCssClass = function (match) { | ||||
|         var className = this.className; | ||||
|         if (!className) { | ||||
|             return ""; | ||||
|         } | ||||
|         else { | ||||
|             var returnClasses = [className], cssClassSuffixes = match.getCssClassSuffixes(); | ||||
|             for (var i = 0, len = cssClassSuffixes.length; i < len; i++) { | ||||
|                 returnClasses.push(className + '-' + cssClassSuffixes[i]); | ||||
|             } | ||||
|             return returnClasses.join(' '); | ||||
|         } | ||||
|     }; | ||||
|     /** | ||||
|      * Processes the `anchorText` by truncating the text according to the | ||||
|      * {@link #truncate} config. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {String} anchorText The anchor tag's text (i.e. what will be | ||||
|      *   displayed). | ||||
|      * @return {String} The processed `anchorText`. | ||||
|      */ | ||||
|     AnchorTagBuilder.prototype.processAnchorText = function (anchorText) { | ||||
|         anchorText = this.doTruncate(anchorText); | ||||
|         return anchorText; | ||||
|     }; | ||||
|     /** | ||||
|      * Performs the truncation of the `anchorText` based on the {@link #truncate} | ||||
|      * option. If the `anchorText` is longer than the length specified by the | ||||
|      * {@link #truncate} option, the truncation is performed based on the | ||||
|      * `location` property. See {@link #truncate} for details. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {String} anchorText The anchor tag's text (i.e. what will be | ||||
|      *   displayed). | ||||
|      * @return {String} The truncated anchor text. | ||||
|      */ | ||||
|     AnchorTagBuilder.prototype.doTruncate = function (anchorText) { | ||||
|         var truncate = this.truncate; | ||||
|         if (!truncate || !truncate.length) | ||||
|             return anchorText; | ||||
|         var truncateLength = truncate.length, truncateLocation = truncate.location; | ||||
|         if (truncateLocation === 'smart') { | ||||
|             return truncateSmart(anchorText, truncateLength); | ||||
|         } | ||||
|         else if (truncateLocation === 'middle') { | ||||
|             return truncateMiddle(anchorText, truncateLength); | ||||
|         } | ||||
|         else { | ||||
|             return truncateEnd(anchorText, truncateLength); | ||||
|         } | ||||
|     }; | ||||
|     return AnchorTagBuilder; | ||||
| }()); | ||||
| export { AnchorTagBuilder }; | ||||
|  | ||||
| //# sourceMappingURL=anchor-tag-builder.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/anchor-tag-builder.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/anchor-tag-builder.js.map
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										699
									
								
								src/modules/autolinker/autolinker.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										699
									
								
								src/modules/autolinker/autolinker.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,699 @@ | ||||
| import { AnchorTagBuilder } from "./anchor-tag-builder"; | ||||
| import { Match } from "./match/match"; | ||||
| import { EmailMatch } from "./match/email-match"; | ||||
| import { HashtagMatch } from "./match/hashtag-match"; | ||||
| import { MentionMatch } from "./match/mention-match"; | ||||
| import { PhoneMatch } from "./match/phone-match"; | ||||
| import { UrlMatch } from "./match/url-match"; | ||||
| import { Matcher } from "./matcher/matcher"; | ||||
| import { HtmlTag } from "./html-tag"; | ||||
| import { EmailMatcher } from "./matcher/email-matcher"; | ||||
| import { UrlMatcher } from "./matcher/url-matcher"; | ||||
| import { HashtagMatcher } from "./matcher/hashtag-matcher"; | ||||
| import { PhoneMatcher } from "./matcher/phone-matcher"; | ||||
| import { MentionMatcher } from "./matcher/mention-matcher"; | ||||
| /** | ||||
|  * @class Autolinker | ||||
|  * @extends Object | ||||
|  * | ||||
|  * Utility class used to process a given string of text, and wrap the matches in | ||||
|  * the appropriate anchor (<a>) tags to turn them into links. | ||||
|  * | ||||
|  * Any of the configuration options may be provided in an Object provided | ||||
|  * to the Autolinker constructor, which will configure how the {@link #link link()} | ||||
|  * method will process the links. | ||||
|  * | ||||
|  * For example: | ||||
|  * | ||||
|  *     var autolinker = new Autolinker( { | ||||
|  *         newWindow : false, | ||||
|  *         truncate  : 30 | ||||
|  *     } ); | ||||
|  * | ||||
|  *     var html = autolinker.link( "Joe went to www.yahoo.com" ); | ||||
|  *     // produces: 'Joe went to <a href="http://www.yahoo.com">yahoo.com</a>' | ||||
|  * | ||||
|  * | ||||
|  * The {@link #static-link static link()} method may also be used to inline | ||||
|  * options into a single call, which may be more convenient for one-off uses. | ||||
|  * For example: | ||||
|  * | ||||
|  *     var html = Autolinker.link( "Joe went to www.yahoo.com", { | ||||
|  *         newWindow : false, | ||||
|  *         truncate  : 30 | ||||
|  *     } ); | ||||
|  *     // produces: 'Joe went to <a href="http://www.yahoo.com">yahoo.com</a>' | ||||
|  * | ||||
|  * | ||||
|  * ## Custom Replacements of Links | ||||
|  * | ||||
|  * If the configuration options do not provide enough flexibility, a {@link #replaceFn} | ||||
|  * may be provided to fully customize the output of Autolinker. This function is | ||||
|  * called once for each URL/Email/Phone#/Hashtag/Mention (Twitter, Instagram, Soundcloud) | ||||
|  * match that is encountered. | ||||
|  * | ||||
|  * For example: | ||||
|  * | ||||
|  *     var input = "...";  // string with URLs, Email Addresses, Phone #s, Hashtags, and Mentions (Twitter, Instagram, Soundcloud) | ||||
|  * | ||||
|  *     var linkedText = Autolinker.link( input, { | ||||
|  *         replaceFn : function( match ) { | ||||
|  *             console.log( "href = ", match.getAnchorHref() ); | ||||
|  *             console.log( "text = ", match.getAnchorText() ); | ||||
|  * | ||||
|  *             switch( match.getType() ) { | ||||
|  *                 case 'url' : | ||||
|  *                     console.log( "url: ", match.getUrl() ); | ||||
|  * | ||||
|  *                     if( match.getUrl().indexOf( 'mysite.com' ) === -1 ) { | ||||
|  *                         var tag = match.buildTag();  // returns an `Autolinker.HtmlTag` instance, which provides mutator methods for easy changes | ||||
|  *                         tag.setAttr( 'rel', 'nofollow' ); | ||||
|  *                         tag.addClass( 'external-link' ); | ||||
|  * | ||||
|  *                         return tag; | ||||
|  * | ||||
|  *                     } else { | ||||
|  *                         return true;  // let Autolinker perform its normal anchor tag replacement | ||||
|  *                     } | ||||
|  * | ||||
|  *                 case 'email' : | ||||
|  *                     var email = match.getEmail(); | ||||
|  *                     console.log( "email: ", email ); | ||||
|  * | ||||
|  *                     if( email === "my@own.address" ) { | ||||
|  *                         return false;  // don't auto-link this particular email address; leave as-is | ||||
|  *                     } else { | ||||
|  *                         return;  // no return value will have Autolinker perform its normal anchor tag replacement (same as returning `true`) | ||||
|  *                     } | ||||
|  * | ||||
|  *                 case 'phone' : | ||||
|  *                     var phoneNumber = match.getPhoneNumber(); | ||||
|  *                     console.log( phoneNumber ); | ||||
|  * | ||||
|  *                     return '<a href="http://newplace.to.link.phone.numbers.to/">' + phoneNumber + '</a>'; | ||||
|  * | ||||
|  *                 case 'hashtag' : | ||||
|  *                     var hashtag = match.getHashtag(); | ||||
|  *                     console.log( hashtag ); | ||||
|  * | ||||
|  *                     return '<a href="http://newplace.to.link.hashtag.handles.to/">' + hashtag + '</a>'; | ||||
|  * | ||||
|  *                 case 'mention' : | ||||
|  *                     var mention = match.getMention(); | ||||
|  *                     console.log( mention ); | ||||
|  * | ||||
|  *                     return '<a href="http://newplace.to.link.mention.to/">' + mention + '</a>'; | ||||
|  *             } | ||||
|  *         } | ||||
|  *     } ); | ||||
|  * | ||||
|  * | ||||
|  * The function may return the following values: | ||||
|  * | ||||
|  * - `true` (Boolean): Allow Autolinker to replace the match as it normally | ||||
|  *   would. | ||||
|  * - `false` (Boolean): Do not replace the current match at all - leave as-is. | ||||
|  * - Any String: If a string is returned from the function, the string will be | ||||
|  *   used directly as the replacement HTML for the match. | ||||
|  * - An {@link Autolinker.HtmlTag} instance, which can be used to build/modify | ||||
|  *   an HTML tag before writing out its HTML text. | ||||
|  */ | ||||
| export default class Autolinker { | ||||
|     /** | ||||
|      * @static | ||||
|      * @property {String} version | ||||
|      * | ||||
|      * The Autolinker version number in the form major.minor.patch | ||||
|      * | ||||
|      * Ex: 0.25.1 | ||||
|      */ | ||||
|     static readonly version = "3.14.1"; | ||||
|     /** | ||||
|      * For backwards compatibility with Autolinker 1.x, the AnchorTagBuilder | ||||
|      * class is provided as a static on the Autolinker class. | ||||
|      */ | ||||
|     static readonly AnchorTagBuilder: typeof AnchorTagBuilder; | ||||
|     /** | ||||
|      * For backwards compatibility with Autolinker 1.x, the HtmlTag class is | ||||
|      * provided as a static on the Autolinker class. | ||||
|      */ | ||||
|     static readonly HtmlTag: typeof HtmlTag; | ||||
|     /** | ||||
|      * For backwards compatibility with Autolinker 1.x, the Matcher classes are | ||||
|      * provided as statics on the Autolinker class. | ||||
|      */ | ||||
|     static readonly matcher: { | ||||
|         Email: typeof EmailMatcher; | ||||
|         Hashtag: typeof HashtagMatcher; | ||||
|         Matcher: typeof Matcher; | ||||
|         Mention: typeof MentionMatcher; | ||||
|         Phone: typeof PhoneMatcher; | ||||
|         Url: typeof UrlMatcher; | ||||
|     }; | ||||
|     /** | ||||
|      * For backwards compatibility with Autolinker 1.x, the Match classes are | ||||
|      * provided as statics on the Autolinker class. | ||||
|      */ | ||||
|     static readonly match: { | ||||
|         Email: typeof EmailMatch; | ||||
|         Hashtag: typeof HashtagMatch; | ||||
|         Match: typeof Match; | ||||
|         Mention: typeof MentionMatch; | ||||
|         Phone: typeof PhoneMatch; | ||||
|         Url: typeof UrlMatch; | ||||
|     }; | ||||
|     /** | ||||
|      * Automatically links URLs, Email addresses, Phone Numbers, Twitter handles, | ||||
|      * Hashtags, and Mentions 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 <a href="http://google.com">google.com</a>" | ||||
|      * | ||||
|      * @static | ||||
|      * @param {String} textOrHtml The HTML or text to find matches within (depending | ||||
|      *   on if the {@link #urls}, {@link #email}, {@link #phone}, {@link #mention}, | ||||
|      *   {@link #hashtag}, and {@link #mention} options are enabled). | ||||
|      * @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 matches automatically linked. | ||||
|      */ | ||||
|     static link(textOrHtml: string, options?: AutolinkerConfig): string; | ||||
|     /** | ||||
|      * Parses the input `textOrHtml` looking for URLs, email addresses, phone | ||||
|      * numbers, username handles, and hashtags (depending on the configuration | ||||
|      * of the Autolinker instance), and returns an array of {@link Autolinker.match.Match} | ||||
|      * objects describing those matches (without making any replacements). | ||||
|      * | ||||
|      * Note that if parsing multiple pieces of text, it is slightly more efficient | ||||
|      * to create an Autolinker instance, and use the instance-level {@link #parse} | ||||
|      * method. | ||||
|      * | ||||
|      * Example: | ||||
|      * | ||||
|      *     var matches = Autolinker.parse( "Hello google.com, I am asdf@asdf.com", { | ||||
|      *         urls: true, | ||||
|      *         email: true | ||||
|      *     } ); | ||||
|      * | ||||
|      *     console.log( matches.length );           // 2 | ||||
|      *     console.log( matches[ 0 ].getType() );   // 'url' | ||||
|      *     console.log( matches[ 0 ].getUrl() );    // 'google.com' | ||||
|      *     console.log( matches[ 1 ].getType() );   // 'email' | ||||
|      *     console.log( matches[ 1 ].getEmail() );  // 'asdf@asdf.com' | ||||
|      * | ||||
|      * @static | ||||
|      * @param {String} textOrHtml The HTML or text to find matches within | ||||
|      *   (depending on if the {@link #urls}, {@link #email}, {@link #phone}, | ||||
|      *   {@link #hashtag}, and {@link #mention} options are enabled). | ||||
|      * @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 {Autolinker.match.Match[]} The array of Matches found in the | ||||
|      *   given input `textOrHtml`. | ||||
|      */ | ||||
|     static parse(textOrHtml: string, options: AutolinkerConfig): Match[]; | ||||
|     /** | ||||
|      * The Autolinker version number exposed on the instance itself. | ||||
|      * | ||||
|      * Ex: 0.25.1 | ||||
|      */ | ||||
|     readonly version = "3.14.1"; | ||||
|     /** | ||||
|      * @cfg {Boolean/Object} [urls] | ||||
|      * | ||||
|      * `true` if URLs should be automatically linked, `false` if they should not | ||||
|      * be. Defaults to `true`. | ||||
|      * | ||||
|      * Examples: | ||||
|      * | ||||
|      *     urls: true | ||||
|      * | ||||
|      *     // or | ||||
|      * | ||||
|      *     urls: { | ||||
|      *         schemeMatches : true, | ||||
|      *         wwwMatches    : true, | ||||
|      *         tldMatches    : true | ||||
|      *     } | ||||
|      * | ||||
|      * As shown above, this option also accepts an Object form with 3 properties | ||||
|      * to allow for more customization of what exactly gets linked. All default | ||||
|      * to `true`: | ||||
|      * | ||||
|      * @cfg {Boolean} [urls.schemeMatches] `true` to match URLs found prefixed | ||||
|      *   with a scheme, i.e. `http://google.com`, or `other+scheme://google.com`, | ||||
|      *   `false` to prevent these types of matches. | ||||
|      * @cfg {Boolean} [urls.wwwMatches] `true` to match urls found prefixed with | ||||
|      *   `'www.'`, i.e. `www.google.com`. `false` to prevent these types of | ||||
|      *   matches. Note that if the URL had a prefixed scheme, and | ||||
|      *   `schemeMatches` is true, it will still be linked. | ||||
|      * @cfg {Boolean} [urls.tldMatches] `true` to match URLs with known top | ||||
|      *   level domains (.com, .net, etc.) that are not prefixed with a scheme or | ||||
|      *   `'www.'`. This option attempts to match anything that looks like a URL | ||||
|      *   in the given text. Ex: `google.com`, `asdf.org/?page=1`, etc. `false` | ||||
|      *   to prevent these types of matches. | ||||
|      */ | ||||
|     private readonly urls; | ||||
|     /** | ||||
|      * @cfg {Boolean} [email=true] | ||||
|      * | ||||
|      * `true` if email addresses should be automatically linked, `false` if they | ||||
|      * should not be. | ||||
|      */ | ||||
|     private readonly email; | ||||
|     /** | ||||
|      * @cfg {Boolean} [phone=true] | ||||
|      * | ||||
|      * `true` if Phone numbers ("(555)555-5555") should be automatically linked, | ||||
|      * `false` if they should not be. | ||||
|      */ | ||||
|     private readonly phone; | ||||
|     /** | ||||
|      * @cfg {Boolean/String} [hashtag=false] | ||||
|      * | ||||
|      * A string for the service name to have hashtags (ex: "#myHashtag") | ||||
|      * auto-linked to. The currently-supported values are: | ||||
|      * | ||||
|      * - 'twitter' | ||||
|      * - 'facebook' | ||||
|      * - 'instagram' | ||||
|      * | ||||
|      * Pass `false` to skip auto-linking of hashtags. | ||||
|      */ | ||||
|     private readonly hashtag; | ||||
|     /** | ||||
|      * @cfg {String/Boolean} [mention=false] | ||||
|      * | ||||
|      * A string for the service name to have mentions (ex: "@myuser") | ||||
|      * auto-linked to. The currently supported values are: | ||||
|      * | ||||
|      * - 'twitter' | ||||
|      * - 'instagram' | ||||
|      * - 'soundcloud' | ||||
|      * | ||||
|      * Defaults to `false` to skip auto-linking of mentions. | ||||
|      */ | ||||
|     private readonly mention; | ||||
|     /** | ||||
|      * @cfg {Boolean} [newWindow=true] | ||||
|      * | ||||
|      * `true` if the links should open in a new window, `false` otherwise. | ||||
|      */ | ||||
|     private readonly newWindow; | ||||
|     /** | ||||
|      * @cfg {Boolean/Object} [stripPrefix=true] | ||||
|      * | ||||
|      * `true` if 'http://' (or 'https://') and/or the 'www.' should be stripped | ||||
|      * from the beginning of URL links' text, `false` otherwise. Defaults to | ||||
|      * `true`. | ||||
|      * | ||||
|      * Examples: | ||||
|      * | ||||
|      *     stripPrefix: true | ||||
|      * | ||||
|      *     // or | ||||
|      * | ||||
|      *     stripPrefix: { | ||||
|      *         scheme : true, | ||||
|      *         www    : true | ||||
|      *     } | ||||
|      * | ||||
|      * As shown above, this option also accepts an Object form with 2 properties | ||||
|      * to allow for more customization of what exactly is prevented from being | ||||
|      * displayed. Both default to `true`: | ||||
|      * | ||||
|      * @cfg {Boolean} [stripPrefix.scheme] `true` to prevent the scheme part of | ||||
|      *   a URL match from being displayed to the user. Example: | ||||
|      *   `'http://google.com'` will be displayed as `'google.com'`. `false` to | ||||
|      *   not strip the scheme. NOTE: Only an `'http://'` or `'https://'` scheme | ||||
|      *   will be removed, so as not to remove a potentially dangerous scheme | ||||
|      *   (such as `'file://'` or `'javascript:'`) | ||||
|      * @cfg {Boolean} [stripPrefix.www] www (Boolean): `true` to prevent the | ||||
|      *   `'www.'` part of a URL match from being displayed to the user. Ex: | ||||
|      *   `'www.google.com'` will be displayed as `'google.com'`. `false` to not | ||||
|      *   strip the `'www'`. | ||||
|      */ | ||||
|     private readonly stripPrefix; | ||||
|     /** | ||||
|      * @cfg {Boolean} [stripTrailingSlash=true] | ||||
|      * | ||||
|      * `true` to remove the trailing slash from URL matches, `false` to keep | ||||
|      *  the trailing slash. | ||||
|      * | ||||
|      *  Example when `true`: `http://google.com/` will be displayed as | ||||
|      *  `http://google.com`. | ||||
|      */ | ||||
|     private readonly stripTrailingSlash; | ||||
|     /** | ||||
|      * @cfg {Boolean} [decodePercentEncoding=true] | ||||
|      * | ||||
|      * `true` to decode percent-encoded characters in URL matches, `false` to keep | ||||
|      *  the percent-encoded characters. | ||||
|      * | ||||
|      *  Example when `true`: `https://en.wikipedia.org/wiki/San_Jos%C3%A9` will | ||||
|      *  be displayed as `https://en.wikipedia.org/wiki/San_José`. | ||||
|      */ | ||||
|     private readonly decodePercentEncoding; | ||||
|     /** | ||||
|      * @cfg {Number/Object} [truncate=0] | ||||
|      * | ||||
|      * ## Number Form | ||||
|      * | ||||
|      * A number for how many characters matched text should be truncated to | ||||
|      * inside the text of a link. If the matched text is over this number of | ||||
|      * characters, it will be truncated to this length by 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: | ||||
|      * 'yahoo.com/some/long/pat..' | ||||
|      * | ||||
|      * Example Usage: | ||||
|      * | ||||
|      *     truncate: 25 | ||||
|      * | ||||
|      * | ||||
|      *  Defaults to `0` for "no truncation." | ||||
|      * | ||||
|      * | ||||
|      * ## Object Form | ||||
|      * | ||||
|      * An Object may also be provided with two properties: `length` (Number) and | ||||
|      * `location` (String). `location` may be one of the following: 'end' | ||||
|      * (default), 'middle', or 'smart'. | ||||
|      * | ||||
|      * Example Usage: | ||||
|      * | ||||
|      *     truncate: { length: 25, location: 'middle' } | ||||
|      * | ||||
|      * @cfg {Number} [truncate.length=0] How many characters to allow before | ||||
|      *   truncation will occur. Defaults to `0` for "no truncation." | ||||
|      * @cfg {"end"/"middle"/"smart"} [truncate.location="end"] | ||||
|      * | ||||
|      * - 'end' (default): will truncate up to the number of characters, and then | ||||
|      *   add an ellipsis at the end. Ex: 'yahoo.com/some/long/pat..' | ||||
|      * - 'middle': will truncate and add the ellipsis in the middle. Ex: | ||||
|      *   'yahoo.com/s..th/to/a/file' | ||||
|      * - 'smart': for URLs where the algorithm attempts to strip out unnecessary | ||||
|      *   parts first (such as the 'www.', then URL scheme, hash, etc.), | ||||
|      *   attempting to make the URL human-readable before looking for a good | ||||
|      *   point to insert the ellipsis if it is still too long. Ex: | ||||
|      *   'yahoo.com/some..to/a/file'. For more details, see | ||||
|      *   {@link Autolinker.truncate.TruncateSmart}. | ||||
|      */ | ||||
|     private readonly truncate; | ||||
|     /** | ||||
|      * @cfg {String} className | ||||
|      * | ||||
|      * A CSS class name to add to the generated links. This class will be added | ||||
|      * to all links, as well as this class plus match suffixes for styling | ||||
|      * url/email/phone/hashtag/mention links differently. | ||||
|      * | ||||
|      * For example, if this config is provided as "myLink", then: | ||||
|      * | ||||
|      * - URL links will have the CSS classes: "myLink myLink-url" | ||||
|      * - Email links will have the CSS classes: "myLink myLink-email", and | ||||
|      * - Phone links will have the CSS classes: "myLink myLink-phone" | ||||
|      * - Hashtag links will have the CSS classes: "myLink myLink-hashtag" | ||||
|      * - Mention links will have the CSS classes: "myLink myLink-mention myLink-[type]" | ||||
|      *   where [type] is either "instagram", "twitter" or "soundcloud" | ||||
|      */ | ||||
|     private readonly className; | ||||
|     /** | ||||
|      * @cfg {Function} replaceFn | ||||
|      * | ||||
|      * A function to individually process each match found in the input string. | ||||
|      * | ||||
|      * See the class's description for usage. | ||||
|      * | ||||
|      * The `replaceFn` can be called with a different context object (`this` | ||||
|      * reference) using the {@link #context} cfg. | ||||
|      * | ||||
|      * This function is called with the following parameter: | ||||
|      * | ||||
|      * @cfg {Autolinker.match.Match} replaceFn.match The Match instance which | ||||
|      *   can be used to retrieve information about the match that the `replaceFn` | ||||
|      *   is currently processing. See {@link Autolinker.match.Match} subclasses | ||||
|      *   for details. | ||||
|      */ | ||||
|     private readonly replaceFn; | ||||
|     /** | ||||
|      * @cfg {Object} context | ||||
|      * | ||||
|      * The context object (`this` reference) to call the `replaceFn` with. | ||||
|      * | ||||
|      * Defaults to this Autolinker instance. | ||||
|      */ | ||||
|     private readonly context; | ||||
|     /** | ||||
|      * @cfg {Boolean} [sanitizeHtml=false] | ||||
|      * | ||||
|      * `true` to HTML-encode the start and end brackets of existing HTML tags found | ||||
|      * in the input string. This will escape `<` and `>` characters to `<` and | ||||
|      * `>`, respectively. | ||||
|      * | ||||
|      * Setting this to `true` will prevent XSS (Cross-site Scripting) attacks, | ||||
|      * but will remove the significance of existing HTML tags in the input string. If | ||||
|      * you would like to maintain the significance of existing HTML tags while also | ||||
|      * making the output HTML string safe, leave this option as `false` and use a | ||||
|      * tool like https://github.com/cure53/DOMPurify (or others) on the input string | ||||
|      * before running Autolinker. | ||||
|      */ | ||||
|     private readonly sanitizeHtml; | ||||
|     /** | ||||
|      * @private | ||||
|      * @property {Autolinker.matcher.Matcher[]} matchers | ||||
|      * | ||||
|      * The {@link Autolinker.matcher.Matcher} instances for this Autolinker | ||||
|      * instance. | ||||
|      * | ||||
|      * This is lazily created in {@link #getMatchers}. | ||||
|      */ | ||||
|     private matchers; | ||||
|     /** | ||||
|      * @private | ||||
|      * @property {Autolinker.AnchorTagBuilder} tagBuilder | ||||
|      * | ||||
|      * The AnchorTagBuilder instance used to build match replacement anchor tags. | ||||
|      * Note: this is lazily instantiated in the {@link #getTagBuilder} method. | ||||
|      */ | ||||
|     private tagBuilder; | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} [cfg] The configuration options for the Autolinker instance, | ||||
|      *   specified in an Object (map). | ||||
|      */ | ||||
|     constructor(cfg?: AutolinkerConfig); | ||||
|     /** | ||||
|      * Normalizes the {@link #urls} config into an Object with 3 properties: | ||||
|      * `schemeMatches`, `wwwMatches`, and `tldMatches`, all Booleans. | ||||
|      * | ||||
|      * See {@link #urls} config for details. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {Boolean/Object} urls | ||||
|      * @return {Object} | ||||
|      */ | ||||
|     private normalizeUrlsCfg; | ||||
|     /** | ||||
|      * Normalizes the {@link #stripPrefix} config into an Object with 2 | ||||
|      * properties: `scheme`, and `www` - both Booleans. | ||||
|      * | ||||
|      * See {@link #stripPrefix} config for details. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {Boolean/Object} stripPrefix | ||||
|      * @return {Object} | ||||
|      */ | ||||
|     private normalizeStripPrefixCfg; | ||||
|     /** | ||||
|      * Normalizes the {@link #truncate} config into an Object with 2 properties: | ||||
|      * `length` (Number), and `location` (String). | ||||
|      * | ||||
|      * See {@link #truncate} config for details. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {Number/Object} truncate | ||||
|      * @return {Object} | ||||
|      */ | ||||
|     private normalizeTruncateCfg; | ||||
|     /** | ||||
|      * Parses the input `textOrHtml` looking for URLs, email addresses, phone | ||||
|      * numbers, username handles, and hashtags (depending on the configuration | ||||
|      * of the Autolinker instance), and returns an array of {@link Autolinker.match.Match} | ||||
|      * objects describing those matches (without making any replacements). | ||||
|      * | ||||
|      * This method is used by the {@link #link} method, but can also be used to | ||||
|      * simply do parsing of the input in order to discover what kinds of links | ||||
|      * there are and how many. | ||||
|      * | ||||
|      * Example usage: | ||||
|      * | ||||
|      *     var autolinker = new Autolinker( { | ||||
|      *         urls: true, | ||||
|      *         email: true | ||||
|      *     } ); | ||||
|      * | ||||
|      *     var matches = autolinker.parse( "Hello google.com, I am asdf@asdf.com" ); | ||||
|      * | ||||
|      *     console.log( matches.length );           // 2 | ||||
|      *     console.log( matches[ 0 ].getType() );   // 'url' | ||||
|      *     console.log( matches[ 0 ].getUrl() );    // 'google.com' | ||||
|      *     console.log( matches[ 1 ].getType() );   // 'email' | ||||
|      *     console.log( matches[ 1 ].getEmail() );  // 'asdf@asdf.com' | ||||
|      * | ||||
|      * @param {String} textOrHtml The HTML or text to find matches within | ||||
|      *   (depending on if the {@link #urls}, {@link #email}, {@link #phone}, | ||||
|      *   {@link #hashtag}, and {@link #mention} options are enabled). | ||||
|      * @return {Autolinker.match.Match[]} The array of Matches found in the | ||||
|      *   given input `textOrHtml`. | ||||
|      */ | ||||
|     parse(textOrHtml: string): Match[]; | ||||
|     /** | ||||
|      * After we have found all matches, we need to remove matches that overlap | ||||
|      * with a previous match. This can happen for instance with URLs, where the | ||||
|      * url 'google.com/#link' would match '#link' as a hashtag. Because the | ||||
|      * '#link' part is contained in a larger match that comes before the HashTag | ||||
|      * match, we'll remove the HashTag match. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {Autolinker.match.Match[]} matches | ||||
|      * @return {Autolinker.match.Match[]} | ||||
|      */ | ||||
|     private compactMatches; | ||||
|     /** | ||||
|      * Removes matches for matchers that were turned off in the options. For | ||||
|      * example, if {@link #hashtag hashtags} were not to be matched, we'll | ||||
|      * remove them from the `matches` array here. | ||||
|      * | ||||
|      * Note: we *must* use all Matchers on the input string, and then filter | ||||
|      * them out later. For example, if the options were `{ url: false, hashtag: true }`, | ||||
|      * we wouldn't want to match the text '#link' as a HashTag inside of the text | ||||
|      * 'google.com/#link'. The way the algorithm works is that we match the full | ||||
|      * URL first (which prevents the accidental HashTag match), and then we'll | ||||
|      * simply throw away the URL match. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {Autolinker.match.Match[]} matches The array of matches to remove | ||||
|      *   the unwanted matches from. Note: this array is mutated for the | ||||
|      *   removals. | ||||
|      * @return {Autolinker.match.Match[]} The mutated input `matches` array. | ||||
|      */ | ||||
|     private removeUnwantedMatches; | ||||
|     /** | ||||
|      * Parses the input `text` looking for URLs, email addresses, phone | ||||
|      * numbers, username handles, and hashtags (depending on the configuration | ||||
|      * of the Autolinker instance), and returns an array of {@link Autolinker.match.Match} | ||||
|      * objects describing those matches. | ||||
|      * | ||||
|      * This method processes a **non-HTML string**, and is used to parse and | ||||
|      * match within the text nodes of an HTML string. This method is used | ||||
|      * internally by {@link #parse}. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {String} text The text to find matches within (depending on if the | ||||
|      *   {@link #urls}, {@link #email}, {@link #phone}, | ||||
|      *   {@link #hashtag}, and {@link #mention} options are enabled). This must be a non-HTML string. | ||||
|      * @param {Number} [offset=0] The offset of the text node within the | ||||
|      *   original string. This is used when parsing with the {@link #parse} | ||||
|      *   method to generate correct offsets within the {@link Autolinker.match.Match} | ||||
|      *   instances, but may be omitted if calling this method publicly. | ||||
|      * @return {Autolinker.match.Match[]} The array of Matches found in the | ||||
|      *   given input `text`. | ||||
|      */ | ||||
|     private parseText; | ||||
|     /** | ||||
|      * Automatically links URLs, Email addresses, Phone numbers, Hashtags, | ||||
|      * and Mentions (Twitter, Instagram, Soundcloud) 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>` | ||||
|      * | ||||
|      * This method finds the text around any HTML elements in the input | ||||
|      * `textOrHtml`, which will be the text that is processed. Any original HTML | ||||
|      * elements will be left as-is, as well as the text that is already wrapped | ||||
|      * in anchor (<a>) tags. | ||||
|      * | ||||
|      * @param {String} textOrHtml The HTML or text to autolink matches within | ||||
|      *   (depending on if the {@link #urls}, {@link #email}, {@link #phone}, {@link #hashtag}, and {@link #mention} options are enabled). | ||||
|      * @return {String} The HTML, with matches automatically linked. | ||||
|      */ | ||||
|     link(textOrHtml: string): string; | ||||
|     /** | ||||
|      * Creates the return string value for a given match in the input string. | ||||
|      * | ||||
|      * This method handles the {@link #replaceFn}, if one was provided. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {Autolinker.match.Match} match The Match object that represents | ||||
|      *   the match. | ||||
|      * @return {String} The string that the `match` should be replaced with. | ||||
|      *   This is usually the anchor tag string, but may be the `matchStr` itself | ||||
|      *   if the match is not to be replaced. | ||||
|      */ | ||||
|     private createMatchReturnVal; | ||||
|     /** | ||||
|      * Lazily instantiates and returns the {@link Autolinker.matcher.Matcher} | ||||
|      * instances for this Autolinker instance. | ||||
|      * | ||||
|      * @private | ||||
|      * @return {Autolinker.matcher.Matcher[]} | ||||
|      */ | ||||
|     private getMatchers; | ||||
|     /** | ||||
|      * Returns the {@link #tagBuilder} instance for this Autolinker instance, | ||||
|      * lazily instantiating it if it does not yet exist. | ||||
|      * | ||||
|      * @private | ||||
|      * @return {Autolinker.AnchorTagBuilder} | ||||
|      */ | ||||
|     private getTagBuilder; | ||||
| } | ||||
| export interface AutolinkerConfig { | ||||
|     urls?: UrlsConfig; | ||||
|     email?: boolean; | ||||
|     phone?: boolean; | ||||
|     hashtag?: HashtagConfig; | ||||
|     mention?: MentionConfig; | ||||
|     newWindow?: boolean; | ||||
|     stripPrefix?: StripPrefixConfig; | ||||
|     stripTrailingSlash?: boolean; | ||||
|     truncate?: TruncateConfig; | ||||
|     className?: string; | ||||
|     replaceFn?: ReplaceFn | null; | ||||
|     context?: any; | ||||
|     sanitizeHtml?: boolean; | ||||
|     decodePercentEncoding?: boolean; | ||||
| } | ||||
| export declare type UrlsConfig = boolean | UrlsConfigObj; | ||||
| export interface UrlsConfigObj { | ||||
|     schemeMatches?: boolean; | ||||
|     wwwMatches?: boolean; | ||||
|     tldMatches?: boolean; | ||||
| } | ||||
| export declare type UrlMatchTypeOptions = 'scheme' | 'www' | 'tld'; | ||||
| export declare type StripPrefixConfig = boolean | StripPrefixConfigObj; | ||||
| export interface StripPrefixConfigObj { | ||||
|     scheme?: boolean; | ||||
|     www?: boolean; | ||||
| } | ||||
| export declare type TruncateConfig = number | TruncateConfigObj; | ||||
| export interface TruncateConfigObj { | ||||
|     length?: number; | ||||
|     location?: "end" | "middle" | "smart"; | ||||
| } | ||||
| export declare type HashtagConfig = false | HashtagServices; | ||||
| export declare type HashtagServices = 'twitter' | 'facebook' | 'instagram'; | ||||
| export declare type MentionConfig = false | MentionServices; | ||||
| export declare type MentionServices = 'mastodon' | 'twitter' | 'instagram' | 'soundcloud'; | ||||
| export declare type ReplaceFn = (match: Match) => ReplaceFnReturn; | ||||
| export declare type ReplaceFnReturn = boolean | string | HtmlTag | null | undefined | void; | ||||
							
								
								
									
										907
									
								
								src/modules/autolinker/autolinker.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										907
									
								
								src/modules/autolinker/autolinker.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,907 @@ | ||||
| import { defaults, remove, splitAndCapture } from "./utils"; | ||||
| import { AnchorTagBuilder } from "./anchor-tag-builder"; | ||||
| import { Match } from "./match/match"; | ||||
| import { EmailMatch } from "./match/email-match"; | ||||
| import { HashtagMatch } from "./match/hashtag-match"; | ||||
| import { MentionMatch } from "./match/mention-match"; | ||||
| import { PhoneMatch } from "./match/phone-match"; | ||||
| import { UrlMatch } from "./match/url-match"; | ||||
| import { Matcher } from "./matcher/matcher"; | ||||
| import { HtmlTag } from "./html-tag"; | ||||
| import { EmailMatcher } from "./matcher/email-matcher"; | ||||
| import { UrlMatcher } from "./matcher/url-matcher"; | ||||
| import { HashtagMatcher } from "./matcher/hashtag-matcher"; | ||||
| import { PhoneMatcher } from "./matcher/phone-matcher"; | ||||
| import { MentionMatcher } from "./matcher/mention-matcher"; | ||||
| import { parseHtml } from './htmlParser/parse-html'; | ||||
| /** | ||||
|  * @class Autolinker | ||||
|  * @extends Object | ||||
|  * | ||||
|  * Utility class used to process a given string of text, and wrap the matches in | ||||
|  * the appropriate anchor (<a>) tags to turn them into links. | ||||
|  * | ||||
|  * Any of the configuration options may be provided in an Object provided | ||||
|  * to the Autolinker constructor, which will configure how the {@link #link link()} | ||||
|  * method will process the links. | ||||
|  * | ||||
|  * For example: | ||||
|  * | ||||
|  *     var autolinker = new Autolinker( { | ||||
|  *         newWindow : false, | ||||
|  *         truncate  : 30 | ||||
|  *     } ); | ||||
|  * | ||||
|  *     var html = autolinker.link( "Joe went to www.yahoo.com" ); | ||||
|  *     // produces: 'Joe went to <a href="http://www.yahoo.com">yahoo.com</a>' | ||||
|  * | ||||
|  * | ||||
|  * The {@link #static-link static link()} method may also be used to inline | ||||
|  * options into a single call, which may be more convenient for one-off uses. | ||||
|  * For example: | ||||
|  * | ||||
|  *     var html = Autolinker.link( "Joe went to www.yahoo.com", { | ||||
|  *         newWindow : false, | ||||
|  *         truncate  : 30 | ||||
|  *     } ); | ||||
|  *     // produces: 'Joe went to <a href="http://www.yahoo.com">yahoo.com</a>' | ||||
|  * | ||||
|  * | ||||
|  * ## Custom Replacements of Links | ||||
|  * | ||||
|  * If the configuration options do not provide enough flexibility, a {@link #replaceFn} | ||||
|  * may be provided to fully customize the output of Autolinker. This function is | ||||
|  * called once for each URL/Email/Phone#/Hashtag/Mention (Twitter, Instagram, Soundcloud) | ||||
|  * match that is encountered. | ||||
|  * | ||||
|  * For example: | ||||
|  * | ||||
|  *     var input = "...";  // string with URLs, Email Addresses, Phone #s, Hashtags, and Mentions (Twitter, Instagram, Soundcloud) | ||||
|  * | ||||
|  *     var linkedText = Autolinker.link( input, { | ||||
|  *         replaceFn : function( match ) { | ||||
|  *             console.log( "href = ", match.getAnchorHref() ); | ||||
|  *             console.log( "text = ", match.getAnchorText() ); | ||||
|  * | ||||
|  *             switch( match.getType() ) { | ||||
|  *                 case 'url' : | ||||
|  *                     console.log( "url: ", match.getUrl() ); | ||||
|  * | ||||
|  *                     if( match.getUrl().indexOf( 'mysite.com' ) === -1 ) { | ||||
|  *                         var tag = match.buildTag();  // returns an `Autolinker.HtmlTag` instance, which provides mutator methods for easy changes | ||||
|  *                         tag.setAttr( 'rel', 'nofollow' ); | ||||
|  *                         tag.addClass( 'external-link' ); | ||||
|  * | ||||
|  *                         return tag; | ||||
|  * | ||||
|  *                     } else { | ||||
|  *                         return true;  // let Autolinker perform its normal anchor tag replacement | ||||
|  *                     } | ||||
|  * | ||||
|  *                 case 'email' : | ||||
|  *                     var email = match.getEmail(); | ||||
|  *                     console.log( "email: ", email ); | ||||
|  * | ||||
|  *                     if( email === "my@own.address" ) { | ||||
|  *                         return false;  // don't auto-link this particular email address; leave as-is | ||||
|  *                     } else { | ||||
|  *                         return;  // no return value will have Autolinker perform its normal anchor tag replacement (same as returning `true`) | ||||
|  *                     } | ||||
|  * | ||||
|  *                 case 'phone' : | ||||
|  *                     var phoneNumber = match.getPhoneNumber(); | ||||
|  *                     console.log( phoneNumber ); | ||||
|  * | ||||
|  *                     return '<a href="http://newplace.to.link.phone.numbers.to/">' + phoneNumber + '</a>'; | ||||
|  * | ||||
|  *                 case 'hashtag' : | ||||
|  *                     var hashtag = match.getHashtag(); | ||||
|  *                     console.log( hashtag ); | ||||
|  * | ||||
|  *                     return '<a href="http://newplace.to.link.hashtag.handles.to/">' + hashtag + '</a>'; | ||||
|  * | ||||
|  *                 case 'mention' : | ||||
|  *                     var mention = match.getMention(); | ||||
|  *                     console.log( mention ); | ||||
|  * | ||||
|  *                     return '<a href="http://newplace.to.link.mention.to/">' + mention + '</a>'; | ||||
|  *             } | ||||
|  *         } | ||||
|  *     } ); | ||||
|  * | ||||
|  * | ||||
|  * The function may return the following values: | ||||
|  * | ||||
|  * - `true` (Boolean): Allow Autolinker to replace the match as it normally | ||||
|  *   would. | ||||
|  * - `false` (Boolean): Do not replace the current match at all - leave as-is. | ||||
|  * - Any String: If a string is returned from the function, the string will be | ||||
|  *   used directly as the replacement HTML for the match. | ||||
|  * - An {@link Autolinker.HtmlTag} instance, which can be used to build/modify | ||||
|  *   an HTML tag before writing out its HTML text. | ||||
|  */ | ||||
| var Autolinker = /** @class */ (function () { | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} [cfg] The configuration options for the Autolinker instance, | ||||
|      *   specified in an Object (map). | ||||
|      */ | ||||
|     function Autolinker(cfg) { | ||||
|         if (cfg === void 0) { cfg = {}; } | ||||
|         /** | ||||
|          * The Autolinker version number exposed on the instance itself. | ||||
|          * | ||||
|          * Ex: 0.25.1 | ||||
|          */ | ||||
|         this.version = Autolinker.version; | ||||
|         /** | ||||
|          * @cfg {Boolean/Object} [urls] | ||||
|          * | ||||
|          * `true` if URLs should be automatically linked, `false` if they should not | ||||
|          * be. Defaults to `true`. | ||||
|          * | ||||
|          * Examples: | ||||
|          * | ||||
|          *     urls: true | ||||
|          * | ||||
|          *     // or | ||||
|          * | ||||
|          *     urls: { | ||||
|          *         schemeMatches : true, | ||||
|          *         wwwMatches    : true, | ||||
|          *         tldMatches    : true | ||||
|          *     } | ||||
|          * | ||||
|          * As shown above, this option also accepts an Object form with 3 properties | ||||
|          * to allow for more customization of what exactly gets linked. All default | ||||
|          * to `true`: | ||||
|          * | ||||
|          * @cfg {Boolean} [urls.schemeMatches] `true` to match URLs found prefixed | ||||
|          *   with a scheme, i.e. `http://google.com`, or `other+scheme://google.com`, | ||||
|          *   `false` to prevent these types of matches. | ||||
|          * @cfg {Boolean} [urls.wwwMatches] `true` to match urls found prefixed with | ||||
|          *   `'www.'`, i.e. `www.google.com`. `false` to prevent these types of | ||||
|          *   matches. Note that if the URL had a prefixed scheme, and | ||||
|          *   `schemeMatches` is true, it will still be linked. | ||||
|          * @cfg {Boolean} [urls.tldMatches] `true` to match URLs with known top | ||||
|          *   level domains (.com, .net, etc.) that are not prefixed with a scheme or | ||||
|          *   `'www.'`. This option attempts to match anything that looks like a URL | ||||
|          *   in the given text. Ex: `google.com`, `asdf.org/?page=1`, etc. `false` | ||||
|          *   to prevent these types of matches. | ||||
|          */ | ||||
|         this.urls = {}; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {Boolean} [email=true] | ||||
|          * | ||||
|          * `true` if email addresses should be automatically linked, `false` if they | ||||
|          * should not be. | ||||
|          */ | ||||
|         this.email = true; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {Boolean} [phone=true] | ||||
|          * | ||||
|          * `true` if Phone numbers ("(555)555-5555") should be automatically linked, | ||||
|          * `false` if they should not be. | ||||
|          */ | ||||
|         this.phone = true; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {Boolean/String} [hashtag=false] | ||||
|          * | ||||
|          * A string for the service name to have hashtags (ex: "#myHashtag") | ||||
|          * auto-linked to. The currently-supported values are: | ||||
|          * | ||||
|          * - 'twitter' | ||||
|          * - 'facebook' | ||||
|          * - 'instagram' | ||||
|          * | ||||
|          * Pass `false` to skip auto-linking of hashtags. | ||||
|          */ | ||||
|         this.hashtag = false; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {String/Boolean} [mention=false] | ||||
|          * | ||||
|          * A string for the service name to have mentions (ex: "@myuser") | ||||
|          * auto-linked to. The currently supported values are: | ||||
|          * | ||||
|          * - 'twitter' | ||||
|          * - 'instagram' | ||||
|          * - 'soundcloud' | ||||
|          * | ||||
|          * Defaults to `false` to skip auto-linking of mentions. | ||||
|          */ | ||||
|         this.mention = false; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {Boolean} [newWindow=true] | ||||
|          * | ||||
|          * `true` if the links should open in a new window, `false` otherwise. | ||||
|          */ | ||||
|         this.newWindow = true; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {Boolean/Object} [stripPrefix=true] | ||||
|          * | ||||
|          * `true` if 'http://' (or 'https://') and/or the 'www.' should be stripped | ||||
|          * from the beginning of URL links' text, `false` otherwise. Defaults to | ||||
|          * `true`. | ||||
|          * | ||||
|          * Examples: | ||||
|          * | ||||
|          *     stripPrefix: true | ||||
|          * | ||||
|          *     // or | ||||
|          * | ||||
|          *     stripPrefix: { | ||||
|          *         scheme : true, | ||||
|          *         www    : true | ||||
|          *     } | ||||
|          * | ||||
|          * As shown above, this option also accepts an Object form with 2 properties | ||||
|          * to allow for more customization of what exactly is prevented from being | ||||
|          * displayed. Both default to `true`: | ||||
|          * | ||||
|          * @cfg {Boolean} [stripPrefix.scheme] `true` to prevent the scheme part of | ||||
|          *   a URL match from being displayed to the user. Example: | ||||
|          *   `'http://google.com'` will be displayed as `'google.com'`. `false` to | ||||
|          *   not strip the scheme. NOTE: Only an `'http://'` or `'https://'` scheme | ||||
|          *   will be removed, so as not to remove a potentially dangerous scheme | ||||
|          *   (such as `'file://'` or `'javascript:'`) | ||||
|          * @cfg {Boolean} [stripPrefix.www] www (Boolean): `true` to prevent the | ||||
|          *   `'www.'` part of a URL match from being displayed to the user. Ex: | ||||
|          *   `'www.google.com'` will be displayed as `'google.com'`. `false` to not | ||||
|          *   strip the `'www'`. | ||||
|          */ | ||||
|         this.stripPrefix = { scheme: true, www: true }; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {Boolean} [stripTrailingSlash=true] | ||||
|          * | ||||
|          * `true` to remove the trailing slash from URL matches, `false` to keep | ||||
|          *  the trailing slash. | ||||
|          * | ||||
|          *  Example when `true`: `http://google.com/` will be displayed as | ||||
|          *  `http://google.com`. | ||||
|          */ | ||||
|         this.stripTrailingSlash = true; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {Boolean} [decodePercentEncoding=true] | ||||
|          * | ||||
|          * `true` to decode percent-encoded characters in URL matches, `false` to keep | ||||
|          *  the percent-encoded characters. | ||||
|          * | ||||
|          *  Example when `true`: `https://en.wikipedia.org/wiki/San_Jos%C3%A9` will | ||||
|          *  be displayed as `https://en.wikipedia.org/wiki/San_José`. | ||||
|          */ | ||||
|         this.decodePercentEncoding = true; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {Number/Object} [truncate=0] | ||||
|          * | ||||
|          * ## Number Form | ||||
|          * | ||||
|          * A number for how many characters matched text should be truncated to | ||||
|          * inside the text of a link. If the matched text is over this number of | ||||
|          * characters, it will be truncated to this length by 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: | ||||
|          * 'yahoo.com/some/long/pat..' | ||||
|          * | ||||
|          * Example Usage: | ||||
|          * | ||||
|          *     truncate: 25 | ||||
|          * | ||||
|          * | ||||
|          *  Defaults to `0` for "no truncation." | ||||
|          * | ||||
|          * | ||||
|          * ## Object Form | ||||
|          * | ||||
|          * An Object may also be provided with two properties: `length` (Number) and | ||||
|          * `location` (String). `location` may be one of the following: 'end' | ||||
|          * (default), 'middle', or 'smart'. | ||||
|          * | ||||
|          * Example Usage: | ||||
|          * | ||||
|          *     truncate: { length: 25, location: 'middle' } | ||||
|          * | ||||
|          * @cfg {Number} [truncate.length=0] How many characters to allow before | ||||
|          *   truncation will occur. Defaults to `0` for "no truncation." | ||||
|          * @cfg {"end"/"middle"/"smart"} [truncate.location="end"] | ||||
|          * | ||||
|          * - 'end' (default): will truncate up to the number of characters, and then | ||||
|          *   add an ellipsis at the end. Ex: 'yahoo.com/some/long/pat..' | ||||
|          * - 'middle': will truncate and add the ellipsis in the middle. Ex: | ||||
|          *   'yahoo.com/s..th/to/a/file' | ||||
|          * - 'smart': for URLs where the algorithm attempts to strip out unnecessary | ||||
|          *   parts first (such as the 'www.', then URL scheme, hash, etc.), | ||||
|          *   attempting to make the URL human-readable before looking for a good | ||||
|          *   point to insert the ellipsis if it is still too long. Ex: | ||||
|          *   'yahoo.com/some..to/a/file'. For more details, see | ||||
|          *   {@link Autolinker.truncate.TruncateSmart}. | ||||
|          */ | ||||
|         this.truncate = { length: 0, location: 'end' }; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {String} className | ||||
|          * | ||||
|          * A CSS class name to add to the generated links. This class will be added | ||||
|          * to all links, as well as this class plus match suffixes for styling | ||||
|          * url/email/phone/hashtag/mention links differently. | ||||
|          * | ||||
|          * For example, if this config is provided as "myLink", then: | ||||
|          * | ||||
|          * - URL links will have the CSS classes: "myLink myLink-url" | ||||
|          * - Email links will have the CSS classes: "myLink myLink-email", and | ||||
|          * - Phone links will have the CSS classes: "myLink myLink-phone" | ||||
|          * - Hashtag links will have the CSS classes: "myLink myLink-hashtag" | ||||
|          * - Mention links will have the CSS classes: "myLink myLink-mention myLink-[type]" | ||||
|          *   where [type] is either "instagram", "twitter" or "soundcloud" | ||||
|          */ | ||||
|         this.className = ''; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {Function} replaceFn | ||||
|          * | ||||
|          * A function to individually process each match found in the input string. | ||||
|          * | ||||
|          * See the class's description for usage. | ||||
|          * | ||||
|          * The `replaceFn` can be called with a different context object (`this` | ||||
|          * reference) using the {@link #context} cfg. | ||||
|          * | ||||
|          * This function is called with the following parameter: | ||||
|          * | ||||
|          * @cfg {Autolinker.match.Match} replaceFn.match The Match instance which | ||||
|          *   can be used to retrieve information about the match that the `replaceFn` | ||||
|          *   is currently processing. See {@link Autolinker.match.Match} subclasses | ||||
|          *   for details. | ||||
|          */ | ||||
|         this.replaceFn = null; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {Object} context | ||||
|          * | ||||
|          * The context object (`this` reference) to call the `replaceFn` with. | ||||
|          * | ||||
|          * Defaults to this Autolinker instance. | ||||
|          */ | ||||
|         this.context = undefined; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {Boolean} [sanitizeHtml=false] | ||||
|          * | ||||
|          * `true` to HTML-encode the start and end brackets of existing HTML tags found | ||||
|          * in the input string. This will escape `<` and `>` characters to `<` and | ||||
|          * `>`, respectively. | ||||
|          * | ||||
|          * Setting this to `true` will prevent XSS (Cross-site Scripting) attacks, | ||||
|          * but will remove the significance of existing HTML tags in the input string. If | ||||
|          * you would like to maintain the significance of existing HTML tags while also | ||||
|          * making the output HTML string safe, leave this option as `false` and use a | ||||
|          * tool like https://github.com/cure53/DOMPurify (or others) on the input string | ||||
|          * before running Autolinker. | ||||
|          */ | ||||
|         this.sanitizeHtml = false; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @private | ||||
|          * @property {Autolinker.matcher.Matcher[]} matchers | ||||
|          * | ||||
|          * The {@link Autolinker.matcher.Matcher} instances for this Autolinker | ||||
|          * instance. | ||||
|          * | ||||
|          * This is lazily created in {@link #getMatchers}. | ||||
|          */ | ||||
|         this.matchers = null; | ||||
|         /** | ||||
|          * @private | ||||
|          * @property {Autolinker.AnchorTagBuilder} tagBuilder | ||||
|          * | ||||
|          * The AnchorTagBuilder instance used to build match replacement anchor tags. | ||||
|          * Note: this is lazily instantiated in the {@link #getTagBuilder} method. | ||||
|          */ | ||||
|         this.tagBuilder = null; | ||||
|         // Note: when `this.something` is used in the rhs of these assignments, | ||||
|         //       it refers to the default values set above the constructor | ||||
|         this.urls = this.normalizeUrlsCfg(cfg.urls); | ||||
|         this.email = typeof cfg.email === 'boolean' ? cfg.email : this.email; | ||||
|         this.phone = typeof cfg.phone === 'boolean' ? cfg.phone : this.phone; | ||||
|         this.hashtag = cfg.hashtag || this.hashtag; | ||||
|         this.mention = cfg.mention || this.mention; | ||||
|         this.newWindow = typeof cfg.newWindow === 'boolean' ? cfg.newWindow : this.newWindow; | ||||
|         this.stripPrefix = this.normalizeStripPrefixCfg(cfg.stripPrefix); | ||||
|         this.stripTrailingSlash = typeof cfg.stripTrailingSlash === 'boolean' ? cfg.stripTrailingSlash : this.stripTrailingSlash; | ||||
|         this.decodePercentEncoding = typeof cfg.decodePercentEncoding === 'boolean' ? cfg.decodePercentEncoding : this.decodePercentEncoding; | ||||
|         this.sanitizeHtml = cfg.sanitizeHtml || false; | ||||
|         // Validate the value of the `mention` cfg | ||||
|         var mention = this.mention; | ||||
|         if (mention !== false && mention !== 'mastodon' && mention !== 'twitter' && mention !== 'instagram' && mention !== 'soundcloud') { | ||||
|             throw new Error("invalid `mention` cfg - see docs"); | ||||
|         } | ||||
|         // Validate the value of the `hashtag` cfg | ||||
|         var hashtag = this.hashtag; | ||||
|         if (hashtag !== false && hashtag !== 'twitter' && hashtag !== 'facebook' && hashtag !== 'instagram') { | ||||
|             throw new Error("invalid `hashtag` cfg - see docs"); | ||||
|         } | ||||
|         this.truncate = this.normalizeTruncateCfg(cfg.truncate); | ||||
|         this.className = cfg.className || this.className; | ||||
|         this.replaceFn = cfg.replaceFn || this.replaceFn; | ||||
|         this.context = cfg.context || this; | ||||
|     } | ||||
|     /** | ||||
|      * Automatically links URLs, Email addresses, Phone Numbers, Twitter handles, | ||||
|      * Hashtags, and Mentions 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 <a href="http://google.com">google.com</a>" | ||||
|      * | ||||
|      * @static | ||||
|      * @param {String} textOrHtml The HTML or text to find matches within (depending | ||||
|      *   on if the {@link #urls}, {@link #email}, {@link #phone}, {@link #mention}, | ||||
|      *   {@link #hashtag}, and {@link #mention} options are enabled). | ||||
|      * @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 matches automatically linked. | ||||
|      */ | ||||
|     Autolinker.link = function (textOrHtml, options) { | ||||
|         var autolinker = new Autolinker(options); | ||||
|         return autolinker.link(textOrHtml); | ||||
|     }; | ||||
|     /** | ||||
|      * Parses the input `textOrHtml` looking for URLs, email addresses, phone | ||||
|      * numbers, username handles, and hashtags (depending on the configuration | ||||
|      * of the Autolinker instance), and returns an array of {@link Autolinker.match.Match} | ||||
|      * objects describing those matches (without making any replacements). | ||||
|      * | ||||
|      * Note that if parsing multiple pieces of text, it is slightly more efficient | ||||
|      * to create an Autolinker instance, and use the instance-level {@link #parse} | ||||
|      * method. | ||||
|      * | ||||
|      * Example: | ||||
|      * | ||||
|      *     var matches = Autolinker.parse( "Hello google.com, I am asdf@asdf.com", { | ||||
|      *         urls: true, | ||||
|      *         email: true | ||||
|      *     } ); | ||||
|      * | ||||
|      *     console.log( matches.length );           // 2 | ||||
|      *     console.log( matches[ 0 ].getType() );   // 'url' | ||||
|      *     console.log( matches[ 0 ].getUrl() );    // 'google.com' | ||||
|      *     console.log( matches[ 1 ].getType() );   // 'email' | ||||
|      *     console.log( matches[ 1 ].getEmail() );  // 'asdf@asdf.com' | ||||
|      * | ||||
|      * @static | ||||
|      * @param {String} textOrHtml The HTML or text to find matches within | ||||
|      *   (depending on if the {@link #urls}, {@link #email}, {@link #phone}, | ||||
|      *   {@link #hashtag}, and {@link #mention} options are enabled). | ||||
|      * @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 {Autolinker.match.Match[]} The array of Matches found in the | ||||
|      *   given input `textOrHtml`. | ||||
|      */ | ||||
|     Autolinker.parse = function (textOrHtml, options) { | ||||
|         var autolinker = new Autolinker(options); | ||||
|         return autolinker.parse(textOrHtml); | ||||
|     }; | ||||
|     /** | ||||
|      * Normalizes the {@link #urls} config into an Object with 3 properties: | ||||
|      * `schemeMatches`, `wwwMatches`, and `tldMatches`, all Booleans. | ||||
|      * | ||||
|      * See {@link #urls} config for details. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {Boolean/Object} urls | ||||
|      * @return {Object} | ||||
|      */ | ||||
|     Autolinker.prototype.normalizeUrlsCfg = function (urls) { | ||||
|         if (urls == null) | ||||
|             urls = true; // default to `true` | ||||
|         if (typeof urls === 'boolean') { | ||||
|             return { schemeMatches: urls, wwwMatches: urls, tldMatches: urls }; | ||||
|         } | ||||
|         else { // object form | ||||
|             return { | ||||
|                 schemeMatches: typeof urls.schemeMatches === 'boolean' ? urls.schemeMatches : true, | ||||
|                 wwwMatches: typeof urls.wwwMatches === 'boolean' ? urls.wwwMatches : true, | ||||
|                 tldMatches: typeof urls.tldMatches === 'boolean' ? urls.tldMatches : true | ||||
|             }; | ||||
|         } | ||||
|     }; | ||||
|     /** | ||||
|      * Normalizes the {@link #stripPrefix} config into an Object with 2 | ||||
|      * properties: `scheme`, and `www` - both Booleans. | ||||
|      * | ||||
|      * See {@link #stripPrefix} config for details. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {Boolean/Object} stripPrefix | ||||
|      * @return {Object} | ||||
|      */ | ||||
|     Autolinker.prototype.normalizeStripPrefixCfg = function (stripPrefix) { | ||||
|         if (stripPrefix == null) | ||||
|             stripPrefix = true; // default to `true` | ||||
|         if (typeof stripPrefix === 'boolean') { | ||||
|             return { scheme: stripPrefix, www: stripPrefix }; | ||||
|         } | ||||
|         else { // object form | ||||
|             return { | ||||
|                 scheme: typeof stripPrefix.scheme === 'boolean' ? stripPrefix.scheme : true, | ||||
|                 www: typeof stripPrefix.www === 'boolean' ? stripPrefix.www : true | ||||
|             }; | ||||
|         } | ||||
|     }; | ||||
|     /** | ||||
|      * Normalizes the {@link #truncate} config into an Object with 2 properties: | ||||
|      * `length` (Number), and `location` (String). | ||||
|      * | ||||
|      * See {@link #truncate} config for details. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {Number/Object} truncate | ||||
|      * @return {Object} | ||||
|      */ | ||||
|     Autolinker.prototype.normalizeTruncateCfg = function (truncate) { | ||||
|         if (typeof truncate === 'number') { | ||||
|             return { length: truncate, location: 'end' }; | ||||
|         } | ||||
|         else { // object, or undefined/null | ||||
|             return defaults(truncate || {}, { | ||||
|                 length: Number.POSITIVE_INFINITY, | ||||
|                 location: 'end' | ||||
|             }); | ||||
|         } | ||||
|     }; | ||||
|     /** | ||||
|      * Parses the input `textOrHtml` looking for URLs, email addresses, phone | ||||
|      * numbers, username handles, and hashtags (depending on the configuration | ||||
|      * of the Autolinker instance), and returns an array of {@link Autolinker.match.Match} | ||||
|      * objects describing those matches (without making any replacements). | ||||
|      * | ||||
|      * This method is used by the {@link #link} method, but can also be used to | ||||
|      * simply do parsing of the input in order to discover what kinds of links | ||||
|      * there are and how many. | ||||
|      * | ||||
|      * Example usage: | ||||
|      * | ||||
|      *     var autolinker = new Autolinker( { | ||||
|      *         urls: true, | ||||
|      *         email: true | ||||
|      *     } ); | ||||
|      * | ||||
|      *     var matches = autolinker.parse( "Hello google.com, I am asdf@asdf.com" ); | ||||
|      * | ||||
|      *     console.log( matches.length );           // 2 | ||||
|      *     console.log( matches[ 0 ].getType() );   // 'url' | ||||
|      *     console.log( matches[ 0 ].getUrl() );    // 'google.com' | ||||
|      *     console.log( matches[ 1 ].getType() );   // 'email' | ||||
|      *     console.log( matches[ 1 ].getEmail() );  // 'asdf@asdf.com' | ||||
|      * | ||||
|      * @param {String} textOrHtml The HTML or text to find matches within | ||||
|      *   (depending on if the {@link #urls}, {@link #email}, {@link #phone}, | ||||
|      *   {@link #hashtag}, and {@link #mention} options are enabled). | ||||
|      * @return {Autolinker.match.Match[]} The array of Matches found in the | ||||
|      *   given input `textOrHtml`. | ||||
|      */ | ||||
|     Autolinker.prototype.parse = function (textOrHtml) { | ||||
|         var _this = this; | ||||
|         var skipTagNames = ['a', 'style', 'script'], skipTagsStackCount = 0, // used to only Autolink text outside of anchor/script/style tags. We don't want to autolink something that is already linked inside of an <a> tag, for instance | ||||
|         matches = []; | ||||
|         // Find all matches within the `textOrHtml` (but not matches that are | ||||
|         // already nested within <a>, <style> and <script> tags) | ||||
|         parseHtml(textOrHtml, { | ||||
|             onOpenTag: function (tagName) { | ||||
|                 if (skipTagNames.indexOf(tagName) >= 0) { | ||||
|                     skipTagsStackCount++; | ||||
|                 } | ||||
|             }, | ||||
|             onText: function (text, offset) { | ||||
|                 // Only process text nodes that are not within an <a>, <style> or <script> tag | ||||
|                 if (skipTagsStackCount === 0) { | ||||
|                     // "Walk around" common HTML entities. An ' ' (for example) | ||||
|                     // could be at the end of a URL, but we don't want to  | ||||
|                     // include the trailing '&' in the URL. See issue #76 | ||||
|                     // TODO: Handle HTML entities separately in parseHtml() and | ||||
|                     // don't emit them as "text" except for & entities | ||||
|                     var htmlCharacterEntitiesRegex = /( | |<|<|>|>|"|"|')/gi; | ||||
|                     var textSplit = splitAndCapture(text, htmlCharacterEntitiesRegex); | ||||
|                     var currentOffset_1 = offset; | ||||
|                     textSplit.forEach(function (splitText, i) { | ||||
|                         // even number matches are text, odd numbers are html entities | ||||
|                         if (i % 2 === 0) { | ||||
|                             var textNodeMatches = _this.parseText(splitText, currentOffset_1); | ||||
|                             matches.push.apply(matches, textNodeMatches); | ||||
|                         } | ||||
|                         currentOffset_1 += splitText.length; | ||||
|                     }); | ||||
|                 } | ||||
|             }, | ||||
|             onCloseTag: function (tagName) { | ||||
|                 if (skipTagNames.indexOf(tagName) >= 0) { | ||||
|                     skipTagsStackCount = Math.max(skipTagsStackCount - 1, 0); // attempt to handle extraneous </a> tags by making sure the stack count never goes below 0 | ||||
|                 } | ||||
|             }, | ||||
|             onComment: function (offset) { }, | ||||
|             onDoctype: function (offset) { }, | ||||
|         }); | ||||
|         // After we have found all matches, remove subsequent matches that | ||||
|         // overlap with a previous match. This can happen for instance with URLs, | ||||
|         // where the url 'google.com/#link' would match '#link' as a hashtag. | ||||
|         matches = this.compactMatches(matches); | ||||
|         // And finally, remove matches for match types that have been turned | ||||
|         // off. We needed to have all match types turned on initially so that | ||||
|         // things like hashtags could be filtered out if they were really just | ||||
|         // part of a URL match (for instance, as a named anchor). | ||||
|         matches = this.removeUnwantedMatches(matches); | ||||
|         return matches; | ||||
|     }; | ||||
|     /** | ||||
|      * After we have found all matches, we need to remove matches that overlap | ||||
|      * with a previous match. This can happen for instance with URLs, where the | ||||
|      * url 'google.com/#link' would match '#link' as a hashtag. Because the | ||||
|      * '#link' part is contained in a larger match that comes before the HashTag | ||||
|      * match, we'll remove the HashTag match. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {Autolinker.match.Match[]} matches | ||||
|      * @return {Autolinker.match.Match[]} | ||||
|      */ | ||||
|     Autolinker.prototype.compactMatches = function (matches) { | ||||
|         // First, the matches need to be sorted in order of offset | ||||
|         matches.sort(function (a, b) { return a.getOffset() - b.getOffset(); }); | ||||
|         for (var i = 0; i < matches.length - 1; i++) { | ||||
|             var match = matches[i], offset = match.getOffset(), matchedTextLength = match.getMatchedText().length, endIdx = offset + matchedTextLength; | ||||
|             if (i + 1 < matches.length) { | ||||
|                 // Remove subsequent matches that equal offset with current match | ||||
|                 if (matches[i + 1].getOffset() === offset) { | ||||
|                     var removeIdx = matches[i + 1].getMatchedText().length > matchedTextLength ? i : i + 1; | ||||
|                     matches.splice(removeIdx, 1); | ||||
|                     continue; | ||||
|                 } | ||||
|                 // Remove subsequent matches that overlap with the current match | ||||
|                 if (matches[i + 1].getOffset() < endIdx) { | ||||
|                     matches.splice(i + 1, 1); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return matches; | ||||
|     }; | ||||
|     /** | ||||
|      * Removes matches for matchers that were turned off in the options. For | ||||
|      * example, if {@link #hashtag hashtags} were not to be matched, we'll | ||||
|      * remove them from the `matches` array here. | ||||
|      * | ||||
|      * Note: we *must* use all Matchers on the input string, and then filter | ||||
|      * them out later. For example, if the options were `{ url: false, hashtag: true }`, | ||||
|      * we wouldn't want to match the text '#link' as a HashTag inside of the text | ||||
|      * 'google.com/#link'. The way the algorithm works is that we match the full | ||||
|      * URL first (which prevents the accidental HashTag match), and then we'll | ||||
|      * simply throw away the URL match. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {Autolinker.match.Match[]} matches The array of matches to remove | ||||
|      *   the unwanted matches from. Note: this array is mutated for the | ||||
|      *   removals. | ||||
|      * @return {Autolinker.match.Match[]} The mutated input `matches` array. | ||||
|      */ | ||||
|     Autolinker.prototype.removeUnwantedMatches = function (matches) { | ||||
|         if (!this.hashtag) | ||||
|             remove(matches, function (match) { return match.getType() === 'hashtag'; }); | ||||
|         if (!this.email) | ||||
|             remove(matches, function (match) { return match.getType() === 'email'; }); | ||||
|         if (!this.phone) | ||||
|             remove(matches, function (match) { return match.getType() === 'phone'; }); | ||||
|         if (!this.mention) | ||||
|             remove(matches, function (match) { return match.getType() === 'mention'; }); | ||||
|         if (!this.urls.schemeMatches) { | ||||
|             remove(matches, function (m) { return m.getType() === 'url' && m.getUrlMatchType() === 'scheme'; }); | ||||
|         } | ||||
|         if (!this.urls.wwwMatches) { | ||||
|             remove(matches, function (m) { return m.getType() === 'url' && m.getUrlMatchType() === 'www'; }); | ||||
|         } | ||||
|         if (!this.urls.tldMatches) { | ||||
|             remove(matches, function (m) { return m.getType() === 'url' && m.getUrlMatchType() === 'tld'; }); | ||||
|         } | ||||
|         return matches; | ||||
|     }; | ||||
|     /** | ||||
|      * Parses the input `text` looking for URLs, email addresses, phone | ||||
|      * numbers, username handles, and hashtags (depending on the configuration | ||||
|      * of the Autolinker instance), and returns an array of {@link Autolinker.match.Match} | ||||
|      * objects describing those matches. | ||||
|      * | ||||
|      * This method processes a **non-HTML string**, and is used to parse and | ||||
|      * match within the text nodes of an HTML string. This method is used | ||||
|      * internally by {@link #parse}. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {String} text The text to find matches within (depending on if the | ||||
|      *   {@link #urls}, {@link #email}, {@link #phone}, | ||||
|      *   {@link #hashtag}, and {@link #mention} options are enabled). This must be a non-HTML string. | ||||
|      * @param {Number} [offset=0] The offset of the text node within the | ||||
|      *   original string. This is used when parsing with the {@link #parse} | ||||
|      *   method to generate correct offsets within the {@link Autolinker.match.Match} | ||||
|      *   instances, but may be omitted if calling this method publicly. | ||||
|      * @return {Autolinker.match.Match[]} The array of Matches found in the | ||||
|      *   given input `text`. | ||||
|      */ | ||||
|     Autolinker.prototype.parseText = function (text, offset) { | ||||
|         if (offset === void 0) { offset = 0; } | ||||
|         offset = offset || 0; | ||||
|         var matchers = this.getMatchers(), matches = []; | ||||
|         for (var i = 0, numMatchers = matchers.length; i < numMatchers; i++) { | ||||
|             var textMatches = matchers[i].parseMatches(text); | ||||
|             // Correct the offset of each of the matches. They are originally | ||||
|             // the offset of the match within the provided text node, but we | ||||
|             // need to correct them to be relative to the original HTML input | ||||
|             // string (i.e. the one provided to #parse). | ||||
|             for (var j = 0, numTextMatches = textMatches.length; j < numTextMatches; j++) { | ||||
|                 textMatches[j].setOffset(offset + textMatches[j].getOffset()); | ||||
|             } | ||||
|             matches.push.apply(matches, textMatches); | ||||
|         } | ||||
|         return matches; | ||||
|     }; | ||||
|     /** | ||||
|      * Automatically links URLs, Email addresses, Phone numbers, Hashtags, | ||||
|      * and Mentions (Twitter, Instagram, Soundcloud) 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>` | ||||
|      * | ||||
|      * This method finds the text around any HTML elements in the input | ||||
|      * `textOrHtml`, which will be the text that is processed. Any original HTML | ||||
|      * elements will be left as-is, as well as the text that is already wrapped | ||||
|      * in anchor (<a>) tags. | ||||
|      * | ||||
|      * @param {String} textOrHtml The HTML or text to autolink matches within | ||||
|      *   (depending on if the {@link #urls}, {@link #email}, {@link #phone}, {@link #hashtag}, and {@link #mention} options are enabled). | ||||
|      * @return {String} The HTML, with matches automatically linked. | ||||
|      */ | ||||
|     Autolinker.prototype.link = function (textOrHtml) { | ||||
|         if (!textOrHtml) { | ||||
|             return ""; | ||||
|         } // handle `null` and `undefined` (for JavaScript users that don't have TypeScript support) | ||||
|         /* We would want to sanitize the start and end characters of a tag | ||||
|          * before processing the string in order to avoid an XSS scenario. | ||||
|          * This behaviour can be changed by toggling the sanitizeHtml option. | ||||
|          */ | ||||
|         if (this.sanitizeHtml) { | ||||
|             textOrHtml = textOrHtml | ||||
|                 .replace(/</g, '<') | ||||
|                 .replace(/>/g, '>'); | ||||
|         } | ||||
|         var matches = this.parse(textOrHtml), newHtml = [], lastIndex = 0; | ||||
|         for (var i = 0, len = matches.length; i < len; i++) { | ||||
|             var match = matches[i]; | ||||
|             newHtml.push(textOrHtml.substring(lastIndex, match.getOffset())); | ||||
|             newHtml.push(this.createMatchReturnVal(match)); | ||||
|             lastIndex = match.getOffset() + match.getMatchedText().length; | ||||
|         } | ||||
|         newHtml.push(textOrHtml.substring(lastIndex)); // handle the text after the last match | ||||
|         return newHtml.join(''); | ||||
|     }; | ||||
|     /** | ||||
|      * Creates the return string value for a given match in the input string. | ||||
|      * | ||||
|      * This method handles the {@link #replaceFn}, if one was provided. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {Autolinker.match.Match} match The Match object that represents | ||||
|      *   the match. | ||||
|      * @return {String} The string that the `match` should be replaced with. | ||||
|      *   This is usually the anchor tag string, but may be the `matchStr` itself | ||||
|      *   if the match is not to be replaced. | ||||
|      */ | ||||
|     Autolinker.prototype.createMatchReturnVal = function (match) { | ||||
|         // Handle a custom `replaceFn` being provided | ||||
|         var replaceFnResult; | ||||
|         if (this.replaceFn) { | ||||
|             replaceFnResult = this.replaceFn.call(this.context, match); // Autolinker instance is the context | ||||
|         } | ||||
|         if (typeof replaceFnResult === 'string') { | ||||
|             return replaceFnResult; // `replaceFn` returned a string, use that | ||||
|         } | ||||
|         else if (replaceFnResult === false) { | ||||
|             return match.getMatchedText(); // no replacement for the match | ||||
|         } | ||||
|         else if (replaceFnResult instanceof HtmlTag) { | ||||
|             return replaceFnResult.toAnchorString(); | ||||
|         } | ||||
|         else { // replaceFnResult === true, or no/unknown return value from function | ||||
|             // Perform Autolinker's default anchor tag generation | ||||
|             var anchorTag = match.buildTag(); // returns an Autolinker.HtmlTag instance | ||||
|             return anchorTag.toAnchorString(); | ||||
|         } | ||||
|     }; | ||||
|     /** | ||||
|      * Lazily instantiates and returns the {@link Autolinker.matcher.Matcher} | ||||
|      * instances for this Autolinker instance. | ||||
|      * | ||||
|      * @private | ||||
|      * @return {Autolinker.matcher.Matcher[]} | ||||
|      */ | ||||
|     Autolinker.prototype.getMatchers = function () { | ||||
|         if (!this.matchers) { | ||||
|             var tagBuilder = this.getTagBuilder(); | ||||
|             var matchers = [ | ||||
|                 new HashtagMatcher({ tagBuilder: tagBuilder, serviceName: this.hashtag }), | ||||
|                 new EmailMatcher({ tagBuilder: tagBuilder }), | ||||
|                 new PhoneMatcher({ tagBuilder: tagBuilder }), | ||||
|                 new MentionMatcher({ tagBuilder: tagBuilder, serviceName: this.mention }), | ||||
|                 new UrlMatcher({ tagBuilder: tagBuilder, stripPrefix: this.stripPrefix, stripTrailingSlash: this.stripTrailingSlash, decodePercentEncoding: this.decodePercentEncoding }) | ||||
|             ]; | ||||
|             return (this.matchers = matchers); | ||||
|         } | ||||
|         else { | ||||
|             return this.matchers; | ||||
|         } | ||||
|     }; | ||||
|     /** | ||||
|      * Returns the {@link #tagBuilder} instance for this Autolinker instance, | ||||
|      * lazily instantiating it if it does not yet exist. | ||||
|      * | ||||
|      * @private | ||||
|      * @return {Autolinker.AnchorTagBuilder} | ||||
|      */ | ||||
|     Autolinker.prototype.getTagBuilder = function () { | ||||
|         var tagBuilder = this.tagBuilder; | ||||
|         if (!tagBuilder) { | ||||
|             tagBuilder = this.tagBuilder = new AnchorTagBuilder({ | ||||
|                 newWindow: this.newWindow, | ||||
|                 truncate: this.truncate, | ||||
|                 className: this.className | ||||
|             }); | ||||
|         } | ||||
|         return tagBuilder; | ||||
|     }; | ||||
|     /** | ||||
|      * @static | ||||
|      * @property {String} version | ||||
|      * | ||||
|      * The Autolinker version number in the form major.minor.patch | ||||
|      * | ||||
|      * Ex: 0.25.1 | ||||
|      */ | ||||
|     Autolinker.version = '3.14.1'; | ||||
|     /** | ||||
|      * For backwards compatibility with Autolinker 1.x, the AnchorTagBuilder | ||||
|      * class is provided as a static on the Autolinker class. | ||||
|      */ | ||||
|     Autolinker.AnchorTagBuilder = AnchorTagBuilder; | ||||
|     /** | ||||
|      * For backwards compatibility with Autolinker 1.x, the HtmlTag class is | ||||
|      * provided as a static on the Autolinker class. | ||||
|      */ | ||||
|     Autolinker.HtmlTag = HtmlTag; | ||||
|     /** | ||||
|      * For backwards compatibility with Autolinker 1.x, the Matcher classes are | ||||
|      * provided as statics on the Autolinker class. | ||||
|      */ | ||||
|     Autolinker.matcher = { | ||||
|         Email: EmailMatcher, | ||||
|         Hashtag: HashtagMatcher, | ||||
|         Matcher: Matcher, | ||||
|         Mention: MentionMatcher, | ||||
|         Phone: PhoneMatcher, | ||||
|         Url: UrlMatcher | ||||
|     }; | ||||
|     /** | ||||
|      * For backwards compatibility with Autolinker 1.x, the Match classes are | ||||
|      * provided as statics on the Autolinker class. | ||||
|      */ | ||||
|     Autolinker.match = { | ||||
|         Email: EmailMatch, | ||||
|         Hashtag: HashtagMatch, | ||||
|         Match: Match, | ||||
|         Mention: MentionMatch, | ||||
|         Phone: PhoneMatch, | ||||
|         Url: UrlMatch | ||||
|     }; | ||||
|     return Autolinker; | ||||
| }()); | ||||
| export default Autolinker; | ||||
|  | ||||
| //# sourceMappingURL=autolinker.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/autolinker.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/autolinker.js.map
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										238
									
								
								src/modules/autolinker/html-tag.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										238
									
								
								src/modules/autolinker/html-tag.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,238 @@ | ||||
| /** | ||||
|  * @class Autolinker.HtmlTag | ||||
|  * @extends Object | ||||
|  * | ||||
|  * Represents an HTML tag, which can be used to easily build/modify HTML tags programmatically. | ||||
|  * | ||||
|  * Autolinker uses this abstraction to create HTML tags, and then write them out as strings. You may also use | ||||
|  * this class in your code, especially within a {@link Autolinker#replaceFn replaceFn}. | ||||
|  * | ||||
|  * ## Examples | ||||
|  * | ||||
|  * Example instantiation: | ||||
|  * | ||||
|  *     var tag = new Autolinker.HtmlTag( { | ||||
|  *         tagName : 'a', | ||||
|  *         attrs   : { 'href': 'http://google.com', 'class': 'external-link' }, | ||||
|  *         innerHtml : 'Google' | ||||
|  *     } ); | ||||
|  * | ||||
|  *     tag.toAnchorString();  // <a href="http://google.com" class="external-link">Google</a> | ||||
|  * | ||||
|  *     // Individual accessor methods | ||||
|  *     tag.getTagName();                 // 'a' | ||||
|  *     tag.getAttr( 'href' );            // 'http://google.com' | ||||
|  *     tag.hasClass( 'external-link' );  // true | ||||
|  * | ||||
|  * | ||||
|  * Using mutator methods (which may be used in combination with instantiation config properties): | ||||
|  * | ||||
|  *     var tag = new Autolinker.HtmlTag(); | ||||
|  *     tag.setTagName( 'a' ); | ||||
|  *     tag.setAttr( 'href', 'http://google.com' ); | ||||
|  *     tag.addClass( 'external-link' ); | ||||
|  *     tag.setInnerHtml( 'Google' ); | ||||
|  * | ||||
|  *     tag.getTagName();                 // 'a' | ||||
|  *     tag.getAttr( 'href' );            // 'http://google.com' | ||||
|  *     tag.hasClass( 'external-link' );  // true | ||||
|  * | ||||
|  *     tag.toAnchorString();  // <a href="http://google.com" class="external-link">Google</a> | ||||
|  * | ||||
|  * | ||||
|  * ## Example use within a {@link Autolinker#replaceFn replaceFn} | ||||
|  * | ||||
|  *     var html = Autolinker.link( "Test google.com", { | ||||
|  *         replaceFn : function( match ) { | ||||
|  *             var tag = match.buildTag();  // returns an {@link Autolinker.HtmlTag} instance, configured with the Match's href and anchor text | ||||
|  *             tag.setAttr( 'rel', 'nofollow' ); | ||||
|  * | ||||
|  *             return tag; | ||||
|  *         } | ||||
|  *     } ); | ||||
|  * | ||||
|  *     // generated html: | ||||
|  *     //   Test <a href="http://google.com" target="_blank" rel="nofollow">google.com</a> | ||||
|  * | ||||
|  * | ||||
|  * ## Example use with a new tag for the replacement | ||||
|  * | ||||
|  *     var html = Autolinker.link( "Test google.com", { | ||||
|  *         replaceFn : function( match ) { | ||||
|  *             var tag = new Autolinker.HtmlTag( { | ||||
|  *                 tagName : 'button', | ||||
|  *                 attrs   : { 'title': 'Load URL: ' + match.getAnchorHref() }, | ||||
|  *                 innerHtml : 'Load URL: ' + match.getAnchorText() | ||||
|  *             } ); | ||||
|  * | ||||
|  *             return tag; | ||||
|  *         } | ||||
|  *     } ); | ||||
|  * | ||||
|  *     // generated html: | ||||
|  *     //   Test <button title="Load URL: http://google.com">Load URL: google.com</button> | ||||
|  */ | ||||
| export declare class HtmlTag { | ||||
|     /** | ||||
|      * @cfg {String} tagName | ||||
|      * | ||||
|      * The tag name. Ex: 'a', 'button', etc. | ||||
|      * | ||||
|      * Not required at instantiation time, but should be set using {@link #setTagName} before {@link #toAnchorString} | ||||
|      * is executed. | ||||
|      */ | ||||
|     private tagName; | ||||
|     /** | ||||
|      * @cfg {Object.<String, String>} attrs | ||||
|      * | ||||
|      * An key/value Object (map) of attributes to create the tag with. The keys are the attribute names, and the | ||||
|      * values are the attribute values. | ||||
|      */ | ||||
|     private attrs; | ||||
|     /** | ||||
|      * @cfg {String} innerHTML | ||||
|      * | ||||
|      * The inner HTML for the tag. | ||||
|      */ | ||||
|     private innerHTML; | ||||
|     /** | ||||
|      * @protected | ||||
|      * @property {RegExp} whitespaceRegex | ||||
|      * | ||||
|      * Regular expression used to match whitespace in a string of CSS classes. | ||||
|      */ | ||||
|     protected whitespaceRegex: RegExp; | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} [cfg] The configuration properties for this class, in an Object (map) | ||||
|      */ | ||||
|     constructor(cfg?: HtmlTagCfg); | ||||
|     /** | ||||
|      * Sets the tag name that will be used to generate the tag with. | ||||
|      * | ||||
|      * @param {String} tagName | ||||
|      * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. | ||||
|      */ | ||||
|     setTagName(tagName: string): this; | ||||
|     /** | ||||
|      * Retrieves the tag name. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getTagName(): string; | ||||
|     /** | ||||
|      * Sets an attribute on the HtmlTag. | ||||
|      * | ||||
|      * @param {String} attrName The attribute name to set. | ||||
|      * @param {String} attrValue The attribute value to set. | ||||
|      * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. | ||||
|      */ | ||||
|     setAttr(attrName: string, attrValue: string): this; | ||||
|     /** | ||||
|      * Retrieves an attribute from the HtmlTag. If the attribute does not exist, returns `undefined`. | ||||
|      * | ||||
|      * @param {String} attrName The attribute name to retrieve. | ||||
|      * @return {String} The attribute's value, or `undefined` if it does not exist on the HtmlTag. | ||||
|      */ | ||||
|     getAttr(attrName: string): string; | ||||
|     /** | ||||
|      * Sets one or more attributes on the HtmlTag. | ||||
|      * | ||||
|      * @param {Object.<String, String>} attrs A key/value Object (map) of the attributes to set. | ||||
|      * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. | ||||
|      */ | ||||
|     setAttrs(attrs: { | ||||
|         [attr: string]: string; | ||||
|     }): this; | ||||
|     /** | ||||
|      * Retrieves the attributes Object (map) for the HtmlTag. | ||||
|      * | ||||
|      * @return {Object.<String, String>} A key/value object of the attributes for the HtmlTag. | ||||
|      */ | ||||
|     getAttrs(): { | ||||
|         [key: string]: string; | ||||
|     }; | ||||
|     /** | ||||
|      * Sets the provided `cssClass`, overwriting any current CSS classes on the HtmlTag. | ||||
|      * | ||||
|      * @param {String} cssClass One or more space-separated CSS classes to set (overwrite). | ||||
|      * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. | ||||
|      */ | ||||
|     setClass(cssClass: string): this; | ||||
|     /** | ||||
|      * Convenience method to add one or more CSS classes to the HtmlTag. Will not add duplicate CSS classes. | ||||
|      * | ||||
|      * @param {String} cssClass One or more space-separated CSS classes to add. | ||||
|      * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. | ||||
|      */ | ||||
|     addClass(cssClass: string): this; | ||||
|     /** | ||||
|      * Convenience method to remove one or more CSS classes from the HtmlTag. | ||||
|      * | ||||
|      * @param {String} cssClass One or more space-separated CSS classes to remove. | ||||
|      * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. | ||||
|      */ | ||||
|     removeClass(cssClass: string): this; | ||||
|     /** | ||||
|      * Convenience method to retrieve the CSS class(es) for the HtmlTag, which will each be separated by spaces when | ||||
|      * there are multiple. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getClass(): string; | ||||
|     /** | ||||
|      * Convenience method to check if the tag has a CSS class or not. | ||||
|      * | ||||
|      * @param {String} cssClass The CSS class to check for. | ||||
|      * @return {Boolean} `true` if the HtmlTag has the CSS class, `false` otherwise. | ||||
|      */ | ||||
|     hasClass(cssClass: string): boolean; | ||||
|     /** | ||||
|      * Sets the inner HTML for the tag. | ||||
|      * | ||||
|      * @param {String} html The inner HTML to set. | ||||
|      * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. | ||||
|      */ | ||||
|     setInnerHTML(html: string): this; | ||||
|     /** | ||||
|      * Backwards compatibility method name. | ||||
|      * | ||||
|      * @param {String} html The inner HTML to set. | ||||
|      * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. | ||||
|      */ | ||||
|     setInnerHtml(html: string): this; | ||||
|     /** | ||||
|      * Retrieves the inner HTML for the tag. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getInnerHTML(): string; | ||||
|     /** | ||||
|      * Backward compatibility method name. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getInnerHtml(): string; | ||||
|     /** | ||||
|      * Override of superclass method used to generate the HTML string for the tag. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     toAnchorString(): string; | ||||
|     /** | ||||
|      * Support method for {@link #toAnchorString}, returns the string space-separated key="value" pairs, used to populate | ||||
|      * the stringified HtmlTag. | ||||
|      * | ||||
|      * @protected | ||||
|      * @return {String} Example return: `attr1="value1" attr2="value2"` | ||||
|      */ | ||||
|     protected buildAttrsStr(): string; | ||||
| } | ||||
| export interface HtmlTagCfg { | ||||
|     tagName?: string; | ||||
|     attrs?: { | ||||
|         [key: string]: string; | ||||
|     }; | ||||
|     innerHtml?: string; | ||||
|     innerHTML?: string; | ||||
| } | ||||
							
								
								
									
										300
									
								
								src/modules/autolinker/html-tag.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										300
									
								
								src/modules/autolinker/html-tag.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,300 @@ | ||||
| import { indexOf } from "./utils"; | ||||
| /** | ||||
|  * @class Autolinker.HtmlTag | ||||
|  * @extends Object | ||||
|  * | ||||
|  * Represents an HTML tag, which can be used to easily build/modify HTML tags programmatically. | ||||
|  * | ||||
|  * Autolinker uses this abstraction to create HTML tags, and then write them out as strings. You may also use | ||||
|  * this class in your code, especially within a {@link Autolinker#replaceFn replaceFn}. | ||||
|  * | ||||
|  * ## Examples | ||||
|  * | ||||
|  * Example instantiation: | ||||
|  * | ||||
|  *     var tag = new Autolinker.HtmlTag( { | ||||
|  *         tagName : 'a', | ||||
|  *         attrs   : { 'href': 'http://google.com', 'class': 'external-link' }, | ||||
|  *         innerHtml : 'Google' | ||||
|  *     } ); | ||||
|  * | ||||
|  *     tag.toAnchorString();  // <a href="http://google.com" class="external-link">Google</a> | ||||
|  * | ||||
|  *     // Individual accessor methods | ||||
|  *     tag.getTagName();                 // 'a' | ||||
|  *     tag.getAttr( 'href' );            // 'http://google.com' | ||||
|  *     tag.hasClass( 'external-link' );  // true | ||||
|  * | ||||
|  * | ||||
|  * Using mutator methods (which may be used in combination with instantiation config properties): | ||||
|  * | ||||
|  *     var tag = new Autolinker.HtmlTag(); | ||||
|  *     tag.setTagName( 'a' ); | ||||
|  *     tag.setAttr( 'href', 'http://google.com' ); | ||||
|  *     tag.addClass( 'external-link' ); | ||||
|  *     tag.setInnerHtml( 'Google' ); | ||||
|  * | ||||
|  *     tag.getTagName();                 // 'a' | ||||
|  *     tag.getAttr( 'href' );            // 'http://google.com' | ||||
|  *     tag.hasClass( 'external-link' );  // true | ||||
|  * | ||||
|  *     tag.toAnchorString();  // <a href="http://google.com" class="external-link">Google</a> | ||||
|  * | ||||
|  * | ||||
|  * ## Example use within a {@link Autolinker#replaceFn replaceFn} | ||||
|  * | ||||
|  *     var html = Autolinker.link( "Test google.com", { | ||||
|  *         replaceFn : function( match ) { | ||||
|  *             var tag = match.buildTag();  // returns an {@link Autolinker.HtmlTag} instance, configured with the Match's href and anchor text | ||||
|  *             tag.setAttr( 'rel', 'nofollow' ); | ||||
|  * | ||||
|  *             return tag; | ||||
|  *         } | ||||
|  *     } ); | ||||
|  * | ||||
|  *     // generated html: | ||||
|  *     //   Test <a href="http://google.com" target="_blank" rel="nofollow">google.com</a> | ||||
|  * | ||||
|  * | ||||
|  * ## Example use with a new tag for the replacement | ||||
|  * | ||||
|  *     var html = Autolinker.link( "Test google.com", { | ||||
|  *         replaceFn : function( match ) { | ||||
|  *             var tag = new Autolinker.HtmlTag( { | ||||
|  *                 tagName : 'button', | ||||
|  *                 attrs   : { 'title': 'Load URL: ' + match.getAnchorHref() }, | ||||
|  *                 innerHtml : 'Load URL: ' + match.getAnchorText() | ||||
|  *             } ); | ||||
|  * | ||||
|  *             return tag; | ||||
|  *         } | ||||
|  *     } ); | ||||
|  * | ||||
|  *     // generated html: | ||||
|  *     //   Test <button title="Load URL: http://google.com">Load URL: google.com</button> | ||||
|  */ | ||||
| var HtmlTag = /** @class */ (function () { | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} [cfg] The configuration properties for this class, in an Object (map) | ||||
|      */ | ||||
|     function HtmlTag(cfg) { | ||||
|         if (cfg === void 0) { cfg = {}; } | ||||
|         /** | ||||
|          * @cfg {String} tagName | ||||
|          * | ||||
|          * The tag name. Ex: 'a', 'button', etc. | ||||
|          * | ||||
|          * Not required at instantiation time, but should be set using {@link #setTagName} before {@link #toAnchorString} | ||||
|          * is executed. | ||||
|          */ | ||||
|         this.tagName = ''; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {Object.<String, String>} attrs | ||||
|          * | ||||
|          * An key/value Object (map) of attributes to create the tag with. The keys are the attribute names, and the | ||||
|          * values are the attribute values. | ||||
|          */ | ||||
|         this.attrs = {}; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {String} innerHTML | ||||
|          * | ||||
|          * The inner HTML for the tag. | ||||
|          */ | ||||
|         this.innerHTML = ''; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @protected | ||||
|          * @property {RegExp} whitespaceRegex | ||||
|          * | ||||
|          * Regular expression used to match whitespace in a string of CSS classes. | ||||
|          */ | ||||
|         this.whitespaceRegex = /\s+/; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         this.tagName = cfg.tagName || ''; | ||||
|         this.attrs = cfg.attrs || {}; | ||||
|         this.innerHTML = cfg.innerHtml || cfg.innerHTML || ''; // accept either the camelCased form or the fully capitalized acronym as in the DOM | ||||
|     } | ||||
|     /** | ||||
|      * Sets the tag name that will be used to generate the tag with. | ||||
|      * | ||||
|      * @param {String} tagName | ||||
|      * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. | ||||
|      */ | ||||
|     HtmlTag.prototype.setTagName = function (tagName) { | ||||
|         this.tagName = tagName; | ||||
|         return this; | ||||
|     }; | ||||
|     /** | ||||
|      * Retrieves the tag name. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     HtmlTag.prototype.getTagName = function () { | ||||
|         return this.tagName || ''; | ||||
|     }; | ||||
|     /** | ||||
|      * Sets an attribute on the HtmlTag. | ||||
|      * | ||||
|      * @param {String} attrName The attribute name to set. | ||||
|      * @param {String} attrValue The attribute value to set. | ||||
|      * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. | ||||
|      */ | ||||
|     HtmlTag.prototype.setAttr = function (attrName, attrValue) { | ||||
|         var tagAttrs = this.getAttrs(); | ||||
|         tagAttrs[attrName] = attrValue; | ||||
|         return this; | ||||
|     }; | ||||
|     /** | ||||
|      * Retrieves an attribute from the HtmlTag. If the attribute does not exist, returns `undefined`. | ||||
|      * | ||||
|      * @param {String} attrName The attribute name to retrieve. | ||||
|      * @return {String} The attribute's value, or `undefined` if it does not exist on the HtmlTag. | ||||
|      */ | ||||
|     HtmlTag.prototype.getAttr = function (attrName) { | ||||
|         return this.getAttrs()[attrName]; | ||||
|     }; | ||||
|     /** | ||||
|      * Sets one or more attributes on the HtmlTag. | ||||
|      * | ||||
|      * @param {Object.<String, String>} attrs A key/value Object (map) of the attributes to set. | ||||
|      * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. | ||||
|      */ | ||||
|     HtmlTag.prototype.setAttrs = function (attrs) { | ||||
|         Object.assign(this.getAttrs(), attrs); | ||||
|         return this; | ||||
|     }; | ||||
|     /** | ||||
|      * Retrieves the attributes Object (map) for the HtmlTag. | ||||
|      * | ||||
|      * @return {Object.<String, String>} A key/value object of the attributes for the HtmlTag. | ||||
|      */ | ||||
|     HtmlTag.prototype.getAttrs = function () { | ||||
|         return this.attrs || (this.attrs = {}); | ||||
|     }; | ||||
|     /** | ||||
|      * Sets the provided `cssClass`, overwriting any current CSS classes on the HtmlTag. | ||||
|      * | ||||
|      * @param {String} cssClass One or more space-separated CSS classes to set (overwrite). | ||||
|      * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. | ||||
|      */ | ||||
|     HtmlTag.prototype.setClass = function (cssClass) { | ||||
|         return this.setAttr('class', cssClass); | ||||
|     }; | ||||
|     /** | ||||
|      * Convenience method to add one or more CSS classes to the HtmlTag. Will not add duplicate CSS classes. | ||||
|      * | ||||
|      * @param {String} cssClass One or more space-separated CSS classes to add. | ||||
|      * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. | ||||
|      */ | ||||
|     HtmlTag.prototype.addClass = function (cssClass) { | ||||
|         var classAttr = this.getClass(), whitespaceRegex = this.whitespaceRegex, classes = (!classAttr) ? [] : classAttr.split(whitespaceRegex), newClasses = cssClass.split(whitespaceRegex), newClass; | ||||
|         while (newClass = newClasses.shift()) { | ||||
|             if (indexOf(classes, newClass) === -1) { | ||||
|                 classes.push(newClass); | ||||
|             } | ||||
|         } | ||||
|         this.getAttrs()['class'] = classes.join(" "); | ||||
|         return this; | ||||
|     }; | ||||
|     /** | ||||
|      * Convenience method to remove one or more CSS classes from the HtmlTag. | ||||
|      * | ||||
|      * @param {String} cssClass One or more space-separated CSS classes to remove. | ||||
|      * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. | ||||
|      */ | ||||
|     HtmlTag.prototype.removeClass = function (cssClass) { | ||||
|         var classAttr = this.getClass(), whitespaceRegex = this.whitespaceRegex, classes = (!classAttr) ? [] : classAttr.split(whitespaceRegex), removeClasses = cssClass.split(whitespaceRegex), removeClass; | ||||
|         while (classes.length && (removeClass = removeClasses.shift())) { | ||||
|             var idx = indexOf(classes, removeClass); | ||||
|             if (idx !== -1) { | ||||
|                 classes.splice(idx, 1); | ||||
|             } | ||||
|         } | ||||
|         this.getAttrs()['class'] = classes.join(" "); | ||||
|         return this; | ||||
|     }; | ||||
|     /** | ||||
|      * Convenience method to retrieve the CSS class(es) for the HtmlTag, which will each be separated by spaces when | ||||
|      * there are multiple. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     HtmlTag.prototype.getClass = function () { | ||||
|         return this.getAttrs()['class'] || ""; | ||||
|     }; | ||||
|     /** | ||||
|      * Convenience method to check if the tag has a CSS class or not. | ||||
|      * | ||||
|      * @param {String} cssClass The CSS class to check for. | ||||
|      * @return {Boolean} `true` if the HtmlTag has the CSS class, `false` otherwise. | ||||
|      */ | ||||
|     HtmlTag.prototype.hasClass = function (cssClass) { | ||||
|         return (' ' + this.getClass() + ' ').indexOf(' ' + cssClass + ' ') !== -1; | ||||
|     }; | ||||
|     /** | ||||
|      * Sets the inner HTML for the tag. | ||||
|      * | ||||
|      * @param {String} html The inner HTML to set. | ||||
|      * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. | ||||
|      */ | ||||
|     HtmlTag.prototype.setInnerHTML = function (html) { | ||||
|         this.innerHTML = html; | ||||
|         return this; | ||||
|     }; | ||||
|     /** | ||||
|      * Backwards compatibility method name. | ||||
|      * | ||||
|      * @param {String} html The inner HTML to set. | ||||
|      * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. | ||||
|      */ | ||||
|     HtmlTag.prototype.setInnerHtml = function (html) { | ||||
|         return this.setInnerHTML(html); | ||||
|     }; | ||||
|     /** | ||||
|      * Retrieves the inner HTML for the tag. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     HtmlTag.prototype.getInnerHTML = function () { | ||||
|         return this.innerHTML || ""; | ||||
|     }; | ||||
|     /** | ||||
|      * Backward compatibility method name. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     HtmlTag.prototype.getInnerHtml = function () { | ||||
|         return this.getInnerHTML(); | ||||
|     }; | ||||
|     /** | ||||
|      * Override of superclass method used to generate the HTML string for the tag. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     HtmlTag.prototype.toAnchorString = function () { | ||||
|         var tagName = this.getTagName(), attrsStr = this.buildAttrsStr(); | ||||
|         attrsStr = (attrsStr) ? ' ' + attrsStr : ''; // prepend a space if there are actually attributes | ||||
|         return ['<', tagName, attrsStr, '>', this.getInnerHtml(), '</', tagName, '>'].join(""); | ||||
|     }; | ||||
|     /** | ||||
|      * Support method for {@link #toAnchorString}, returns the string space-separated key="value" pairs, used to populate | ||||
|      * the stringified HtmlTag. | ||||
|      * | ||||
|      * @protected | ||||
|      * @return {String} Example return: `attr1="value1" attr2="value2"` | ||||
|      */ | ||||
|     HtmlTag.prototype.buildAttrsStr = function () { | ||||
|         if (!this.attrs) | ||||
|             return ""; // no `attrs` Object (map) has been set, return empty string | ||||
|         var attrs = this.getAttrs(), attrsArr = []; | ||||
|         for (var prop in attrs) { | ||||
|             if (attrs.hasOwnProperty(prop)) { | ||||
|                 attrsArr.push(prop + '="' + attrs[prop] + '"'); | ||||
|             } | ||||
|         } | ||||
|         return attrsArr.join(" "); | ||||
|     }; | ||||
|     return HtmlTag; | ||||
| }()); | ||||
| export { HtmlTag }; | ||||
|  | ||||
| //# sourceMappingURL=html-tag.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/html-tag.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/html-tag.js.map
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										58
									
								
								src/modules/autolinker/htmlParser/parse-html.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/modules/autolinker/htmlParser/parse-html.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| /** | ||||
|  * Parses an HTML string, calling the callbacks to notify of tags and text. | ||||
|  * | ||||
|  * ## History | ||||
|  * | ||||
|  * This file previously used a regular expression to find html tags in the input | ||||
|  * text. Unfortunately, we ran into a bunch of catastrophic backtracking issues | ||||
|  * with certain input text, causing Autolinker to either hang or just take a | ||||
|  * really long time to parse the string. | ||||
|  * | ||||
|  * The current code is intended to be a O(n) algorithm that walks through | ||||
|  * the string in one pass, and tries to be as cheap as possible. We don't need | ||||
|  * to implement the full HTML spec, but rather simply determine where the string | ||||
|  * looks like an HTML tag, and where it looks like text (so that we can autolink | ||||
|  * that). | ||||
|  * | ||||
|  * This state machine parser is intended just to be a simple but performant | ||||
|  * parser of HTML for the subset of requirements we have. We simply need to: | ||||
|  * | ||||
|  * 1. Determine where HTML tags are | ||||
|  * 2. Determine the tag name (Autolinker specifically only cares about <a>, | ||||
|  *    <script>, and <style> tags, so as not to link any text within them) | ||||
|  * | ||||
|  * We don't need to: | ||||
|  * | ||||
|  * 1. Create a parse tree | ||||
|  * 2. Auto-close tags with invalid markup | ||||
|  * 3. etc. | ||||
|  * | ||||
|  * The other intention behind this is that we didn't want to add external | ||||
|  * dependencies on the Autolinker utility which would increase its size. For | ||||
|  * instance, adding htmlparser2 adds 125kb to the minified output file, | ||||
|  * increasing its final size from 47kb to 172kb (at the time of writing). It | ||||
|  * also doesn't work exactly correctly, treating the string "<3 blah blah blah" | ||||
|  * as an HTML tag. | ||||
|  * | ||||
|  * Reference for HTML spec: | ||||
|  * | ||||
|  *     https://www.w3.org/TR/html51/syntax.html#sec-tokenization | ||||
|  * | ||||
|  * @param {String} html The HTML to parse | ||||
|  * @param {Object} callbacks | ||||
|  * @param {Function} callbacks.onOpenTag Callback function to call when an open | ||||
|  *   tag is parsed. Called with the tagName as its argument. | ||||
|  * @param {Function} callbacks.onCloseTag Callback function to call when a close | ||||
|  *   tag is parsed. Called with the tagName as its argument. If a self-closing | ||||
|  *   tag is found, `onCloseTag` is called immediately after `onOpenTag`. | ||||
|  * @param {Function} callbacks.onText Callback function to call when text (i.e | ||||
|  *   not an HTML tag) is parsed. Called with the text (string) as its first | ||||
|  *   argument, and offset (number) into the string as its second. | ||||
|  */ | ||||
| export declare function parseHtml(html: string, { onOpenTag, onCloseTag, onText, onComment, onDoctype }: { | ||||
|     onOpenTag: (tagName: string, offset: number) => void; | ||||
|     onCloseTag: (tagName: string, offset: number) => void; | ||||
|     onText: (text: string, offset: number) => void; | ||||
|     onComment: (offset: number) => void; | ||||
|     onDoctype: (offset: number) => void; | ||||
| }): void; | ||||
							
								
								
									
										629
									
								
								src/modules/autolinker/htmlParser/parse-html.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										629
									
								
								src/modules/autolinker/htmlParser/parse-html.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,629 @@ | ||||
| import * as tslib_1 from "tslib"; | ||||
| import { letterRe, digitRe, whitespaceRe, quoteRe, controlCharsRe } from '../regex-lib'; | ||||
| import { throwUnhandledCaseError } from '../utils'; | ||||
| // For debugging: search for other "For debugging" lines | ||||
| // import CliTable from 'cli-table'; | ||||
| /** | ||||
|  * Parses an HTML string, calling the callbacks to notify of tags and text. | ||||
|  * | ||||
|  * ## History | ||||
|  * | ||||
|  * This file previously used a regular expression to find html tags in the input | ||||
|  * text. Unfortunately, we ran into a bunch of catastrophic backtracking issues | ||||
|  * with certain input text, causing Autolinker to either hang or just take a | ||||
|  * really long time to parse the string. | ||||
|  * | ||||
|  * The current code is intended to be a O(n) algorithm that walks through | ||||
|  * the string in one pass, and tries to be as cheap as possible. We don't need | ||||
|  * to implement the full HTML spec, but rather simply determine where the string | ||||
|  * looks like an HTML tag, and where it looks like text (so that we can autolink | ||||
|  * that). | ||||
|  * | ||||
|  * This state machine parser is intended just to be a simple but performant | ||||
|  * parser of HTML for the subset of requirements we have. We simply need to: | ||||
|  * | ||||
|  * 1. Determine where HTML tags are | ||||
|  * 2. Determine the tag name (Autolinker specifically only cares about <a>, | ||||
|  *    <script>, and <style> tags, so as not to link any text within them) | ||||
|  * | ||||
|  * We don't need to: | ||||
|  * | ||||
|  * 1. Create a parse tree | ||||
|  * 2. Auto-close tags with invalid markup | ||||
|  * 3. etc. | ||||
|  * | ||||
|  * The other intention behind this is that we didn't want to add external | ||||
|  * dependencies on the Autolinker utility which would increase its size. For | ||||
|  * instance, adding htmlparser2 adds 125kb to the minified output file, | ||||
|  * increasing its final size from 47kb to 172kb (at the time of writing). It | ||||
|  * also doesn't work exactly correctly, treating the string "<3 blah blah blah" | ||||
|  * as an HTML tag. | ||||
|  * | ||||
|  * Reference for HTML spec: | ||||
|  * | ||||
|  *     https://www.w3.org/TR/html51/syntax.html#sec-tokenization | ||||
|  * | ||||
|  * @param {String} html The HTML to parse | ||||
|  * @param {Object} callbacks | ||||
|  * @param {Function} callbacks.onOpenTag Callback function to call when an open | ||||
|  *   tag is parsed. Called with the tagName as its argument. | ||||
|  * @param {Function} callbacks.onCloseTag Callback function to call when a close | ||||
|  *   tag is parsed. Called with the tagName as its argument. If a self-closing | ||||
|  *   tag is found, `onCloseTag` is called immediately after `onOpenTag`. | ||||
|  * @param {Function} callbacks.onText Callback function to call when text (i.e | ||||
|  *   not an HTML tag) is parsed. Called with the text (string) as its first | ||||
|  *   argument, and offset (number) into the string as its second. | ||||
|  */ | ||||
| export function parseHtml(html, _a) { | ||||
|     var onOpenTag = _a.onOpenTag, onCloseTag = _a.onCloseTag, onText = _a.onText, onComment = _a.onComment, onDoctype = _a.onDoctype; | ||||
|     var noCurrentTag = new CurrentTag(); | ||||
|     var charIdx = 0, len = html.length, state = 0 /* Data */, currentDataIdx = 0, // where the current data start index is | ||||
|     currentTag = noCurrentTag; // describes the current tag that is being read | ||||
|     // For debugging: search for other "For debugging" lines | ||||
|     // const table = new CliTable( { | ||||
|     // 	head: [ 'charIdx', 'char', 'state', 'currentDataIdx', 'currentOpenTagIdx', 'tag.type' ] | ||||
|     // } ); | ||||
|     while (charIdx < len) { | ||||
|         var char = html.charAt(charIdx); | ||||
|         // For debugging: search for other "For debugging" lines | ||||
|         // ALSO: Temporarily remove the 'const' keyword on the State enum | ||||
|         // table.push(  | ||||
|         // 	[ charIdx, char, State[ state ], currentDataIdx, currentTag.idx, currentTag.idx === -1 ? '' : currentTag.type ]  | ||||
|         // ); | ||||
|         switch (state) { | ||||
|             case 0 /* Data */: | ||||
|                 stateData(char); | ||||
|                 break; | ||||
|             case 1 /* TagOpen */: | ||||
|                 stateTagOpen(char); | ||||
|                 break; | ||||
|             case 2 /* EndTagOpen */: | ||||
|                 stateEndTagOpen(char); | ||||
|                 break; | ||||
|             case 3 /* TagName */: | ||||
|                 stateTagName(char); | ||||
|                 break; | ||||
|             case 4 /* BeforeAttributeName */: | ||||
|                 stateBeforeAttributeName(char); | ||||
|                 break; | ||||
|             case 5 /* AttributeName */: | ||||
|                 stateAttributeName(char); | ||||
|                 break; | ||||
|             case 6 /* AfterAttributeName */: | ||||
|                 stateAfterAttributeName(char); | ||||
|                 break; | ||||
|             case 7 /* BeforeAttributeValue */: | ||||
|                 stateBeforeAttributeValue(char); | ||||
|                 break; | ||||
|             case 8 /* AttributeValueDoubleQuoted */: | ||||
|                 stateAttributeValueDoubleQuoted(char); | ||||
|                 break; | ||||
|             case 9 /* AttributeValueSingleQuoted */: | ||||
|                 stateAttributeValueSingleQuoted(char); | ||||
|                 break; | ||||
|             case 10 /* AttributeValueUnquoted */: | ||||
|                 stateAttributeValueUnquoted(char); | ||||
|                 break; | ||||
|             case 11 /* AfterAttributeValueQuoted */: | ||||
|                 stateAfterAttributeValueQuoted(char); | ||||
|                 break; | ||||
|             case 12 /* SelfClosingStartTag */: | ||||
|                 stateSelfClosingStartTag(char); | ||||
|                 break; | ||||
|             case 13 /* MarkupDeclarationOpenState */: | ||||
|                 stateMarkupDeclarationOpen(char); | ||||
|                 break; | ||||
|             case 14 /* CommentStart */: | ||||
|                 stateCommentStart(char); | ||||
|                 break; | ||||
|             case 15 /* CommentStartDash */: | ||||
|                 stateCommentStartDash(char); | ||||
|                 break; | ||||
|             case 16 /* Comment */: | ||||
|                 stateComment(char); | ||||
|                 break; | ||||
|             case 17 /* CommentEndDash */: | ||||
|                 stateCommentEndDash(char); | ||||
|                 break; | ||||
|             case 18 /* CommentEnd */: | ||||
|                 stateCommentEnd(char); | ||||
|                 break; | ||||
|             case 19 /* CommentEndBang */: | ||||
|                 stateCommentEndBang(char); | ||||
|                 break; | ||||
|             case 20 /* Doctype */: | ||||
|                 stateDoctype(char); | ||||
|                 break; | ||||
|             default: | ||||
|                 throwUnhandledCaseError(state); | ||||
|         } | ||||
|         // For debugging: search for other "For debugging" lines | ||||
|         // ALSO: Temporarily remove the 'const' keyword on the State enum | ||||
|         // table.push(  | ||||
|         // 	[ charIdx, char, State[ state ], currentDataIdx, currentTag.idx, currentTag.idx === -1 ? '' : currentTag.type ]  | ||||
|         // ); | ||||
|         charIdx++; | ||||
|     } | ||||
|     if (currentDataIdx < charIdx) { | ||||
|         emitText(); | ||||
|     } | ||||
|     // For debugging: search for other "For debugging" lines | ||||
|     // console.log( '\n' + table.toString() ); | ||||
|     // Called when non-tags are being read (i.e. the text around HTML †ags) | ||||
|     // https://www.w3.org/TR/html51/syntax.html#data-state | ||||
|     function stateData(char) { | ||||
|         if (char === '<') { | ||||
|             startNewTag(); | ||||
|         } | ||||
|     } | ||||
|     // Called after a '<' is read from the Data state | ||||
|     // https://www.w3.org/TR/html51/syntax.html#tag-open-state | ||||
|     function stateTagOpen(char) { | ||||
|         if (char === '!') { | ||||
|             state = 13 /* MarkupDeclarationOpenState */; | ||||
|         } | ||||
|         else if (char === '/') { | ||||
|             state = 2 /* EndTagOpen */; | ||||
|             currentTag = new CurrentTag(tslib_1.__assign({}, currentTag, { isClosing: true })); | ||||
|         } | ||||
|         else if (char === '<') { | ||||
|             // start of another tag (ignore the previous, incomplete one) | ||||
|             startNewTag(); | ||||
|         } | ||||
|         else if (letterRe.test(char)) { | ||||
|             // tag name start (and no '/' read) | ||||
|             state = 3 /* TagName */; | ||||
|             currentTag = new CurrentTag(tslib_1.__assign({}, currentTag, { isOpening: true })); | ||||
|         } | ||||
|         else { | ||||
|             // Any other  | ||||
|             state = 0 /* Data */; | ||||
|             currentTag = noCurrentTag; | ||||
|         } | ||||
|     } | ||||
|     // After a '<x', '</x' sequence is read (where 'x' is a letter character),  | ||||
|     // this is to continue reading the tag name | ||||
|     // https://www.w3.org/TR/html51/syntax.html#tag-name-state | ||||
|     function stateTagName(char) { | ||||
|         if (whitespaceRe.test(char)) { | ||||
|             currentTag = new CurrentTag(tslib_1.__assign({}, currentTag, { name: captureTagName() })); | ||||
|             state = 4 /* BeforeAttributeName */; | ||||
|         } | ||||
|         else if (char === '<') { | ||||
|             // start of another tag (ignore the previous, incomplete one) | ||||
|             startNewTag(); | ||||
|         } | ||||
|         else if (char === '/') { | ||||
|             currentTag = new CurrentTag(tslib_1.__assign({}, currentTag, { name: captureTagName() })); | ||||
|             state = 12 /* SelfClosingStartTag */; | ||||
|         } | ||||
|         else if (char === '>') { | ||||
|             currentTag = new CurrentTag(tslib_1.__assign({}, currentTag, { name: captureTagName() })); | ||||
|             emitTagAndPreviousTextNode(); // resets to Data state as well | ||||
|         } | ||||
|         else if (!letterRe.test(char) && !digitRe.test(char) && char !== ':') { | ||||
|             // Anything else that does not form an html tag. Note: the colon  | ||||
|             // character is accepted for XML namespaced tags | ||||
|             resetToDataState(); | ||||
|         } | ||||
|         else { | ||||
|             // continue reading tag name | ||||
|         } | ||||
|     } | ||||
|     // Called after the '/' is read from a '</' sequence | ||||
|     // https://www.w3.org/TR/html51/syntax.html#end-tag-open-state | ||||
|     function stateEndTagOpen(char) { | ||||
|         if (char === '>') { // parse error. Encountered "</>". Skip it without treating as a tag | ||||
|             resetToDataState(); | ||||
|         } | ||||
|         else if (letterRe.test(char)) { | ||||
|             state = 3 /* TagName */; | ||||
|         } | ||||
|         else { | ||||
|             // some other non-tag-like character, don't treat this as a tag | ||||
|             resetToDataState(); | ||||
|         } | ||||
|     } | ||||
|     // https://www.w3.org/TR/html51/syntax.html#before-attribute-name-state | ||||
|     function stateBeforeAttributeName(char) { | ||||
|         if (whitespaceRe.test(char)) { | ||||
|             // stay in BeforeAttributeName state - continue reading chars | ||||
|         } | ||||
|         else if (char === '/') { | ||||
|             state = 12 /* SelfClosingStartTag */; | ||||
|         } | ||||
|         else if (char === '>') { | ||||
|             emitTagAndPreviousTextNode(); // resets to Data state as well | ||||
|         } | ||||
|         else if (char === '<') { | ||||
|             // start of another tag (ignore the previous, incomplete one) | ||||
|             startNewTag(); | ||||
|         } | ||||
|         else if (char === "=" || quoteRe.test(char) || controlCharsRe.test(char)) { | ||||
|             // "Parse error" characters that, according to the spec, should be | ||||
|             // appended to the attribute name, but we'll treat these characters | ||||
|             // as not forming a real HTML tag | ||||
|             resetToDataState(); | ||||
|         } | ||||
|         else { | ||||
|             // Any other char, start of a new attribute name | ||||
|             state = 5 /* AttributeName */; | ||||
|         } | ||||
|     } | ||||
|     // https://www.w3.org/TR/html51/syntax.html#attribute-name-state | ||||
|     function stateAttributeName(char) { | ||||
|         if (whitespaceRe.test(char)) { | ||||
|             state = 6 /* AfterAttributeName */; | ||||
|         } | ||||
|         else if (char === '/') { | ||||
|             state = 12 /* SelfClosingStartTag */; | ||||
|         } | ||||
|         else if (char === '=') { | ||||
|             state = 7 /* BeforeAttributeValue */; | ||||
|         } | ||||
|         else if (char === '>') { | ||||
|             emitTagAndPreviousTextNode(); // resets to Data state as well | ||||
|         } | ||||
|         else if (char === '<') { | ||||
|             // start of another tag (ignore the previous, incomplete one) | ||||
|             startNewTag(); | ||||
|         } | ||||
|         else if (quoteRe.test(char)) { | ||||
|             // "Parse error" characters that, according to the spec, should be | ||||
|             // appended to the attribute name, but we'll treat these characters | ||||
|             // as not forming a real HTML tag | ||||
|             resetToDataState(); | ||||
|         } | ||||
|         else { | ||||
|             // anything else: continue reading attribute name | ||||
|         } | ||||
|     } | ||||
|     // https://www.w3.org/TR/html51/syntax.html#after-attribute-name-state | ||||
|     function stateAfterAttributeName(char) { | ||||
|         if (whitespaceRe.test(char)) { | ||||
|             // ignore the character - continue reading | ||||
|         } | ||||
|         else if (char === '/') { | ||||
|             state = 12 /* SelfClosingStartTag */; | ||||
|         } | ||||
|         else if (char === '=') { | ||||
|             state = 7 /* BeforeAttributeValue */; | ||||
|         } | ||||
|         else if (char === '>') { | ||||
|             emitTagAndPreviousTextNode(); | ||||
|         } | ||||
|         else if (char === '<') { | ||||
|             // start of another tag (ignore the previous, incomplete one) | ||||
|             startNewTag(); | ||||
|         } | ||||
|         else if (quoteRe.test(char)) { | ||||
|             // "Parse error" characters that, according to the spec, should be | ||||
|             // appended to the attribute name, but we'll treat these characters | ||||
|             // as not forming a real HTML tag | ||||
|             resetToDataState(); | ||||
|         } | ||||
|         else { | ||||
|             // Any other character, start a new attribute in the current tag | ||||
|             state = 5 /* AttributeName */; | ||||
|         } | ||||
|     } | ||||
|     // https://www.w3.org/TR/html51/syntax.html#before-attribute-value-state | ||||
|     function stateBeforeAttributeValue(char) { | ||||
|         if (whitespaceRe.test(char)) { | ||||
|             // ignore the character - continue reading | ||||
|         } | ||||
|         else if (char === "\"") { | ||||
|             state = 8 /* AttributeValueDoubleQuoted */; | ||||
|         } | ||||
|         else if (char === "'") { | ||||
|             state = 9 /* AttributeValueSingleQuoted */; | ||||
|         } | ||||
|         else if (/[>=`]/.test(char)) { | ||||
|             // Invalid chars after an '=' for an attribute value, don't count  | ||||
|             // the current tag as an HTML tag | ||||
|             resetToDataState(); | ||||
|         } | ||||
|         else if (char === '<') { | ||||
|             // start of another tag (ignore the previous, incomplete one) | ||||
|             startNewTag(); | ||||
|         } | ||||
|         else { | ||||
|             // Any other character, consider it an unquoted attribute value | ||||
|             state = 10 /* AttributeValueUnquoted */; | ||||
|         } | ||||
|     } | ||||
|     // https://www.w3.org/TR/html51/syntax.html#attribute-value-double-quoted-state | ||||
|     function stateAttributeValueDoubleQuoted(char) { | ||||
|         if (char === "\"") { // end the current double-quoted attribute | ||||
|             state = 11 /* AfterAttributeValueQuoted */; | ||||
|         } | ||||
|         else { | ||||
|             // consume the character as part of the double-quoted attribute value | ||||
|         } | ||||
|     } | ||||
|     // https://www.w3.org/TR/html51/syntax.html#attribute-value-single-quoted-state | ||||
|     function stateAttributeValueSingleQuoted(char) { | ||||
|         if (char === "'") { // end the current single-quoted attribute | ||||
|             state = 11 /* AfterAttributeValueQuoted */; | ||||
|         } | ||||
|         else { | ||||
|             // consume the character as part of the double-quoted attribute value | ||||
|         } | ||||
|     } | ||||
|     // https://www.w3.org/TR/html51/syntax.html#attribute-value-unquoted-state | ||||
|     function stateAttributeValueUnquoted(char) { | ||||
|         if (whitespaceRe.test(char)) { | ||||
|             state = 4 /* BeforeAttributeName */; | ||||
|         } | ||||
|         else if (char === '>') { | ||||
|             emitTagAndPreviousTextNode(); | ||||
|         } | ||||
|         else if (char === '<') { | ||||
|             // start of another tag (ignore the previous, incomplete one) | ||||
|             startNewTag(); | ||||
|         } | ||||
|         else { | ||||
|             // Any other character, treat it as part of the attribute value | ||||
|         } | ||||
|     } | ||||
|     // https://www.w3.org/TR/html51/syntax.html#after-attribute-value-quoted-state | ||||
|     function stateAfterAttributeValueQuoted(char) { | ||||
|         if (whitespaceRe.test(char)) { | ||||
|             state = 4 /* BeforeAttributeName */; | ||||
|         } | ||||
|         else if (char === '/') { | ||||
|             state = 12 /* SelfClosingStartTag */; | ||||
|         } | ||||
|         else if (char === '>') { | ||||
|             emitTagAndPreviousTextNode(); | ||||
|         } | ||||
|         else if (char === '<') { | ||||
|             // start of another tag (ignore the previous, incomplete one) | ||||
|             startNewTag(); | ||||
|         } | ||||
|         else { | ||||
|             // Any other character, "parse error". Spec says to switch to the | ||||
|             // BeforeAttributeState and re-consume the character, as it may be | ||||
|             // the start of a new attribute name | ||||
|             state = 4 /* BeforeAttributeName */; | ||||
|             reconsumeCurrentCharacter(); | ||||
|         } | ||||
|     } | ||||
|     // A '/' has just been read in the current tag (presumably for '/>'), and  | ||||
|     // this handles the next character | ||||
|     // https://www.w3.org/TR/html51/syntax.html#self-closing-start-tag-state | ||||
|     function stateSelfClosingStartTag(char) { | ||||
|         if (char === '>') { | ||||
|             currentTag = new CurrentTag(tslib_1.__assign({}, currentTag, { isClosing: true })); | ||||
|             emitTagAndPreviousTextNode(); // resets to Data state as well | ||||
|         } | ||||
|         else { | ||||
|             state = 4 /* BeforeAttributeName */; | ||||
|         } | ||||
|     } | ||||
|     // https://www.w3.org/TR/html51/syntax.html#markup-declaration-open-state | ||||
|     // (HTML Comments or !DOCTYPE) | ||||
|     function stateMarkupDeclarationOpen(char) { | ||||
|         if (html.substr(charIdx, 2) === '--') { // html comment | ||||
|             charIdx += 2; // "consume" characters | ||||
|             currentTag = new CurrentTag(tslib_1.__assign({}, currentTag, { type: 'comment' })); | ||||
|             state = 14 /* CommentStart */; | ||||
|         } | ||||
|         else if (html.substr(charIdx, 7).toUpperCase() === 'DOCTYPE') { | ||||
|             charIdx += 7; // "consume" characters | ||||
|             currentTag = new CurrentTag(tslib_1.__assign({}, currentTag, { type: 'doctype' })); | ||||
|             state = 20 /* Doctype */; | ||||
|         } | ||||
|         else { | ||||
|             // At this point, the spec specifies that the state machine should | ||||
|             // enter the "bogus comment" state, in which case any character(s)  | ||||
|             // after the '<!' that were read should become an HTML comment up | ||||
|             // until the first '>' that is read (or EOF). Instead, we'll assume | ||||
|             // that a user just typed '<!' as part of text data | ||||
|             resetToDataState(); | ||||
|         } | ||||
|     } | ||||
|     // Handles after the sequence '<!--' has been read | ||||
|     // https://www.w3.org/TR/html51/syntax.html#comment-start-state | ||||
|     function stateCommentStart(char) { | ||||
|         if (char === '-') { | ||||
|             // We've read the sequence '<!---' at this point (3 dashes) | ||||
|             state = 15 /* CommentStartDash */; | ||||
|         } | ||||
|         else if (char === '>') { | ||||
|             // At this point, we'll assume the comment wasn't a real comment | ||||
|             // so we'll just emit it as data. We basically read the sequence  | ||||
|             // '<!-->' | ||||
|             resetToDataState(); | ||||
|         } | ||||
|         else { | ||||
|             // Any other char, take it as part of the comment | ||||
|             state = 16 /* Comment */; | ||||
|         } | ||||
|     } | ||||
|     // We've read the sequence '<!---' at this point (3 dashes) | ||||
|     // https://www.w3.org/TR/html51/syntax.html#comment-start-dash-state | ||||
|     function stateCommentStartDash(char) { | ||||
|         if (char === '-') { | ||||
|             // We've read '<!----' (4 dashes) at this point | ||||
|             state = 18 /* CommentEnd */; | ||||
|         } | ||||
|         else if (char === '>') { | ||||
|             // At this point, we'll assume the comment wasn't a real comment | ||||
|             // so we'll just emit it as data. We basically read the sequence  | ||||
|             // '<!--->' | ||||
|             resetToDataState(); | ||||
|         } | ||||
|         else { | ||||
|             // Anything else, take it as a valid comment | ||||
|             state = 16 /* Comment */; | ||||
|         } | ||||
|     } | ||||
|     // Currently reading the comment's text (data) | ||||
|     // https://www.w3.org/TR/html51/syntax.html#comment-state | ||||
|     function stateComment(char) { | ||||
|         if (char === '-') { | ||||
|             state = 17 /* CommentEndDash */; | ||||
|         } | ||||
|         else { | ||||
|             // Any other character, stay in the Comment state | ||||
|         } | ||||
|     } | ||||
|     // When we we've read the first dash inside a comment, it may signal the | ||||
|     // end of the comment if we read another dash | ||||
|     // https://www.w3.org/TR/html51/syntax.html#comment-end-dash-state | ||||
|     function stateCommentEndDash(char) { | ||||
|         if (char === '-') { | ||||
|             state = 18 /* CommentEnd */; | ||||
|         } | ||||
|         else { | ||||
|             // Wasn't a dash, must still be part of the comment | ||||
|             state = 16 /* Comment */; | ||||
|         } | ||||
|     } | ||||
|     // After we've read two dashes inside a comment, it may signal the end of  | ||||
|     // the comment if we then read a '>' char | ||||
|     // https://www.w3.org/TR/html51/syntax.html#comment-end-state | ||||
|     function stateCommentEnd(char) { | ||||
|         if (char === '>') { | ||||
|             emitTagAndPreviousTextNode(); | ||||
|         } | ||||
|         else if (char === '!') { | ||||
|             state = 19 /* CommentEndBang */; | ||||
|         } | ||||
|         else if (char === '-') { | ||||
|             // A 3rd '-' has been read: stay in the CommentEnd state | ||||
|         } | ||||
|         else { | ||||
|             // Anything else, switch back to the comment state since we didn't | ||||
|             // read the full "end comment" sequence (i.e. '-->') | ||||
|             state = 16 /* Comment */; | ||||
|         } | ||||
|     } | ||||
|     // We've read the sequence '--!' inside of a comment | ||||
|     // https://www.w3.org/TR/html51/syntax.html#comment-end-bang-state | ||||
|     function stateCommentEndBang(char) { | ||||
|         if (char === '-') { | ||||
|             // We read the sequence '--!-' inside of a comment. The last dash | ||||
|             // could signify that the comment is going to close | ||||
|             state = 17 /* CommentEndDash */; | ||||
|         } | ||||
|         else if (char === '>') { | ||||
|             // End of comment with the sequence '--!>' | ||||
|             emitTagAndPreviousTextNode(); | ||||
|         } | ||||
|         else { | ||||
|             // The '--!' was not followed by a '>', continue reading the  | ||||
|             // comment's text | ||||
|             state = 16 /* Comment */; | ||||
|         } | ||||
|     } | ||||
|     /** | ||||
|      * For DOCTYPES in particular, we don't care about the attributes. Just | ||||
|      * advance to the '>' character and emit the tag, unless we find a '<' | ||||
|      * character in which case we'll start a new tag. | ||||
|      * | ||||
|      * Example doctype tag: | ||||
|      *    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> | ||||
|      * | ||||
|      * Actual spec: https://www.w3.org/TR/html51/syntax.html#doctype-state | ||||
|      */ | ||||
|     function stateDoctype(char) { | ||||
|         if (char === '>') { | ||||
|             emitTagAndPreviousTextNode(); | ||||
|         } | ||||
|         else if (char === '<') { | ||||
|             startNewTag(); | ||||
|         } | ||||
|         else { | ||||
|             // stay in the Doctype state | ||||
|         } | ||||
|     } | ||||
|     /** | ||||
|      * Resets the state back to the Data state, and removes the current tag. | ||||
|      * | ||||
|      * We'll generally run this function whenever a "parse error" is | ||||
|      * encountered, where the current tag that is being read no longer looks | ||||
|      * like a real HTML tag. | ||||
|      */ | ||||
|     function resetToDataState() { | ||||
|         state = 0 /* Data */; | ||||
|         currentTag = noCurrentTag; | ||||
|     } | ||||
|     /** | ||||
|      * Starts a new HTML tag at the current index, ignoring any previous HTML | ||||
|      * tag that was being read. | ||||
|      * | ||||
|      * We'll generally run this function whenever we read a new '<' character, | ||||
|      * including when we read a '<' character inside of an HTML tag that we were | ||||
|      * previously reading. | ||||
|      */ | ||||
|     function startNewTag() { | ||||
|         state = 1 /* TagOpen */; | ||||
|         currentTag = new CurrentTag({ idx: charIdx }); | ||||
|     } | ||||
|     /** | ||||
|      * Once we've decided to emit an open tag, that means we can also emit the | ||||
|      * text node before it. | ||||
|      */ | ||||
|     function emitTagAndPreviousTextNode() { | ||||
|         var textBeforeTag = html.slice(currentDataIdx, currentTag.idx); | ||||
|         if (textBeforeTag) { | ||||
|             // the html tag was the first element in the html string, or two  | ||||
|             // tags next to each other, in which case we should not emit a text  | ||||
|             // node | ||||
|             onText(textBeforeTag, currentDataIdx); | ||||
|         } | ||||
|         if (currentTag.type === 'comment') { | ||||
|             onComment(currentTag.idx); | ||||
|         } | ||||
|         else if (currentTag.type === 'doctype') { | ||||
|             onDoctype(currentTag.idx); | ||||
|         } | ||||
|         else { | ||||
|             if (currentTag.isOpening) { | ||||
|                 onOpenTag(currentTag.name, currentTag.idx); | ||||
|             } | ||||
|             if (currentTag.isClosing) { // note: self-closing tags will emit both opening and closing | ||||
|                 onCloseTag(currentTag.name, currentTag.idx); | ||||
|             } | ||||
|         } | ||||
|         // Since we just emitted a tag, reset to the data state for the next char | ||||
|         resetToDataState(); | ||||
|         currentDataIdx = charIdx + 1; | ||||
|     } | ||||
|     function emitText() { | ||||
|         var text = html.slice(currentDataIdx, charIdx); | ||||
|         onText(text, currentDataIdx); | ||||
|         currentDataIdx = charIdx + 1; | ||||
|     } | ||||
|     /** | ||||
|      * Captures the tag name from the start of the tag to the current character | ||||
|      * index, and converts it to lower case | ||||
|      */ | ||||
|     function captureTagName() { | ||||
|         var startIdx = currentTag.idx + (currentTag.isClosing ? 2 : 1); | ||||
|         return html.slice(startIdx, charIdx).toLowerCase(); | ||||
|     } | ||||
|     /** | ||||
|      * Causes the main loop to re-consume the current character, such as after | ||||
|      * encountering a "parse error" that changed state and needs to reconsume | ||||
|      * the same character in that new state. | ||||
|      */ | ||||
|     function reconsumeCurrentCharacter() { | ||||
|         charIdx--; | ||||
|     } | ||||
| } | ||||
| var CurrentTag = /** @class */ (function () { | ||||
|     function CurrentTag(cfg) { | ||||
|         if (cfg === void 0) { cfg = {}; } | ||||
|         this.idx = cfg.idx !== undefined ? cfg.idx : -1; | ||||
|         this.type = cfg.type || 'tag'; | ||||
|         this.name = cfg.name || ''; | ||||
|         this.isOpening = !!cfg.isOpening; | ||||
|         this.isClosing = !!cfg.isClosing; | ||||
|     } | ||||
|     return CurrentTag; | ||||
| }()); | ||||
|  | ||||
| //# sourceMappingURL=parse-html.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/htmlParser/parse-html.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/htmlParser/parse-html.js.map
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										27
									
								
								src/modules/autolinker/htmlParser/state.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/modules/autolinker/htmlParser/state.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| /** | ||||
|  * The subset of the parser states defined in https://www.w3.org/TR/html51/syntax.html | ||||
|  * which are useful for Autolinker. | ||||
|  */ | ||||
| export declare const enum State { | ||||
|     Data = 0, | ||||
|     TagOpen = 1, | ||||
|     EndTagOpen = 2, | ||||
|     TagName = 3, | ||||
|     BeforeAttributeName = 4, | ||||
|     AttributeName = 5, | ||||
|     AfterAttributeName = 6, | ||||
|     BeforeAttributeValue = 7, | ||||
|     AttributeValueDoubleQuoted = 8, | ||||
|     AttributeValueSingleQuoted = 9, | ||||
|     AttributeValueUnquoted = 10, | ||||
|     AfterAttributeValueQuoted = 11, | ||||
|     SelfClosingStartTag = 12, | ||||
|     MarkupDeclarationOpenState = 13, | ||||
|     CommentStart = 14, | ||||
|     CommentStartDash = 15, | ||||
|     Comment = 16, | ||||
|     CommentEndDash = 17, | ||||
|     CommentEnd = 18, | ||||
|     CommentEndBang = 19, | ||||
|     Doctype = 20 | ||||
| } | ||||
							
								
								
									
										3
									
								
								src/modules/autolinker/htmlParser/state.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/modules/autolinker/htmlParser/state.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
|  | ||||
|  | ||||
| //# sourceMappingURL=state.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/htmlParser/state.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/htmlParser/state.js.map
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| {"version":3,"sources":["../src/htmlParser/state.ts"],"names":[],"mappings":"","file":"state.js","sourcesContent":["/**\n * The subset of the parser states defined in https://www.w3.org/TR/html51/syntax.html\n * which are useful for Autolinker.\n */\nexport const enum State {\n\tData = 0,\n\tTagOpen,\n\tEndTagOpen,\n\tTagName,\n\tBeforeAttributeName,\n\tAttributeName,\n\tAfterAttributeName,\n\tBeforeAttributeValue,\n\tAttributeValueDoubleQuoted,\n\tAttributeValueSingleQuoted,\n\tAttributeValueUnquoted,\n\tAfterAttributeValueQuoted,\n\tSelfClosingStartTag,\n\tMarkupDeclarationOpenState,  // When the sequence '<!' is read for an HTML comment or doctype\n\tCommentStart,\n\tCommentStartDash,\n\tComment,\n\tCommentEndDash,\n\tCommentEnd,\n\tCommentEndBang,\n\tDoctype\n}"]} | ||||
							
								
								
									
										7
									
								
								src/modules/autolinker/index.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/modules/autolinker/index.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| export { default } from './autolinker'; | ||||
| export { default as Autolinker } from './autolinker'; | ||||
| export * from './autolinker'; | ||||
| export * from './anchor-tag-builder'; | ||||
| export * from './html-tag'; | ||||
| export * from './match/index'; | ||||
| export * from './matcher/index'; | ||||
							
								
								
									
										13
									
								
								src/modules/autolinker/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/modules/autolinker/index.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| // WARNING: This file is modified a bit when it is compiled into index.js in  | ||||
| // order to support nodejs interoperability with require('autolinker') directly.  | ||||
| // This is done by the buildSrcFixCommonJsIndexTask() function in the gulpfile.  | ||||
| // See that function for more details. | ||||
| export { default } from './autolinker'; | ||||
| export { default as Autolinker } from './autolinker'; | ||||
| export * from './autolinker'; | ||||
| export * from './anchor-tag-builder'; | ||||
| export * from './html-tag'; | ||||
| export * from './match/index'; | ||||
| export * from './matcher/index'; | ||||
|  | ||||
| //# sourceMappingURL=index.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/index.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/index.js.map
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,iFAAiF;AACjF,gFAAgF;AAChF,sCAAsC;AAEtC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AAErD,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC","file":"index.js","sourcesContent":["// WARNING: This file is modified a bit when it is compiled into index.js in \n// order to support nodejs interoperability with require('autolinker') directly. \n// This is done by the buildSrcFixCommonJsIndexTask() function in the gulpfile. \n// See that function for more details.\n\nexport { default } from './autolinker';\nexport { default as Autolinker } from './autolinker';\n\nexport * from './autolinker';\nexport * from './anchor-tag-builder';\nexport * from './html-tag';\nexport * from './match/index';\nexport * from './matcher/index';\n"]} | ||||
							
								
								
									
										51
									
								
								src/modules/autolinker/match/email-match.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/modules/autolinker/match/email-match.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| import { Match, MatchConfig } from "./match"; | ||||
| /** | ||||
|  * @class Autolinker.match.Email | ||||
|  * @extends Autolinker.match.Match | ||||
|  * | ||||
|  * Represents a Email match found in an input string which should be Autolinked. | ||||
|  * | ||||
|  * See this class's superclass ({@link Autolinker.match.Match}) for more details. | ||||
|  */ | ||||
| export declare class EmailMatch extends Match { | ||||
|     /** | ||||
|      * @cfg {String} email (required) | ||||
|      * | ||||
|      * The email address that was matched. | ||||
|      */ | ||||
|     private readonly email; | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} cfg The configuration properties for the Match | ||||
|      *   instance, specified in an Object (map). | ||||
|      */ | ||||
|     constructor(cfg: EmailMatchConfig); | ||||
|     /** | ||||
|      * Returns a string name for the type of match that this class represents. | ||||
|      * For the case of EmailMatch, returns 'email'. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getType(): string; | ||||
|     /** | ||||
|      * Returns the email address that was matched. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getEmail(): string; | ||||
|     /** | ||||
|      * Returns the anchor href that should be generated for the match. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getAnchorHref(): string; | ||||
|     /** | ||||
|      * Returns the anchor text that should be generated for the match. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getAnchorText(): string; | ||||
| } | ||||
| export interface EmailMatchConfig extends MatchConfig { | ||||
|     email: string; | ||||
| } | ||||
							
								
								
									
										66
									
								
								src/modules/autolinker/match/email-match.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/modules/autolinker/match/email-match.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| import * as tslib_1 from "tslib"; | ||||
| import { Match } from "./match"; | ||||
| /** | ||||
|  * @class Autolinker.match.Email | ||||
|  * @extends Autolinker.match.Match | ||||
|  * | ||||
|  * Represents a Email match found in an input string which should be Autolinked. | ||||
|  * | ||||
|  * See this class's superclass ({@link Autolinker.match.Match}) for more details. | ||||
|  */ | ||||
| var EmailMatch = /** @class */ (function (_super) { | ||||
|     tslib_1.__extends(EmailMatch, _super); | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} cfg The configuration properties for the Match | ||||
|      *   instance, specified in an Object (map). | ||||
|      */ | ||||
|     function EmailMatch(cfg) { | ||||
|         var _this = _super.call(this, cfg) || this; | ||||
|         /** | ||||
|          * @cfg {String} email (required) | ||||
|          * | ||||
|          * The email address that was matched. | ||||
|          */ | ||||
|         _this.email = ''; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         _this.email = cfg.email; | ||||
|         return _this; | ||||
|     } | ||||
|     /** | ||||
|      * Returns a string name for the type of match that this class represents. | ||||
|      * For the case of EmailMatch, returns 'email'. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     EmailMatch.prototype.getType = function () { | ||||
|         return 'email'; | ||||
|     }; | ||||
|     /** | ||||
|      * Returns the email address that was matched. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     EmailMatch.prototype.getEmail = function () { | ||||
|         return this.email; | ||||
|     }; | ||||
|     /** | ||||
|      * Returns the anchor href that should be generated for the match. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     EmailMatch.prototype.getAnchorHref = function () { | ||||
|         return 'mailto:' + this.email; | ||||
|     }; | ||||
|     /** | ||||
|      * Returns the anchor text that should be generated for the match. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     EmailMatch.prototype.getAnchorText = function () { | ||||
|         return this.email; | ||||
|     }; | ||||
|     return EmailMatch; | ||||
| }(Match)); | ||||
| export { EmailMatch }; | ||||
|  | ||||
| //# sourceMappingURL=email-match.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/match/email-match.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/match/email-match.js.map
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| {"version":3,"sources":["../src/match/email-match.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAe,MAAM,SAAS,CAAC;AAE7C;;;;;;;GAOG;AACH;IAAgC,sCAAK;IAUpC;;;;OAIG;IACH,oBAAa,GAAqB;QAAlC,YACC,kBAAO,GAAG,CAAE,SAGZ;QAjBD;;;;WAIG;QACc,WAAK,GAAW,EAAE,CAAC,CAAE,gGAAgG;QAWrI,KAAI,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;;IACxB,CAAC;IAGD;;;;;OAKG;IACH,4BAAO,GAAP;QACC,OAAO,OAAO,CAAC;IAChB,CAAC;IAGD;;;;OAIG;IACH,6BAAQ,GAAR;QACC,OAAO,IAAI,CAAC,KAAK,CAAC;IACnB,CAAC;IAGD;;;;OAIG;IACH,kCAAa,GAAb;QACC,OAAO,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC;IAC/B,CAAC;IAGD;;;;OAIG;IACH,kCAAa,GAAb;QACC,OAAO,IAAI,CAAC,KAAK,CAAC;IACnB,CAAC;IAEF,iBAAC;AAAD,CA9DA,AA8DC,CA9D+B,KAAK,GA8DpC","file":"email-match.js","sourcesContent":["import { Match, MatchConfig } from \"./match\";\n\n/**\n * @class Autolinker.match.Email\n * @extends Autolinker.match.Match\n *\n * Represents a Email match found in an input string which should be Autolinked.\n *\n * See this class's superclass ({@link Autolinker.match.Match}) for more details.\n */\nexport class EmailMatch extends Match {\n\n\t/**\n\t * @cfg {String} email (required)\n\t *\n\t * The email address that was matched.\n\t */\n\tprivate readonly email: string = '';  // default value just to get the above doc comment in the ES5 output and documentation generator\n\n\n\t/**\n\t * @method constructor\n\t * @param {Object} cfg The configuration properties for the Match\n\t *   instance, specified in an Object (map).\n\t */\n\tconstructor( cfg: EmailMatchConfig ) {\n\t\tsuper( cfg );\n\n\t\tthis.email = cfg.email;\n\t}\n\n\n\t/**\n\t * Returns a string name for the type of match that this class represents.\n\t * For the case of EmailMatch, returns 'email'.\n\t *\n\t * @return {String}\n\t */\n\tgetType() {\n\t\treturn 'email';\n\t}\n\n\n\t/**\n\t * Returns the email address that was matched.\n\t *\n\t * @return {String}\n\t */\n\tgetEmail() {\n\t\treturn this.email;\n\t}\n\n\n\t/**\n\t * Returns the anchor href that should be generated for the match.\n\t *\n\t * @return {String}\n\t */\n\tgetAnchorHref() {\n\t\treturn 'mailto:' + this.email;\n\t}\n\n\n\t/**\n\t * Returns the anchor text that should be generated for the match.\n\t *\n\t * @return {String}\n\t */\n\tgetAnchorText() {\n\t\treturn this.email;\n\t}\n\n}\n\n\nexport interface EmailMatchConfig extends MatchConfig {\n\temail: string;\n}"]} | ||||
							
								
								
									
										68
									
								
								src/modules/autolinker/match/hashtag-match.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								src/modules/autolinker/match/hashtag-match.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| import { Match, MatchConfig } from "./match"; | ||||
| /** | ||||
|  * @class Autolinker.match.Hashtag | ||||
|  * @extends Autolinker.match.Match | ||||
|  * | ||||
|  * Represents a Hashtag match found in an input string which should be | ||||
|  * Autolinked. | ||||
|  * | ||||
|  * See this class's superclass ({@link Autolinker.match.Match}) for more | ||||
|  * details. | ||||
|  */ | ||||
| export declare class HashtagMatch extends Match { | ||||
|     /** | ||||
|      * @cfg {String} serviceName | ||||
|      * | ||||
|      * The service to point hashtag matches to. See {@link Autolinker#hashtag} | ||||
|      * for available values. | ||||
|      */ | ||||
|     private readonly serviceName; | ||||
|     /** | ||||
|      * @cfg {String} hashtag (required) | ||||
|      * | ||||
|      * The HashtagMatch that was matched, without the '#'. | ||||
|      */ | ||||
|     private readonly hashtag; | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} cfg The configuration properties for the Match | ||||
|      *   instance, specified in an Object (map). | ||||
|      */ | ||||
|     constructor(cfg: HashtagMatchConfig); | ||||
|     /** | ||||
|      * Returns a string name for the type of match that this class represents. | ||||
|      * For the case of HashtagMatch, returns 'hashtag'. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getType(): string; | ||||
|     /** | ||||
|      * Returns the configured {@link #serviceName} to point the HashtagMatch to. | ||||
|      * Ex: 'facebook', 'twitter'. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getServiceName(): string; | ||||
|     /** | ||||
|      * Returns the matched hashtag, without the '#' character. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getHashtag(): string; | ||||
|     /** | ||||
|      * Returns the anchor href that should be generated for the match. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getAnchorHref(): string; | ||||
|     /** | ||||
|      * Returns the anchor text that should be generated for the match. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getAnchorText(): string; | ||||
| } | ||||
| export interface HashtagMatchConfig extends MatchConfig { | ||||
|     serviceName: string; | ||||
|     hashtag: string; | ||||
| } | ||||
							
								
								
									
										95
									
								
								src/modules/autolinker/match/hashtag-match.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								src/modules/autolinker/match/hashtag-match.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | ||||
| import * as tslib_1 from "tslib"; | ||||
| import { Match } from "./match"; | ||||
| /** | ||||
|  * @class Autolinker.match.Hashtag | ||||
|  * @extends Autolinker.match.Match | ||||
|  * | ||||
|  * Represents a Hashtag match found in an input string which should be | ||||
|  * Autolinked. | ||||
|  * | ||||
|  * See this class's superclass ({@link Autolinker.match.Match}) for more | ||||
|  * details. | ||||
|  */ | ||||
| var HashtagMatch = /** @class */ (function (_super) { | ||||
|     tslib_1.__extends(HashtagMatch, _super); | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} cfg The configuration properties for the Match | ||||
|      *   instance, specified in an Object (map). | ||||
|      */ | ||||
|     function HashtagMatch(cfg) { | ||||
|         var _this = _super.call(this, cfg) || this; | ||||
|         /** | ||||
|          * @cfg {String} serviceName | ||||
|          * | ||||
|          * The service to point hashtag matches to. See {@link Autolinker#hashtag} | ||||
|          * for available values. | ||||
|          */ | ||||
|         _this.serviceName = ''; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {String} hashtag (required) | ||||
|          * | ||||
|          * The HashtagMatch that was matched, without the '#'. | ||||
|          */ | ||||
|         _this.hashtag = ''; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         _this.serviceName = cfg.serviceName; | ||||
|         _this.hashtag = cfg.hashtag; | ||||
|         return _this; | ||||
|     } | ||||
|     /** | ||||
|      * Returns a string name for the type of match that this class represents. | ||||
|      * For the case of HashtagMatch, returns 'hashtag'. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     HashtagMatch.prototype.getType = function () { | ||||
|         return 'hashtag'; | ||||
|     }; | ||||
|     /** | ||||
|      * Returns the configured {@link #serviceName} to point the HashtagMatch to. | ||||
|      * Ex: 'facebook', 'twitter'. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     HashtagMatch.prototype.getServiceName = function () { | ||||
|         return this.serviceName; | ||||
|     }; | ||||
|     /** | ||||
|      * Returns the matched hashtag, without the '#' character. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     HashtagMatch.prototype.getHashtag = function () { | ||||
|         return this.hashtag; | ||||
|     }; | ||||
|     /** | ||||
|      * Returns the anchor href that should be generated for the match. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     HashtagMatch.prototype.getAnchorHref = function () { | ||||
|         var serviceName = this.serviceName, hashtag = this.hashtag; | ||||
|         switch (serviceName) { | ||||
|             case 'twitter': | ||||
|                 return 'https://twitter.com/hashtag/' + hashtag; | ||||
|             case 'facebook': | ||||
|                 return 'https://www.facebook.com/hashtag/' + hashtag; | ||||
|             case 'instagram': | ||||
|                 return 'https://instagram.com/explore/tags/' + hashtag; | ||||
|             default: // Shouldn't happen because Autolinker's constructor should block any invalid values, but just in case. | ||||
|                 throw new Error('Unknown service name to point hashtag to: ' + serviceName); | ||||
|         } | ||||
|     }; | ||||
|     /** | ||||
|      * Returns the anchor text that should be generated for the match. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     HashtagMatch.prototype.getAnchorText = function () { | ||||
|         return '#' + this.hashtag; | ||||
|     }; | ||||
|     return HashtagMatch; | ||||
| }(Match)); | ||||
| export { HashtagMatch }; | ||||
|  | ||||
| //# sourceMappingURL=hashtag-match.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/match/hashtag-match.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/match/hashtag-match.js.map
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| {"version":3,"sources":["../src/match/hashtag-match.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAe,MAAM,SAAS,CAAC;AAE7C;;;;;;;;;GASG;AACH;IAAkC,wCAAK;IAkBtC;;;;OAIG;IACH,sBAAa,GAAuB;QAApC,YACC,kBAAO,GAAG,CAAE,SAIZ;QA1BD;;;;;WAKG;QACc,iBAAW,GAAW,EAAE,CAAC,CAAE,gGAAgG;QAE5I;;;;WAIG;QACc,aAAO,GAAW,EAAE,CAAC,CAAE,gGAAgG;QAWvI,KAAI,CAAC,WAAW,GAAG,GAAG,CAAC,WAAW,CAAC;QACnC,KAAI,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;;IAC5B,CAAC;IAGD;;;;;OAKG;IACH,8BAAO,GAAP;QACC,OAAO,SAAS,CAAC;IAClB,CAAC;IAGD;;;;;OAKG;IACH,qCAAc,GAAd;QACC,OAAO,IAAI,CAAC,WAAW,CAAC;IACzB,CAAC;IAGD;;;;OAIG;IACH,iCAAU,GAAV;QACC,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAGD;;;;OAIG;IACH,oCAAa,GAAb;QACC,IAAI,WAAW,GAAG,IAAI,CAAC,WAAW,EAC9B,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAE3B,QAAQ,WAAW,EAAG;YACrB,KAAK,SAAS;gBACb,OAAO,8BAA8B,GAAG,OAAO,CAAC;YACjD,KAAK,UAAU;gBACd,OAAO,mCAAmC,GAAG,OAAO,CAAC;YACtD,KAAK,WAAW;gBACf,OAAO,qCAAqC,GAAG,OAAO,CAAC;YAExD,SAAW,uGAAuG;gBACjH,MAAM,IAAI,KAAK,CAAE,4CAA4C,GAAG,WAAW,CAAE,CAAC;SAC/E;IACF,CAAC;IAGD;;;;OAIG;IACH,oCAAa,GAAb;QACC,OAAO,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC;IAC3B,CAAC;IAEF,mBAAC;AAAD,CA/FA,AA+FC,CA/FiC,KAAK,GA+FtC","file":"hashtag-match.js","sourcesContent":["import { Match, MatchConfig } from \"./match\";\n\n/**\n * @class Autolinker.match.Hashtag\n * @extends Autolinker.match.Match\n *\n * Represents a Hashtag match found in an input string which should be\n * Autolinked.\n *\n * See this class's superclass ({@link Autolinker.match.Match}) for more\n * details.\n */\nexport class HashtagMatch extends Match {\n\n\t/**\n\t * @cfg {String} serviceName\n\t *\n\t * The service to point hashtag matches to. See {@link Autolinker#hashtag}\n\t * for available values.\n\t */\n\tprivate readonly serviceName: string = '';  // default value just to get the above doc comment in the ES5 output and documentation generator\n\n\t/**\n\t * @cfg {String} hashtag (required)\n\t *\n\t * The HashtagMatch that was matched, without the '#'.\n\t */\n\tprivate readonly hashtag: string = '';  // default value just to get the above doc comment in the ES5 output and documentation generator\n\n\n\t/**\n\t * @method constructor\n\t * @param {Object} cfg The configuration properties for the Match\n\t *   instance, specified in an Object (map).\n\t */\n\tconstructor( cfg: HashtagMatchConfig ) {\n\t\tsuper( cfg );\n\n\t\tthis.serviceName = cfg.serviceName;\n\t\tthis.hashtag = cfg.hashtag;\n\t}\n\n\n\t/**\n\t * Returns a string name for the type of match that this class represents.\n\t * For the case of HashtagMatch, returns 'hashtag'.\n\t *\n\t * @return {String}\n\t */\n\tgetType() {\n\t\treturn 'hashtag';\n\t}\n\n\n\t/**\n\t * Returns the configured {@link #serviceName} to point the HashtagMatch to.\n\t * Ex: 'facebook', 'twitter'.\n\t *\n\t * @return {String}\n\t */\n\tgetServiceName() {\n\t\treturn this.serviceName;\n\t}\n\n\n\t/**\n\t * Returns the matched hashtag, without the '#' character.\n\t *\n\t * @return {String}\n\t */\n\tgetHashtag() {\n\t\treturn this.hashtag;\n\t}\n\n\n\t/**\n\t * Returns the anchor href that should be generated for the match.\n\t *\n\t * @return {String}\n\t */\n\tgetAnchorHref() {\n\t\tlet serviceName = this.serviceName,\n\t\t    hashtag = this.hashtag;\n\n\t\tswitch( serviceName ) {\n\t\t\tcase 'twitter' :\n\t\t\t\treturn 'https://twitter.com/hashtag/' + hashtag;\n\t\t\tcase 'facebook' :\n\t\t\t\treturn 'https://www.facebook.com/hashtag/' + hashtag;\n\t\t\tcase 'instagram' :\n\t\t\t\treturn 'https://instagram.com/explore/tags/' + hashtag;\n\n\t\t\tdefault :  // Shouldn't happen because Autolinker's constructor should block any invalid values, but just in case.\n\t\t\t\tthrow new Error( 'Unknown service name to point hashtag to: ' + serviceName );\n\t\t}\n\t}\n\n\n\t/**\n\t * Returns the anchor text that should be generated for the match.\n\t *\n\t * @return {String}\n\t */\n\tgetAnchorText() {\n\t\treturn '#' + this.hashtag;\n\t}\n\n}\n\nexport interface HashtagMatchConfig extends MatchConfig {\n\tserviceName: string;\n\thashtag: string;\n}"]} | ||||
							
								
								
									
										6
									
								
								src/modules/autolinker/match/index.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/modules/autolinker/match/index.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| export * from './email-match'; | ||||
| export * from './hashtag-match'; | ||||
| export * from './match'; | ||||
| export * from './mention-match'; | ||||
| export * from './phone-match'; | ||||
| export * from './url-match'; | ||||
							
								
								
									
										8
									
								
								src/modules/autolinker/match/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/modules/autolinker/match/index.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| export * from './email-match'; | ||||
| export * from './hashtag-match'; | ||||
| export * from './match'; | ||||
| export * from './mention-match'; | ||||
| export * from './phone-match'; | ||||
| export * from './url-match'; | ||||
|  | ||||
| //# sourceMappingURL=index.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/match/index.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/match/index.js.map
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| {"version":3,"sources":["../src/match/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC;AACxB,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC","file":"index.js","sourcesContent":["export * from './email-match';\nexport * from './hashtag-match';\nexport * from './match';\nexport * from './mention-match';\nexport * from './phone-match';\nexport * from './url-match';\n"]} | ||||
							
								
								
									
										165
									
								
								src/modules/autolinker/match/match.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								src/modules/autolinker/match/match.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,165 @@ | ||||
| import { AnchorTagBuilder } from "../anchor-tag-builder"; | ||||
| /** | ||||
|  * @abstract | ||||
|  * @class Autolinker.match.Match | ||||
|  * | ||||
|  * Represents a match found in an input string which should be Autolinked. A Match object is what is provided in a | ||||
|  * {@link Autolinker#replaceFn replaceFn}, and may be used to query for details about the match. | ||||
|  * | ||||
|  * For example: | ||||
|  * | ||||
|  *     var input = "...";  // string with URLs, Email Addresses, and Mentions (Twitter, Instagram, Soundcloud) | ||||
|  * | ||||
|  *     var linkedText = Autolinker.link( input, { | ||||
|  *         replaceFn : function( match ) { | ||||
|  *             console.log( "href = ", match.getAnchorHref() ); | ||||
|  *             console.log( "text = ", match.getAnchorText() ); | ||||
|  * | ||||
|  *             switch( match.getType() ) { | ||||
|  *                 case 'url' : | ||||
|  *                     console.log( "url: ", match.getUrl() ); | ||||
|  * | ||||
|  *                 case 'email' : | ||||
|  *                     console.log( "email: ", match.getEmail() ); | ||||
|  * | ||||
|  *                 case 'mention' : | ||||
|  *                     console.log( "mention: ", match.getMention() ); | ||||
|  *             } | ||||
|  *         } | ||||
|  *     } ); | ||||
|  * | ||||
|  * See the {@link Autolinker} class for more details on using the {@link Autolinker#replaceFn replaceFn}. | ||||
|  */ | ||||
| export declare abstract class Match { | ||||
|     /** | ||||
|      * @cfg {Autolinker.AnchorTagBuilder} tagBuilder (required) | ||||
|      * | ||||
|      * Reference to the AnchorTagBuilder instance to use to generate an anchor | ||||
|      * tag for the Match. | ||||
|      */ | ||||
|     private __jsduckDummyDocProp; | ||||
|     private readonly tagBuilder; | ||||
|     /** | ||||
|      * @cfg {String} matchedText (required) | ||||
|      * | ||||
|      * The original text that was matched by the {@link Autolinker.matcher.Matcher}. | ||||
|      */ | ||||
|     protected readonly matchedText: string; | ||||
|     /** | ||||
|      * @cfg {Number} offset (required) | ||||
|      * | ||||
|      * The offset of where the match was made in the input string. | ||||
|      */ | ||||
|     private offset; | ||||
|     /** | ||||
|      * @member Autolinker.match.Match | ||||
|      * @method constructor | ||||
|      * @param {Object} cfg The configuration properties for the Match | ||||
|      *   instance, specified in an Object (map). | ||||
|      */ | ||||
|     constructor(cfg: MatchConfig); | ||||
|     /** | ||||
|      * Returns a string name for the type of match that this class represents. | ||||
|      * | ||||
|      * @abstract | ||||
|      * @return {String} | ||||
|      */ | ||||
|     abstract getType(): string; | ||||
|     /** | ||||
|      * Returns the original text that was matched. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getMatchedText(): string; | ||||
|     /** | ||||
|      * Sets the {@link #offset} of where the match was made in the input string. | ||||
|      * | ||||
|      * A {@link Autolinker.matcher.Matcher} will be fed only HTML text nodes, | ||||
|      * and will therefore set an original offset that is relative to the HTML | ||||
|      * text node itself. However, we want this offset to be relative to the full | ||||
|      * HTML input string, and thus if using {@link Autolinker#parse} (rather | ||||
|      * than calling a {@link Autolinker.matcher.Matcher} directly), then this | ||||
|      * offset is corrected after the Matcher itself has done its job. | ||||
|      * | ||||
|      * @param {Number} offset | ||||
|      */ | ||||
|     setOffset(offset: number): void; | ||||
|     /** | ||||
|      * Returns the offset of where the match was made in the input string. This | ||||
|      * is the 0-based index of the match. | ||||
|      * | ||||
|      * @return {Number} | ||||
|      */ | ||||
|     getOffset(): number; | ||||
|     /** | ||||
|      * Returns the anchor href that should be generated for the match. | ||||
|      * | ||||
|      * @abstract | ||||
|      * @return {String} | ||||
|      */ | ||||
|     abstract getAnchorHref(): string; | ||||
|     /** | ||||
|      * Returns the anchor text that should be generated for the match. | ||||
|      * | ||||
|      * @abstract | ||||
|      * @return {String} | ||||
|      */ | ||||
|     abstract getAnchorText(): string; | ||||
|     /** | ||||
|      * Returns the CSS class suffix(es) for this match. | ||||
|      * | ||||
|      * A CSS class suffix is appended to the {@link Autolinker#className} in | ||||
|      * the {@link Autolinker.AnchorTagBuilder} when a match is translated into | ||||
|      * an anchor tag. | ||||
|      * | ||||
|      * For example, if {@link Autolinker#className} was configured as 'myLink', | ||||
|      * and this method returns `[ 'url' ]`, the final class name of the element | ||||
|      * will become: 'myLink myLink-url'. | ||||
|      * | ||||
|      * The match may provide multiple CSS class suffixes to be appended to the | ||||
|      * {@link Autolinker#className} in order to facilitate better styling | ||||
|      * options for different match criteria. See {@link Autolinker.match.Mention} | ||||
|      * for an example. | ||||
|      * | ||||
|      * By default, this method returns a single array with the match's | ||||
|      * {@link #getType type} name, but may be overridden by subclasses. | ||||
|      * | ||||
|      * @return {String[]} | ||||
|      */ | ||||
|     getCssClassSuffixes(): string[]; | ||||
|     /** | ||||
|      * Builds and returns an {@link Autolinker.HtmlTag} instance based on the | ||||
|      * Match. | ||||
|      * | ||||
|      * This can be used to easily generate anchor tags from matches, and either | ||||
|      * return their HTML string, or modify them before doing so. | ||||
|      * | ||||
|      * Example Usage: | ||||
|      * | ||||
|      *     var tag = match.buildTag(); | ||||
|      *     tag.addClass( 'cordova-link' ); | ||||
|      *     tag.setAttr( 'target', '_system' ); | ||||
|      * | ||||
|      *     tag.toAnchorString();  // <a href="http://google.com" class="cordova-link" target="_system">Google</a> | ||||
|      * | ||||
|      * Example Usage in {@link Autolinker#replaceFn}: | ||||
|      * | ||||
|      *     var html = Autolinker.link( "Test google.com", { | ||||
|      *         replaceFn : function( match ) { | ||||
|      *             var tag = match.buildTag();  // returns an {@link Autolinker.HtmlTag} instance | ||||
|      *             tag.setAttr( 'rel', 'nofollow' ); | ||||
|      * | ||||
|      *             return tag; | ||||
|      *         } | ||||
|      *     } ); | ||||
|      * | ||||
|      *     // generated html: | ||||
|      *     //   Test <a href="http://google.com" target="_blank" rel="nofollow">google.com</a> | ||||
|      */ | ||||
|     buildTag(): import("..").HtmlTag; | ||||
| } | ||||
| export interface MatchConfig { | ||||
|     tagBuilder: AnchorTagBuilder; | ||||
|     matchedText: string; | ||||
|     offset: number; | ||||
| } | ||||
							
								
								
									
										155
									
								
								src/modules/autolinker/match/match.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								src/modules/autolinker/match/match.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,155 @@ | ||||
| /** | ||||
|  * @abstract | ||||
|  * @class Autolinker.match.Match | ||||
|  * | ||||
|  * Represents a match found in an input string which should be Autolinked. A Match object is what is provided in a | ||||
|  * {@link Autolinker#replaceFn replaceFn}, and may be used to query for details about the match. | ||||
|  * | ||||
|  * For example: | ||||
|  * | ||||
|  *     var input = "...";  // string with URLs, Email Addresses, and Mentions (Twitter, Instagram, Soundcloud) | ||||
|  * | ||||
|  *     var linkedText = Autolinker.link( input, { | ||||
|  *         replaceFn : function( match ) { | ||||
|  *             console.log( "href = ", match.getAnchorHref() ); | ||||
|  *             console.log( "text = ", match.getAnchorText() ); | ||||
|  * | ||||
|  *             switch( match.getType() ) { | ||||
|  *                 case 'url' : | ||||
|  *                     console.log( "url: ", match.getUrl() ); | ||||
|  * | ||||
|  *                 case 'email' : | ||||
|  *                     console.log( "email: ", match.getEmail() ); | ||||
|  * | ||||
|  *                 case 'mention' : | ||||
|  *                     console.log( "mention: ", match.getMention() ); | ||||
|  *             } | ||||
|  *         } | ||||
|  *     } ); | ||||
|  * | ||||
|  * See the {@link Autolinker} class for more details on using the {@link Autolinker#replaceFn replaceFn}. | ||||
|  */ | ||||
| var Match = /** @class */ (function () { | ||||
|     /** | ||||
|      * @member Autolinker.match.Match | ||||
|      * @method constructor | ||||
|      * @param {Object} cfg The configuration properties for the Match | ||||
|      *   instance, specified in an Object (map). | ||||
|      */ | ||||
|     function Match(cfg) { | ||||
|         /** | ||||
|          * @cfg {Autolinker.AnchorTagBuilder} tagBuilder (required) | ||||
|          * | ||||
|          * Reference to the AnchorTagBuilder instance to use to generate an anchor | ||||
|          * tag for the Match. | ||||
|          */ | ||||
|         this.__jsduckDummyDocProp = null; // property used just to get the above doc comment into the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {String} matchedText (required) | ||||
|          * | ||||
|          * The original text that was matched by the {@link Autolinker.matcher.Matcher}. | ||||
|          */ | ||||
|         this.matchedText = ''; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {Number} offset (required) | ||||
|          * | ||||
|          * The offset of where the match was made in the input string. | ||||
|          */ | ||||
|         this.offset = 0; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         this.tagBuilder = cfg.tagBuilder; | ||||
|         this.matchedText = cfg.matchedText; | ||||
|         this.offset = cfg.offset; | ||||
|     } | ||||
|     /** | ||||
|      * Returns the original text that was matched. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     Match.prototype.getMatchedText = function () { | ||||
|         return this.matchedText; | ||||
|     }; | ||||
|     /** | ||||
|      * Sets the {@link #offset} of where the match was made in the input string. | ||||
|      * | ||||
|      * A {@link Autolinker.matcher.Matcher} will be fed only HTML text nodes, | ||||
|      * and will therefore set an original offset that is relative to the HTML | ||||
|      * text node itself. However, we want this offset to be relative to the full | ||||
|      * HTML input string, and thus if using {@link Autolinker#parse} (rather | ||||
|      * than calling a {@link Autolinker.matcher.Matcher} directly), then this | ||||
|      * offset is corrected after the Matcher itself has done its job. | ||||
|      * | ||||
|      * @param {Number} offset | ||||
|      */ | ||||
|     Match.prototype.setOffset = function (offset) { | ||||
|         this.offset = offset; | ||||
|     }; | ||||
|     /** | ||||
|      * Returns the offset of where the match was made in the input string. This | ||||
|      * is the 0-based index of the match. | ||||
|      * | ||||
|      * @return {Number} | ||||
|      */ | ||||
|     Match.prototype.getOffset = function () { | ||||
|         return this.offset; | ||||
|     }; | ||||
|     /** | ||||
|      * Returns the CSS class suffix(es) for this match. | ||||
|      * | ||||
|      * A CSS class suffix is appended to the {@link Autolinker#className} in | ||||
|      * the {@link Autolinker.AnchorTagBuilder} when a match is translated into | ||||
|      * an anchor tag. | ||||
|      * | ||||
|      * For example, if {@link Autolinker#className} was configured as 'myLink', | ||||
|      * and this method returns `[ 'url' ]`, the final class name of the element | ||||
|      * will become: 'myLink myLink-url'. | ||||
|      * | ||||
|      * The match may provide multiple CSS class suffixes to be appended to the | ||||
|      * {@link Autolinker#className} in order to facilitate better styling | ||||
|      * options for different match criteria. See {@link Autolinker.match.Mention} | ||||
|      * for an example. | ||||
|      * | ||||
|      * By default, this method returns a single array with the match's | ||||
|      * {@link #getType type} name, but may be overridden by subclasses. | ||||
|      * | ||||
|      * @return {String[]} | ||||
|      */ | ||||
|     Match.prototype.getCssClassSuffixes = function () { | ||||
|         return [this.getType()]; | ||||
|     }; | ||||
|     /** | ||||
|      * Builds and returns an {@link Autolinker.HtmlTag} instance based on the | ||||
|      * Match. | ||||
|      * | ||||
|      * This can be used to easily generate anchor tags from matches, and either | ||||
|      * return their HTML string, or modify them before doing so. | ||||
|      * | ||||
|      * Example Usage: | ||||
|      * | ||||
|      *     var tag = match.buildTag(); | ||||
|      *     tag.addClass( 'cordova-link' ); | ||||
|      *     tag.setAttr( 'target', '_system' ); | ||||
|      * | ||||
|      *     tag.toAnchorString();  // <a href="http://google.com" class="cordova-link" target="_system">Google</a> | ||||
|      * | ||||
|      * Example Usage in {@link Autolinker#replaceFn}: | ||||
|      * | ||||
|      *     var html = Autolinker.link( "Test google.com", { | ||||
|      *         replaceFn : function( match ) { | ||||
|      *             var tag = match.buildTag();  // returns an {@link Autolinker.HtmlTag} instance | ||||
|      *             tag.setAttr( 'rel', 'nofollow' ); | ||||
|      * | ||||
|      *             return tag; | ||||
|      *         } | ||||
|      *     } ); | ||||
|      * | ||||
|      *     // generated html: | ||||
|      *     //   Test <a href="http://google.com" target="_blank" rel="nofollow">google.com</a> | ||||
|      */ | ||||
|     Match.prototype.buildTag = function () { | ||||
|         return this.tagBuilder.build(this); | ||||
|     }; | ||||
|     return Match; | ||||
| }()); | ||||
| export { Match }; | ||||
|  | ||||
| //# sourceMappingURL=match.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/match/match.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/match/match.js.map
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										75
									
								
								src/modules/autolinker/match/mention-match.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								src/modules/autolinker/match/mention-match.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | ||||
| import { Match, MatchConfig } from "./match"; | ||||
| import { MentionServices } from "../autolinker"; | ||||
| /** | ||||
|  * @class Autolinker.match.Mention | ||||
|  * @extends Autolinker.match.Match | ||||
|  * | ||||
|  * Represents a Mention match found in an input string which should be Autolinked. | ||||
|  * | ||||
|  * See this class's superclass ({@link Autolinker.match.Match}) for more details. | ||||
|  */ | ||||
| export declare class MentionMatch extends Match { | ||||
|     /** | ||||
|      * @cfg {String} serviceName | ||||
|      * | ||||
|      * The service to point mention matches to. See {@link Autolinker#mention} | ||||
|      * for available values. | ||||
|      */ | ||||
|     private readonly serviceName; | ||||
|     /** | ||||
|      * @cfg {String} mention (required) | ||||
|      * | ||||
|      * The Mention that was matched, without the '@' character. | ||||
|      */ | ||||
|     private readonly mention; | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} cfg The configuration properties for the Match | ||||
|      *   instance, specified in an Object (map). | ||||
|      */ | ||||
|     constructor(cfg: MentionMatchConfig); | ||||
|     /** | ||||
|      * Returns a string name for the type of match that this class represents. | ||||
|      * For the case of MentionMatch, returns 'mention'. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getType(): string; | ||||
|     /** | ||||
|      * Returns the mention, without the '@' character. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getMention(): string; | ||||
|     /** | ||||
|      * Returns the configured {@link #serviceName} to point the mention to. | ||||
|      * Ex: 'instagram', 'twitter', 'soundcloud'. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getServiceName(): MentionServices; | ||||
|     /** | ||||
|      * Returns the anchor href that should be generated for the match. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getAnchorHref(): string; | ||||
|     /** | ||||
|      * Returns the anchor text that should be generated for the match. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getAnchorText(): string; | ||||
|     /** | ||||
|      * Returns the CSS class suffixes that should be used on a tag built with | ||||
|      * the match. See {@link Autolinker.match.Match#getCssClassSuffixes} for | ||||
|      * details. | ||||
|      * | ||||
|      * @return {String[]} | ||||
|      */ | ||||
|     getCssClassSuffixes(): string[]; | ||||
| } | ||||
| export interface MentionMatchConfig extends MatchConfig { | ||||
|     serviceName: MentionServices; | ||||
|     mention: string; | ||||
| } | ||||
							
								
								
									
										106
									
								
								src/modules/autolinker/match/mention-match.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								src/modules/autolinker/match/mention-match.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,106 @@ | ||||
| import * as tslib_1 from "tslib"; | ||||
| import { Match } from "./match"; | ||||
| /** | ||||
|  * @class Autolinker.match.Mention | ||||
|  * @extends Autolinker.match.Match | ||||
|  * | ||||
|  * Represents a Mention match found in an input string which should be Autolinked. | ||||
|  * | ||||
|  * See this class's superclass ({@link Autolinker.match.Match}) for more details. | ||||
|  */ | ||||
| var MentionMatch = /** @class */ (function (_super) { | ||||
|     tslib_1.__extends(MentionMatch, _super); | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} cfg The configuration properties for the Match | ||||
|      *   instance, specified in an Object (map). | ||||
|      */ | ||||
|     function MentionMatch(cfg) { | ||||
|         var _this = _super.call(this, cfg) || this; | ||||
|         /** | ||||
|          * @cfg {String} serviceName | ||||
|          * | ||||
|          * The service to point mention matches to. See {@link Autolinker#mention} | ||||
|          * for available values. | ||||
|          */ | ||||
|         _this.serviceName = 'twitter'; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {String} mention (required) | ||||
|          * | ||||
|          * The Mention that was matched, without the '@' character. | ||||
|          */ | ||||
|         _this.mention = ''; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         _this.mention = cfg.mention; | ||||
|         _this.serviceName = cfg.serviceName; | ||||
|         return _this; | ||||
|     } | ||||
|     /** | ||||
|      * Returns a string name for the type of match that this class represents. | ||||
|      * For the case of MentionMatch, returns 'mention'. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     MentionMatch.prototype.getType = function () { | ||||
|         return 'mention'; | ||||
|     }; | ||||
|     /** | ||||
|      * Returns the mention, without the '@' character. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     MentionMatch.prototype.getMention = function () { | ||||
|         return this.mention; | ||||
|     }; | ||||
|     /** | ||||
|      * Returns the configured {@link #serviceName} to point the mention to. | ||||
|      * Ex: 'instagram', 'twitter', 'soundcloud'. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     MentionMatch.prototype.getServiceName = function () { | ||||
|         return this.serviceName; | ||||
|     }; | ||||
|     /** | ||||
|      * Returns the anchor href that should be generated for the match. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     MentionMatch.prototype.getAnchorHref = function () { | ||||
|         switch (this.serviceName) { | ||||
|             case 'twitter': | ||||
|                 return 'https://twitter.com/' + this.mention; | ||||
|             case 'instagram': | ||||
|                 return 'https://instagram.com/' + this.mention; | ||||
|             case 'soundcloud': | ||||
|                 return 'https://soundcloud.com/' + this.mention; | ||||
|             default: // Shouldn't happen because Autolinker's constructor should block any invalid values, but just in case. | ||||
|                 throw new Error('Unknown service name to point mention to: ' + this.serviceName); | ||||
|         } | ||||
|     }; | ||||
|     /** | ||||
|      * Returns the anchor text that should be generated for the match. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     MentionMatch.prototype.getAnchorText = function () { | ||||
|         return '@' + this.mention; | ||||
|     }; | ||||
|     /** | ||||
|      * Returns the CSS class suffixes that should be used on a tag built with | ||||
|      * the match. See {@link Autolinker.match.Match#getCssClassSuffixes} for | ||||
|      * details. | ||||
|      * | ||||
|      * @return {String[]} | ||||
|      */ | ||||
|     MentionMatch.prototype.getCssClassSuffixes = function () { | ||||
|         var cssClassSuffixes = _super.prototype.getCssClassSuffixes.call(this), serviceName = this.getServiceName(); | ||||
|         if (serviceName) { | ||||
|             cssClassSuffixes.push(serviceName); | ||||
|         } | ||||
|         return cssClassSuffixes; | ||||
|     }; | ||||
|     return MentionMatch; | ||||
| }(Match)); | ||||
| export { MentionMatch }; | ||||
|  | ||||
| //# sourceMappingURL=mention-match.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/match/mention-match.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/match/mention-match.js.map
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| {"version":3,"sources":["../src/match/mention-match.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAe,MAAM,SAAS,CAAC;AAG7C;;;;;;;GAOG;AACH;IAAkC,wCAAK;IAkBtC;;;;OAIG;IACH,sBAAa,GAAuB;QAApC,YACC,kBAAO,GAAG,CAAE,SAIZ;QA1BD;;;;;WAKG;QACc,iBAAW,GAAoB,SAAS,CAAC,CAAE,gGAAgG;QAE5J;;;;WAIG;QACc,aAAO,GAAW,EAAE,CAAC,CAAE,gGAAgG;QAWvI,KAAI,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;QAC3B,KAAI,CAAC,WAAW,GAAG,GAAG,CAAC,WAAW,CAAC;;IACpC,CAAC;IAGD;;;;;OAKG;IACH,8BAAO,GAAP;QACC,OAAO,SAAS,CAAC;IAClB,CAAC;IAGD;;;;OAIG;IACH,iCAAU,GAAV;QACC,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAGD;;;;;OAKG;IACH,qCAAc,GAAd;QACC,OAAO,IAAI,CAAC,WAAW,CAAC;IACzB,CAAC;IAGD;;;;OAIG;IACH,oCAAa,GAAb;QACC,QAAQ,IAAI,CAAC,WAAW,EAAG;YAC1B,KAAK,SAAS;gBACb,OAAO,sBAAsB,GAAG,IAAI,CAAC,OAAO,CAAC;YAC9C,KAAK,WAAW;gBACf,OAAO,wBAAwB,GAAG,IAAI,CAAC,OAAO,CAAC;YAChD,KAAK,YAAY;gBAChB,OAAO,yBAAyB,GAAG,IAAI,CAAC,OAAO,CAAC;YAEjD,SAAW,uGAAuG;gBACjH,MAAM,IAAI,KAAK,CAAE,4CAA4C,GAAG,IAAI,CAAC,WAAW,CAAE,CAAC;SACpF;IACF,CAAC;IAGD;;;;OAIG;IACH,oCAAa,GAAb;QACC,OAAO,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC;IAC3B,CAAC;IAGD;;;;;;OAMG;IACH,0CAAmB,GAAnB;QACC,IAAI,gBAAgB,GAAG,iBAAM,mBAAmB,WAAE,EAC9C,WAAW,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QAExC,IAAI,WAAW,EAAG;YACjB,gBAAgB,CAAC,IAAI,CAAE,WAAW,CAAE,CAAC;SACrC;QACD,OAAO,gBAAgB,CAAC;IACzB,CAAC;IAEF,mBAAC;AAAD,CA9GA,AA8GC,CA9GiC,KAAK,GA8GtC","file":"mention-match.js","sourcesContent":["import { Match, MatchConfig } from \"./match\";\nimport { MentionServices } from \"../autolinker\";\n\n/**\n * @class Autolinker.match.Mention\n * @extends Autolinker.match.Match\n *\n * Represents a Mention match found in an input string which should be Autolinked.\n *\n * See this class's superclass ({@link Autolinker.match.Match}) for more details.\n */\nexport class MentionMatch extends Match {\n\n\t/**\n\t * @cfg {String} serviceName\n\t *\n\t * The service to point mention matches to. See {@link Autolinker#mention}\n\t * for available values.\n\t */\n\tprivate readonly serviceName: MentionServices = 'twitter';  // default value just to get the above doc comment in the ES5 output and documentation generator\n\n\t/**\n\t * @cfg {String} mention (required)\n\t *\n\t * The Mention that was matched, without the '@' character.\n\t */\n\tprivate readonly mention: string = '';  // default value just to get the above doc comment in the ES5 output and documentation generator\n\n\n\t/**\n\t * @method constructor\n\t * @param {Object} cfg The configuration properties for the Match\n\t *   instance, specified in an Object (map).\n\t */\n\tconstructor( cfg: MentionMatchConfig ) {\n\t\tsuper( cfg );\n\n\t\tthis.mention = cfg.mention;\n\t\tthis.serviceName = cfg.serviceName;\n\t}\n\n\n\t/**\n\t * Returns a string name for the type of match that this class represents.\n\t * For the case of MentionMatch, returns 'mention'.\n\t *\n\t * @return {String}\n\t */\n\tgetType() {\n\t\treturn 'mention';\n\t}\n\n\n\t/**\n\t * Returns the mention, without the '@' character.\n\t *\n\t * @return {String}\n\t */\n\tgetMention() {\n\t\treturn this.mention;\n\t}\n\n\n\t/**\n\t * Returns the configured {@link #serviceName} to point the mention to.\n\t * Ex: 'instagram', 'twitter', 'soundcloud'.\n\t *\n\t * @return {String}\n\t */\n\tgetServiceName() {\n\t\treturn this.serviceName;\n\t}\n\n\n\t/**\n\t * Returns the anchor href that should be generated for the match.\n\t *\n\t * @return {String}\n\t */\n\tgetAnchorHref() {\n\t\tswitch( this.serviceName ) {\n\t\t\tcase 'twitter' :\n\t\t\t\treturn 'https://twitter.com/' + this.mention;\n\t\t\tcase 'instagram' :\n\t\t\t\treturn 'https://instagram.com/' + this.mention;\n\t\t\tcase 'soundcloud' :\n\t\t\t\treturn 'https://soundcloud.com/' + this.mention;\n\n\t\t\tdefault :  // Shouldn't happen because Autolinker's constructor should block any invalid values, but just in case.\n\t\t\t\tthrow new Error( 'Unknown service name to point mention to: ' + this.serviceName );\n\t\t}\n\t}\n\n\n\t/**\n\t * Returns the anchor text that should be generated for the match.\n\t *\n\t * @return {String}\n\t */\n\tgetAnchorText() {\n\t\treturn '@' + this.mention;\n\t}\n\n\n\t/**\n\t * Returns the CSS class suffixes that should be used on a tag built with\n\t * the match. See {@link Autolinker.match.Match#getCssClassSuffixes} for\n\t * details.\n\t *\n\t * @return {String[]}\n\t */\n\tgetCssClassSuffixes() {\n\t\tlet cssClassSuffixes = super.getCssClassSuffixes(),\n\t\t    serviceName = this.getServiceName();\n\n\t\tif( serviceName ) {\n\t\t\tcssClassSuffixes.push( serviceName );\n\t\t}\n\t\treturn cssClassSuffixes;\n\t}\n\n}\n\nexport interface MentionMatchConfig extends MatchConfig {\n\tserviceName: MentionServices;\n\tmention: string;\n}"]} | ||||
							
								
								
									
										79
									
								
								src/modules/autolinker/match/phone-match.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								src/modules/autolinker/match/phone-match.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| import { Match, MatchConfig } from "./match"; | ||||
| /** | ||||
|  * @class Autolinker.match.Phone | ||||
|  * @extends Autolinker.match.Match | ||||
|  * | ||||
|  * Represents a Phone number match found in an input string which should be | ||||
|  * Autolinked. | ||||
|  * | ||||
|  * See this class's superclass ({@link Autolinker.match.Match}) for more | ||||
|  * details. | ||||
|  */ | ||||
| export declare class PhoneMatch extends Match { | ||||
|     /** | ||||
|      * @protected | ||||
|      * @property {String} number (required) | ||||
|      * | ||||
|      * The phone number that was matched, without any delimiter characters. | ||||
|      * | ||||
|      * Note: This is a string to allow for prefixed 0's. | ||||
|      */ | ||||
|     private readonly number; | ||||
|     /** | ||||
|      * @protected | ||||
|      * @property  {Boolean} plusSign (required) | ||||
|      * | ||||
|      * `true` if the matched phone number started with a '+' sign. We'll include | ||||
|      * it in the `tel:` URL if so, as this is needed for international numbers. | ||||
|      * | ||||
|      * Ex: '+1 (123) 456 7879' | ||||
|      */ | ||||
|     private readonly plusSign; | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} cfg The configuration properties for the Match | ||||
|      *   instance, specified in an Object (map). | ||||
|      */ | ||||
|     constructor(cfg: PhoneMatchConfig); | ||||
|     /** | ||||
|      * Returns a string name for the type of match that this class represents. | ||||
|      * For the case of PhoneMatch, returns 'phone'. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getType(): string; | ||||
|     /** | ||||
|      * Returns the phone number that was matched as a string, without any | ||||
|      * delimiter characters. | ||||
|      * | ||||
|      * Note: This is a string to allow for prefixed 0's. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getPhoneNumber(): string; | ||||
|     /** | ||||
|      * Alias of {@link #getPhoneNumber}, returns the phone number that was | ||||
|      * matched as a string, without any delimiter characters. | ||||
|      * | ||||
|      * Note: This is a string to allow for prefixed 0's. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getNumber(): string; | ||||
|     /** | ||||
|      * Returns the anchor href that should be generated for the match. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getAnchorHref(): string; | ||||
|     /** | ||||
|      * Returns the anchor text that should be generated for the match. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getAnchorText(): string; | ||||
| } | ||||
| export interface PhoneMatchConfig extends MatchConfig { | ||||
|     number: string; | ||||
|     plusSign: boolean; | ||||
| } | ||||
							
								
								
									
										96
									
								
								src/modules/autolinker/match/phone-match.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								src/modules/autolinker/match/phone-match.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| import * as tslib_1 from "tslib"; | ||||
| import { Match } from "./match"; | ||||
| /** | ||||
|  * @class Autolinker.match.Phone | ||||
|  * @extends Autolinker.match.Match | ||||
|  * | ||||
|  * Represents a Phone number match found in an input string which should be | ||||
|  * Autolinked. | ||||
|  * | ||||
|  * See this class's superclass ({@link Autolinker.match.Match}) for more | ||||
|  * details. | ||||
|  */ | ||||
| var PhoneMatch = /** @class */ (function (_super) { | ||||
|     tslib_1.__extends(PhoneMatch, _super); | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} cfg The configuration properties for the Match | ||||
|      *   instance, specified in an Object (map). | ||||
|      */ | ||||
|     function PhoneMatch(cfg) { | ||||
|         var _this = _super.call(this, cfg) || this; | ||||
|         /** | ||||
|          * @protected | ||||
|          * @property {String} number (required) | ||||
|          * | ||||
|          * The phone number that was matched, without any delimiter characters. | ||||
|          * | ||||
|          * Note: This is a string to allow for prefixed 0's. | ||||
|          */ | ||||
|         _this.number = ''; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @protected | ||||
|          * @property  {Boolean} plusSign (required) | ||||
|          * | ||||
|          * `true` if the matched phone number started with a '+' sign. We'll include | ||||
|          * it in the `tel:` URL if so, as this is needed for international numbers. | ||||
|          * | ||||
|          * Ex: '+1 (123) 456 7879' | ||||
|          */ | ||||
|         _this.plusSign = false; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         _this.number = cfg.number; | ||||
|         _this.plusSign = cfg.plusSign; | ||||
|         return _this; | ||||
|     } | ||||
|     /** | ||||
|      * Returns a string name for the type of match that this class represents. | ||||
|      * For the case of PhoneMatch, returns 'phone'. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     PhoneMatch.prototype.getType = function () { | ||||
|         return 'phone'; | ||||
|     }; | ||||
|     /** | ||||
|      * Returns the phone number that was matched as a string, without any | ||||
|      * delimiter characters. | ||||
|      * | ||||
|      * Note: This is a string to allow for prefixed 0's. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     PhoneMatch.prototype.getPhoneNumber = function () { | ||||
|         return this.number; | ||||
|     }; | ||||
|     /** | ||||
|      * Alias of {@link #getPhoneNumber}, returns the phone number that was | ||||
|      * matched as a string, without any delimiter characters. | ||||
|      * | ||||
|      * Note: This is a string to allow for prefixed 0's. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     PhoneMatch.prototype.getNumber = function () { | ||||
|         return this.getPhoneNumber(); | ||||
|     }; | ||||
|     /** | ||||
|      * Returns the anchor href that should be generated for the match. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     PhoneMatch.prototype.getAnchorHref = function () { | ||||
|         return 'tel:' + (this.plusSign ? '+' : '') + this.number; | ||||
|     }; | ||||
|     /** | ||||
|      * Returns the anchor text that should be generated for the match. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     PhoneMatch.prototype.getAnchorText = function () { | ||||
|         return this.matchedText; | ||||
|     }; | ||||
|     return PhoneMatch; | ||||
| }(Match)); | ||||
| export { PhoneMatch }; | ||||
|  | ||||
| //# sourceMappingURL=phone-match.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/match/phone-match.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/match/phone-match.js.map
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| {"version":3,"sources":["../src/match/phone-match.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAe,MAAM,SAAS,CAAC;AAE7C;;;;;;;;;GASG;AACH;IAAgC,sCAAK;IAwBpC;;;;OAIG;IACH,oBAAa,GAAqB;QAAlC,YACC,kBAAO,GAAG,CAAE,SAIZ;QAhCD;;;;;;;WAOG;QACc,YAAM,GAAW,EAAE,CAAC,CAAE,gGAAgG;QAEvI;;;;;;;;WAQG;QACc,cAAQ,GAAY,KAAK,CAAC,CAAE,gGAAgG;QAW5I,KAAI,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;QACzB,KAAI,CAAC,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;;IAC9B,CAAC;IAGD;;;;;OAKG;IACH,4BAAO,GAAP;QACC,OAAO,OAAO,CAAC;IAChB,CAAC;IAGD;;;;;;;OAOG;IACH,mCAAc,GAAd;QACC,OAAO,IAAI,CAAC,MAAM,CAAC;IACpB,CAAC;IAGD;;;;;;;OAOG;IACH,8BAAS,GAAT;QACC,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC;IAC9B,CAAC;IAGD;;;;OAIG;IACH,kCAAa,GAAb;QACC,OAAO,MAAM,GAAG,CAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAE,GAAG,IAAI,CAAC,MAAM,CAAC;IAC5D,CAAC;IAGD;;;;OAIG;IACH,kCAAa,GAAb;QACC,OAAO,IAAI,CAAC,WAAW,CAAC;IACzB,CAAC;IAEF,iBAAC;AAAD,CA7FA,AA6FC,CA7F+B,KAAK,GA6FpC","file":"phone-match.js","sourcesContent":["import { Match, MatchConfig } from \"./match\";\n\n/**\n * @class Autolinker.match.Phone\n * @extends Autolinker.match.Match\n *\n * Represents a Phone number match found in an input string which should be\n * Autolinked.\n *\n * See this class's superclass ({@link Autolinker.match.Match}) for more\n * details.\n */\nexport class PhoneMatch extends Match {\n\n\t/**\n\t * @protected\n\t * @property {String} number (required)\n\t *\n\t * The phone number that was matched, without any delimiter characters.\n\t *\n\t * Note: This is a string to allow for prefixed 0's.\n\t */\n\tprivate readonly number: string = '';  // default value just to get the above doc comment in the ES5 output and documentation generator\n\n\t/**\n\t * @protected\n\t * @property  {Boolean} plusSign (required)\n\t *\n\t * `true` if the matched phone number started with a '+' sign. We'll include\n\t * it in the `tel:` URL if so, as this is needed for international numbers.\n\t *\n\t * Ex: '+1 (123) 456 7879'\n\t */\n\tprivate readonly plusSign: boolean = false;  // default value just to get the above doc comment in the ES5 output and documentation generator\n\n\n\t/**\n\t * @method constructor\n\t * @param {Object} cfg The configuration properties for the Match\n\t *   instance, specified in an Object (map).\n\t */\n\tconstructor( cfg: PhoneMatchConfig ) {\n\t\tsuper( cfg );\n\n\t\tthis.number = cfg.number;\n\t\tthis.plusSign = cfg.plusSign;\n\t}\n\n\n\t/**\n\t * Returns a string name for the type of match that this class represents.\n\t * For the case of PhoneMatch, returns 'phone'.\n\t *\n\t * @return {String}\n\t */\n\tgetType() {\n\t\treturn 'phone';\n\t}\n\n\n\t/**\n\t * Returns the phone number that was matched as a string, without any \n\t * delimiter characters. \n\t *\n\t * Note: This is a string to allow for prefixed 0's.\n\t *\n\t * @return {String}\n\t */\n\tgetPhoneNumber() {\n\t\treturn this.number;\n\t}\n\n\n\t/**\n\t * Alias of {@link #getPhoneNumber}, returns the phone number that was \n\t * matched as a string, without any delimiter characters.\n\t *\n\t * Note: This is a string to allow for prefixed 0's.\n\t *\n\t * @return {String}\n\t */\n\tgetNumber() {\n\t\treturn this.getPhoneNumber();\n\t}\n\n\n\t/**\n\t * Returns the anchor href that should be generated for the match.\n\t *\n\t * @return {String}\n\t */\n\tgetAnchorHref() {\n\t\treturn 'tel:' + ( this.plusSign ? '+' : '' ) + this.number;\n\t}\n\n\n\t/**\n\t * Returns the anchor text that should be generated for the match.\n\t *\n\t * @return {String}\n\t */\n\tgetAnchorText() {\n\t\treturn this.matchedText;\n\t}\n\n}\n\n\nexport interface PhoneMatchConfig extends MatchConfig {\n\tnumber: string;\n\tplusSign: boolean;\n}"]} | ||||
							
								
								
									
										190
									
								
								src/modules/autolinker/match/url-match.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								src/modules/autolinker/match/url-match.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,190 @@ | ||||
| import { Match, MatchConfig } from "./match"; | ||||
| import { StripPrefixConfigObj, UrlMatchTypeOptions } from "../autolinker"; | ||||
| /** | ||||
|  * @class Autolinker.match.Url | ||||
|  * @extends Autolinker.match.Match | ||||
|  * | ||||
|  * Represents a Url match found in an input string which should be Autolinked. | ||||
|  * | ||||
|  * See this class's superclass ({@link Autolinker.match.Match}) for more details. | ||||
|  */ | ||||
| export declare class UrlMatch extends Match { | ||||
|     /** | ||||
|      * @cfg {String} url (required) | ||||
|      * | ||||
|      * The url that was matched. | ||||
|      */ | ||||
|     private url; | ||||
|     /** | ||||
|      * @cfg {"scheme"/"www"/"tld"} urlMatchType (required) | ||||
|      * | ||||
|      * The type of URL match that this class represents. This helps to determine | ||||
|      * if the match was made in the original text with a prefixed scheme (ex: | ||||
|      * 'http://www.google.com'), a prefixed 'www' (ex: 'www.google.com'), or | ||||
|      * was matched by a known top-level domain (ex: 'google.com'). | ||||
|      */ | ||||
|     private readonly urlMatchType; | ||||
|     /** | ||||
|      * @cfg {Boolean} protocolUrlMatch (required) | ||||
|      * | ||||
|      * `true` if the URL is a match which already has a protocol (i.e. | ||||
|      * 'http://'), `false` if the match was from a 'www' or known TLD match. | ||||
|      */ | ||||
|     private readonly protocolUrlMatch; | ||||
|     /** | ||||
|      * @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 readonly protocolRelativeMatch; | ||||
|     /** | ||||
|      * @cfg {Object} stripPrefix (required) | ||||
|      * | ||||
|      * The Object form of {@link Autolinker#cfg-stripPrefix}. | ||||
|      */ | ||||
|     private readonly stripPrefix; | ||||
|     /** | ||||
|      * @cfg {Boolean} stripTrailingSlash (required) | ||||
|      * @inheritdoc Autolinker#cfg-stripTrailingSlash | ||||
|      */ | ||||
|     private readonly stripTrailingSlash; | ||||
|     /** | ||||
|      * @cfg {Boolean} decodePercentEncoding (required) | ||||
|      * @inheritdoc Autolinker#cfg-decodePercentEncoding | ||||
|      */ | ||||
|     private readonly decodePercentEncoding; | ||||
|     /** | ||||
|      * @private | ||||
|      * @property {RegExp} schemePrefixRegex | ||||
|      * | ||||
|      * A regular expression used to remove the 'http://' or 'https://' from | ||||
|      * URLs. | ||||
|      */ | ||||
|     schemePrefixRegex: RegExp; | ||||
|     /** | ||||
|      * @private | ||||
|      * @property {RegExp} wwwPrefixRegex | ||||
|      * | ||||
|      * A regular expression used to remove the 'www.' from URLs. | ||||
|      */ | ||||
|     wwwPrefixRegex: RegExp; | ||||
|     /** | ||||
|      * @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: RegExp; | ||||
|     /** | ||||
|      * @private | ||||
|      * @property {Boolean} protocolPrepended | ||||
|      * | ||||
|      * Will be set to `true` if the 'http://' protocol has been prepended to the {@link #url} (because the | ||||
|      * {@link #url} did not have a protocol) | ||||
|      */ | ||||
|     protocolPrepended: boolean; | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} cfg The configuration properties for the Match | ||||
|      *   instance, specified in an Object (map). | ||||
|      */ | ||||
|     constructor(cfg: UrlMatchConfig); | ||||
|     /** | ||||
|      * Returns a string name for the type of match that this class represents. | ||||
|      * For the case of UrlMatch, returns 'url'. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getType(): string; | ||||
|     /** | ||||
|      * Returns a string name for the type of URL match that this class | ||||
|      * represents. | ||||
|      * | ||||
|      * This helps to determine if the match was made in the original text with a | ||||
|      * prefixed scheme (ex: 'http://www.google.com'), a prefixed 'www' (ex: | ||||
|      * 'www.google.com'), or was matched by a known top-level domain (ex: | ||||
|      * 'google.com'). | ||||
|      * | ||||
|      * @return {"scheme"/"www"/"tld"} | ||||
|      */ | ||||
|     getUrlMatchType(): UrlMatchTypeOptions; | ||||
|     /** | ||||
|      * Returns the url that was matched, assuming the protocol to be 'http://' if the original | ||||
|      * match was missing a protocol. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getUrl(): string; | ||||
|     /** | ||||
|      * Returns the anchor href that should be generated for the match. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getAnchorHref(): string; | ||||
|     /** | ||||
|      * Returns the anchor text that should be generated for the match. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     getAnchorText(): string; | ||||
|     /** | ||||
|      * Strips the scheme prefix (such as "http://" or "https://") from the given | ||||
|      * `url`. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {String} url The text of the anchor that is being generated, for | ||||
|      *   which to strip off the url scheme. | ||||
|      * @return {String} The `url`, with the scheme stripped. | ||||
|      */ | ||||
|     private stripSchemePrefix; | ||||
|     /** | ||||
|      * Strips the 'www' prefix from the given `url`. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {String} url The text of the anchor that is being generated, for | ||||
|      *   which to strip off the 'www' if it exists. | ||||
|      * @return {String} The `url`, with the 'www' stripped. | ||||
|      */ | ||||
|     private stripWwwPrefix; | ||||
|     /** | ||||
|      * Strips any protocol-relative '//' from the anchor text. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {String} text The text of the anchor that is being generated, for which to strip off the | ||||
|      *   protocol-relative prefix (such as stripping off "//") | ||||
|      * @return {String} The `anchorText`, with the protocol-relative prefix stripped. | ||||
|      */ | ||||
|     private stripProtocolRelativePrefix; | ||||
|     /** | ||||
|      * 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 | ||||
|      *   slash ('/') that may exist. | ||||
|      * @return {String} The `anchorText`, with the trailing slash removed. | ||||
|      */ | ||||
|     private removeTrailingSlash; | ||||
|     /** | ||||
|      * Decodes percent-encoded characters 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 decode any percent-encoded characters. | ||||
|      * @return {String} The `anchorText`, with the percent-encoded characters | ||||
|      *   decoded. | ||||
|      */ | ||||
|     private removePercentEncoding; | ||||
| } | ||||
| export interface UrlMatchConfig extends MatchConfig { | ||||
|     url: string; | ||||
|     urlMatchType: UrlMatchTypeOptions; | ||||
|     protocolUrlMatch: boolean; | ||||
|     protocolRelativeMatch: boolean; | ||||
|     stripPrefix: Required<StripPrefixConfigObj>; | ||||
|     stripTrailingSlash: boolean; | ||||
|     decodePercentEncoding: boolean; | ||||
| } | ||||
							
								
								
									
										260
									
								
								src/modules/autolinker/match/url-match.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										260
									
								
								src/modules/autolinker/match/url-match.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,260 @@ | ||||
| import * as tslib_1 from "tslib"; | ||||
| import { Match } from "./match"; | ||||
| /** | ||||
|  * @class Autolinker.match.Url | ||||
|  * @extends Autolinker.match.Match | ||||
|  * | ||||
|  * Represents a Url match found in an input string which should be Autolinked. | ||||
|  * | ||||
|  * See this class's superclass ({@link Autolinker.match.Match}) for more details. | ||||
|  */ | ||||
| var UrlMatch = /** @class */ (function (_super) { | ||||
|     tslib_1.__extends(UrlMatch, _super); | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} cfg The configuration properties for the Match | ||||
|      *   instance, specified in an Object (map). | ||||
|      */ | ||||
|     function UrlMatch(cfg) { | ||||
|         var _this = _super.call(this, cfg) || this; | ||||
|         /** | ||||
|          * @cfg {String} url (required) | ||||
|          * | ||||
|          * The url that was matched. | ||||
|          */ | ||||
|         _this.url = ''; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {"scheme"/"www"/"tld"} urlMatchType (required) | ||||
|          * | ||||
|          * The type of URL match that this class represents. This helps to determine | ||||
|          * if the match was made in the original text with a prefixed scheme (ex: | ||||
|          * 'http://www.google.com'), a prefixed 'www' (ex: 'www.google.com'), or | ||||
|          * was matched by a known top-level domain (ex: 'google.com'). | ||||
|          */ | ||||
|         _this.urlMatchType = 'scheme'; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {Boolean} protocolUrlMatch (required) | ||||
|          * | ||||
|          * `true` if the URL is a match which already has a protocol (i.e. | ||||
|          * 'http://'), `false` if the match was from a 'www' or known TLD match. | ||||
|          */ | ||||
|         _this.protocolUrlMatch = false; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @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. | ||||
|          */ | ||||
|         _this.protocolRelativeMatch = false; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {Object} stripPrefix (required) | ||||
|          * | ||||
|          * The Object form of {@link Autolinker#cfg-stripPrefix}. | ||||
|          */ | ||||
|         _this.stripPrefix = { scheme: true, www: true }; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {Boolean} stripTrailingSlash (required) | ||||
|          * @inheritdoc Autolinker#cfg-stripTrailingSlash | ||||
|          */ | ||||
|         _this.stripTrailingSlash = true; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {Boolean} decodePercentEncoding (required) | ||||
|          * @inheritdoc Autolinker#cfg-decodePercentEncoding | ||||
|          */ | ||||
|         _this.decodePercentEncoding = true; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @private | ||||
|          * @property {RegExp} schemePrefixRegex | ||||
|          * | ||||
|          * A regular expression used to remove the 'http://' or 'https://' from | ||||
|          * URLs. | ||||
|          */ | ||||
|         _this.schemePrefixRegex = /^(https?:\/\/)?/i; | ||||
|         /** | ||||
|          * @private | ||||
|          * @property {RegExp} wwwPrefixRegex | ||||
|          * | ||||
|          * A regular expression used to remove the 'www.' from URLs. | ||||
|          */ | ||||
|         _this.wwwPrefixRegex = /^(https?:\/\/)?(www\.)?/i; | ||||
|         /** | ||||
|          * @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" | ||||
|          */ | ||||
|         _this.protocolRelativeRegex = /^\/\//; | ||||
|         /** | ||||
|          * @private | ||||
|          * @property {Boolean} protocolPrepended | ||||
|          * | ||||
|          * Will be set to `true` if the 'http://' protocol has been prepended to the {@link #url} (because the | ||||
|          * {@link #url} did not have a protocol) | ||||
|          */ | ||||
|         _this.protocolPrepended = false; | ||||
|         _this.urlMatchType = cfg.urlMatchType; | ||||
|         _this.url = cfg.url; | ||||
|         _this.protocolUrlMatch = cfg.protocolUrlMatch; | ||||
|         _this.protocolRelativeMatch = cfg.protocolRelativeMatch; | ||||
|         _this.stripPrefix = cfg.stripPrefix; | ||||
|         _this.stripTrailingSlash = cfg.stripTrailingSlash; | ||||
|         _this.decodePercentEncoding = cfg.decodePercentEncoding; | ||||
|         return _this; | ||||
|     } | ||||
|     /** | ||||
|      * Returns a string name for the type of match that this class represents. | ||||
|      * For the case of UrlMatch, returns 'url'. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     UrlMatch.prototype.getType = function () { | ||||
|         return 'url'; | ||||
|     }; | ||||
|     /** | ||||
|      * Returns a string name for the type of URL match that this class | ||||
|      * represents. | ||||
|      * | ||||
|      * This helps to determine if the match was made in the original text with a | ||||
|      * prefixed scheme (ex: 'http://www.google.com'), a prefixed 'www' (ex: | ||||
|      * 'www.google.com'), or was matched by a known top-level domain (ex: | ||||
|      * 'google.com'). | ||||
|      * | ||||
|      * @return {"scheme"/"www"/"tld"} | ||||
|      */ | ||||
|     UrlMatch.prototype.getUrlMatchType = function () { | ||||
|         return this.urlMatchType; | ||||
|     }; | ||||
|     /** | ||||
|      * Returns the url that was matched, assuming the protocol to be 'http://' if the original | ||||
|      * match was missing a protocol. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     UrlMatch.prototype.getUrl = function () { | ||||
|         var url = this.url; | ||||
|         // if the url string doesn't begin with a protocol, assume 'http://' | ||||
|         if (!this.protocolRelativeMatch && !this.protocolUrlMatch && !this.protocolPrepended) { | ||||
|             url = this.url = 'http://' + url; | ||||
|             this.protocolPrepended = true; | ||||
|         } | ||||
|         return url; | ||||
|     }; | ||||
|     /** | ||||
|      * Returns the anchor href that should be generated for the match. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     UrlMatch.prototype.getAnchorHref = function () { | ||||
|         var url = this.getUrl(); | ||||
|         return url.replace(/&/g, '&'); // any &'s in the URL should be converted back to '&' if they were displayed as & in the source html | ||||
|     }; | ||||
|     /** | ||||
|      * Returns the anchor text that should be generated for the match. | ||||
|      * | ||||
|      * @return {String} | ||||
|      */ | ||||
|     UrlMatch.prototype.getAnchorText = function () { | ||||
|         var anchorText = this.getMatchedText(); | ||||
|         if (this.protocolRelativeMatch) { | ||||
|             // Strip off any protocol-relative '//' from the anchor text | ||||
|             anchorText = this.stripProtocolRelativePrefix(anchorText); | ||||
|         } | ||||
|         if (this.stripPrefix.scheme) { | ||||
|             anchorText = this.stripSchemePrefix(anchorText); | ||||
|         } | ||||
|         if (this.stripPrefix.www) { | ||||
|             anchorText = this.stripWwwPrefix(anchorText); | ||||
|         } | ||||
|         if (this.stripTrailingSlash) { | ||||
|             anchorText = this.removeTrailingSlash(anchorText); // remove trailing slash, if there is one | ||||
|         } | ||||
|         if (this.decodePercentEncoding) { | ||||
|             anchorText = this.removePercentEncoding(anchorText); | ||||
|         } | ||||
|         return anchorText; | ||||
|     }; | ||||
|     // --------------------------------------- | ||||
|     // Utility Functionality | ||||
|     /** | ||||
|      * Strips the scheme prefix (such as "http://" or "https://") from the given | ||||
|      * `url`. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {String} url The text of the anchor that is being generated, for | ||||
|      *   which to strip off the url scheme. | ||||
|      * @return {String} The `url`, with the scheme stripped. | ||||
|      */ | ||||
|     UrlMatch.prototype.stripSchemePrefix = function (url) { | ||||
|         return url.replace(this.schemePrefixRegex, ''); | ||||
|     }; | ||||
|     /** | ||||
|      * Strips the 'www' prefix from the given `url`. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {String} url The text of the anchor that is being generated, for | ||||
|      *   which to strip off the 'www' if it exists. | ||||
|      * @return {String} The `url`, with the 'www' stripped. | ||||
|      */ | ||||
|     UrlMatch.prototype.stripWwwPrefix = function (url) { | ||||
|         return url.replace(this.wwwPrefixRegex, '$1'); // leave any scheme ($1), it one exists | ||||
|     }; | ||||
|     /** | ||||
|      * Strips any protocol-relative '//' from the anchor text. | ||||
|      * | ||||
|      * @private | ||||
|      * @param {String} text The text of the anchor that is being generated, for which to strip off the | ||||
|      *   protocol-relative prefix (such as stripping off "//") | ||||
|      * @return {String} The `anchorText`, with the protocol-relative prefix stripped. | ||||
|      */ | ||||
|     UrlMatch.prototype.stripProtocolRelativePrefix = function (text) { | ||||
|         return text.replace(this.protocolRelativeRegex, ''); | ||||
|     }; | ||||
|     /** | ||||
|      * 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 | ||||
|      *   slash ('/') that may exist. | ||||
|      * @return {String} The `anchorText`, with the trailing slash removed. | ||||
|      */ | ||||
|     UrlMatch.prototype.removeTrailingSlash = function (anchorText) { | ||||
|         if (anchorText.charAt(anchorText.length - 1) === '/') { | ||||
|             anchorText = anchorText.slice(0, -1); | ||||
|         } | ||||
|         return anchorText; | ||||
|     }; | ||||
|     /** | ||||
|      * Decodes percent-encoded characters 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 decode any percent-encoded characters. | ||||
|      * @return {String} The `anchorText`, with the percent-encoded characters | ||||
|      *   decoded. | ||||
|      */ | ||||
|     UrlMatch.prototype.removePercentEncoding = function (anchorText) { | ||||
|         // First, convert a few of the known % encodings to the corresponding | ||||
|         // HTML entities that could accidentally be interpretted as special | ||||
|         // HTML characters | ||||
|         var preProcessedEntityAnchorText = anchorText | ||||
|             .replace(/%22/gi, '"') // " char | ||||
|             .replace(/%26/gi, '&') // & char | ||||
|             .replace(/%27/gi, ''') // ' char | ||||
|             .replace(/%3C/gi, '<') // < char | ||||
|             .replace(/%3E/gi, '>'); // > char | ||||
|         try { | ||||
|             // Now attempt to decode the rest of the anchor text | ||||
|             return decodeURIComponent(preProcessedEntityAnchorText); | ||||
|         } | ||||
|         catch (e) { // Invalid % escape sequence in the anchor text | ||||
|             return preProcessedEntityAnchorText; | ||||
|         } | ||||
|     }; | ||||
|     return UrlMatch; | ||||
| }(Match)); | ||||
| export { UrlMatch }; | ||||
|  | ||||
| //# sourceMappingURL=url-match.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/match/url-match.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/match/url-match.js.map
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										26
									
								
								src/modules/autolinker/matcher/email-matcher.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/modules/autolinker/matcher/email-matcher.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| import { Matcher } from "./matcher"; | ||||
| import { Match } from "../match/match"; | ||||
| /** | ||||
|  * @class Autolinker.matcher.Email | ||||
|  * @extends Autolinker.matcher.Matcher | ||||
|  * | ||||
|  * Matcher to find email matches in an input string. | ||||
|  * | ||||
|  * See this class's superclass ({@link Autolinker.matcher.Matcher}) for more details. | ||||
|  */ | ||||
| export declare class EmailMatcher extends Matcher { | ||||
|     /** | ||||
|      * Valid characters that can be used in the "local" part of an email address, | ||||
|      * i.e. the "name" part of "name@site.com" | ||||
|      */ | ||||
|     protected localPartCharRegex: RegExp; | ||||
|     /** | ||||
|      * Stricter TLD regex which adds a beginning and end check to ensure | ||||
|      * the string is a valid TLD | ||||
|      */ | ||||
|     protected strictTldRegex: RegExp; | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     parseMatches(text: string): Match[]; | ||||
| } | ||||
							
								
								
									
										311
									
								
								src/modules/autolinker/matcher/email-matcher.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										311
									
								
								src/modules/autolinker/matcher/email-matcher.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,311 @@ | ||||
| import * as tslib_1 from "tslib"; | ||||
| import { Matcher } from "./matcher"; | ||||
| import { alphaNumericAndMarksCharsStr, domainNameCharRegex } from "../regex-lib"; | ||||
| import { EmailMatch } from "../match/email-match"; | ||||
| import { throwUnhandledCaseError } from '../utils'; | ||||
| import { tldRegex } from "./tld-regex"; | ||||
| // For debugging: search for other "For debugging" lines | ||||
| // import CliTable from 'cli-table'; | ||||
| // RegExp objects which are shared by all instances of EmailMatcher. These are | ||||
| // here to avoid re-instantiating the RegExp objects if `Autolinker.link()` is | ||||
| // called multiple times, thus instantiating EmailMatcher and its RegExp  | ||||
| // objects each time (which is very expensive - see https://github.com/gregjacobs/Autolinker.js/issues/314).  | ||||
| // See descriptions of the properties where they are used for details about them | ||||
| var localPartCharRegex = new RegExp("[" + alphaNumericAndMarksCharsStr + "!#$%&'*+/=?^_`{|}~-]"); | ||||
| var strictTldRegex = new RegExp("^" + tldRegex.source + "$"); | ||||
| /** | ||||
|  * @class Autolinker.matcher.Email | ||||
|  * @extends Autolinker.matcher.Matcher | ||||
|  * | ||||
|  * Matcher to find email matches in an input string. | ||||
|  * | ||||
|  * See this class's superclass ({@link Autolinker.matcher.Matcher}) for more details. | ||||
|  */ | ||||
| var EmailMatcher = /** @class */ (function (_super) { | ||||
|     tslib_1.__extends(EmailMatcher, _super); | ||||
|     function EmailMatcher() { | ||||
|         var _this = _super !== null && _super.apply(this, arguments) || this; | ||||
|         /** | ||||
|          * Valid characters that can be used in the "local" part of an email address, | ||||
|          * i.e. the "name" part of "name@site.com" | ||||
|          */ | ||||
|         _this.localPartCharRegex = localPartCharRegex; | ||||
|         /** | ||||
|          * Stricter TLD regex which adds a beginning and end check to ensure | ||||
|          * the string is a valid TLD | ||||
|          */ | ||||
|         _this.strictTldRegex = strictTldRegex; | ||||
|         return _this; | ||||
|     } | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     EmailMatcher.prototype.parseMatches = function (text) { | ||||
|         var tagBuilder = this.tagBuilder, localPartCharRegex = this.localPartCharRegex, strictTldRegex = this.strictTldRegex, matches = [], len = text.length, noCurrentEmailMatch = new CurrentEmailMatch(); | ||||
|         // for matching a 'mailto:' prefix | ||||
|         var mailtoTransitions = { | ||||
|             'm': 'a', | ||||
|             'a': 'i', | ||||
|             'i': 'l', | ||||
|             'l': 't', | ||||
|             't': 'o', | ||||
|             'o': ':', | ||||
|         }; | ||||
|         var charIdx = 0, state = 0 /* NonEmailMatch */, currentEmailMatch = noCurrentEmailMatch; | ||||
|         // For debugging: search for other "For debugging" lines | ||||
|         // const table = new CliTable( { | ||||
|         // 	head: [ 'charIdx', 'char', 'state', 'charIdx', 'currentEmailAddress.idx', 'hasDomainDot' ] | ||||
|         // } ); | ||||
|         while (charIdx < len) { | ||||
|             var char = text.charAt(charIdx); | ||||
|             // For debugging: search for other "For debugging" lines | ||||
|             // table.push(  | ||||
|             // 	[ charIdx, char, State[ state ], charIdx, currentEmailAddress.idx, currentEmailAddress.hasDomainDot ]  | ||||
|             // ); | ||||
|             switch (state) { | ||||
|                 case 0 /* NonEmailMatch */: | ||||
|                     stateNonEmailAddress(char); | ||||
|                     break; | ||||
|                 case 1 /* Mailto */: | ||||
|                     stateMailTo(text.charAt(charIdx - 1), char); | ||||
|                     break; | ||||
|                 case 2 /* LocalPart */: | ||||
|                     stateLocalPart(char); | ||||
|                     break; | ||||
|                 case 3 /* LocalPartDot */: | ||||
|                     stateLocalPartDot(char); | ||||
|                     break; | ||||
|                 case 4 /* AtSign */: | ||||
|                     stateAtSign(char); | ||||
|                     break; | ||||
|                 case 5 /* DomainChar */: | ||||
|                     stateDomainChar(char); | ||||
|                     break; | ||||
|                 case 6 /* DomainHyphen */: | ||||
|                     stateDomainHyphen(char); | ||||
|                     break; | ||||
|                 case 7 /* DomainDot */: | ||||
|                     stateDomainDot(char); | ||||
|                     break; | ||||
|                 default: | ||||
|                     throwUnhandledCaseError(state); | ||||
|             } | ||||
|             // For debugging: search for other "For debugging" lines | ||||
|             // table.push(  | ||||
|             // 	[ charIdx, char, State[ state ], charIdx, currentEmailAddress.idx, currentEmailAddress.hasDomainDot ]  | ||||
|             // ); | ||||
|             charIdx++; | ||||
|         } | ||||
|         // Capture any valid match at the end of the string | ||||
|         captureMatchIfValidAndReset(); | ||||
|         // For debugging: search for other "For debugging" lines | ||||
|         //console.log( '\n' + table.toString() ); | ||||
|         return matches; | ||||
|         // Handles the state when we're not in an email address | ||||
|         function stateNonEmailAddress(char) { | ||||
|             if (char === 'm') { | ||||
|                 beginEmailMatch(1 /* Mailto */); | ||||
|             } | ||||
|             else if (localPartCharRegex.test(char)) { | ||||
|                 beginEmailMatch(); | ||||
|             } | ||||
|             else { | ||||
|                 // not an email address character, continue | ||||
|             } | ||||
|         } | ||||
|         // Handles if we're reading a 'mailto:' prefix on the string | ||||
|         function stateMailTo(prevChar, char) { | ||||
|             if (prevChar === ':') { | ||||
|                 // We've reached the end of the 'mailto:' prefix | ||||
|                 if (localPartCharRegex.test(char)) { | ||||
|                     state = 2 /* LocalPart */; | ||||
|                     currentEmailMatch = new CurrentEmailMatch(tslib_1.__assign({}, currentEmailMatch, { hasMailtoPrefix: true })); | ||||
|                 } | ||||
|                 else { | ||||
|                     // we've matched 'mailto:' but didn't get anything meaningful | ||||
|                     // immediately afterwards (for example, we encountered a  | ||||
|                     // space character, or an '@' character which formed 'mailto:@' | ||||
|                     resetToNonEmailMatchState(); | ||||
|                 } | ||||
|             } | ||||
|             else if (mailtoTransitions[prevChar] === char) { | ||||
|                 // We're currently reading the 'mailto:' prefix, stay in | ||||
|                 // Mailto state | ||||
|             } | ||||
|             else if (localPartCharRegex.test(char)) { | ||||
|                 // We we're reading a prefix of 'mailto:', but encountered a | ||||
|                 // different character that didn't continue the prefix | ||||
|                 state = 2 /* LocalPart */; | ||||
|             } | ||||
|             else if (char === '.') { | ||||
|                 // We we're reading a prefix of 'mailto:', but encountered a | ||||
|                 // dot character | ||||
|                 state = 3 /* LocalPartDot */; | ||||
|             } | ||||
|             else if (char === '@') { | ||||
|                 // We we're reading a prefix of 'mailto:', but encountered a | ||||
|                 // an @ character | ||||
|                 state = 4 /* AtSign */; | ||||
|             } | ||||
|             else { | ||||
|                 // not an email address character, return to "NonEmailAddress" state | ||||
|                 resetToNonEmailMatchState(); | ||||
|             } | ||||
|         } | ||||
|         // Handles the state when we're currently in the "local part" of an  | ||||
|         // email address (as opposed to the "domain part") | ||||
|         function stateLocalPart(char) { | ||||
|             if (char === '.') { | ||||
|                 state = 3 /* LocalPartDot */; | ||||
|             } | ||||
|             else if (char === '@') { | ||||
|                 state = 4 /* AtSign */; | ||||
|             } | ||||
|             else if (localPartCharRegex.test(char)) { | ||||
|                 // stay in the "local part" of the email address | ||||
|             } | ||||
|             else { | ||||
|                 // not an email address character, return to "NonEmailAddress" state | ||||
|                 resetToNonEmailMatchState(); | ||||
|             } | ||||
|         } | ||||
|         // Handles the state where we've read  | ||||
|         function stateLocalPartDot(char) { | ||||
|             if (char === '.') { | ||||
|                 // We read a second '.' in a row, not a valid email address  | ||||
|                 // local part | ||||
|                 resetToNonEmailMatchState(); | ||||
|             } | ||||
|             else if (char === '@') { | ||||
|                 // We read the '@' character immediately after a dot ('.'), not  | ||||
|                 // an email address | ||||
|                 resetToNonEmailMatchState(); | ||||
|             } | ||||
|             else if (localPartCharRegex.test(char)) { | ||||
|                 state = 2 /* LocalPart */; | ||||
|             } | ||||
|             else { | ||||
|                 // Anything else, not an email address | ||||
|                 resetToNonEmailMatchState(); | ||||
|             } | ||||
|         } | ||||
|         function stateAtSign(char) { | ||||
|             if (domainNameCharRegex.test(char)) { | ||||
|                 state = 5 /* DomainChar */; | ||||
|             } | ||||
|             else { | ||||
|                 // Anything else, not an email address | ||||
|                 resetToNonEmailMatchState(); | ||||
|             } | ||||
|         } | ||||
|         function stateDomainChar(char) { | ||||
|             if (char === '.') { | ||||
|                 state = 7 /* DomainDot */; | ||||
|             } | ||||
|             else if (char === '-') { | ||||
|                 state = 6 /* DomainHyphen */; | ||||
|             } | ||||
|             else if (domainNameCharRegex.test(char)) { | ||||
|                 // Stay in the DomainChar state | ||||
|             } | ||||
|             else { | ||||
|                 // Anything else, we potentially matched if the criteria has | ||||
|                 // been met | ||||
|                 captureMatchIfValidAndReset(); | ||||
|             } | ||||
|         } | ||||
|         function stateDomainHyphen(char) { | ||||
|             if (char === '-' || char === '.') { | ||||
|                 // Not valid to have two hyphens ("--") or hypen+dot ("-.") | ||||
|                 captureMatchIfValidAndReset(); | ||||
|             } | ||||
|             else if (domainNameCharRegex.test(char)) { | ||||
|                 state = 5 /* DomainChar */; | ||||
|             } | ||||
|             else { | ||||
|                 // Anything else | ||||
|                 captureMatchIfValidAndReset(); | ||||
|             } | ||||
|         } | ||||
|         function stateDomainDot(char) { | ||||
|             if (char === '.' || char === '-') { | ||||
|                 // not valid to have two dots ("..") or dot+hypen (".-") | ||||
|                 captureMatchIfValidAndReset(); | ||||
|             } | ||||
|             else if (domainNameCharRegex.test(char)) { | ||||
|                 state = 5 /* DomainChar */; | ||||
|                 // After having read a '.' and then a valid domain character, | ||||
|                 // we now know that the domain part of the email is valid, and | ||||
|                 // we have found at least a partial EmailMatch (however, the | ||||
|                 // email address may have additional characters from this point) | ||||
|                 currentEmailMatch = new CurrentEmailMatch(tslib_1.__assign({}, currentEmailMatch, { hasDomainDot: true })); | ||||
|             } | ||||
|             else { | ||||
|                 // Anything else | ||||
|                 captureMatchIfValidAndReset(); | ||||
|             } | ||||
|         } | ||||
|         function beginEmailMatch(newState) { | ||||
|             if (newState === void 0) { newState = 2 /* LocalPart */; } | ||||
|             state = newState; | ||||
|             currentEmailMatch = new CurrentEmailMatch({ idx: charIdx }); | ||||
|         } | ||||
|         function resetToNonEmailMatchState() { | ||||
|             state = 0 /* NonEmailMatch */; | ||||
|             currentEmailMatch = noCurrentEmailMatch; | ||||
|         } | ||||
|         /* | ||||
|          * Captures the current email address as an EmailMatch if it's valid, | ||||
|          * and resets the state to read another email address. | ||||
|          */ | ||||
|         function captureMatchIfValidAndReset() { | ||||
|             if (currentEmailMatch.hasDomainDot) { // we need at least one dot in the domain to be considered a valid email address | ||||
|                 var matchedText = text.slice(currentEmailMatch.idx, charIdx); | ||||
|                 // If we read a '.' or '-' char that ended the email address | ||||
|                 // (valid domain name characters, but only valid email address | ||||
|                 // characters if they are followed by something else), strip  | ||||
|                 // it off now | ||||
|                 if (/[-.]$/.test(matchedText)) { | ||||
|                     matchedText = matchedText.slice(0, -1); | ||||
|                 } | ||||
|                 var emailAddress = currentEmailMatch.hasMailtoPrefix | ||||
|                     ? matchedText.slice('mailto:'.length) | ||||
|                     : matchedText; | ||||
|                 // if the email address has a valid TLD, add it to the list of matches | ||||
|                 if (doesEmailHaveValidTld(emailAddress)) { | ||||
|                     matches.push(new EmailMatch({ | ||||
|                         tagBuilder: tagBuilder, | ||||
|                         matchedText: matchedText, | ||||
|                         offset: currentEmailMatch.idx, | ||||
|                         email: emailAddress | ||||
|                     })); | ||||
|                 } | ||||
|             } | ||||
|             resetToNonEmailMatchState(); | ||||
|             /** | ||||
|              * Determines if the given email address has a valid TLD or not | ||||
|              * @param {string} emailAddress - email address | ||||
|              * @return {Boolean} - true is email have valid TLD, false otherwise | ||||
|              */ | ||||
|             function doesEmailHaveValidTld(emailAddress) { | ||||
|                 var emailAddressTld = emailAddress.split('.').pop() || ''; | ||||
|                 var emailAddressNormalized = emailAddressTld.toLowerCase(); | ||||
|                 var isValidTld = strictTldRegex.test(emailAddressNormalized); | ||||
|                 return isValidTld; | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
|     return EmailMatcher; | ||||
| }(Matcher)); | ||||
| export { EmailMatcher }; | ||||
| var CurrentEmailMatch = /** @class */ (function () { | ||||
|     function CurrentEmailMatch(cfg) { | ||||
|         if (cfg === void 0) { cfg = {}; } | ||||
|         this.idx = cfg.idx !== undefined ? cfg.idx : -1; | ||||
|         this.hasMailtoPrefix = !!cfg.hasMailtoPrefix; | ||||
|         this.hasDomainDot = !!cfg.hasDomainDot; | ||||
|     } | ||||
|     return CurrentEmailMatch; | ||||
| }()); | ||||
|  | ||||
| //# sourceMappingURL=email-matcher.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/matcher/email-matcher.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/matcher/email-matcher.js.map
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										50
									
								
								src/modules/autolinker/matcher/hashtag-matcher.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/modules/autolinker/matcher/hashtag-matcher.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| import { Matcher, MatcherConfig } from "./matcher"; | ||||
| import { HashtagServices } from "../autolinker"; | ||||
| import { Match } from "../match/match"; | ||||
| /** | ||||
|  * @class Autolinker.matcher.Hashtag | ||||
|  * @extends Autolinker.matcher.Matcher | ||||
|  * | ||||
|  * Matcher to find HashtagMatch matches in an input string. | ||||
|  */ | ||||
| export declare class HashtagMatcher extends Matcher { | ||||
|     /** | ||||
|      * @cfg {String} serviceName | ||||
|      * | ||||
|      * The service to point hashtag matches to. See {@link Autolinker#hashtag} | ||||
|      * for available values. | ||||
|      */ | ||||
|     protected readonly serviceName: HashtagServices; | ||||
|     /** | ||||
|      * The regular expression to match Hashtags. Example match: | ||||
|      * | ||||
|      *     #asdf | ||||
|      * | ||||
|      * @protected | ||||
|      * @property {RegExp} matcherRegex | ||||
|      */ | ||||
|     protected matcherRegex: RegExp; | ||||
|     /** | ||||
|      * The regular expression to use to check the character before a username match to | ||||
|      * make sure we didn't accidentally match an email address. | ||||
|      * | ||||
|      * For example, the string "asdf@asdf.com" should not match "@asdf" as a username. | ||||
|      * | ||||
|      * @protected | ||||
|      * @property {RegExp} nonWordCharRegex | ||||
|      */ | ||||
|     protected nonWordCharRegex: RegExp; | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} cfg The configuration properties for the Match instance, | ||||
|      *   specified in an Object (map). | ||||
|      */ | ||||
|     constructor(cfg: HashtagMatcherConfig); | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     parseMatches(text: string): Match[]; | ||||
| } | ||||
| export interface HashtagMatcherConfig extends MatcherConfig { | ||||
|     serviceName: HashtagServices; | ||||
| } | ||||
							
								
								
									
										83
									
								
								src/modules/autolinker/matcher/hashtag-matcher.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								src/modules/autolinker/matcher/hashtag-matcher.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| import * as tslib_1 from "tslib"; | ||||
| import { Matcher } from "./matcher"; | ||||
| import { alphaNumericAndMarksCharsStr } from "../regex-lib"; | ||||
| import { HashtagMatch } from "../match/hashtag-match"; | ||||
| // RegExp objects which are shared by all instances of HashtagMatcher. These are | ||||
| // here to avoid re-instantiating the RegExp objects if `Autolinker.link()` is | ||||
| // called multiple times, thus instantiating HashtagMatcher and its RegExp  | ||||
| // objects each time (which is very expensive - see https://github.com/gregjacobs/Autolinker.js/issues/314).  | ||||
| // See descriptions of the properties where they are used for details about them | ||||
| var matcherRegex = new RegExp("#[_" + alphaNumericAndMarksCharsStr + "]{1,139}(?![_" + alphaNumericAndMarksCharsStr + "])", 'g'); // lookahead used to make sure we don't match something above 139 characters | ||||
| var nonWordCharRegex = new RegExp('[^' + alphaNumericAndMarksCharsStr + ']'); | ||||
| /** | ||||
|  * @class Autolinker.matcher.Hashtag | ||||
|  * @extends Autolinker.matcher.Matcher | ||||
|  * | ||||
|  * Matcher to find HashtagMatch matches in an input string. | ||||
|  */ | ||||
| var HashtagMatcher = /** @class */ (function (_super) { | ||||
|     tslib_1.__extends(HashtagMatcher, _super); | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} cfg The configuration properties for the Match instance, | ||||
|      *   specified in an Object (map). | ||||
|      */ | ||||
|     function HashtagMatcher(cfg) { | ||||
|         var _this = _super.call(this, cfg) || this; | ||||
|         /** | ||||
|          * @cfg {String} serviceName | ||||
|          * | ||||
|          * The service to point hashtag matches to. See {@link Autolinker#hashtag} | ||||
|          * for available values. | ||||
|          */ | ||||
|         _this.serviceName = 'twitter'; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * The regular expression to match Hashtags. Example match: | ||||
|          * | ||||
|          *     #asdf | ||||
|          * | ||||
|          * @protected | ||||
|          * @property {RegExp} matcherRegex | ||||
|          */ | ||||
|         _this.matcherRegex = matcherRegex; | ||||
|         /** | ||||
|          * The regular expression to use to check the character before a username match to | ||||
|          * make sure we didn't accidentally match an email address. | ||||
|          * | ||||
|          * For example, the string "asdf@asdf.com" should not match "@asdf" as a username. | ||||
|          * | ||||
|          * @protected | ||||
|          * @property {RegExp} nonWordCharRegex | ||||
|          */ | ||||
|         _this.nonWordCharRegex = nonWordCharRegex; | ||||
|         _this.serviceName = cfg.serviceName; | ||||
|         return _this; | ||||
|     } | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     HashtagMatcher.prototype.parseMatches = function (text) { | ||||
|         var matcherRegex = this.matcherRegex, nonWordCharRegex = this.nonWordCharRegex, serviceName = this.serviceName, tagBuilder = this.tagBuilder, matches = [], match; | ||||
|         while ((match = matcherRegex.exec(text)) !== null) { | ||||
|             var offset = match.index, prevChar = text.charAt(offset - 1); | ||||
|             // If we found the match at the beginning of the string, or we found the match | ||||
|             // and there is a whitespace char in front of it (meaning it is not a '#' char | ||||
|             // in the middle of a word), then it is a hashtag match. | ||||
|             if (offset === 0 || nonWordCharRegex.test(prevChar)) { | ||||
|                 var matchedText = match[0], hashtag = match[0].slice(1); // strip off the '#' character at the beginning | ||||
|                 matches.push(new HashtagMatch({ | ||||
|                     tagBuilder: tagBuilder, | ||||
|                     matchedText: matchedText, | ||||
|                     offset: offset, | ||||
|                     serviceName: serviceName, | ||||
|                     hashtag: hashtag | ||||
|                 })); | ||||
|             } | ||||
|         } | ||||
|         return matches; | ||||
|     }; | ||||
|     return HashtagMatcher; | ||||
| }(Matcher)); | ||||
| export { HashtagMatcher }; | ||||
|  | ||||
| //# sourceMappingURL=hashtag-matcher.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/matcher/hashtag-matcher.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/matcher/hashtag-matcher.js.map
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										6
									
								
								src/modules/autolinker/matcher/index.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/modules/autolinker/matcher/index.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| export * from './email-matcher'; | ||||
| export * from './hashtag-matcher'; | ||||
| export * from './matcher'; | ||||
| export * from './mention-matcher'; | ||||
| export * from './phone-matcher'; | ||||
| export * from './url-matcher'; | ||||
							
								
								
									
										8
									
								
								src/modules/autolinker/matcher/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/modules/autolinker/matcher/index.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| export * from './email-matcher'; | ||||
| export * from './hashtag-matcher'; | ||||
| export * from './matcher'; | ||||
| export * from './mention-matcher'; | ||||
| export * from './phone-matcher'; | ||||
| export * from './url-matcher'; | ||||
|  | ||||
| //# sourceMappingURL=index.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/matcher/index.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/matcher/index.js.map
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| {"version":3,"sources":["../src/matcher/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC","file":"index.js","sourcesContent":["export * from './email-matcher';\nexport * from './hashtag-matcher';\nexport * from './matcher';\nexport * from './mention-matcher';\nexport * from './phone-matcher';\nexport * from './url-matcher';\n"]} | ||||
							
								
								
									
										40
									
								
								src/modules/autolinker/matcher/matcher.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/modules/autolinker/matcher/matcher.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| import { AnchorTagBuilder } from "../anchor-tag-builder"; | ||||
| import { Match } from "../match/match"; | ||||
| /** | ||||
|  * @abstract | ||||
|  * @class Autolinker.matcher.Matcher | ||||
|  * | ||||
|  * An abstract class and interface for individual matchers to find matches in | ||||
|  * an input string with linkified versions of them. | ||||
|  * | ||||
|  * Note that Matchers do not take HTML into account - they must be fed the text | ||||
|  * nodes of any HTML string, which is handled by {@link Autolinker#parse}. | ||||
|  */ | ||||
| export declare abstract class Matcher { | ||||
|     /** | ||||
|      * @cfg {Autolinker.AnchorTagBuilder} tagBuilder (required) | ||||
|      * | ||||
|      * Reference to the AnchorTagBuilder instance to use to generate HTML tags | ||||
|      * for {@link Autolinker.match.Match Matches}. | ||||
|      */ | ||||
|     private __jsduckDummyDocProp; | ||||
|     protected tagBuilder: AnchorTagBuilder; | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} cfg The configuration properties for the Matcher | ||||
|      *   instance, specified in an Object (map). | ||||
|      */ | ||||
|     constructor(cfg: MatcherConfig); | ||||
|     /** | ||||
|      * Parses the input `text` and returns the array of {@link Autolinker.match.Match Matches} | ||||
|      * for the matcher. | ||||
|      * | ||||
|      * @abstract | ||||
|      * @param {String} text The text to scan and replace matches in. | ||||
|      * @return {Autolinker.match.Match[]} | ||||
|      */ | ||||
|     abstract parseMatches(text: string): Match[]; | ||||
| } | ||||
| export interface MatcherConfig { | ||||
|     tagBuilder: AnchorTagBuilder; | ||||
| } | ||||
							
								
								
									
										31
									
								
								src/modules/autolinker/matcher/matcher.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/modules/autolinker/matcher/matcher.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| /** | ||||
|  * @abstract | ||||
|  * @class Autolinker.matcher.Matcher | ||||
|  * | ||||
|  * An abstract class and interface for individual matchers to find matches in | ||||
|  * an input string with linkified versions of them. | ||||
|  * | ||||
|  * Note that Matchers do not take HTML into account - they must be fed the text | ||||
|  * nodes of any HTML string, which is handled by {@link Autolinker#parse}. | ||||
|  */ | ||||
| var Matcher = /** @class */ (function () { | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} cfg The configuration properties for the Matcher | ||||
|      *   instance, specified in an Object (map). | ||||
|      */ | ||||
|     function Matcher(cfg) { | ||||
|         /** | ||||
|          * @cfg {Autolinker.AnchorTagBuilder} tagBuilder (required) | ||||
|          * | ||||
|          * Reference to the AnchorTagBuilder instance to use to generate HTML tags | ||||
|          * for {@link Autolinker.match.Match Matches}. | ||||
|          */ | ||||
|         this.__jsduckDummyDocProp = null; // property used just to get the above doc comment into the ES5 output and documentation generator | ||||
|         this.tagBuilder = cfg.tagBuilder; | ||||
|     } | ||||
|     return Matcher; | ||||
| }()); | ||||
| export { Matcher }; | ||||
|  | ||||
| //# sourceMappingURL=matcher.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/matcher/matcher.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/matcher/matcher.js.map
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| {"version":3,"sources":["../src/matcher/matcher.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH;IAcC;;;;OAIG;IACH,iBAAa,GAAkB;QAjB/B;;;;;WAKG;QACK,yBAAoB,GAAG,IAAI,CAAC,CAAE,kGAAkG;QAYvI,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC;IAClC,CAAC;IAaF,cAAC;AAAD,CAlCA,AAkCC,IAAA","file":"matcher.js","sourcesContent":["import { AnchorTagBuilder } from \"../anchor-tag-builder\";\nimport { Match } from \"../match/match\";\n\n/**\n * @abstract\n * @class Autolinker.matcher.Matcher\n *\n * An abstract class and interface for individual matchers to find matches in\n * an input string with linkified versions of them.\n *\n * Note that Matchers do not take HTML into account - they must be fed the text\n * nodes of any HTML string, which is handled by {@link Autolinker#parse}.\n */\nexport abstract class Matcher {\n\n\t/**\n\t * @cfg {Autolinker.AnchorTagBuilder} tagBuilder (required)\n\t *\n\t * Reference to the AnchorTagBuilder instance to use to generate HTML tags\n\t * for {@link Autolinker.match.Match Matches}.\n\t */\n\tprivate __jsduckDummyDocProp = null;  // property used just to get the above doc comment into the ES5 output and documentation generator\n\n\t// Actual property for the above jsdoc comment\n\tprotected tagBuilder: AnchorTagBuilder;\n\n\n\t/**\n\t * @method constructor\n\t * @param {Object} cfg The configuration properties for the Matcher\n\t *   instance, specified in an Object (map).\n\t */\n\tconstructor( cfg: MatcherConfig ) {\n\t\tthis.tagBuilder = cfg.tagBuilder;\n\t}\n\n\n\t/**\n\t * Parses the input `text` and returns the array of {@link Autolinker.match.Match Matches}\n\t * for the matcher.\n\t *\n\t * @abstract\n\t * @param {String} text The text to scan and replace matches in.\n\t * @return {Autolinker.match.Match[]}\n\t */\n\tabstract parseMatches( text: string ): Match[];\n\n}\n\nexport interface MatcherConfig {\n\ttagBuilder: AnchorTagBuilder;\n}"]} | ||||
							
								
								
									
										53
									
								
								src/modules/autolinker/matcher/mention-matcher.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/modules/autolinker/matcher/mention-matcher.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| import { Matcher, MatcherConfig } from "./matcher"; | ||||
| import { MentionServices } from "../autolinker"; | ||||
| import { Match } from "../match/match"; | ||||
| /** | ||||
|  * @class Autolinker.matcher.Mention | ||||
|  * @extends Autolinker.matcher.Matcher | ||||
|  * | ||||
|  * Matcher to find/replace username matches in an input string. | ||||
|  */ | ||||
| export declare class MentionMatcher extends Matcher { | ||||
|     /** | ||||
|      * @cfg {'twitter'/'instagram'/'soundcloud'} protected | ||||
|      * | ||||
|      * The name of service to link @mentions to. | ||||
|      * | ||||
|      * Valid values are: 'twitter', 'instagram', or 'soundcloud' | ||||
|      */ | ||||
|     protected serviceName: MentionServices; | ||||
|     /** | ||||
|      * Hash of regular expression to match username handles. Example match: | ||||
|      * | ||||
|      *     @asdf | ||||
|      * | ||||
|      * @private | ||||
|      * @property {Object} matcherRegexes | ||||
|      */ | ||||
|     protected readonly matcherRegexes: { | ||||
|         [key: string]: RegExp; | ||||
|     }; | ||||
|     /** | ||||
|      * The regular expression to use to check the character before a username match to | ||||
|      * make sure we didn't accidentally match an email address. | ||||
|      * | ||||
|      * For example, the string "asdf@asdf.com" should not match "@asdf" as a username. | ||||
|      * | ||||
|      * @private | ||||
|      * @property {RegExp} nonWordCharRegex | ||||
|      */ | ||||
|     protected readonly nonWordCharRegex: RegExp; | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} cfg The configuration properties for the Match instance, | ||||
|      *   specified in an Object (map). | ||||
|      */ | ||||
|     constructor(cfg: MentionMatcherConfig); | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     parseMatches(text: string): Match[]; | ||||
| } | ||||
| export interface MentionMatcherConfig extends MatcherConfig { | ||||
|     serviceName: MentionServices; | ||||
| } | ||||
							
								
								
									
										96
									
								
								src/modules/autolinker/matcher/mention-matcher.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								src/modules/autolinker/matcher/mention-matcher.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | ||||
| import * as tslib_1 from "tslib"; | ||||
| import { Matcher } from "./matcher"; | ||||
| import { alphaNumericAndMarksCharsStr } from "../regex-lib"; | ||||
| import { MentionMatch } from "../match/mention-match"; | ||||
| // RegExp objects which are shared by all instances of MentionMatcher. These are | ||||
| // here to avoid re-instantiating the RegExp objects if `Autolinker.link()` is | ||||
| // called multiple times, thus instantiating MentionMatcher and its RegExp  | ||||
| // objects each time (which is very expensive - see https://github.com/gregjacobs/Autolinker.js/issues/314).  | ||||
| // See descriptions of the properties where they are used for details about them | ||||
| var mastodonRegex = new RegExp("@[_@." + alphaNumericAndMarksCharsStr + "]{1,}(?![_" + alphaNumericAndMarksCharsStr + "])", 'g'); | ||||
| var twitterRegex = new RegExp("@[_" + alphaNumericAndMarksCharsStr + "]{1,50}(?![_" + alphaNumericAndMarksCharsStr + "])", 'g'); // lookahead used to make sure we don't match something above 50 characters | ||||
| var instagramRegex = new RegExp("@[_." + alphaNumericAndMarksCharsStr + "]{1,30}(?![_" + alphaNumericAndMarksCharsStr + "])", 'g'); // lookahead used to make sure we don't match something above 30 characters | ||||
| var soundcloudRegex = new RegExp("@[-_." + alphaNumericAndMarksCharsStr + "]{1,50}(?![-_" + alphaNumericAndMarksCharsStr + "])", 'g'); // lookahead used to make sure we don't match something above 50 characters | ||||
| var nonWordCharRegex = new RegExp('[^' + alphaNumericAndMarksCharsStr + ']'); | ||||
| /** | ||||
|  * @class Autolinker.matcher.Mention | ||||
|  * @extends Autolinker.matcher.Matcher | ||||
|  * | ||||
|  * Matcher to find/replace username matches in an input string. | ||||
|  */ | ||||
| var MentionMatcher = /** @class */ (function (_super) { | ||||
|     tslib_1.__extends(MentionMatcher, _super); | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} cfg The configuration properties for the Match instance, | ||||
|      *   specified in an Object (map). | ||||
|      */ | ||||
|     function MentionMatcher(cfg) { | ||||
|         var _this = _super.call(this, cfg) || this; | ||||
|         /** | ||||
|          * @cfg {'twitter'/'instagram'/'soundcloud'} protected | ||||
|          * | ||||
|          * The name of service to link @mentions to. | ||||
|          * | ||||
|          * Valid values are: 'twitter', 'instagram', or 'soundcloud' | ||||
|          */ | ||||
|         _this.serviceName = 'mastodon'; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * Hash of regular expression to match username handles. Example match: | ||||
|          * | ||||
|          *     @asdf | ||||
|          * | ||||
|          * @private | ||||
|          * @property {Object} matcherRegexes | ||||
|          */ | ||||
|         _this.matcherRegexes = { | ||||
|             'mastodon': mastodonRegex, | ||||
|             'twitter': twitterRegex, | ||||
|             'instagram': instagramRegex, | ||||
|             'soundcloud': soundcloudRegex | ||||
|         }; | ||||
|         /** | ||||
|          * The regular expression to use to check the character before a username match to | ||||
|          * make sure we didn't accidentally match an email address. | ||||
|          * | ||||
|          * For example, the string "asdf@asdf.com" should not match "@asdf" as a username. | ||||
|          * | ||||
|          * @private | ||||
|          * @property {RegExp} nonWordCharRegex | ||||
|          */ | ||||
|         _this.nonWordCharRegex = nonWordCharRegex; | ||||
|         _this.serviceName = cfg.serviceName; | ||||
|         return _this; | ||||
|     } | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     MentionMatcher.prototype.parseMatches = function (text) { | ||||
|         var serviceName = this.serviceName, matcherRegex = this.matcherRegexes[this.serviceName], nonWordCharRegex = this.nonWordCharRegex, tagBuilder = this.tagBuilder, matches = [], match; | ||||
|         if (!matcherRegex) { | ||||
|             return matches; | ||||
|         } | ||||
|         while ((match = matcherRegex.exec(text)) !== null) { | ||||
|             var offset = match.index, prevChar = text.charAt(offset - 1); | ||||
|             // If we found the match at the beginning of the string, or we found the match | ||||
|             // and there is a whitespace char in front of it (meaning it is not an email | ||||
|             // address), then it is a username match. | ||||
|             if (offset === 0 || nonWordCharRegex.test(prevChar)) { | ||||
|                 var matchedText = match[0].replace(/\.+$/g, ''), // strip off trailing . | ||||
|                 mention = matchedText.slice(1); // strip off the '@' character at the beginning | ||||
|                 matches.push(new MentionMatch({ | ||||
|                     tagBuilder: tagBuilder, | ||||
|                     matchedText: matchedText, | ||||
|                     offset: offset, | ||||
|                     serviceName: serviceName, | ||||
|                     mention: mention | ||||
|                 })); | ||||
|             } | ||||
|         } | ||||
|         return matches; | ||||
|     }; | ||||
|     return MentionMatcher; | ||||
| }(Matcher)); | ||||
| export { MentionMatcher }; | ||||
|  | ||||
| //# sourceMappingURL=mention-matcher.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/matcher/mention-matcher.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/matcher/mention-matcher.js.map
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										37
									
								
								src/modules/autolinker/matcher/phone-matcher.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/modules/autolinker/matcher/phone-matcher.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| import { Matcher } from "./matcher"; | ||||
| import { Match } from "../match/match"; | ||||
| /** | ||||
|  * @class Autolinker.matcher.Phone | ||||
|  * @extends Autolinker.matcher.Matcher | ||||
|  * | ||||
|  * Matcher to find Phone number matches in an input string. | ||||
|  * | ||||
|  * See this class's superclass ({@link Autolinker.matcher.Matcher}) for more | ||||
|  * details. | ||||
|  */ | ||||
| export declare class PhoneMatcher extends Matcher { | ||||
|     /** | ||||
|      * The regular expression to match Phone numbers. Example matches: | ||||
|      * | ||||
|      *     (123) 456-7890 | ||||
|      *     123 456 7890 | ||||
|      *     123-456-7890 | ||||
|      *     +18004441234,,;,10226420346# | ||||
|      *     +1 (800) 444 1234 | ||||
|      *     10226420346# | ||||
|      *     1-800-444-1234,1022,64,20346# | ||||
|      * | ||||
|      * This regular expression has the following capturing groups: | ||||
|      * | ||||
|      * 1 or 2. The prefixed '+' sign, if there is one. | ||||
|      * | ||||
|      * @protected | ||||
|      * @property {RegExp} matcherRegex | ||||
|      */ | ||||
|     protected matcherRegex: RegExp; | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     parseMatches(text: string): Match[]; | ||||
|     protected testMatch(text: string): boolean; | ||||
| } | ||||
							
								
								
									
										74
									
								
								src/modules/autolinker/matcher/phone-matcher.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								src/modules/autolinker/matcher/phone-matcher.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| import * as tslib_1 from "tslib"; | ||||
| import { Matcher } from "./matcher"; | ||||
| import { PhoneMatch } from "../match/phone-match"; | ||||
| import { nonDigitRe } from '../regex-lib'; | ||||
| // RegExp objects which are shared by all instances of PhoneMatcher. These are | ||||
| // here to avoid re-instantiating the RegExp objects if `Autolinker.link()` is | ||||
| // called multiple times, thus instantiating PhoneMatcher and its RegExp  | ||||
| // objects each time (which is very expensive - see https://github.com/gregjacobs/Autolinker.js/issues/314).  | ||||
| // See descriptions of the properties where they are used for details about them | ||||
| var phoneMatcherRegex = /(?:(?:(?:(\+)?\d{1,3}[-\040.]?)?\(?\d{3}\)?[-\040.]?\d{3}[-\040.]?\d{4})|(?:(\+)(?:9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)[-\040.]?(?:\d[-\040.]?){6,12}\d+))([,;]+[0-9]+#?)*/g; | ||||
| /** | ||||
|  * @class Autolinker.matcher.Phone | ||||
|  * @extends Autolinker.matcher.Matcher | ||||
|  * | ||||
|  * Matcher to find Phone number matches in an input string. | ||||
|  * | ||||
|  * See this class's superclass ({@link Autolinker.matcher.Matcher}) for more | ||||
|  * details. | ||||
|  */ | ||||
| var PhoneMatcher = /** @class */ (function (_super) { | ||||
|     tslib_1.__extends(PhoneMatcher, _super); | ||||
|     function PhoneMatcher() { | ||||
|         var _this = _super !== null && _super.apply(this, arguments) || this; | ||||
|         /** | ||||
|          * The regular expression to match Phone numbers. Example matches: | ||||
|          * | ||||
|          *     (123) 456-7890 | ||||
|          *     123 456 7890 | ||||
|          *     123-456-7890 | ||||
|          *     +18004441234,,;,10226420346# | ||||
|          *     +1 (800) 444 1234 | ||||
|          *     10226420346# | ||||
|          *     1-800-444-1234,1022,64,20346# | ||||
|          * | ||||
|          * This regular expression has the following capturing groups: | ||||
|          * | ||||
|          * 1 or 2. The prefixed '+' sign, if there is one. | ||||
|          * | ||||
|          * @protected | ||||
|          * @property {RegExp} matcherRegex | ||||
|          */ | ||||
|         _this.matcherRegex = phoneMatcherRegex; | ||||
|         return _this; | ||||
|     } | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     PhoneMatcher.prototype.parseMatches = function (text) { | ||||
|         var matcherRegex = this.matcherRegex, tagBuilder = this.tagBuilder, matches = [], match; | ||||
|         while ((match = matcherRegex.exec(text)) !== null) { | ||||
|             // Remove non-numeric values from phone number string | ||||
|             var matchedText = match[0], cleanNumber = matchedText.replace(/[^0-9,;#]/g, ''), // strip out non-digit characters exclude comma semicolon and # | ||||
|             plusSign = !!(match[1] || match[2]), // match[ 1 ] or match[ 2 ] is the prefixed plus sign, if there is one | ||||
|             before = match.index == 0 ? '' : text.substr(match.index - 1, 1), after = text.substr(match.index + matchedText.length, 1), contextClear = !before.match(/\d/) && !after.match(/\d/); | ||||
|             if (this.testMatch(match[3]) && this.testMatch(matchedText) && contextClear) { | ||||
|                 matches.push(new PhoneMatch({ | ||||
|                     tagBuilder: tagBuilder, | ||||
|                     matchedText: matchedText, | ||||
|                     offset: match.index, | ||||
|                     number: cleanNumber, | ||||
|                     plusSign: plusSign | ||||
|                 })); | ||||
|             } | ||||
|         } | ||||
|         return matches; | ||||
|     }; | ||||
|     PhoneMatcher.prototype.testMatch = function (text) { | ||||
|         return nonDigitRe.test(text); | ||||
|     }; | ||||
|     return PhoneMatcher; | ||||
| }(Matcher)); | ||||
| export { PhoneMatcher }; | ||||
|  | ||||
| //# sourceMappingURL=phone-matcher.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/matcher/phone-matcher.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/matcher/phone-matcher.js.map
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| {"version":3,"sources":["../src/matcher/phone-matcher.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,8EAA8E;AAC9E,8EAA8E;AAC9E,yEAAyE;AACzE,6GAA6G;AAC7G,gFAAgF;AAChF,IAAM,iBAAiB,GAAG,uRAAuR,CAAC;AAElT;;;;;;;;GAQG;AACH;IAAkC,wCAAO;IAAzC;QAAA,qEA2DC;QAzDA;;;;;;;;;;;;;;;;;WAiBG;QACO,kBAAY,GAAG,iBAAiB,CAAC;;IAuC5C,CAAC;IArCA;;OAEG;IACH,mCAAY,GAAZ,UAAc,IAAY;QACzB,IAAI,YAAY,GAAG,IAAI,CAAC,YAAY,EACnC,UAAU,GAAG,IAAI,CAAC,UAAU,EAC5B,OAAO,GAAY,EAAE,EACrB,KAA6B,CAAC;QAE/B,OAAO,CAAE,KAAK,GAAG,YAAY,CAAC,IAAI,CAAE,IAAI,CAAE,CAAE,KAAK,IAAI,EAAG;YACvD,qDAAqD;YACrD,IAAI,WAAW,GAAG,KAAK,CAAE,CAAC,CAAE,EAC3B,WAAW,GAAG,WAAW,CAAC,OAAO,CAAE,YAAY,EAAE,EAAE,CAAE,EAAE,+DAA+D;YACtH,QAAQ,GAAG,CAAC,CAAC,CAAE,KAAK,CAAE,CAAC,CAAE,IAAI,KAAK,CAAE,CAAC,CAAE,CAAE,EAAE,sEAAsE;YACjH,MAAM,GAAG,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAE,KAAK,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC,CAAE,EAClE,KAAK,GAAG,IAAI,CAAC,MAAM,CAAE,KAAK,CAAC,KAAK,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,CAAE,EAC1D,YAAY,GAAG,CAAC,MAAM,CAAC,KAAK,CAAE,IAAI,CAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAE,IAAI,CAAE,CAAC;YAE9D,IAAI,IAAI,CAAC,SAAS,CAAE,KAAK,CAAE,CAAC,CAAE,CAAE,IAAI,IAAI,CAAC,SAAS,CAAE,WAAW,CAAE,IAAI,YAAY,EAAG;gBACnF,OAAO,CAAC,IAAI,CAAE,IAAI,UAAU,CAAE;oBAC7B,UAAU,EAAE,UAAU;oBACtB,WAAW,EAAE,WAAW;oBACxB,MAAM,EAAE,KAAK,CAAC,KAAK;oBACnB,MAAM,EAAE,WAAW;oBACnB,QAAQ,EAAE,QAAQ;iBAClB,CAAE,CAAE,CAAC;aACN;SACD;QAED,OAAO,OAAO,CAAC;IAChB,CAAC;IAGS,gCAAS,GAAnB,UAAqB,IAAY;QAChC,OAAO,UAAU,CAAC,IAAI,CAAE,IAAI,CAAE,CAAC;IAChC,CAAC;IAEF,mBAAC;AAAD,CA3DA,AA2DC,CA3DiC,OAAO,GA2DxC","file":"phone-matcher.js","sourcesContent":["import { Matcher } from \"./matcher\";\nimport { PhoneMatch } from \"../match/phone-match\";\nimport { Match } from \"../match/match\";\nimport { nonDigitRe } from '../regex-lib';\n\n// RegExp objects which are shared by all instances of PhoneMatcher. These are\n// here to avoid re-instantiating the RegExp objects if `Autolinker.link()` is\n// called multiple times, thus instantiating PhoneMatcher and its RegExp \n// objects each time (which is very expensive - see https://github.com/gregjacobs/Autolinker.js/issues/314). \n// See descriptions of the properties where they are used for details about them\nconst phoneMatcherRegex = /(?:(?:(?:(\\+)?\\d{1,3}[-\\040.]?)?\\(?\\d{3}\\)?[-\\040.]?\\d{3}[-\\040.]?\\d{4})|(?:(\\+)(?:9[976]\\d|8[987530]\\d|6[987]\\d|5[90]\\d|42\\d|3[875]\\d|2[98654321]\\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)[-\\040.]?(?:\\d[-\\040.]?){6,12}\\d+))([,;]+[0-9]+#?)*/g;\n\n/**\n * @class Autolinker.matcher.Phone\n * @extends Autolinker.matcher.Matcher\n *\n * Matcher to find Phone number matches in an input string.\n *\n * See this class's superclass ({@link Autolinker.matcher.Matcher}) for more\n * details.\n */\nexport class PhoneMatcher extends Matcher {\n\n\t/**\n\t * The regular expression to match Phone numbers. Example matches:\n\t *\n\t *     (123) 456-7890\n\t *     123 456 7890\n\t *     123-456-7890\n\t *     +18004441234,,;,10226420346#\n\t *     +1 (800) 444 1234\n\t *     10226420346#\n\t *     1-800-444-1234,1022,64,20346#\n\t *\n\t * This regular expression has the following capturing groups:\n\t *\n\t * 1 or 2. The prefixed '+' sign, if there is one.\n\t *\n\t * @protected\n\t * @property {RegExp} matcherRegex\n\t */\n\tprotected matcherRegex = phoneMatcherRegex;\n\n\t/**\n\t * @inheritdoc\n\t */\n\tparseMatches( text: string ) {\n\t\tlet matcherRegex = this.matcherRegex,\n\t\t\ttagBuilder = this.tagBuilder,\n\t\t\tmatches: Match[] = [],\n\t\t\tmatch: RegExpExecArray | null;\n\n\t\twhile( ( match = matcherRegex.exec( text ) ) !== null ) {\n\t\t\t// Remove non-numeric values from phone number string\n\t\t\tvar matchedText = match[ 0 ],\n\t\t\t\tcleanNumber = matchedText.replace( /[^0-9,;#]/g, '' ), // strip out non-digit characters exclude comma semicolon and #\n\t\t\t\tplusSign = !!( match[ 1 ] || match[ 2 ] ), // match[ 1 ] or match[ 2 ] is the prefixed plus sign, if there is one\n\t\t\t\tbefore = match.index == 0 ? '' : text.substr( match.index - 1, 1 ),\n\t\t\t\tafter = text.substr( match.index + matchedText.length, 1 ),\n\t\t\t\tcontextClear = !before.match( /\\d/ ) && !after.match( /\\d/ );\n\n\t\t\tif( this.testMatch( match[ 3 ] ) && this.testMatch( matchedText ) && contextClear ) {\n\t\t\t\tmatches.push( new PhoneMatch( {\n\t\t\t\t\ttagBuilder: tagBuilder,\n\t\t\t\t\tmatchedText: matchedText,\n\t\t\t\t\toffset: match.index,\n\t\t\t\t\tnumber: cleanNumber,\n\t\t\t\t\tplusSign: plusSign\n\t\t\t\t} ) );\n\t\t\t}\n\t\t}\n\n\t\treturn matches;\n\t}\n\n\n\tprotected testMatch( text: string ) {\n\t\treturn nonDigitRe.test( text );\n\t}\n\n}\n"]} | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/matcher/tld-regex.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/matcher/tld-regex.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| export declare const tldRegex: RegExp; | ||||
							
								
								
									
										5
									
								
								src/modules/autolinker/matcher/tld-regex.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/modules/autolinker/matcher/tld-regex.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								src/modules/autolinker/matcher/tld-regex.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/matcher/tld-regex.js.map
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										127
									
								
								src/modules/autolinker/matcher/url-match-validator.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								src/modules/autolinker/matcher/url-match-validator.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,127 @@ | ||||
| /** | ||||
|  * @private | ||||
|  * @class Autolinker.matcher.UrlMatchValidator | ||||
|  * @singleton | ||||
|  * | ||||
|  * Used by Autolinker to filter out false URL positives from the | ||||
|  * {@link Autolinker.matcher.Url UrlMatcher}. | ||||
|  * | ||||
|  * Due to the limitations of regular expressions (including the missing feature | ||||
|  * of look-behinds in JS regular expressions), we cannot always determine the | ||||
|  * validity of a given match. This class applies a bit of additional logic to | ||||
|  * filter out any false positives that have been matched by the | ||||
|  * {@link Autolinker.matcher.Url UrlMatcher}. | ||||
|  */ | ||||
| export declare class UrlMatchValidator { | ||||
|     /** | ||||
|      * Regex to test for a full protocol, with the two trailing slashes. Ex: 'http://' | ||||
|      * | ||||
|      * @private | ||||
|      * @property {RegExp} hasFullProtocolRegex | ||||
|      */ | ||||
|     static hasFullProtocolRegex: RegExp; | ||||
|     /** | ||||
|      * Regex to find the URI scheme, such as 'mailto:'. | ||||
|      * | ||||
|      * This is used to filter out 'javascript:' and 'vbscript:' schemes. | ||||
|      * | ||||
|      * @private | ||||
|      * @property {RegExp} uriSchemeRegex | ||||
|      */ | ||||
|     static uriSchemeRegex: RegExp; | ||||
|     /** | ||||
|      * Regex to determine if at least one word char exists after the protocol (i.e. after the ':') | ||||
|      * | ||||
|      * @private | ||||
|      * @property {RegExp} hasWordCharAfterProtocolRegex | ||||
|      */ | ||||
|     static hasWordCharAfterProtocolRegex: RegExp; | ||||
|     /** | ||||
|      * Regex to determine if the string is a valid IP address | ||||
|      * | ||||
|      * @private | ||||
|      * @property {RegExp} ipRegex | ||||
|      */ | ||||
|     static ipRegex: RegExp; | ||||
|     /** | ||||
|      * Determines if a given URL match found by the {@link Autolinker.matcher.Url UrlMatcher} | ||||
|      * is valid. Will return `false` for: | ||||
|      * | ||||
|      * 1) URL matches which do not have at least have one period ('.') in the | ||||
|      *    domain name (effectively skipping over matches like "abc:def"). | ||||
|      *    However, URL matches with a protocol will be allowed (ex: 'http://localhost') | ||||
|      * 2) URL matches which do not have at least one word character in the | ||||
|      *    domain name (effectively skipping over matches like "git:1.0"). | ||||
|      *    However, URL matches with a protocol will be allowed (ex: 'intra-net://271219.76') | ||||
|      * 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`. | ||||
|      * | ||||
|      * @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} protocolUrlMatch The match URL string for a protocol | ||||
|      *   match. Ex: 'http://yahoo.com'. This is used to match something like | ||||
|      *   'http://localhost', where we won't double check that the domain name | ||||
|      *   has at least one '.' in it. | ||||
|      * @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. | ||||
|      */ | ||||
|     static isValid(urlMatch: string, protocolUrlMatch: string): boolean; | ||||
|     static isValidIpAddress(uriSchemeMatch: string): boolean; | ||||
|     private static containsMultipleDots; | ||||
|     /** | ||||
|      * Determines if the URI scheme is a valid scheme to be autolinked. Returns | ||||
|      * `false` if the scheme is 'javascript:' or 'vbscript:' | ||||
|      * | ||||
|      * @private | ||||
|      * @param {String} uriSchemeMatch The match URL string for a full URI scheme | ||||
|      *   match. Ex: 'http://yahoo.com' or 'mailto:a@a.com'. | ||||
|      * @return {Boolean} `true` if the scheme is a valid one, `false` otherwise. | ||||
|      */ | ||||
|     static isValidUriScheme(uriSchemeMatch: string): boolean; | ||||
|     /** | ||||
|      * Determines if a URL match does not have either: | ||||
|      * | ||||
|      * a) a full protocol (i.e. 'http://'), or | ||||
|      * b) at least one dot ('.') in the domain name (for a non-full-protocol | ||||
|      *    match). | ||||
|      * | ||||
|      * Either situation is considered an invalid URL (ex: 'git:d' does not have | ||||
|      * either the '://' part, or at least one dot in the domain name. If the | ||||
|      * match was 'git:abc.com', we would consider this valid.) | ||||
|      * | ||||
|      * @private | ||||
|      * @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} protocolUrlMatch The match URL string for a protocol | ||||
|      *   match. Ex: 'http://yahoo.com'. This is used to match something like | ||||
|      *   'http://localhost', where we won't double check that the domain name | ||||
|      *   has at least one '.' in it. | ||||
|      * @return {Boolean} `true` if the URL match does not have a full protocol, | ||||
|      *   or at least one dot ('.') in a non-full-protocol match. | ||||
|      */ | ||||
|     static urlMatchDoesNotHaveProtocolOrDot(urlMatch: string, protocolUrlMatch: string): boolean; | ||||
|     /** | ||||
|      * Determines if a URL match does not have either: | ||||
|      * | ||||
|      * a) a full protocol (i.e. 'http://'), or | ||||
|      * b) at least one word character after the protocol (i.e. in the domain name) | ||||
|      * | ||||
|      * At least one letter character must exist in the domain name after a | ||||
|      * protocol match. Ex: skip over something like "git:1.0" | ||||
|      * | ||||
|      * @private | ||||
|      * @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} protocolUrlMatch The match URL string for a protocol | ||||
|      *   match. Ex: 'http://yahoo.com'. This is used to know whether or not we | ||||
|      *   have a protocol in the URL string, in order to check for a word | ||||
|      *   character after the protocol separator (':'). | ||||
|      * @return {Boolean} `true` if the URL match does not have a full protocol, or | ||||
|      * at least one word character in it, `false` otherwise. | ||||
|      */ | ||||
|     static urlMatchDoesNotHaveAtLeastOneWordChar(urlMatch: string, protocolUrlMatch: string): boolean; | ||||
| } | ||||
							
								
								
									
										165
									
								
								src/modules/autolinker/matcher/url-match-validator.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								src/modules/autolinker/matcher/url-match-validator.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,165 @@ | ||||
| import { alphaCharsStr } from "../regex-lib"; | ||||
| /** | ||||
|  * @private | ||||
|  * @class Autolinker.matcher.UrlMatchValidator | ||||
|  * @singleton | ||||
|  * | ||||
|  * Used by Autolinker to filter out false URL positives from the | ||||
|  * {@link Autolinker.matcher.Url UrlMatcher}. | ||||
|  * | ||||
|  * Due to the limitations of regular expressions (including the missing feature | ||||
|  * of look-behinds in JS regular expressions), we cannot always determine the | ||||
|  * validity of a given match. This class applies a bit of additional logic to | ||||
|  * filter out any false positives that have been matched by the | ||||
|  * {@link Autolinker.matcher.Url UrlMatcher}. | ||||
|  */ | ||||
| var UrlMatchValidator = /** @class */ (function () { | ||||
|     function UrlMatchValidator() { | ||||
|     } | ||||
|     /** | ||||
|      * Determines if a given URL match found by the {@link Autolinker.matcher.Url UrlMatcher} | ||||
|      * is valid. Will return `false` for: | ||||
|      * | ||||
|      * 1) URL matches which do not have at least have one period ('.') in the | ||||
|      *    domain name (effectively skipping over matches like "abc:def"). | ||||
|      *    However, URL matches with a protocol will be allowed (ex: 'http://localhost') | ||||
|      * 2) URL matches which do not have at least one word character in the | ||||
|      *    domain name (effectively skipping over matches like "git:1.0"). | ||||
|      *    However, URL matches with a protocol will be allowed (ex: 'intra-net://271219.76') | ||||
|      * 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`. | ||||
|      * | ||||
|      * @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} protocolUrlMatch The match URL string for a protocol | ||||
|      *   match. Ex: 'http://yahoo.com'. This is used to match something like | ||||
|      *   'http://localhost', where we won't double check that the domain name | ||||
|      *   has at least one '.' in it. | ||||
|      * @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. | ||||
|      */ | ||||
|     UrlMatchValidator.isValid = function (urlMatch, protocolUrlMatch) { | ||||
|         if ((protocolUrlMatch && !this.isValidUriScheme(protocolUrlMatch)) || | ||||
|             this.urlMatchDoesNotHaveProtocolOrDot(urlMatch, protocolUrlMatch) || // At least one period ('.') must exist in the URL match for us to consider it an actual URL, *unless* it was a full protocol match (like 'http://localhost') | ||||
|             (this.urlMatchDoesNotHaveAtLeastOneWordChar(urlMatch, protocolUrlMatch) && // At least one letter character must exist in the domain name after a protocol match. Ex: skip over something like "git:1.0" | ||||
|                 !this.isValidIpAddress(urlMatch)) || // Except if it's an IP address | ||||
|             this.containsMultipleDots(urlMatch)) { | ||||
|             return false; | ||||
|         } | ||||
|         return true; | ||||
|     }; | ||||
|     UrlMatchValidator.isValidIpAddress = function (uriSchemeMatch) { | ||||
|         var newRegex = new RegExp(this.hasFullProtocolRegex.source + this.ipRegex.source); | ||||
|         var uriScheme = uriSchemeMatch.match(newRegex); | ||||
|         return uriScheme !== null; | ||||
|     }; | ||||
|     UrlMatchValidator.containsMultipleDots = function (urlMatch) { | ||||
|         var stringBeforeSlash = urlMatch; | ||||
|         if (this.hasFullProtocolRegex.test(urlMatch)) { | ||||
|             stringBeforeSlash = urlMatch.split('://')[1]; | ||||
|         } | ||||
|         return stringBeforeSlash.split('/')[0].indexOf("..") > -1; | ||||
|     }; | ||||
|     /** | ||||
|      * Determines if the URI scheme is a valid scheme to be autolinked. Returns | ||||
|      * `false` if the scheme is 'javascript:' or 'vbscript:' | ||||
|      * | ||||
|      * @private | ||||
|      * @param {String} uriSchemeMatch The match URL string for a full URI scheme | ||||
|      *   match. Ex: 'http://yahoo.com' or 'mailto:a@a.com'. | ||||
|      * @return {Boolean} `true` if the scheme is a valid one, `false` otherwise. | ||||
|      */ | ||||
|     UrlMatchValidator.isValidUriScheme = function (uriSchemeMatch) { | ||||
|         var uriSchemeMatchArr = uriSchemeMatch.match(this.uriSchemeRegex), uriScheme = uriSchemeMatchArr && uriSchemeMatchArr[0].toLowerCase(); | ||||
|         return (uriScheme !== 'javascript:' && uriScheme !== 'vbscript:'); | ||||
|     }; | ||||
|     /** | ||||
|      * Determines if a URL match does not have either: | ||||
|      * | ||||
|      * a) a full protocol (i.e. 'http://'), or | ||||
|      * b) at least one dot ('.') in the domain name (for a non-full-protocol | ||||
|      *    match). | ||||
|      * | ||||
|      * Either situation is considered an invalid URL (ex: 'git:d' does not have | ||||
|      * either the '://' part, or at least one dot in the domain name. If the | ||||
|      * match was 'git:abc.com', we would consider this valid.) | ||||
|      * | ||||
|      * @private | ||||
|      * @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} protocolUrlMatch The match URL string for a protocol | ||||
|      *   match. Ex: 'http://yahoo.com'. This is used to match something like | ||||
|      *   'http://localhost', where we won't double check that the domain name | ||||
|      *   has at least one '.' in it. | ||||
|      * @return {Boolean} `true` if the URL match does not have a full protocol, | ||||
|      *   or at least one dot ('.') in a non-full-protocol match. | ||||
|      */ | ||||
|     UrlMatchValidator.urlMatchDoesNotHaveProtocolOrDot = function (urlMatch, protocolUrlMatch) { | ||||
|         return (!!urlMatch && (!protocolUrlMatch || !this.hasFullProtocolRegex.test(protocolUrlMatch)) && urlMatch.indexOf('.') === -1); | ||||
|     }; | ||||
|     /** | ||||
|      * Determines if a URL match does not have either: | ||||
|      * | ||||
|      * a) a full protocol (i.e. 'http://'), or | ||||
|      * b) at least one word character after the protocol (i.e. in the domain name) | ||||
|      * | ||||
|      * At least one letter character must exist in the domain name after a | ||||
|      * protocol match. Ex: skip over something like "git:1.0" | ||||
|      * | ||||
|      * @private | ||||
|      * @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} protocolUrlMatch The match URL string for a protocol | ||||
|      *   match. Ex: 'http://yahoo.com'. This is used to know whether or not we | ||||
|      *   have a protocol in the URL string, in order to check for a word | ||||
|      *   character after the protocol separator (':'). | ||||
|      * @return {Boolean} `true` if the URL match does not have a full protocol, or | ||||
|      * at least one word character in it, `false` otherwise. | ||||
|      */ | ||||
|     UrlMatchValidator.urlMatchDoesNotHaveAtLeastOneWordChar = function (urlMatch, protocolUrlMatch) { | ||||
|         if (urlMatch && protocolUrlMatch) { | ||||
|             return !this.hasFullProtocolRegex.test(protocolUrlMatch) && !this.hasWordCharAfterProtocolRegex.test(urlMatch); | ||||
|         } | ||||
|         else { | ||||
|             return false; | ||||
|         } | ||||
|     }; | ||||
|     /** | ||||
|      * Regex to test for a full protocol, with the two trailing slashes. Ex: 'http://' | ||||
|      * | ||||
|      * @private | ||||
|      * @property {RegExp} hasFullProtocolRegex | ||||
|      */ | ||||
|     UrlMatchValidator.hasFullProtocolRegex = /^[A-Za-z][-.+A-Za-z0-9]*:\/\//; | ||||
|     /** | ||||
|      * Regex to find the URI scheme, such as 'mailto:'. | ||||
|      * | ||||
|      * This is used to filter out 'javascript:' and 'vbscript:' schemes. | ||||
|      * | ||||
|      * @private | ||||
|      * @property {RegExp} uriSchemeRegex | ||||
|      */ | ||||
|     UrlMatchValidator.uriSchemeRegex = /^[A-Za-z][-.+A-Za-z0-9]*:/; | ||||
|     /** | ||||
|      * Regex to determine if at least one word char exists after the protocol (i.e. after the ':') | ||||
|      * | ||||
|      * @private | ||||
|      * @property {RegExp} hasWordCharAfterProtocolRegex | ||||
|      */ | ||||
|     UrlMatchValidator.hasWordCharAfterProtocolRegex = new RegExp(":[^\\s]*?[" + alphaCharsStr + "]"); | ||||
|     /** | ||||
|      * Regex to determine if the string is a valid IP address | ||||
|      * | ||||
|      * @private | ||||
|      * @property {RegExp} ipRegex | ||||
|      */ | ||||
|     UrlMatchValidator.ipRegex = /[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?(:[0-9]*)?\/?$/; | ||||
|     return UrlMatchValidator; | ||||
| }()); | ||||
| export { UrlMatchValidator }; | ||||
|  | ||||
| //# sourceMappingURL=url-match-validator.js.map | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										136
									
								
								src/modules/autolinker/matcher/url-matcher.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								src/modules/autolinker/matcher/url-matcher.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,136 @@ | ||||
| import { Matcher, MatcherConfig } from "./matcher"; | ||||
| import { StripPrefixConfigObj } from "../autolinker"; | ||||
| import { Match } from "../match/match"; | ||||
| /** | ||||
|  * @class Autolinker.matcher.Url | ||||
|  * @extends Autolinker.matcher.Matcher | ||||
|  * | ||||
|  * Matcher to find URL matches in an input string. | ||||
|  * | ||||
|  * See this class's superclass ({@link Autolinker.matcher.Matcher}) for more details. | ||||
|  */ | ||||
| export declare class UrlMatcher extends Matcher { | ||||
|     /** | ||||
|      * @cfg {Object} stripPrefix (required) | ||||
|      * | ||||
|      * The Object form of {@link Autolinker#cfg-stripPrefix}. | ||||
|      */ | ||||
|     protected stripPrefix: Required<StripPrefixConfigObj>; | ||||
|     /** | ||||
|      * @cfg {Boolean} stripTrailingSlash (required) | ||||
|      * @inheritdoc Autolinker#stripTrailingSlash | ||||
|      */ | ||||
|     protected stripTrailingSlash: boolean; | ||||
|     /** | ||||
|      * @cfg {Boolean} decodePercentEncoding (required) | ||||
|      * @inheritdoc Autolinker#decodePercentEncoding | ||||
|      */ | ||||
|     protected decodePercentEncoding: boolean; | ||||
|     /** | ||||
|      * @protected | ||||
|      * @property {RegExp} matcherRegex | ||||
|      * | ||||
|      * The regular expression to match URLs with an optional scheme, port | ||||
|      * number, path, query string, and hash anchor. | ||||
|      * | ||||
|      * Example matches: | ||||
|      * | ||||
|      *     http://google.com | ||||
|      *     www.google.com | ||||
|      *     google.com/path/to/file?q1=1&q2=2#myAnchor | ||||
|      * | ||||
|      * | ||||
|      * This regular expression will have the following capturing groups: | ||||
|      * | ||||
|      * 1.  Group that matches a scheme-prefixed URL (i.e. 'http://google.com'). | ||||
|      *     This is used to match scheme URLs with just a single word, such as | ||||
|      *     'http://localhost', where we won't double check that the domain name | ||||
|      *     has at least one dot ('.') in it. | ||||
|      * 2.  Group that matches a 'www.' prefixed URL. This is only matched if the | ||||
|      *     'www.' text was not prefixed by a scheme (i.e.: not prefixed by | ||||
|      *     'http://', 'ftp:', etc.) | ||||
|      * 3.  A protocol-relative ('//') match for the case of a 'www.' prefixed | ||||
|      *     URL. Will be an empty string if it is not a protocol-relative match. | ||||
|      *     We need to know the character before the '//' in order to determine | ||||
|      *     if it is a valid match or the // was in a string we don't want to | ||||
|      *     auto-link. | ||||
|      * 4.  Group that matches a known TLD (top level domain), when a scheme | ||||
|      *     or 'www.'-prefixed domain is not matched. | ||||
|      * 5.  A protocol-relative ('//') match for the case of a known TLD prefixed | ||||
|      *     URL. Will be an empty string if it is not a protocol-relative match. | ||||
|      *     See #3 for more info. | ||||
|      */ | ||||
|     protected matcherRegex: RegExp; | ||||
|     /** | ||||
|      * A regular expression to use to check the character before a protocol-relative | ||||
|      * URL match. We don't want to match a protocol-relative URL if it is part | ||||
|      * of another word. | ||||
|      * | ||||
|      * For example, we want to match something like "Go to: //google.com", | ||||
|      * but we don't want to match something like "abc//google.com" | ||||
|      * | ||||
|      * This regular expression is used to test the character before the '//'. | ||||
|      * | ||||
|      * @protected | ||||
|      * @type {RegExp} wordCharRegExp | ||||
|      */ | ||||
|     protected wordCharRegExp: RegExp; | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} cfg The configuration properties for the Match instance, | ||||
|      *   specified in an Object (map). | ||||
|      */ | ||||
|     constructor(cfg: UrlMatcherConfig); | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     parseMatches(text: string): Match[]; | ||||
|     /** | ||||
|      * Determines if a match found has an unmatched closing parenthesis, | ||||
|      * square bracket or curly bracket. If so, the symbol will be removed | ||||
|      * from the match itself, and appended after the generated anchor tag. | ||||
|      * | ||||
|      * A match may have an extra closing parenthesis at the end of the match | ||||
|      * because the regular expression must include parenthesis for URLs such as | ||||
|      * "wikipedia.com/something_(disambiguation)", which should be auto-linked. | ||||
|      * | ||||
|      * However, an extra parenthesis *will* be included when the URL itself is | ||||
|      * wrapped in parenthesis, such as in the case of: | ||||
|      *     "(wikipedia.com/something_(disambiguation))" | ||||
|      * In this case, the last closing parenthesis should *not* be part of the | ||||
|      * URL itself, and this method will return `true`. | ||||
|      * | ||||
|      * For square brackets in URLs such as in PHP arrays, the same behavior as | ||||
|      * parenthesis discussed above should happen: | ||||
|      *     "[http://www.example.com/foo.php?bar[]=1&bar[]=2&bar[]=3]" | ||||
|      * The closing square bracket should not be part of the URL itself, and this | ||||
|      * method will return `true`. | ||||
|      * | ||||
|      * @protected | ||||
|      * @param {String} matchStr The full match string from the {@link #matcherRegex}. | ||||
|      * @return {Boolean} `true` if there is an unbalanced closing parenthesis or | ||||
|      *   square bracket at the end of the `matchStr`, `false` otherwise. | ||||
|      */ | ||||
|     protected matchHasUnbalancedClosingParen(matchStr: string): boolean; | ||||
|     /** | ||||
|      * Determine if there's an invalid character after the TLD in a URL. Valid | ||||
|      * characters after TLD are ':/?#'. Exclude scheme matched URLs from this | ||||
|      * check. | ||||
|      * | ||||
|      * @protected | ||||
|      * @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} schemeUrlMatch The match URL string for a scheme | ||||
|      *   match. Ex: 'http://yahoo.com'. This is used to match something like | ||||
|      *   'http://localhost', where we won't double check that the domain name | ||||
|      *   has at least one '.' in it. | ||||
|      * @return {Number} the position where the invalid character was found. If | ||||
|      *   no such character was found, returns -1 | ||||
|      */ | ||||
|     protected matchHasInvalidCharAfterTld(urlMatch: string, schemeUrlMatch: string): number; | ||||
| } | ||||
| export interface UrlMatcherConfig extends MatcherConfig { | ||||
|     stripPrefix: Required<StripPrefixConfigObj>; | ||||
|     stripTrailingSlash: boolean; | ||||
|     decodePercentEncoding: boolean; | ||||
| } | ||||
							
								
								
									
										312
									
								
								src/modules/autolinker/matcher/url-matcher.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										312
									
								
								src/modules/autolinker/matcher/url-matcher.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,312 @@ | ||||
| import * as tslib_1 from "tslib"; | ||||
| import { Matcher } from "./matcher"; | ||||
| import { alphaNumericCharsStr, alphaNumericAndMarksCharsStr, getDomainNameStr } from "../regex-lib"; | ||||
| import { tldRegex } from "./tld-regex"; | ||||
| import { UrlMatch } from "../match/url-match"; | ||||
| import { UrlMatchValidator } from "./url-match-validator"; | ||||
| // RegExp objects which are shared by all instances of UrlMatcher. These are | ||||
| // here to avoid re-instantiating the RegExp objects if `Autolinker.link()` is | ||||
| // called multiple times, thus instantiating UrlMatcher and its RegExp  | ||||
| // objects each time (which is very expensive - see https://github.com/gregjacobs/Autolinker.js/issues/314).  | ||||
| // See descriptions of the properties where they are used for details about them | ||||
| var matcherRegex = (function () { | ||||
|     var schemeRegex = /(?:[A-Za-z][-.+A-Za-z0-9]{0,63}:(?![A-Za-z][-.+A-Za-z0-9]{0,63}:\/\/)(?!\d+\/?)(?:\/\/)?)/, // match protocol, allow in format "http://" or "mailto:". However, do not match the first part of something like 'link:http://www.google.com' (i.e. don't match "link:"). Also, make sure we don't interpret 'google.com:8000' as if 'google.com' was a protocol here (i.e. ignore a trailing port number in this regex) | ||||
|     wwwRegex = /(?:www\.)/, // starting with 'www.' | ||||
|     // Allow optional path, query string, and hash anchor, not ending in the following characters: "?!:,.;" | ||||
|     // http://blog.codinghorror.com/the-problem-with-urls/ | ||||
|     urlSuffixRegex = new RegExp('[/?#](?:[' + alphaNumericAndMarksCharsStr + '\\-+&@#/%=~_()|\'$*\\[\\]{}?!:,.;^\u2713]*[' + alphaNumericAndMarksCharsStr + '\\-+&@#/%=~_()|\'$*\\[\\]{}\u2713])?'); | ||||
|     return new RegExp([ | ||||
|         '(?:', | ||||
|         '(', | ||||
|         schemeRegex.source, | ||||
|         getDomainNameStr(2), | ||||
|         ')', | ||||
|         '|', | ||||
|         '(', | ||||
|         '(//)?', | ||||
|         wwwRegex.source, | ||||
|         getDomainNameStr(6), | ||||
|         ')', | ||||
|         '|', | ||||
|         '(', | ||||
|         '(//)?', | ||||
|         getDomainNameStr(10) + '\\.', | ||||
|         tldRegex.source, | ||||
|         '(?![-' + alphaNumericCharsStr + '])', | ||||
|         ')', | ||||
|         ')', | ||||
|         '(?::[0-9]+)?', | ||||
|         '(?:' + urlSuffixRegex.source + ')?' // match for path, query string, and/or hash anchor - optional | ||||
|     ].join(""), 'gi'); | ||||
| })(); | ||||
| var wordCharRegExp = new RegExp('[' + alphaNumericAndMarksCharsStr + ']'); | ||||
| /** | ||||
|  * @class Autolinker.matcher.Url | ||||
|  * @extends Autolinker.matcher.Matcher | ||||
|  * | ||||
|  * Matcher to find URL matches in an input string. | ||||
|  * | ||||
|  * See this class's superclass ({@link Autolinker.matcher.Matcher}) for more details. | ||||
|  */ | ||||
| var UrlMatcher = /** @class */ (function (_super) { | ||||
|     tslib_1.__extends(UrlMatcher, _super); | ||||
|     /** | ||||
|      * @method constructor | ||||
|      * @param {Object} cfg The configuration properties for the Match instance, | ||||
|      *   specified in an Object (map). | ||||
|      */ | ||||
|     function UrlMatcher(cfg) { | ||||
|         var _this = _super.call(this, cfg) || this; | ||||
|         /** | ||||
|          * @cfg {Object} stripPrefix (required) | ||||
|          * | ||||
|          * The Object form of {@link Autolinker#cfg-stripPrefix}. | ||||
|          */ | ||||
|         _this.stripPrefix = { scheme: true, www: true }; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {Boolean} stripTrailingSlash (required) | ||||
|          * @inheritdoc Autolinker#stripTrailingSlash | ||||
|          */ | ||||
|         _this.stripTrailingSlash = true; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @cfg {Boolean} decodePercentEncoding (required) | ||||
|          * @inheritdoc Autolinker#decodePercentEncoding | ||||
|          */ | ||||
|         _this.decodePercentEncoding = true; // default value just to get the above doc comment in the ES5 output and documentation generator | ||||
|         /** | ||||
|          * @protected | ||||
|          * @property {RegExp} matcherRegex | ||||
|          * | ||||
|          * The regular expression to match URLs with an optional scheme, port | ||||
|          * number, path, query string, and hash anchor. | ||||
|          * | ||||
|          * Example matches: | ||||
|          * | ||||
|          *     http://google.com | ||||
|          *     www.google.com | ||||
|          *     google.com/path/to/file?q1=1&q2=2#myAnchor | ||||
|          * | ||||
|          * | ||||
|          * This regular expression will have the following capturing groups: | ||||
|          * | ||||
|          * 1.  Group that matches a scheme-prefixed URL (i.e. 'http://google.com'). | ||||
|          *     This is used to match scheme URLs with just a single word, such as | ||||
|          *     'http://localhost', where we won't double check that the domain name | ||||
|          *     has at least one dot ('.') in it. | ||||
|          * 2.  Group that matches a 'www.' prefixed URL. This is only matched if the | ||||
|          *     'www.' text was not prefixed by a scheme (i.e.: not prefixed by | ||||
|          *     'http://', 'ftp:', etc.) | ||||
|          * 3.  A protocol-relative ('//') match for the case of a 'www.' prefixed | ||||
|          *     URL. Will be an empty string if it is not a protocol-relative match. | ||||
|          *     We need to know the character before the '//' in order to determine | ||||
|          *     if it is a valid match or the // was in a string we don't want to | ||||
|          *     auto-link. | ||||
|          * 4.  Group that matches a known TLD (top level domain), when a scheme | ||||
|          *     or 'www.'-prefixed domain is not matched. | ||||
|          * 5.  A protocol-relative ('//') match for the case of a known TLD prefixed | ||||
|          *     URL. Will be an empty string if it is not a protocol-relative match. | ||||
|          *     See #3 for more info. | ||||
|          */ | ||||
|         _this.matcherRegex = matcherRegex; | ||||
|         /** | ||||
|          * A regular expression to use to check the character before a protocol-relative | ||||
|          * URL match. We don't want to match a protocol-relative URL if it is part | ||||
|          * of another word. | ||||
|          * | ||||
|          * For example, we want to match something like "Go to: //google.com", | ||||
|          * but we don't want to match something like "abc//google.com" | ||||
|          * | ||||
|          * This regular expression is used to test the character before the '//'. | ||||
|          * | ||||
|          * @protected | ||||
|          * @type {RegExp} wordCharRegExp | ||||
|          */ | ||||
|         _this.wordCharRegExp = wordCharRegExp; | ||||
|         _this.stripPrefix = cfg.stripPrefix; | ||||
|         _this.stripTrailingSlash = cfg.stripTrailingSlash; | ||||
|         _this.decodePercentEncoding = cfg.decodePercentEncoding; | ||||
|         return _this; | ||||
|     } | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     UrlMatcher.prototype.parseMatches = function (text) { | ||||
|         var matcherRegex = this.matcherRegex, stripPrefix = this.stripPrefix, stripTrailingSlash = this.stripTrailingSlash, decodePercentEncoding = this.decodePercentEncoding, tagBuilder = this.tagBuilder, matches = [], match; | ||||
|         var _loop_1 = function () { | ||||
|             var matchStr = match[0], schemeUrlMatch = match[1], wwwUrlMatch = match[4], wwwProtocolRelativeMatch = match[5],  | ||||
|             //tldUrlMatch = match[ 8 ],  -- not needed at the moment | ||||
|             tldProtocolRelativeMatch = match[9], offset = match.index, protocolRelativeMatch = wwwProtocolRelativeMatch || tldProtocolRelativeMatch, prevChar = text.charAt(offset - 1); | ||||
|             if (!UrlMatchValidator.isValid(matchStr, schemeUrlMatch)) { | ||||
|                 return "continue"; | ||||
|             } | ||||
|             // If the match is preceded by an '@' character, then it is either | ||||
|             // an email address or a username. Skip these types of matches. | ||||
|             if (offset > 0 && prevChar === '@') { | ||||
|                 return "continue"; | ||||
|             } | ||||
|             // If it's a protocol-relative '//' match, but the character before the '//' | ||||
|             // was a word character (i.e. a letter/number), then we found the '//' in the | ||||
|             // middle of another word (such as "asdf//asdf.com"). In this case, skip the | ||||
|             // match. | ||||
|             if (offset > 0 && protocolRelativeMatch && this_1.wordCharRegExp.test(prevChar)) { | ||||
|                 return "continue"; | ||||
|             } | ||||
|             // If the URL ends with a question mark, don't include the question | ||||
|             // mark as part of the URL. We'll assume the question mark was the | ||||
|             // end of a sentence, such as: "Going to google.com?" | ||||
|             if (/\?$/.test(matchStr)) { | ||||
|                 matchStr = matchStr.substr(0, matchStr.length - 1); | ||||
|             } | ||||
|             // Handle a closing parenthesis or square bracket at the end of the  | ||||
|             // match, and exclude it if there is not a matching open parenthesis  | ||||
|             // or square bracket in the match itself. | ||||
|             if (this_1.matchHasUnbalancedClosingParen(matchStr)) { | ||||
|                 matchStr = matchStr.substr(0, matchStr.length - 1); // remove the trailing ")" | ||||
|             } | ||||
|             else { | ||||
|                 // Handle an invalid character after the TLD | ||||
|                 var pos = this_1.matchHasInvalidCharAfterTld(matchStr, schemeUrlMatch); | ||||
|                 if (pos > -1) { | ||||
|                     matchStr = matchStr.substr(0, pos); // remove the trailing invalid chars | ||||
|                 } | ||||
|             } | ||||
|             // The autolinker accepts many characters in a url's scheme (like `fake://test.com`). | ||||
|             // However, in cases where a URL is missing whitespace before an obvious link, | ||||
|             // (for example: `nowhitespacehttp://www.test.com`), we only want the match to start | ||||
|             // at the http:// part. We will check if the match contains a common scheme and then  | ||||
|             // shift the match to start from there. 		 | ||||
|             var foundCommonScheme = ['http://', 'https://'].find(function (commonScheme) { return !!schemeUrlMatch && schemeUrlMatch.indexOf(commonScheme) !== -1; }); | ||||
|             if (foundCommonScheme) { | ||||
|                 // If we found an overmatched URL, we want to find the index | ||||
|                 // of where the match should start and shift the match to | ||||
|                 // start from the beginning of the common scheme | ||||
|                 var indexOfSchemeStart = matchStr.indexOf(foundCommonScheme); | ||||
|                 matchStr = matchStr.substr(indexOfSchemeStart); | ||||
|                 schemeUrlMatch = schemeUrlMatch.substr(indexOfSchemeStart); | ||||
|                 offset = offset + indexOfSchemeStart; | ||||
|             } | ||||
|             var urlMatchType = schemeUrlMatch ? 'scheme' : (wwwUrlMatch ? 'www' : 'tld'), protocolUrlMatch = !!schemeUrlMatch; | ||||
|             matches.push(new UrlMatch({ | ||||
|                 tagBuilder: tagBuilder, | ||||
|                 matchedText: matchStr, | ||||
|                 offset: offset, | ||||
|                 urlMatchType: urlMatchType, | ||||
|                 url: matchStr, | ||||
|                 protocolUrlMatch: protocolUrlMatch, | ||||
|                 protocolRelativeMatch: !!protocolRelativeMatch, | ||||
|                 stripPrefix: stripPrefix, | ||||
|                 stripTrailingSlash: stripTrailingSlash, | ||||
|                 decodePercentEncoding: decodePercentEncoding, | ||||
|             })); | ||||
|         }; | ||||
|         var this_1 = this; | ||||
|         while ((match = matcherRegex.exec(text)) !== null) { | ||||
|             _loop_1(); | ||||
|         } | ||||
|         return matches; | ||||
|     }; | ||||
|     /** | ||||
|      * Determines if a match found has an unmatched closing parenthesis, | ||||
|      * square bracket or curly bracket. If so, the symbol will be removed | ||||
|      * from the match itself, and appended after the generated anchor tag. | ||||
|      * | ||||
|      * A match may have an extra closing parenthesis at the end of the match | ||||
|      * because the regular expression must include parenthesis for URLs such as | ||||
|      * "wikipedia.com/something_(disambiguation)", which should be auto-linked. | ||||
|      * | ||||
|      * However, an extra parenthesis *will* be included when the URL itself is | ||||
|      * wrapped in parenthesis, such as in the case of: | ||||
|      *     "(wikipedia.com/something_(disambiguation))" | ||||
|      * In this case, the last closing parenthesis should *not* be part of the | ||||
|      * URL itself, and this method will return `true`. | ||||
|      * | ||||
|      * For square brackets in URLs such as in PHP arrays, the same behavior as | ||||
|      * parenthesis discussed above should happen: | ||||
|      *     "[http://www.example.com/foo.php?bar[]=1&bar[]=2&bar[]=3]" | ||||
|      * The closing square bracket should not be part of the URL itself, and this | ||||
|      * method will return `true`. | ||||
|      * | ||||
|      * @protected | ||||
|      * @param {String} matchStr The full match string from the {@link #matcherRegex}. | ||||
|      * @return {Boolean} `true` if there is an unbalanced closing parenthesis or | ||||
|      *   square bracket at the end of the `matchStr`, `false` otherwise. | ||||
|      */ | ||||
|     UrlMatcher.prototype.matchHasUnbalancedClosingParen = function (matchStr) { | ||||
|         var endChar = matchStr.charAt(matchStr.length - 1); | ||||
|         var startChar; | ||||
|         if (endChar === ')') { | ||||
|             startChar = '('; | ||||
|         } | ||||
|         else if (endChar === ']') { | ||||
|             startChar = '['; | ||||
|         } | ||||
|         else if (endChar === '}') { | ||||
|             startChar = '{'; | ||||
|         } | ||||
|         else { | ||||
|             return false; // not a close parenthesis or square bracket | ||||
|         } | ||||
|         // Find if there are the same number of open braces as close braces in | ||||
|         // the URL string, minus the last character (which we have already  | ||||
|         // determined to be either ')', ']' or '}' | ||||
|         var numOpenBraces = 0; | ||||
|         for (var i = 0, len = matchStr.length - 1; i < len; i++) { | ||||
|             var char = matchStr.charAt(i); | ||||
|             if (char === startChar) { | ||||
|                 numOpenBraces++; | ||||
|             } | ||||
|             else if (char === endChar) { | ||||
|                 numOpenBraces = Math.max(numOpenBraces - 1, 0); | ||||
|             } | ||||
|         } | ||||
|         // If the number of open braces matches the number of close braces in | ||||
|         // the URL minus the last character, then the match has *unbalanced* | ||||
|         // braces because of the last character. Example of unbalanced braces | ||||
|         // from the regex match: | ||||
|         //     "http://example.com?a[]=1]" | ||||
|         if (numOpenBraces === 0) { | ||||
|             return true; | ||||
|         } | ||||
|         return false; | ||||
|     }; | ||||
|     /** | ||||
|      * Determine if there's an invalid character after the TLD in a URL. Valid | ||||
|      * characters after TLD are ':/?#'. Exclude scheme matched URLs from this | ||||
|      * check. | ||||
|      * | ||||
|      * @protected | ||||
|      * @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} schemeUrlMatch The match URL string for a scheme | ||||
|      *   match. Ex: 'http://yahoo.com'. This is used to match something like | ||||
|      *   'http://localhost', where we won't double check that the domain name | ||||
|      *   has at least one '.' in it. | ||||
|      * @return {Number} the position where the invalid character was found. If | ||||
|      *   no such character was found, returns -1 | ||||
|      */ | ||||
|     UrlMatcher.prototype.matchHasInvalidCharAfterTld = function (urlMatch, schemeUrlMatch) { | ||||
|         if (!urlMatch) { | ||||
|             return -1; | ||||
|         } | ||||
|         var offset = 0; | ||||
|         if (schemeUrlMatch) { | ||||
|             offset = urlMatch.indexOf(':'); | ||||
|             urlMatch = urlMatch.slice(offset); | ||||
|         } | ||||
|         var re = new RegExp("^((.?\/\/)?[-." + alphaNumericAndMarksCharsStr + "]*[-" + alphaNumericAndMarksCharsStr + "]\\.[-" + alphaNumericAndMarksCharsStr + "]+)"); | ||||
|         var res = re.exec(urlMatch); | ||||
|         if (res === null) { | ||||
|             return -1; | ||||
|         } | ||||
|         offset += res[1].length; | ||||
|         urlMatch = urlMatch.slice(res[1].length); | ||||
|         if (/^[^-.A-Za-z0-9:\/?#]/.test(urlMatch)) { | ||||
|             return offset; | ||||
|         } | ||||
|         return -1; | ||||
|     }; | ||||
|     return UrlMatcher; | ||||
| }(Matcher)); | ||||
| export { UrlMatcher }; | ||||
|  | ||||
| //# sourceMappingURL=url-matcher.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/matcher/url-matcher.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/matcher/url-matcher.js.map
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										147
									
								
								src/modules/autolinker/regex-lib.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								src/modules/autolinker/regex-lib.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,147 @@ | ||||
| /** | ||||
|  * Regular expression to match upper and lowercase ASCII letters | ||||
|  */ | ||||
| export declare const letterRe: RegExp; | ||||
| /** | ||||
|  * Regular expression to match ASCII digits | ||||
|  */ | ||||
| export declare const digitRe: RegExp; | ||||
| /** | ||||
|  * Regular expression to match everything *except* ASCII digits | ||||
|  */ | ||||
| export declare const nonDigitRe: RegExp; | ||||
| /** | ||||
|  * Regular expression to match whitespace | ||||
|  */ | ||||
| export declare const whitespaceRe: RegExp; | ||||
| /** | ||||
|  * Regular expression to match quote characters | ||||
|  */ | ||||
| export declare const quoteRe: RegExp; | ||||
| /** | ||||
|  * Regular expression to match the range of ASCII control characters (0-31), and | ||||
|  * the backspace char (127) | ||||
|  */ | ||||
| export declare const controlCharsRe: RegExp; | ||||
| /** | ||||
|  * The string form of a regular expression that would match all of the | ||||
|  * alphabetic ("letter") chars in the unicode character set when placed in a | ||||
|  * RegExp character class (`[]`). This includes all international alphabetic | ||||
|  * characters. | ||||
|  * | ||||
|  * These would be the characters matched by unicode regex engines `\p{L}` | ||||
|  * escape ("all letters"). | ||||
|  * | ||||
|  * Taken from the XRegExp library: http://xregexp.com/ (thanks @https://github.com/slevithan) | ||||
|  * Specifically: http://xregexp.com/v/3.2.0/xregexp-all.js, the 'Letter' | ||||
|  *   regex's bmp | ||||
|  * | ||||
|  * VERY IMPORTANT: This set of characters is defined inside of a Regular | ||||
|  *   Expression literal rather than a string literal to prevent UglifyJS from | ||||
|  *   compressing the unicode escape sequences into their actual unicode | ||||
|  *   characters. If Uglify compresses these into the unicode characters | ||||
|  *   themselves, this results in the error "Range out of order in character | ||||
|  *   class" when these characters are used inside of a Regular Expression | ||||
|  *   character class (`[]`). See usages of this const. Alternatively, we can set | ||||
|  *   the UglifyJS option `ascii_only` to true for the build, but that doesn't | ||||
|  *   help others who are pulling in Autolinker into their own build and running | ||||
|  *   UglifyJS themselves. | ||||
|  */ | ||||
| export declare const alphaCharsStr: string; | ||||
| /** | ||||
|  * The string form of a regular expression that would match all emoji characters | ||||
|  * Based on the emoji regex defined in this article: https://thekevinscott.com/emojis-in-javascript/ | ||||
|  */ | ||||
| export declare const emojiStr: string; | ||||
| /** | ||||
|  * The string form of a regular expression that would match all of the | ||||
|  * combining mark characters in the unicode character set when placed in a | ||||
|  * RegExp character class (`[]`). | ||||
|  * | ||||
|  * These would be the characters matched by unicode regex engines `\p{M}` | ||||
|  * escape ("all marks"). | ||||
|  * | ||||
|  * Taken from the XRegExp library: http://xregexp.com/ (thanks @https://github.com/slevithan) | ||||
|  * Specifically: http://xregexp.com/v/3.2.0/xregexp-all.js, the 'Mark' | ||||
|  *   regex's bmp | ||||
|  * | ||||
|  * VERY IMPORTANT: This set of characters is defined inside of a Regular | ||||
|  *   Expression literal rather than a string literal to prevent UglifyJS from | ||||
|  *   compressing the unicode escape sequences into their actual unicode | ||||
|  *   characters. If Uglify compresses these into the unicode characters | ||||
|  *   themselves, this results in the error "Range out of order in character | ||||
|  *   class" when these characters are used inside of a Regular Expression | ||||
|  *   character class (`[]`). See usages of this const. Alternatively, we can set | ||||
|  *   the UglifyJS option `ascii_only` to true for the build, but that doesn't | ||||
|  *   help others who are pulling in Autolinker into their own build and running | ||||
|  *   UglifyJS themselves. | ||||
|  */ | ||||
| export declare const marksStr: string; | ||||
| /** | ||||
|  * The string form of a regular expression that would match all of the | ||||
|  * alphabetic ("letter") chars, emoji, and combining marks in the unicode character set | ||||
|  * when placed in a RegExp character class (`[]`). This includes all | ||||
|  * international alphabetic characters. | ||||
|  * | ||||
|  * These would be the characters matched by unicode regex engines `\p{L}\p{M}` | ||||
|  * escapes and emoji characters. | ||||
|  */ | ||||
| export declare const alphaCharsAndMarksStr: string; | ||||
| /** | ||||
|  * The string form of a regular expression that would match all of the | ||||
|  * decimal number chars in the unicode character set when placed in a RegExp | ||||
|  * character class (`[]`). | ||||
|  * | ||||
|  * These would be the characters matched by unicode regex engines `\p{Nd}` | ||||
|  * escape ("all decimal numbers") | ||||
|  * | ||||
|  * Taken from the XRegExp library: http://xregexp.com/ (thanks @https://github.com/slevithan) | ||||
|  * Specifically: http://xregexp.com/v/3.2.0/xregexp-all.js, the 'Decimal_Number' | ||||
|  *   regex's bmp | ||||
|  * | ||||
|  * VERY IMPORTANT: This set of characters is defined inside of a Regular | ||||
|  *   Expression literal rather than a string literal to prevent UglifyJS from | ||||
|  *   compressing the unicode escape sequences into their actual unicode | ||||
|  *   characters. If Uglify compresses these into the unicode characters | ||||
|  *   themselves, this results in the error "Range out of order in character | ||||
|  *   class" when these characters are used inside of a Regular Expression | ||||
|  *   character class (`[]`). See usages of this const. Alternatively, we can set | ||||
|  *   the UglifyJS option `ascii_only` to true for the build, but that doesn't | ||||
|  *   help others who are pulling in Autolinker into their own build and running | ||||
|  *   UglifyJS themselves. | ||||
|  */ | ||||
| export declare const decimalNumbersStr: string; | ||||
| /** | ||||
|  * The string form of a regular expression that would match all of the | ||||
|  * letters and decimal number chars in the unicode character set when placed in | ||||
|  * a RegExp character class (`[]`). | ||||
|  * | ||||
|  * These would be the characters matched by unicode regex engines | ||||
|  * `[\p{L}\p{Nd}]` escape ("all letters and decimal numbers") | ||||
|  */ | ||||
| export declare const alphaNumericCharsStr: string; | ||||
| /** | ||||
|  * 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 when placed in a RegExp character class (`[]`). | ||||
|  * | ||||
|  * These would be the characters matched by unicode regex engines | ||||
|  * `[\p{L}\p{M}\p{Nd}]` escape ("all letters, combining marks, and decimal | ||||
|  * numbers") | ||||
|  */ | ||||
| export declare const alphaNumericAndMarksCharsStr: string; | ||||
| /** | ||||
|  * A function to match domain names of a URL or email address. | ||||
|  * Ex: 'google', 'yahoo', 'some-other-company', etc. | ||||
|  */ | ||||
| export declare const getDomainNameStr: (group: number) => string; | ||||
| /** | ||||
|  * A regular expression to match domain names of a URL or email address. | ||||
|  * Ex: 'google', 'yahoo', 'some-other-company', etc. | ||||
|  */ | ||||
| export declare const domainNameRegex: RegExp; | ||||
| /** | ||||
|  * A regular expression that is simply the character class of the characters | ||||
|  * that may be used in a domain name, minus the '-' or '.' | ||||
|  */ | ||||
| export declare const domainNameCharRegex: RegExp; | ||||
							
								
								
									
										169
									
								
								src/modules/autolinker/regex-lib.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								src/modules/autolinker/regex-lib.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,169 @@ | ||||
| /* | ||||
|  * This file builds and stores a library of the common regular expressions used | ||||
|  * by the Autolinker utility. | ||||
|  * | ||||
|  * Other regular expressions may exist ad-hoc, but these are generally the | ||||
|  * regular expressions that are shared between source files. | ||||
|  */ | ||||
| /** | ||||
|  * Regular expression to match upper and lowercase ASCII letters | ||||
|  */ | ||||
| export var letterRe = /[A-Za-z]/; | ||||
| /** | ||||
|  * Regular expression to match ASCII digits | ||||
|  */ | ||||
| export var digitRe = /[\d]/; | ||||
| /** | ||||
|  * Regular expression to match everything *except* ASCII digits | ||||
|  */ | ||||
| export var nonDigitRe = /[\D]/; | ||||
| /** | ||||
|  * Regular expression to match whitespace | ||||
|  */ | ||||
| export var whitespaceRe = /\s/; | ||||
| /** | ||||
|  * Regular expression to match quote characters | ||||
|  */ | ||||
| export var quoteRe = /['"]/; | ||||
| /** | ||||
|  * Regular expression to match the range of ASCII control characters (0-31), and | ||||
|  * the backspace char (127) | ||||
|  */ | ||||
| export var controlCharsRe = /[\x00-\x1F\x7F]/; | ||||
| /** | ||||
|  * The string form of a regular expression that would match all of the | ||||
|  * alphabetic ("letter") chars in the unicode character set when placed in a | ||||
|  * RegExp character class (`[]`). This includes all international alphabetic | ||||
|  * characters. | ||||
|  * | ||||
|  * These would be the characters matched by unicode regex engines `\p{L}` | ||||
|  * escape ("all letters"). | ||||
|  * | ||||
|  * Taken from the XRegExp library: http://xregexp.com/ (thanks @https://github.com/slevithan) | ||||
|  * Specifically: http://xregexp.com/v/3.2.0/xregexp-all.js, the 'Letter' | ||||
|  *   regex's bmp | ||||
|  * | ||||
|  * VERY IMPORTANT: This set of characters is defined inside of a Regular | ||||
|  *   Expression literal rather than a string literal to prevent UglifyJS from | ||||
|  *   compressing the unicode escape sequences into their actual unicode | ||||
|  *   characters. If Uglify compresses these into the unicode characters | ||||
|  *   themselves, this results in the error "Range out of order in character | ||||
|  *   class" when these characters are used inside of a Regular Expression | ||||
|  *   character class (`[]`). See usages of this const. Alternatively, we can set | ||||
|  *   the UglifyJS option `ascii_only` to true for the build, but that doesn't | ||||
|  *   help others who are pulling in Autolinker into their own build and running | ||||
|  *   UglifyJS themselves. | ||||
|  */ | ||||
| export var alphaCharsStr = /A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC/ | ||||
|     .source; // see note in above variable description | ||||
| /** | ||||
|  * The string form of a regular expression that would match all emoji characters | ||||
|  * Based on the emoji regex defined in this article: https://thekevinscott.com/emojis-in-javascript/ | ||||
|  */ | ||||
| export var emojiStr = /\u2700-\u27bf\udde6-\uddff\ud800-\udbff\udc00-\udfff\ufe0e\ufe0f\u0300-\u036f\ufe20-\ufe23\u20d0-\u20f0\ud83c\udffb-\udfff\u200d\u3299\u3297\u303d\u3030\u24c2\ud83c\udd70-\udd71\udd7e-\udd7f\udd8e\udd91-\udd9a\udde6-\uddff\ude01-\ude02\ude1a\ude2f\ude32-\ude3a\ude50-\ude51\u203c\u2049\u25aa-\u25ab\u25b6\u25c0\u25fb-\u25fe\u00a9\u00ae\u2122\u2139\udc04\u2600-\u26FF\u2b05\u2b06\u2b07\u2b1b\u2b1c\u2b50\u2b55\u231a\u231b\u2328\u23cf\u23e9-\u23f3\u23f8-\u23fa\udccf\u2935\u2934\u2190-\u21ff/ | ||||
|     .source; | ||||
| /** | ||||
|  * The string form of a regular expression that would match all of the | ||||
|  * combining mark characters in the unicode character set when placed in a | ||||
|  * RegExp character class (`[]`). | ||||
|  * | ||||
|  * These would be the characters matched by unicode regex engines `\p{M}` | ||||
|  * escape ("all marks"). | ||||
|  * | ||||
|  * Taken from the XRegExp library: http://xregexp.com/ (thanks @https://github.com/slevithan) | ||||
|  * Specifically: http://xregexp.com/v/3.2.0/xregexp-all.js, the 'Mark' | ||||
|  *   regex's bmp | ||||
|  * | ||||
|  * VERY IMPORTANT: This set of characters is defined inside of a Regular | ||||
|  *   Expression literal rather than a string literal to prevent UglifyJS from | ||||
|  *   compressing the unicode escape sequences into their actual unicode | ||||
|  *   characters. If Uglify compresses these into the unicode characters | ||||
|  *   themselves, this results in the error "Range out of order in character | ||||
|  *   class" when these characters are used inside of a Regular Expression | ||||
|  *   character class (`[]`). See usages of this const. Alternatively, we can set | ||||
|  *   the UglifyJS option `ascii_only` to true for the build, but that doesn't | ||||
|  *   help others who are pulling in Autolinker into their own build and running | ||||
|  *   UglifyJS themselves. | ||||
|  */ | ||||
| export var marksStr = /\u0300-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08D4-\u08E1\u08E3-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C00-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D01-\u0D03\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F\u109A-\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u180B-\u180D\u1885\u1886\u18A9\u1920-\u192B\u1930-\u193B\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F\u1AB0-\u1ABE\u1B00-\u1B04\u1B34-\u1B44\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BE6-\u1BF3\u1C24-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF8\u1CF9\u1DC0-\u1DF5\u1DFB-\u1DFF\u20D0-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA66F-\uA672\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C5\uA8E0-\uA8F1\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9E5\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F/ | ||||
|     .source; // see note in above variable description | ||||
| /** | ||||
|  * The string form of a regular expression that would match all of the | ||||
|  * alphabetic ("letter") chars, emoji, and combining marks in the unicode character set | ||||
|  * when placed in a RegExp character class (`[]`). This includes all | ||||
|  * international alphabetic characters. | ||||
|  * | ||||
|  * These would be the characters matched by unicode regex engines `\p{L}\p{M}` | ||||
|  * escapes and emoji characters. | ||||
|  */ | ||||
| export var alphaCharsAndMarksStr = alphaCharsStr + emojiStr + marksStr; | ||||
| /** | ||||
|  * The string form of a regular expression that would match all of the | ||||
|  * decimal number chars in the unicode character set when placed in a RegExp | ||||
|  * character class (`[]`). | ||||
|  * | ||||
|  * These would be the characters matched by unicode regex engines `\p{Nd}` | ||||
|  * escape ("all decimal numbers") | ||||
|  * | ||||
|  * Taken from the XRegExp library: http://xregexp.com/ (thanks @https://github.com/slevithan) | ||||
|  * Specifically: http://xregexp.com/v/3.2.0/xregexp-all.js, the 'Decimal_Number' | ||||
|  *   regex's bmp | ||||
|  * | ||||
|  * VERY IMPORTANT: This set of characters is defined inside of a Regular | ||||
|  *   Expression literal rather than a string literal to prevent UglifyJS from | ||||
|  *   compressing the unicode escape sequences into their actual unicode | ||||
|  *   characters. If Uglify compresses these into the unicode characters | ||||
|  *   themselves, this results in the error "Range out of order in character | ||||
|  *   class" when these characters are used inside of a Regular Expression | ||||
|  *   character class (`[]`). See usages of this const. Alternatively, we can set | ||||
|  *   the UglifyJS option `ascii_only` to true for the build, but that doesn't | ||||
|  *   help others who are pulling in Autolinker into their own build and running | ||||
|  *   UglifyJS themselves. | ||||
|  */ | ||||
| export var decimalNumbersStr = /0-9\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F\u09E6-\u09EF\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE6-\u0BEF\u0C66-\u0C6F\u0CE6-\u0CEF\u0D66-\u0D6F\u0DE6-\u0DEF\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F29\u1040-\u1049\u1090-\u1099\u17E0-\u17E9\u1810-\u1819\u1946-\u194F\u19D0-\u19D9\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\uA620-\uA629\uA8D0-\uA8D9\uA900-\uA909\uA9D0-\uA9D9\uA9F0-\uA9F9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19/ | ||||
|     .source; // see note in above variable description | ||||
| /** | ||||
|  * The string form of a regular expression that would match all of the | ||||
|  * letters and decimal number chars in the unicode character set when placed in | ||||
|  * a RegExp character class (`[]`). | ||||
|  * | ||||
|  * These would be the characters matched by unicode regex engines | ||||
|  * `[\p{L}\p{Nd}]` escape ("all letters and decimal numbers") | ||||
|  */ | ||||
| export var alphaNumericCharsStr = alphaCharsAndMarksStr + decimalNumbersStr; | ||||
| /** | ||||
|  * 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 when placed in a RegExp character class (`[]`). | ||||
|  * | ||||
|  * These would be the characters matched by unicode regex engines | ||||
|  * `[\p{L}\p{M}\p{Nd}]` escape ("all letters, combining marks, and decimal | ||||
|  * numbers") | ||||
|  */ | ||||
| export var alphaNumericAndMarksCharsStr = alphaCharsAndMarksStr + decimalNumbersStr; | ||||
| // Simplified IP regular expression | ||||
| var ipStr = '(?:[' + decimalNumbersStr + ']{1,3}\\.){3}[' + decimalNumbersStr + ']{1,3}'; | ||||
| // Protected domain label which do not allow "-" character on the beginning and the end of a single label | ||||
| var domainLabelStr = '[' + alphaNumericAndMarksCharsStr + '](?:[' + alphaNumericAndMarksCharsStr + '\\-]{0,61}[' + alphaNumericAndMarksCharsStr + '])?'; | ||||
| var getDomainLabelStr = function (group) { | ||||
|     return '(?=(' + domainLabelStr + '))\\' + group; | ||||
| }; | ||||
| /** | ||||
|  * A function to match domain names of a URL or email address. | ||||
|  * Ex: 'google', 'yahoo', 'some-other-company', etc. | ||||
|  */ | ||||
| export var getDomainNameStr = function (group) { | ||||
|     return '(?:' + getDomainLabelStr(group) + '(?:\\.' + getDomainLabelStr(group + 1) + '){0,126}|' + ipStr + ')'; | ||||
| }; | ||||
| /** | ||||
|  * A regular expression to match domain names of a URL or email address. | ||||
|  * Ex: 'google', 'yahoo', 'some-other-company', etc. | ||||
|  */ | ||||
| export var domainNameRegex = new RegExp('[' + alphaNumericAndMarksCharsStr + '.\\-]*[' + alphaNumericAndMarksCharsStr + '\\-]'); | ||||
| /** | ||||
|  * A regular expression that is simply the character class of the characters | ||||
|  * that may be used in a domain name, minus the '-' or '.' | ||||
|  */ | ||||
| export var domainNameCharRegex = new RegExp("[" + alphaNumericAndMarksCharsStr + "]"); | ||||
|  | ||||
| //# sourceMappingURL=regex-lib.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/regex-lib.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/regex-lib.js.map
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										9
									
								
								src/modules/autolinker/truncate/truncate-end.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/modules/autolinker/truncate/truncate-end.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| /** | ||||
|  * A truncation feature where the ellipsis will be placed at the end of the URL. | ||||
|  * | ||||
|  * @param {String} anchorText | ||||
|  * @param {Number} truncateLen The maximum length of the truncated output URL string. | ||||
|  * @param {String} ellipsisChars The characters to place within the url, e.g. "..". | ||||
|  * @return {String} The truncated URL. | ||||
|  */ | ||||
| export declare function truncateEnd(anchorText: string, truncateLen: number, ellipsisChars?: string): string; | ||||
							
								
								
									
										14
									
								
								src/modules/autolinker/truncate/truncate-end.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/modules/autolinker/truncate/truncate-end.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| import { ellipsis } from "../utils"; | ||||
| /** | ||||
|  * A truncation feature where the ellipsis will be placed at the end of the URL. | ||||
|  * | ||||
|  * @param {String} anchorText | ||||
|  * @param {Number} truncateLen The maximum length of the truncated output URL string. | ||||
|  * @param {String} ellipsisChars The characters to place within the url, e.g. "..". | ||||
|  * @return {String} The truncated URL. | ||||
|  */ | ||||
| export function truncateEnd(anchorText, truncateLen, ellipsisChars) { | ||||
|     return ellipsis(anchorText, truncateLen, ellipsisChars); | ||||
| } | ||||
|  | ||||
| //# sourceMappingURL=truncate-end.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/truncate/truncate-end.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/truncate/truncate-end.js.map
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| {"version":3,"sources":["../src/truncate/truncate-end.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAE,UAAkB,EAAE,WAAmB,EAAE,aAAsB;IAC3F,OAAO,QAAQ,CAAE,UAAU,EAAE,WAAW,EAAE,aAAa,CAAE,CAAC;AAC3D,CAAC","file":"truncate-end.js","sourcesContent":["import { ellipsis } from \"../utils\";\n\n/**\n * A truncation feature where the ellipsis will be placed at the end of the URL.\n *\n * @param {String} anchorText\n * @param {Number} truncateLen The maximum length of the truncated output URL string.\n * @param {String} ellipsisChars The characters to place within the url, e.g. \"..\".\n * @return {String} The truncated URL.\n */\nexport function truncateEnd( anchorText: string, truncateLen: number, ellipsisChars?: string){\n\treturn ellipsis( anchorText, truncateLen, ellipsisChars );\n}\n"]} | ||||
							
								
								
									
										12
									
								
								src/modules/autolinker/truncate/truncate-middle.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/modules/autolinker/truncate/truncate-middle.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| /** | ||||
|  * Date: 2015-10-05 | ||||
|  * Author: Kasper Søfren <soefritz@gmail.com> (https://github.com/kafoso) | ||||
|  * | ||||
|  * A truncation feature, where the ellipsis will be placed in the dead-center of the URL. | ||||
|  * | ||||
|  * @param {String} url             A URL. | ||||
|  * @param {Number} truncateLen     The maximum length of the truncated output URL string. | ||||
|  * @param {String} ellipsisChars   The characters to place within the url, e.g. "..". | ||||
|  * @return {String} The truncated URL. | ||||
|  */ | ||||
| export declare function truncateMiddle(url: string, truncateLen: number, ellipsisChars?: string): string; | ||||
							
								
								
									
										35
									
								
								src/modules/autolinker/truncate/truncate-middle.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/modules/autolinker/truncate/truncate-middle.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| /** | ||||
|  * Date: 2015-10-05 | ||||
|  * Author: Kasper Søfren <soefritz@gmail.com> (https://github.com/kafoso) | ||||
|  * | ||||
|  * A truncation feature, where the ellipsis will be placed in the dead-center of the URL. | ||||
|  * | ||||
|  * @param {String} url             A URL. | ||||
|  * @param {Number} truncateLen     The maximum length of the truncated output URL string. | ||||
|  * @param {String} ellipsisChars   The characters to place within the url, e.g. "..". | ||||
|  * @return {String} The truncated URL. | ||||
|  */ | ||||
| export function truncateMiddle(url, truncateLen, ellipsisChars) { | ||||
|     if (url.length <= truncateLen) { | ||||
|         return url; | ||||
|     } | ||||
|     var ellipsisLengthBeforeParsing; | ||||
|     var ellipsisLength; | ||||
|     if (ellipsisChars == null) { | ||||
|         ellipsisChars = '…'; | ||||
|         ellipsisLengthBeforeParsing = 8; | ||||
|         ellipsisLength = 3; | ||||
|     } | ||||
|     else { | ||||
|         ellipsisLengthBeforeParsing = ellipsisChars.length; | ||||
|         ellipsisLength = ellipsisChars.length; | ||||
|     } | ||||
|     var availableLength = truncateLen - ellipsisLength; | ||||
|     var end = ""; | ||||
|     if (availableLength > 0) { | ||||
|         end = url.substr((-1) * Math.floor(availableLength / 2)); | ||||
|     } | ||||
|     return (url.substr(0, Math.ceil(availableLength / 2)) + ellipsisChars + end).substr(0, availableLength + ellipsisLengthBeforeParsing); | ||||
| } | ||||
|  | ||||
| //# sourceMappingURL=truncate-middle.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/truncate/truncate-middle.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/truncate/truncate-middle.js.map
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| {"version":3,"sources":["../src/truncate/truncate-middle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAAE,GAAW,EAAE,WAAmB,EAAE,aAAsB;IACtF,IAAI,GAAG,CAAC,MAAM,IAAI,WAAW,EAAE;QAC7B,OAAO,GAAG,CAAC;KACZ;IAED,IAAI,2BAAmC,CAAC;IACxC,IAAI,cAAsB,CAAC;IAE3B,IAAG,aAAa,IAAI,IAAI,EAAE;QACxB,aAAa,GAAG,UAAU,CAAC;QAC3B,2BAA2B,GAAG,CAAC,CAAC;QAChC,cAAc,GAAG,CAAC,CAAC;KACpB;SAAM;QACL,2BAA2B,GAAG,aAAa,CAAC,MAAM,CAAC;QACnD,cAAc,GAAG,aAAa,CAAC,MAAM,CAAC;KACvC;IAED,IAAI,eAAe,GAAG,WAAW,GAAG,cAAc,CAAC;IACnD,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,eAAe,GAAG,CAAC,EAAE;QACvB,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,GAAC,IAAI,CAAC,KAAK,CAAC,eAAe,GAAC,CAAC,CAAC,CAAC,CAAC;KACtD;IACD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,eAAe,GAAC,CAAC,CAAC,CAAC,GAAG,aAAa,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,eAAe,GAAG,2BAA2B,CAAC,CAAC;AACtI,CAAC","file":"truncate-middle.js","sourcesContent":["/**\n * Date: 2015-10-05\n * Author: Kasper Søfren <soefritz@gmail.com> (https://github.com/kafoso)\n *\n * A truncation feature, where the ellipsis will be placed in the dead-center of the URL.\n *\n * @param {String} url             A URL.\n * @param {Number} truncateLen     The maximum length of the truncated output URL string.\n * @param {String} ellipsisChars   The characters to place within the url, e.g. \"..\".\n * @return {String} The truncated URL.\n */\nexport function truncateMiddle( url: string, truncateLen: number, ellipsisChars?: string ){\n  if (url.length <= truncateLen) {\n    return url;\n  }\n\n  let ellipsisLengthBeforeParsing: number;\n  let ellipsisLength: number;\n\n  if(ellipsisChars == null) {\n    ellipsisChars = '…';\n    ellipsisLengthBeforeParsing = 8;\n    ellipsisLength = 3;\n  } else {\n    ellipsisLengthBeforeParsing = ellipsisChars.length;\n    ellipsisLength = ellipsisChars.length;\n  }\n\n  let availableLength = truncateLen - ellipsisLength;\n  let end = \"\";\n  if (availableLength > 0) {\n    end = url.substr((-1)*Math.floor(availableLength/2));\n  }\n  return (url.substr(0, Math.ceil(availableLength/2)) + ellipsisChars + end).substr(0, availableLength + ellipsisLengthBeforeParsing);\n}\n"]} | ||||
							
								
								
									
										13
									
								
								src/modules/autolinker/truncate/truncate-smart.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/modules/autolinker/truncate/truncate-smart.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| /** | ||||
|  * Date: 2015-10-05 | ||||
|  * Author: Kasper Søfren <soefritz@gmail.com> (https://github.com/kafoso) | ||||
|  * | ||||
|  * A truncation feature, where the ellipsis will be placed at a section within | ||||
|  * the URL making it still somewhat human readable. | ||||
|  * | ||||
|  * @param {String} url						 A URL. | ||||
|  * @param {Number} truncateLen		 The maximum length of the truncated output URL string. | ||||
|  * @param {String} ellipsisChars	 The characters to place within the url, e.g. "...". | ||||
|  * @return {String} The truncated URL. | ||||
|  */ | ||||
| export declare function truncateSmart(url: string, truncateLen: number, ellipsisChars?: string): string; | ||||
							
								
								
									
										164
									
								
								src/modules/autolinker/truncate/truncate-smart.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								src/modules/autolinker/truncate/truncate-smart.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,164 @@ | ||||
| /** | ||||
|  * Date: 2015-10-05 | ||||
|  * Author: Kasper Søfren <soefritz@gmail.com> (https://github.com/kafoso) | ||||
|  * | ||||
|  * A truncation feature, where the ellipsis will be placed at a section within | ||||
|  * the URL making it still somewhat human readable. | ||||
|  * | ||||
|  * @param {String} url						 A URL. | ||||
|  * @param {Number} truncateLen		 The maximum length of the truncated output URL string. | ||||
|  * @param {String} ellipsisChars	 The characters to place within the url, e.g. "...". | ||||
|  * @return {String} The truncated URL. | ||||
|  */ | ||||
| export function truncateSmart(url, truncateLen, ellipsisChars) { | ||||
|     var ellipsisLengthBeforeParsing; | ||||
|     var ellipsisLength; | ||||
|     if (ellipsisChars == null) { | ||||
|         ellipsisChars = '…'; | ||||
|         ellipsisLength = 3; | ||||
|         ellipsisLengthBeforeParsing = 8; | ||||
|     } | ||||
|     else { | ||||
|         ellipsisLength = ellipsisChars.length; | ||||
|         ellipsisLengthBeforeParsing = ellipsisChars.length; | ||||
|     } | ||||
|     var parse_url = function (url) { | ||||
|         var urlObj = {}; | ||||
|         var urlSub = url; | ||||
|         var match = urlSub.match(/^([a-z]+):\/\//i); | ||||
|         if (match) { | ||||
|             urlObj.scheme = match[1]; | ||||
|             urlSub = urlSub.substr(match[0].length); | ||||
|         } | ||||
|         match = urlSub.match(/^(.*?)(?=(\?|#|\/|$))/i); | ||||
|         if (match) { | ||||
|             urlObj.host = match[1]; | ||||
|             urlSub = urlSub.substr(match[0].length); | ||||
|         } | ||||
|         match = urlSub.match(/^\/(.*?)(?=(\?|#|$))/i); | ||||
|         if (match) { | ||||
|             urlObj.path = match[1]; | ||||
|             urlSub = urlSub.substr(match[0].length); | ||||
|         } | ||||
|         match = urlSub.match(/^\?(.*?)(?=(#|$))/i); | ||||
|         if (match) { | ||||
|             urlObj.query = match[1]; | ||||
|             urlSub = urlSub.substr(match[0].length); | ||||
|         } | ||||
|         match = urlSub.match(/^#(.*?)$/i); | ||||
|         if (match) { | ||||
|             urlObj.fragment = match[1]; | ||||
|             //urlSub = urlSub.substr(match[0].length);  -- not used. Uncomment if adding another block. | ||||
|         } | ||||
|         return urlObj; | ||||
|     }; | ||||
|     var buildUrl = function (urlObj) { | ||||
|         var url = ""; | ||||
|         if (urlObj.scheme && urlObj.host) { | ||||
|             url += urlObj.scheme + "://"; | ||||
|         } | ||||
|         if (urlObj.host) { | ||||
|             url += urlObj.host; | ||||
|         } | ||||
|         if (urlObj.path) { | ||||
|             url += "/" + urlObj.path; | ||||
|         } | ||||
|         if (urlObj.query) { | ||||
|             url += "?" + urlObj.query; | ||||
|         } | ||||
|         if (urlObj.fragment) { | ||||
|             url += "#" + urlObj.fragment; | ||||
|         } | ||||
|         return url; | ||||
|     }; | ||||
|     var buildSegment = function (segment, remainingAvailableLength) { | ||||
|         var remainingAvailableLengthHalf = remainingAvailableLength / 2, startOffset = Math.ceil(remainingAvailableLengthHalf), endOffset = (-1) * Math.floor(remainingAvailableLengthHalf), end = ""; | ||||
|         if (endOffset < 0) { | ||||
|             end = segment.substr(endOffset); | ||||
|         } | ||||
|         return segment.substr(0, startOffset) + ellipsisChars + end; | ||||
|     }; | ||||
|     if (url.length <= truncateLen) { | ||||
|         return url; | ||||
|     } | ||||
|     var availableLength = truncateLen - ellipsisLength; | ||||
|     var urlObj = parse_url(url); | ||||
|     // Clean up the URL | ||||
|     if (urlObj.query) { | ||||
|         var matchQuery = urlObj.query.match(/^(.*?)(?=(\?|\#))(.*?)$/i); | ||||
|         if (matchQuery) { | ||||
|             // Malformed URL; two or more "?". Removed any content behind the 2nd. | ||||
|             urlObj.query = urlObj.query.substr(0, matchQuery[1].length); | ||||
|             url = buildUrl(urlObj); | ||||
|         } | ||||
|     } | ||||
|     if (url.length <= truncateLen) { | ||||
|         return url; | ||||
|     } | ||||
|     if (urlObj.host) { | ||||
|         urlObj.host = urlObj.host.replace(/^www\./, ""); | ||||
|         url = buildUrl(urlObj); | ||||
|     } | ||||
|     if (url.length <= truncateLen) { | ||||
|         return url; | ||||
|     } | ||||
|     // Process and build the URL | ||||
|     var str = ""; | ||||
|     if (urlObj.host) { | ||||
|         str += urlObj.host; | ||||
|     } | ||||
|     if (str.length >= availableLength) { | ||||
|         if (urlObj.host.length == truncateLen) { | ||||
|             return (urlObj.host.substr(0, (truncateLen - ellipsisLength)) + ellipsisChars).substr(0, availableLength + ellipsisLengthBeforeParsing); | ||||
|         } | ||||
|         return buildSegment(str, availableLength).substr(0, availableLength + ellipsisLengthBeforeParsing); | ||||
|     } | ||||
|     var pathAndQuery = ""; | ||||
|     if (urlObj.path) { | ||||
|         pathAndQuery += "/" + urlObj.path; | ||||
|     } | ||||
|     if (urlObj.query) { | ||||
|         pathAndQuery += "?" + urlObj.query; | ||||
|     } | ||||
|     if (pathAndQuery) { | ||||
|         if ((str + pathAndQuery).length >= availableLength) { | ||||
|             if ((str + pathAndQuery).length == truncateLen) { | ||||
|                 return (str + pathAndQuery).substr(0, truncateLen); | ||||
|             } | ||||
|             var remainingAvailableLength = availableLength - str.length; | ||||
|             return (str + buildSegment(pathAndQuery, remainingAvailableLength)).substr(0, availableLength + ellipsisLengthBeforeParsing); | ||||
|         } | ||||
|         else { | ||||
|             str += pathAndQuery; | ||||
|         } | ||||
|     } | ||||
|     if (urlObj.fragment) { | ||||
|         var fragment = "#" + urlObj.fragment; | ||||
|         if ((str + fragment).length >= availableLength) { | ||||
|             if ((str + fragment).length == truncateLen) { | ||||
|                 return (str + fragment).substr(0, truncateLen); | ||||
|             } | ||||
|             var remainingAvailableLength2 = availableLength - str.length; | ||||
|             return (str + buildSegment(fragment, remainingAvailableLength2)).substr(0, availableLength + ellipsisLengthBeforeParsing); | ||||
|         } | ||||
|         else { | ||||
|             str += fragment; | ||||
|         } | ||||
|     } | ||||
|     if (urlObj.scheme && urlObj.host) { | ||||
|         var scheme = urlObj.scheme + "://"; | ||||
|         if ((str + scheme).length < availableLength) { | ||||
|             return (scheme + str).substr(0, truncateLen); | ||||
|         } | ||||
|     } | ||||
|     if (str.length <= truncateLen) { | ||||
|         return str; | ||||
|     } | ||||
|     var end = ""; | ||||
|     if (availableLength > 0) { | ||||
|         end = str.substr((-1) * Math.floor(availableLength / 2)); | ||||
|     } | ||||
|     return (str.substr(0, Math.ceil(availableLength / 2)) + ellipsisChars + end).substr(0, availableLength + ellipsisLengthBeforeParsing); | ||||
| } | ||||
|  | ||||
| //# sourceMappingURL=truncate-smart.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/truncate/truncate-smart.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/truncate/truncate-smart.js.map
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										72
									
								
								src/modules/autolinker/utils.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								src/modules/autolinker/utils.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | ||||
| /** | ||||
|  * Assigns (shallow copies) the properties of `src` onto `dest`, if the | ||||
|  * corresponding property on `dest` === `undefined`. | ||||
|  * | ||||
|  * @param {Object} dest The destination object. | ||||
|  * @param {Object} src The source object. | ||||
|  * @return {Object} The destination object (`dest`) | ||||
|  */ | ||||
| export declare function defaults(dest: any, src: any): any; | ||||
| /** | ||||
|  * Truncates the `str` at `len - ellipsisChars.length`, and adds the `ellipsisChars` to the | ||||
|  * end of the string (by default, two periods: '..'). If the `str` length does not exceed | ||||
|  * `len`, the string will be returned unchanged. | ||||
|  * | ||||
|  * @param {String} str The string to truncate and add an ellipsis to. | ||||
|  * @param {Number} truncateLen The length to truncate the string at. | ||||
|  * @param {String} [ellipsisChars=...] The ellipsis character(s) to add to the end of `str` | ||||
|  *   when truncated. Defaults to '...' | ||||
|  */ | ||||
| export declare function ellipsis(str: string, truncateLen: number, ellipsisChars?: string): string; | ||||
| /** | ||||
|  * Supports `Array.prototype.indexOf()` functionality for old IE (IE8 and below). | ||||
|  * | ||||
|  * @param {Array} arr The array to find an element of. | ||||
|  * @param {*} element The element to find in the array, and return the index of. | ||||
|  * @return {Number} The index of the `element`, or -1 if it was not found. | ||||
|  */ | ||||
| export declare function indexOf<T>(arr: T[], element: T): number; | ||||
| /** | ||||
|  * Removes array elements based on a filtering function. Mutates the input | ||||
|  * array. | ||||
|  * | ||||
|  * Using this instead of the ES5 Array.prototype.filter() function, to allow | ||||
|  * Autolinker compatibility with IE8, and also to prevent creating many new | ||||
|  * arrays in memory for filtering. | ||||
|  * | ||||
|  * @param {Array} arr The array to remove elements from. This array is | ||||
|  *   mutated. | ||||
|  * @param {Function} fn A function which should return `true` to | ||||
|  *   remove an element. | ||||
|  * @return {Array} The mutated input `arr`. | ||||
|  */ | ||||
| export declare function remove<T>(arr: T[], fn: (item: T) => boolean): void; | ||||
| /** | ||||
|  * Performs the functionality of what modern browsers do when `String.prototype.split()` is called | ||||
|  * with a regular expression that contains capturing parenthesis. | ||||
|  * | ||||
|  * For example: | ||||
|  * | ||||
|  *     // Modern browsers: | ||||
|  *     "a,b,c".split( /(,)/ );  // --> [ 'a', ',', 'b', ',', 'c' ] | ||||
|  * | ||||
|  *     // Old IE (including IE8): | ||||
|  *     "a,b,c".split( /(,)/ );  // --> [ 'a', 'b', 'c' ] | ||||
|  * | ||||
|  * This method emulates the functionality of modern browsers for the old IE case. | ||||
|  * | ||||
|  * @param {String} str The string to split. | ||||
|  * @param {RegExp} splitRegex The regular expression to split the input `str` on. The splitting | ||||
|  *   character(s) will be spliced into the array, as in the "modern browsers" example in the | ||||
|  *   description of this method. | ||||
|  *   Note #1: the supplied regular expression **must** have the 'g' flag specified. | ||||
|  *   Note #2: for simplicity's sake, the regular expression does not need | ||||
|  *   to contain capturing parenthesis - it will be assumed that any match has them. | ||||
|  * @return {String[]} The split array of strings, with the splitting character(s) included. | ||||
|  */ | ||||
| export declare function splitAndCapture(str: string, splitRegex: RegExp): string[]; | ||||
| /** | ||||
|  * Function that should never be called but is used to check that every | ||||
|  * enum value is handled using TypeScript's 'never' type. | ||||
|  */ | ||||
| export declare function throwUnhandledCaseError(theValue: never): void; | ||||
							
								
								
									
										124
									
								
								src/modules/autolinker/utils.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								src/modules/autolinker/utils.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,124 @@ | ||||
| /** | ||||
|  * Assigns (shallow copies) the properties of `src` onto `dest`, if the | ||||
|  * corresponding property on `dest` === `undefined`. | ||||
|  * | ||||
|  * @param {Object} dest The destination object. | ||||
|  * @param {Object} src The source object. | ||||
|  * @return {Object} The destination object (`dest`) | ||||
|  */ | ||||
| export function defaults(dest, src) { | ||||
|     for (var prop in src) { | ||||
|         if (src.hasOwnProperty(prop) && dest[prop] === undefined) { | ||||
|             dest[prop] = src[prop]; | ||||
|         } | ||||
|     } | ||||
|     return dest; | ||||
| } | ||||
| /** | ||||
|  * Truncates the `str` at `len - ellipsisChars.length`, and adds the `ellipsisChars` to the | ||||
|  * end of the string (by default, two periods: '..'). If the `str` length does not exceed | ||||
|  * `len`, the string will be returned unchanged. | ||||
|  * | ||||
|  * @param {String} str The string to truncate and add an ellipsis to. | ||||
|  * @param {Number} truncateLen The length to truncate the string at. | ||||
|  * @param {String} [ellipsisChars=...] The ellipsis character(s) to add to the end of `str` | ||||
|  *   when truncated. Defaults to '...' | ||||
|  */ | ||||
| export function ellipsis(str, truncateLen, ellipsisChars) { | ||||
|     var ellipsisLength; | ||||
|     if (str.length > truncateLen) { | ||||
|         if (ellipsisChars == null) { | ||||
|             ellipsisChars = '…'; | ||||
|             ellipsisLength = 3; | ||||
|         } | ||||
|         else { | ||||
|             ellipsisLength = ellipsisChars.length; | ||||
|         } | ||||
|         str = str.substring(0, truncateLen - ellipsisLength) + ellipsisChars; | ||||
|     } | ||||
|     return str; | ||||
| } | ||||
| /** | ||||
|  * Supports `Array.prototype.indexOf()` functionality for old IE (IE8 and below). | ||||
|  * | ||||
|  * @param {Array} arr The array to find an element of. | ||||
|  * @param {*} element The element to find in the array, and return the index of. | ||||
|  * @return {Number} The index of the `element`, or -1 if it was not found. | ||||
|  */ | ||||
| export function indexOf(arr, element) { | ||||
|     if (Array.prototype.indexOf) { | ||||
|         return arr.indexOf(element); | ||||
|     } | ||||
|     else { | ||||
|         for (var i = 0, len = arr.length; i < len; i++) { | ||||
|             if (arr[i] === element) | ||||
|                 return i; | ||||
|         } | ||||
|         return -1; | ||||
|     } | ||||
| } | ||||
| /** | ||||
|  * Removes array elements based on a filtering function. Mutates the input | ||||
|  * array. | ||||
|  * | ||||
|  * Using this instead of the ES5 Array.prototype.filter() function, to allow | ||||
|  * Autolinker compatibility with IE8, and also to prevent creating many new | ||||
|  * arrays in memory for filtering. | ||||
|  * | ||||
|  * @param {Array} arr The array to remove elements from. This array is | ||||
|  *   mutated. | ||||
|  * @param {Function} fn A function which should return `true` to | ||||
|  *   remove an element. | ||||
|  * @return {Array} The mutated input `arr`. | ||||
|  */ | ||||
| export function remove(arr, fn) { | ||||
|     for (var i = arr.length - 1; i >= 0; i--) { | ||||
|         if (fn(arr[i]) === true) { | ||||
|             arr.splice(i, 1); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| /** | ||||
|  * Performs the functionality of what modern browsers do when `String.prototype.split()` is called | ||||
|  * with a regular expression that contains capturing parenthesis. | ||||
|  * | ||||
|  * For example: | ||||
|  * | ||||
|  *     // Modern browsers: | ||||
|  *     "a,b,c".split( /(,)/ );  // --> [ 'a', ',', 'b', ',', 'c' ] | ||||
|  * | ||||
|  *     // Old IE (including IE8): | ||||
|  *     "a,b,c".split( /(,)/ );  // --> [ 'a', 'b', 'c' ] | ||||
|  * | ||||
|  * This method emulates the functionality of modern browsers for the old IE case. | ||||
|  * | ||||
|  * @param {String} str The string to split. | ||||
|  * @param {RegExp} splitRegex The regular expression to split the input `str` on. The splitting | ||||
|  *   character(s) will be spliced into the array, as in the "modern browsers" example in the | ||||
|  *   description of this method. | ||||
|  *   Note #1: the supplied regular expression **must** have the 'g' flag specified. | ||||
|  *   Note #2: for simplicity's sake, the regular expression does not need | ||||
|  *   to contain capturing parenthesis - it will be assumed that any match has them. | ||||
|  * @return {String[]} The split array of strings, with the splitting character(s) included. | ||||
|  */ | ||||
| export function splitAndCapture(str, splitRegex) { | ||||
|     if (!splitRegex.global) | ||||
|         throw new Error("`splitRegex` must have the 'g' flag set"); | ||||
|     var result = [], lastIdx = 0, match; | ||||
|     while (match = splitRegex.exec(str)) { | ||||
|         result.push(str.substring(lastIdx, match.index)); | ||||
|         result.push(match[0]); // push the splitting char(s) | ||||
|         lastIdx = match.index + match[0].length; | ||||
|     } | ||||
|     result.push(str.substring(lastIdx)); | ||||
|     return result; | ||||
| } | ||||
| /** | ||||
|  * Function that should never be called but is used to check that every | ||||
|  * enum value is handled using TypeScript's 'never' type. | ||||
|  */ | ||||
| export function throwUnhandledCaseError(theValue) { | ||||
|     throw new Error("Unhandled case for value: '" + theValue + "'"); | ||||
| } | ||||
|  | ||||
| //# sourceMappingURL=utils.js.map | ||||
							
								
								
									
										1
									
								
								src/modules/autolinker/utils.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/modules/autolinker/utils.js.map
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -1,7 +1,9 @@ | ||||
| import { Feather } from '@expo/vector-icons' | ||||
| import React, { useCallback, useEffect, useState } from 'react' | ||||
| import { | ||||
|   Alert, | ||||
|   Keyboard, | ||||
|   KeyboardAvoidingView, | ||||
|   Pressable, | ||||
|   StyleSheet, | ||||
|   Text, | ||||
| @@ -9,7 +11,8 @@ import { | ||||
|   View | ||||
| } from 'react-native' | ||||
| import { createNativeStackNavigator } from 'react-native-screens/native-stack' | ||||
| import Autolinker, { HtmlTag } from 'autolinker' | ||||
| import Autolinker from 'src/modules/autolinker' | ||||
| import { useNavigation } from '@react-navigation/native' | ||||
|  | ||||
| const Stack = createNativeStackNavigator() | ||||
|  | ||||
| @@ -25,7 +28,7 @@ const PostTootMain = () => { | ||||
|       Keyboard.removeListener('keyboardDidShow', _keyboardDidShow) | ||||
|       Keyboard.removeListener('keyboardDidHide', _keyboardDidHide) | ||||
|     } | ||||
|   }) | ||||
|   }, []) | ||||
|   const _keyboardDidShow = (props: any) => { | ||||
|     setKeyboardHeight(props.endCoordinates.height) | ||||
|   } | ||||
| @@ -36,12 +39,13 @@ const PostTootMain = () => { | ||||
|  | ||||
|   const [charCount, setCharCount] = useState(0) | ||||
|   const [formattedText, setFormattedText] = useState<React.ReactNode>() | ||||
|   let prevTags = [] | ||||
|   const onChangeText = useCallback(content => { | ||||
|     const tags: string[] = [] | ||||
|     Autolinker.link(content, { | ||||
|       email: false, | ||||
|       email: true, | ||||
|       phone: false, | ||||
|       mention: 'twitter', | ||||
|       mention: 'mastodon', | ||||
|       hashtag: 'twitter', | ||||
|       replaceFn: props => { | ||||
|         const tag = props.getMatchedText() | ||||
| @@ -49,13 +53,18 @@ const PostTootMain = () => { | ||||
|         return tag | ||||
|       } | ||||
|     }) | ||||
|     prevTags = tags | ||||
|  | ||||
|     let _content = content | ||||
|     const children = [] | ||||
|     tags.forEach(tag => { | ||||
|       const parts = _content.split(tag) | ||||
|       children.push(parts.shift()) | ||||
|       children.push(<Text style={{ color: 'red' }}>{tag}</Text>) | ||||
|       children.push( | ||||
|         <Text style={{ color: 'red' }} key={Math.random()}> | ||||
|           {tag} | ||||
|         </Text> | ||||
|       ) | ||||
|       _content = parts.join(tag) | ||||
|     }) | ||||
|     children.push(_content) | ||||
| @@ -67,43 +76,63 @@ const PostTootMain = () => { | ||||
|   return ( | ||||
|     <View | ||||
|       style={styles.main} | ||||
|       onLayout={({ nativeEvent }) => { | ||||
|         setViewHeight(nativeEvent.layout.height) | ||||
|       }} | ||||
|       onLayout={({ nativeEvent }) => setViewHeight(nativeEvent.layout.height)} | ||||
|     > | ||||
|       <TextInput | ||||
|         style={[styles.textInput, { height: viewHeight - keyboardHeight - 44 }]} | ||||
|         autoCapitalize='none' | ||||
|         autoFocus | ||||
|         enablesReturnKeyAutomatically | ||||
|         multiline | ||||
|         placeholder='想说点什么' | ||||
|         // value={rawText} | ||||
|         onChangeText={onChangeText} | ||||
|         scrollEnabled | ||||
|       > | ||||
|         <Text>{formattedText}</Text> | ||||
|       </TextInput> | ||||
|       <Pressable style={styles.additions} onPress={() => Keyboard.dismiss()}> | ||||
|         <Feather name='paperclip' size={24} /> | ||||
|         <Feather name='bar-chart-2' size={24} /> | ||||
|         <Feather name='eye-off' size={24} /> | ||||
|         <Text>{charCount}</Text> | ||||
|       </Pressable> | ||||
|       <View style={{ height: viewHeight - keyboardHeight }}> | ||||
|         <TextInput | ||||
|           style={styles.textInput} | ||||
|           autoCapitalize='none' | ||||
|           autoFocus | ||||
|           enablesReturnKeyAutomatically | ||||
|           multiline | ||||
|           placeholder='想说点什么' | ||||
|           onChangeText={onChangeText} | ||||
|           scrollEnabled | ||||
|         > | ||||
|           <Text>{formattedText}</Text> | ||||
|         </TextInput> | ||||
|         <Pressable style={styles.additions} onPress={() => Keyboard.dismiss()}> | ||||
|           <Feather name='paperclip' size={24} /> | ||||
|           <Feather name='bar-chart-2' size={24} /> | ||||
|           <Feather name='eye-off' size={24} /> | ||||
|           <Text>{charCount}</Text> | ||||
|         </Pressable> | ||||
|       </View> | ||||
|     </View> | ||||
|   ) | ||||
| } | ||||
|  | ||||
| const PostToot: React.FC = () => { | ||||
|   const navigation = useNavigation() | ||||
|  | ||||
|   return ( | ||||
|     <Stack.Navigator> | ||||
|       <Stack.Screen | ||||
|         name='PostTootMain' | ||||
|         component={PostTootMain} | ||||
|         options={{ | ||||
|           headerLeft: () => <Text>取消</Text>, | ||||
|           headerLeft: () => ( | ||||
|             <Pressable | ||||
|               onPress={() => | ||||
|                 Alert.alert('确认取消编辑?', '', [ | ||||
|                   { text: '继续编辑', style: 'cancel' }, | ||||
|                   { | ||||
|                     text: '退出编辑', | ||||
|                     style: 'destructive', | ||||
|                     onPress: () => navigation.goBack() | ||||
|                   } | ||||
|                 ]) | ||||
|               } | ||||
|             > | ||||
|               <Text>退出编辑</Text> | ||||
|             </Pressable> | ||||
|           ), | ||||
|           headerCenter: () => <></>, | ||||
|           headerRight: () => <Text>发嘟嘟</Text> | ||||
|           headerRight: () => ( | ||||
|             <Pressable> | ||||
|               <Text>发嘟嘟</Text> | ||||
|             </Pressable> | ||||
|           ) | ||||
|         }} | ||||
|       /> | ||||
|     </Stack.Navigator> | ||||
| @@ -112,10 +141,10 @@ const PostToot: React.FC = () => { | ||||
|  | ||||
| const styles = StyleSheet.create({ | ||||
|   main: { | ||||
|     width: '100%', | ||||
|     height: '100%' | ||||
|     flex: 1 | ||||
|   }, | ||||
|   textInput: { | ||||
|     flex: 1, | ||||
|     backgroundColor: 'gray' | ||||
|   }, | ||||
|   additions: { | ||||
|   | ||||
| @@ -47,7 +47,7 @@ const sharedScreens = (Stack: any) => { | ||||
|       name='PostToot' | ||||
|       component={PostToot} | ||||
|       options={{ | ||||
|         stackPresentation: 'modal' | ||||
|         stackPresentation: 'fullScreenModal' | ||||
|       }} | ||||
|     /> | ||||
|   ] | ||||
|   | ||||
		Reference in New Issue
	
	Block a user