@startinblox/core 0.19.0-beta.2 → 0.19.0-beta.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/dist/{_snowpack/pkg/leaflet.markercluster/dist/MarkerCluster.css → assets/MarkerCluster-614dea0a.css} +0 -0
  2. package/dist/{_snowpack/pkg/leaflet.markercluster/dist/MarkerCluster.Default.css → assets/MarkerCluster.Default-61258232.css} +0 -0
  3. package/dist/assets/en-e53105c5.js +14 -0
  4. package/dist/assets/en-e53105c5.js.map +1 -0
  5. package/dist/assets/fr-a7fcdb64.js +14 -0
  6. package/dist/assets/fr-a7fcdb64.js.map +1 -0
  7. package/dist/{_snowpack/pkg/fusejs.js → assets/helpers-411e08e4.js} +499 -454
  8. package/dist/assets/helpers-411e08e4.js.map +1 -0
  9. package/dist/{_snowpack/pkg/leaflet/dist/leaflet.css → assets/leaflet-3c081932.css} +3 -3
  10. package/dist/helpers.js +22 -0
  11. package/dist/helpers.js.map +1 -0
  12. package/dist/index.js +54873 -48
  13. package/dist/index.js.map +1 -0
  14. package/package.json +7 -22
  15. package/dist/_snowpack/pkg/autolinker.js +0 -4429
  16. package/dist/_snowpack/pkg/autolinker.js.map +0 -1
  17. package/dist/_snowpack/pkg/common/_baseUnary-d2677655.js +0 -353
  18. package/dist/_snowpack/pkg/common/_baseUnary-d2677655.js.map +0 -1
  19. package/dist/_snowpack/pkg/common/_commonjsHelpers-0597c316.js +0 -26
  20. package/dist/_snowpack/pkg/common/_commonjsHelpers-0597c316.js.map +0 -1
  21. package/dist/_snowpack/pkg/common/decode-26fbf385.js +0 -185
  22. package/dist/_snowpack/pkg/common/decode-26fbf385.js.map +0 -1
  23. package/dist/_snowpack/pkg/common/lit-html-3647afce.js +0 -1104
  24. package/dist/_snowpack/pkg/common/lit-html-3647afce.js.map +0 -1
  25. package/dist/_snowpack/pkg/delta-markdown-for-quill.js +0 -26198
  26. package/dist/_snowpack/pkg/delta-markdown-for-quill.js.map +0 -1
  27. package/dist/_snowpack/pkg/dialog-polyfill.js +0 -826
  28. package/dist/_snowpack/pkg/dialog-polyfill.js.map +0 -1
  29. package/dist/_snowpack/pkg/fusejs.js.map +0 -1
  30. package/dist/_snowpack/pkg/import-map.json +0 -25
  31. package/dist/_snowpack/pkg/jsonld-context-parser.js +0 -836
  32. package/dist/_snowpack/pkg/jsonld-context-parser.js.map +0 -1
  33. package/dist/_snowpack/pkg/jsonld.js +0 -11760
  34. package/dist/_snowpack/pkg/jsonld.js.map +0 -1
  35. package/dist/_snowpack/pkg/leaflet/dist/leaflet.css.proxy.js +0 -10
  36. package/dist/_snowpack/pkg/leaflet.markercluster/dist/MarkerCluster.Default.css.proxy.js +0 -10
  37. package/dist/_snowpack/pkg/leaflet.markercluster/dist/MarkerCluster.css.proxy.js +0 -10
  38. package/dist/_snowpack/pkg/lit-html/directives/if-defined.js +0 -39
  39. package/dist/_snowpack/pkg/lit-html/directives/if-defined.js.map +0 -1
  40. package/dist/_snowpack/pkg/lit-html/directives/unsafe-html.js +0 -48
  41. package/dist/_snowpack/pkg/lit-html/directives/unsafe-html.js.map +0 -1
  42. package/dist/_snowpack/pkg/lit-html/directives/until.js +0 -87
  43. package/dist/_snowpack/pkg/lit-html/directives/until.js.map +0 -1
  44. package/dist/_snowpack/pkg/lit-html.js +0 -94
  45. package/dist/_snowpack/pkg/lit-html.js.map +0 -1
  46. package/dist/_snowpack/pkg/markdown-it-link-attributes.js +0 -68
  47. package/dist/_snowpack/pkg/markdown-it-link-attributes.js.map +0 -1
  48. package/dist/_snowpack/pkg/markdown-it.js +0 -11307
  49. package/dist/_snowpack/pkg/markdown-it.js.map +0 -1
  50. package/dist/_snowpack/pkg/quill/dist/quill.snow.css.proxy.js +0 -10
  51. package/dist/_snowpack/pkg/quill-delta-to-markdown.js +0 -971
  52. package/dist/_snowpack/pkg/quill-delta-to-markdown.js.map +0 -1
  53. package/dist/_snowpack/pkg/quill.js +0 -14441
  54. package/dist/_snowpack/pkg/quill.js.map +0 -1
  55. package/dist/_snowpack/pkg/slim-select.js +0 -714
  56. package/dist/_snowpack/pkg/slim-select.js.map +0 -1
  57. package/dist/_snowpack/pkg/tui-calendar/dist/tui-calendar.css +0 -1149
  58. package/dist/_snowpack/pkg/tui-calendar/dist/tui-calendar.css.proxy.js +0 -10
  59. package/dist/_snowpack/pkg/tui-calendar.js +0 -46503
  60. package/dist/_snowpack/pkg/tui-calendar.js.map +0 -1
  61. package/dist/components/solid-ac-checker.js +0 -45
  62. package/dist/components/solid-calendar.js +0 -66
  63. package/dist/components/solid-delete.js +0 -96
  64. package/dist/components/solid-display.js +0 -150
  65. package/dist/components/solid-form-search.js +0 -173
  66. package/dist/components/solid-form.js +0 -257
  67. package/dist/components/solid-lang.js +0 -35
  68. package/dist/components/solid-map.js +0 -204
  69. package/dist/components/solid-table.js +0 -181
  70. package/dist/components/solid-widget.js +0 -72
  71. package/dist/import.css +0 -4
  72. package/dist/libs/Component.js +0 -13
  73. package/dist/libs/ComponentFactory.js +0 -165
  74. package/dist/libs/Compositor.js +0 -96
  75. package/dist/libs/Sib.js +0 -44
  76. package/dist/libs/filter.js +0 -184
  77. package/dist/libs/helpers.js +0 -185
  78. package/dist/libs/interfaces.js +0 -6
  79. package/dist/libs/lit-helpers.js +0 -139
  80. package/dist/libs/polyfills.js +0 -35
  81. package/dist/libs/store/custom-getter.js +0 -313
  82. package/dist/libs/store/server-pagination.js +0 -19
  83. package/dist/libs/store/server-search.js +0 -32
  84. package/dist/libs/store/store.js +0 -560
  85. package/dist/locales/en.json +0 -10
  86. package/dist/locales/en.json.proxy.js +0 -2
  87. package/dist/locales/fr.json +0 -10
  88. package/dist/locales/fr.json.proxy.js +0 -2
  89. package/dist/mixins/attributeBinderMixin.js +0 -113
  90. package/dist/mixins/contextMixin.js +0 -26
  91. package/dist/mixins/counterMixin.js +0 -54
  92. package/dist/mixins/federationMixin.js +0 -57
  93. package/dist/mixins/filterMixin.js +0 -152
  94. package/dist/mixins/grouperMixin.js +0 -73
  95. package/dist/mixins/highlighterMixin.js +0 -36
  96. package/dist/mixins/interfaces.js +0 -6
  97. package/dist/mixins/listMixin.js +0 -116
  98. package/dist/mixins/nextMixin.js +0 -23
  99. package/dist/mixins/paginateMixin.js +0 -97
  100. package/dist/mixins/requiredMixin.js +0 -38
  101. package/dist/mixins/serverPaginationMixin.js +0 -122
  102. package/dist/mixins/sorterMixin.js +0 -131
  103. package/dist/mixins/storeMixin.js +0 -139
  104. package/dist/mixins/translationMixin.js +0 -58
  105. package/dist/mixins/validationMixin.js +0 -95
  106. package/dist/mixins/widgetMixin.js +0 -364
  107. package/dist/new-widgets/attributeMixins/actionMixin.js +0 -13
  108. package/dist/new-widgets/attributeMixins/blankMixin.js +0 -7
  109. package/dist/new-widgets/attributeMixins/booleanMixin.js +0 -7
  110. package/dist/new-widgets/attributeMixins/index.js +0 -19
  111. package/dist/new-widgets/attributeMixins/mailtoMixin.js +0 -7
  112. package/dist/new-widgets/attributeMixins/multipleMixin.js +0 -27
  113. package/dist/new-widgets/attributeMixins/numberMixin.js +0 -7
  114. package/dist/new-widgets/attributeMixins/placeholderMixin.js +0 -16
  115. package/dist/new-widgets/attributeMixins/telMixin.js +0 -7
  116. package/dist/new-widgets/baseWidgetMixin.js +0 -109
  117. package/dist/new-widgets/callbackMixins/autocompletionMixin.js +0 -96
  118. package/dist/new-widgets/callbackMixins/index.js +0 -7
  119. package/dist/new-widgets/callbackMixins/richtextMixin.js +0 -37
  120. package/dist/new-widgets/callbackMixins/slimselect.css.proxy.js +0 -10
  121. package/dist/new-widgets/interfaces.js +0 -1
  122. package/dist/new-widgets/new-widget-factory.js +0 -91
  123. package/dist/new-widgets/templateAdditionMixins/addableMixin.js +0 -26
  124. package/dist/new-widgets/templateAdditionMixins/index.js +0 -13
  125. package/dist/new-widgets/templateAdditionMixins/labelLastMixin.js +0 -16
  126. package/dist/new-widgets/templateAdditionMixins/labelMixin.js +0 -18
  127. package/dist/new-widgets/templates/defaultTemplatesDirectory.js +0 -29
  128. package/dist/new-widgets/templates/displayTemplatesDirectory.js +0 -54
  129. package/dist/new-widgets/templates/formTemplatesDirectory.js +0 -423
  130. package/dist/new-widgets/templates/groupTemplatesDirectory.js +0 -11
  131. package/dist/new-widgets/templates/index.js +0 -6
  132. package/dist/new-widgets/templates/setTemplatesDirectory.js +0 -16
  133. package/dist/new-widgets/templatesDependencies/altMixin.js +0 -12
  134. package/dist/new-widgets/templatesDependencies/editableMixin.js +0 -60
  135. package/dist/new-widgets/templatesDependencies/filterRangeFormMixin.js +0 -34
  136. package/dist/new-widgets/templatesDependencies/formCheckboxMixin.js +0 -10
  137. package/dist/new-widgets/templatesDependencies/formCheckboxesMixin.js +0 -41
  138. package/dist/new-widgets/templatesDependencies/formDropdownMixin.js +0 -59
  139. package/dist/new-widgets/templatesDependencies/formFileMixin.js +0 -82
  140. package/dist/new-widgets/templatesDependencies/formLengthMixin.js +0 -18
  141. package/dist/new-widgets/templatesDependencies/formMinMaxMixin.js +0 -18
  142. package/dist/new-widgets/templatesDependencies/formMixin.js +0 -56
  143. package/dist/new-widgets/templatesDependencies/formNumberMixin.js +0 -10
  144. package/dist/new-widgets/templatesDependencies/formRadioMixin.js +0 -12
  145. package/dist/new-widgets/templatesDependencies/formStepMixin.js +0 -12
  146. package/dist/new-widgets/templatesDependencies/linkTextMixin.js +0 -13
  147. package/dist/new-widgets/templatesDependencies/multipleFormMixin.js +0 -125
  148. package/dist/new-widgets/templatesDependencies/multipleselectFormMixin.js +0 -74
  149. package/dist/new-widgets/templatesDependencies/patternMixin.js +0 -18
  150. package/dist/new-widgets/templatesDependencies/rangeMixin.js +0 -100
  151. package/dist/new-widgets/templatesDependencies/setMixin.js +0 -9
  152. package/dist/new-widgets/templatesDependencies/valueRichtextMixin.js +0 -9
  153. package/dist/new-widgets/valueTransformationMixins/autolinkMixin.js +0 -14
  154. package/dist/new-widgets/valueTransformationMixins/dateMixin.js +0 -29
  155. package/dist/new-widgets/valueTransformationMixins/dateTimeMixin.js +0 -12
  156. package/dist/new-widgets/valueTransformationMixins/index.js +0 -15
  157. package/dist/new-widgets/valueTransformationMixins/markdownMixin.js +0 -30
  158. package/dist/new-widgets/valueTransformationMixins/multilineMixin.js +0 -13
  159. package/dist/new-widgets/valueTransformationMixins/oembedMixin.js +0 -21
  160. package/dist/solid-template-element.js +0 -144
  161. package/dist/style/default-theme.css.proxy.js +0 -10
  162. package/dist/widgets/baseWidget.js +0 -267
  163. package/dist/widgets/widget-factory.js +0 -20
  164. /package/dist/{style/default-theme.css → assets/default-theme-d0f20a8a.css} +0 -0
  165. /package/dist/{_snowpack/pkg/quill/dist/quill.snow.css → assets/quill.snow-8f222e44.css} +0 -0
  166. /package/dist/{new-widgets/callbackMixins/slimselect.css → assets/slimselect-43e3ebc8.css} +0 -0
@@ -1,4429 +0,0 @@
1
- // Important: this file is generated from the 'build' script and should not be
2
- // edited directly
3
- var version = '3.16.2';
4
-
5
- /**
6
- * Assigns (shallow copies) the properties of `src` onto `dest`, if the
7
- * corresponding property on `dest` === `undefined`.
8
- *
9
- * @param {Object} dest The destination object.
10
- * @param {Object} src The source object.
11
- * @return {Object} The destination object (`dest`)
12
- */
13
- function defaults(dest, src) {
14
- for (var prop in src) {
15
- if (src.hasOwnProperty(prop) && dest[prop] === undefined) {
16
- dest[prop] = src[prop];
17
- }
18
- }
19
- return dest;
20
- }
21
- /**
22
- * Truncates the `str` at `len - ellipsisChars.length`, and adds the `ellipsisChars` to the
23
- * end of the string (by default, two periods: '..'). If the `str` length does not exceed
24
- * `len`, the string will be returned unchanged.
25
- *
26
- * @param {String} str The string to truncate and add an ellipsis to.
27
- * @param {Number} truncateLen The length to truncate the string at.
28
- * @param {String} [ellipsisChars=...] The ellipsis character(s) to add to the end of `str`
29
- * when truncated. Defaults to '...'
30
- */
31
- function ellipsis(str, truncateLen, ellipsisChars) {
32
- var ellipsisLength;
33
- if (str.length > truncateLen) {
34
- if (ellipsisChars == null) {
35
- ellipsisChars = '…';
36
- ellipsisLength = 3;
37
- } else {
38
- ellipsisLength = ellipsisChars.length;
39
- }
40
- str = str.substring(0, truncateLen - ellipsisLength) + ellipsisChars;
41
- }
42
- return str;
43
- }
44
- /**
45
- * Supports `Array.prototype.indexOf()` functionality for old IE (IE8 and below).
46
- *
47
- * @param {Array} arr The array to find an element of.
48
- * @param {*} element The element to find in the array, and return the index of.
49
- * @return {Number} The index of the `element`, or -1 if it was not found.
50
- */
51
- function indexOf(arr, element) {
52
- // @ts-ignore - As far as TypeScript is concerned, this method will always
53
- // exist (lowest "lib" in TS is "ES5"). Hence we need to ignore this error
54
- // to support IE8 which only implements ES3 and doesn't have this method
55
- if (Array.prototype.indexOf) {
56
- return arr.indexOf(element);
57
- } else {
58
- for (var i = 0, len = arr.length; i < len; i++) {
59
- if (arr[i] === element) return i;
60
- }
61
- return -1;
62
- }
63
- }
64
- /**
65
- * Removes array elements based on a filtering function. Mutates the input
66
- * array.
67
- *
68
- * Using this instead of the ES5 Array.prototype.filter() function, to allow
69
- * Autolinker compatibility with IE8, and also to prevent creating many new
70
- * arrays in memory for filtering.
71
- *
72
- * @param {Array} arr The array to remove elements from. This array is
73
- * mutated.
74
- * @param {Function} fn A function which should return `true` to
75
- * remove an element.
76
- * @return {Array} The mutated input `arr`.
77
- */
78
- function remove(arr, fn) {
79
- for (var i = arr.length - 1; i >= 0; i--) {
80
- if (fn(arr[i]) === true) {
81
- arr.splice(i, 1);
82
- }
83
- }
84
- }
85
- /**
86
- * Performs the functionality of what modern browsers do when `String.prototype.split()` is called
87
- * with a regular expression that contains capturing parenthesis.
88
- *
89
- * For example:
90
- *
91
- * // Modern browsers:
92
- * "a,b,c".split( /(,)/ ); // --> [ 'a', ',', 'b', ',', 'c' ]
93
- *
94
- * // Old IE (including IE8):
95
- * "a,b,c".split( /(,)/ ); // --> [ 'a', 'b', 'c' ]
96
- *
97
- * This method emulates the functionality of modern browsers for the old IE case.
98
- *
99
- * @param {String} str The string to split.
100
- * @param {RegExp} splitRegex The regular expression to split the input `str` on. The splitting
101
- * character(s) will be spliced into the array, as in the "modern browsers" example in the
102
- * description of this method.
103
- * Note #1: the supplied regular expression **must** have the 'g' flag specified.
104
- * Note #2: for simplicity's sake, the regular expression does not need
105
- * to contain capturing parenthesis - it will be assumed that any match has them.
106
- * @return {String[]} The split array of strings, with the splitting character(s) included.
107
- */
108
- function splitAndCapture(str, splitRegex) {
109
- if (!splitRegex.global) throw new Error("`splitRegex` must have the 'g' flag set");
110
- var result = [],
111
- lastIdx = 0,
112
- match;
113
- while (match = splitRegex.exec(str)) {
114
- result.push(str.substring(lastIdx, match.index));
115
- result.push(match[0]); // push the splitting char(s)
116
- lastIdx = match.index + match[0].length;
117
- }
118
- result.push(str.substring(lastIdx));
119
- return result;
120
- }
121
- /**
122
- * Function that should never be called but is used to check that every
123
- * enum value is handled using TypeScript's 'never' type.
124
- */
125
- function throwUnhandledCaseError(theValue) {
126
- throw new Error("Unhandled case for value: '".concat(theValue, "'"));
127
- }
128
-
129
- /**
130
- * @class Autolinker.HtmlTag
131
- * @extends Object
132
- *
133
- * Represents an HTML tag, which can be used to easily build/modify HTML tags programmatically.
134
- *
135
- * Autolinker uses this abstraction to create HTML tags, and then write them out as strings. You may also use
136
- * this class in your code, especially within a {@link Autolinker#replaceFn replaceFn}.
137
- *
138
- * ## Examples
139
- *
140
- * Example instantiation:
141
- *
142
- * var tag = new Autolinker.HtmlTag( {
143
- * tagName : 'a',
144
- * attrs : { 'href': 'http://google.com', 'class': 'external-link' },
145
- * innerHtml : 'Google'
146
- * } );
147
- *
148
- * tag.toAnchorString(); // <a href="http://google.com" class="external-link">Google</a>
149
- *
150
- * // Individual accessor methods
151
- * tag.getTagName(); // 'a'
152
- * tag.getAttr( 'href' ); // 'http://google.com'
153
- * tag.hasClass( 'external-link' ); // true
154
- *
155
- *
156
- * Using mutator methods (which may be used in combination with instantiation config properties):
157
- *
158
- * var tag = new Autolinker.HtmlTag();
159
- * tag.setTagName( 'a' );
160
- * tag.setAttr( 'href', 'http://google.com' );
161
- * tag.addClass( 'external-link' );
162
- * tag.setInnerHtml( 'Google' );
163
- *
164
- * tag.getTagName(); // 'a'
165
- * tag.getAttr( 'href' ); // 'http://google.com'
166
- * tag.hasClass( 'external-link' ); // true
167
- *
168
- * tag.toAnchorString(); // <a href="http://google.com" class="external-link">Google</a>
169
- *
170
- *
171
- * ## Example use within a {@link Autolinker#replaceFn replaceFn}
172
- *
173
- * var html = Autolinker.link( "Test google.com", {
174
- * replaceFn : function( match ) {
175
- * var tag = match.buildTag(); // returns an {@link Autolinker.HtmlTag} instance, configured with the Match's href and anchor text
176
- * tag.setAttr( 'rel', 'nofollow' );
177
- *
178
- * return tag;
179
- * }
180
- * } );
181
- *
182
- * // generated html:
183
- * // Test <a href="http://google.com" target="_blank" rel="nofollow">google.com</a>
184
- *
185
- *
186
- * ## Example use with a new tag for the replacement
187
- *
188
- * var html = Autolinker.link( "Test google.com", {
189
- * replaceFn : function( match ) {
190
- * var tag = new Autolinker.HtmlTag( {
191
- * tagName : 'button',
192
- * attrs : { 'title': 'Load URL: ' + match.getAnchorHref() },
193
- * innerHtml : 'Load URL: ' + match.getAnchorText()
194
- * } );
195
- *
196
- * return tag;
197
- * }
198
- * } );
199
- *
200
- * // generated html:
201
- * // Test <button title="Load URL: http://google.com">Load URL: google.com</button>
202
- */
203
- var HtmlTag = /** @class */function () {
204
- /**
205
- * @method constructor
206
- * @param {Object} [cfg] The configuration properties for this class, in an Object (map)
207
- */
208
- function HtmlTag(cfg) {
209
- if (cfg === void 0) {
210
- cfg = {};
211
- }
212
- /**
213
- * @cfg {String} tagName
214
- *
215
- * The tag name. Ex: 'a', 'button', etc.
216
- *
217
- * Not required at instantiation time, but should be set using {@link #setTagName} before {@link #toAnchorString}
218
- * is executed.
219
- */
220
- this.tagName = ''; // default value just to get the above doc comment in the ES5 output and documentation generator
221
- /**
222
- * @cfg {Object.<String, String>} attrs
223
- *
224
- * An key/value Object (map) of attributes to create the tag with. The keys are the attribute names, and the
225
- * values are the attribute values.
226
- */
227
- this.attrs = {}; // default value just to get the above doc comment in the ES5 output and documentation generator
228
- /**
229
- * @cfg {String} innerHTML
230
- *
231
- * The inner HTML for the tag.
232
- */
233
- this.innerHTML = ''; // default value just to get the above doc comment in the ES5 output and documentation generator
234
- /**
235
- * @protected
236
- * @property {RegExp} whitespaceRegex
237
- *
238
- * Regular expression used to match whitespace in a string of CSS classes.
239
- */
240
- this.whitespaceRegex = /\s+/; // default value just to get the above doc comment in the ES5 output and documentation generator
241
- this.tagName = cfg.tagName || '';
242
- this.attrs = cfg.attrs || {};
243
- this.innerHTML = cfg.innerHtml || cfg.innerHTML || ''; // accept either the camelCased form or the fully capitalized acronym as in the DOM
244
- }
245
- /**
246
- * Sets the tag name that will be used to generate the tag with.
247
- *
248
- * @param {String} tagName
249
- * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained.
250
- */
251
- HtmlTag.prototype.setTagName = function (tagName) {
252
- this.tagName = tagName;
253
- return this;
254
- };
255
- /**
256
- * Retrieves the tag name.
257
- *
258
- * @return {String}
259
- */
260
- HtmlTag.prototype.getTagName = function () {
261
- return this.tagName || '';
262
- };
263
- /**
264
- * Sets an attribute on the HtmlTag.
265
- *
266
- * @param {String} attrName The attribute name to set.
267
- * @param {String} attrValue The attribute value to set.
268
- * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained.
269
- */
270
- HtmlTag.prototype.setAttr = function (attrName, attrValue) {
271
- var tagAttrs = this.getAttrs();
272
- tagAttrs[attrName] = attrValue;
273
- return this;
274
- };
275
- /**
276
- * Retrieves an attribute from the HtmlTag. If the attribute does not exist, returns `undefined`.
277
- *
278
- * @param {String} attrName The attribute name to retrieve.
279
- * @return {String} The attribute's value, or `undefined` if it does not exist on the HtmlTag.
280
- */
281
- HtmlTag.prototype.getAttr = function (attrName) {
282
- return this.getAttrs()[attrName];
283
- };
284
- /**
285
- * Sets one or more attributes on the HtmlTag.
286
- *
287
- * @param {Object.<String, String>} attrs A key/value Object (map) of the attributes to set.
288
- * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained.
289
- */
290
- HtmlTag.prototype.setAttrs = function (attrs) {
291
- Object.assign(this.getAttrs(), attrs);
292
- return this;
293
- };
294
- /**
295
- * Retrieves the attributes Object (map) for the HtmlTag.
296
- *
297
- * @return {Object.<String, String>} A key/value object of the attributes for the HtmlTag.
298
- */
299
- HtmlTag.prototype.getAttrs = function () {
300
- return this.attrs || (this.attrs = {});
301
- };
302
- /**
303
- * Sets the provided `cssClass`, overwriting any current CSS classes on the HtmlTag.
304
- *
305
- * @param {String} cssClass One or more space-separated CSS classes to set (overwrite).
306
- * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained.
307
- */
308
- HtmlTag.prototype.setClass = function (cssClass) {
309
- return this.setAttr('class', cssClass);
310
- };
311
- /**
312
- * Convenience method to add one or more CSS classes to the HtmlTag. Will not add duplicate CSS classes.
313
- *
314
- * @param {String} cssClass One or more space-separated CSS classes to add.
315
- * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained.
316
- */
317
- HtmlTag.prototype.addClass = function (cssClass) {
318
- var classAttr = this.getClass(),
319
- whitespaceRegex = this.whitespaceRegex,
320
- classes = !classAttr ? [] : classAttr.split(whitespaceRegex),
321
- newClasses = cssClass.split(whitespaceRegex),
322
- newClass;
323
- while (newClass = newClasses.shift()) {
324
- if (indexOf(classes, newClass) === -1) {
325
- classes.push(newClass);
326
- }
327
- }
328
- this.getAttrs()['class'] = classes.join(' ');
329
- return this;
330
- };
331
- /**
332
- * Convenience method to remove one or more CSS classes from the HtmlTag.
333
- *
334
- * @param {String} cssClass One or more space-separated CSS classes to remove.
335
- * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained.
336
- */
337
- HtmlTag.prototype.removeClass = function (cssClass) {
338
- var classAttr = this.getClass(),
339
- whitespaceRegex = this.whitespaceRegex,
340
- classes = !classAttr ? [] : classAttr.split(whitespaceRegex),
341
- removeClasses = cssClass.split(whitespaceRegex),
342
- removeClass;
343
- while (classes.length && (removeClass = removeClasses.shift())) {
344
- var idx = indexOf(classes, removeClass);
345
- if (idx !== -1) {
346
- classes.splice(idx, 1);
347
- }
348
- }
349
- this.getAttrs()['class'] = classes.join(' ');
350
- return this;
351
- };
352
- /**
353
- * Convenience method to retrieve the CSS class(es) for the HtmlTag, which will each be separated by spaces when
354
- * there are multiple.
355
- *
356
- * @return {String}
357
- */
358
- HtmlTag.prototype.getClass = function () {
359
- return this.getAttrs()['class'] || '';
360
- };
361
- /**
362
- * Convenience method to check if the tag has a CSS class or not.
363
- *
364
- * @param {String} cssClass The CSS class to check for.
365
- * @return {Boolean} `true` if the HtmlTag has the CSS class, `false` otherwise.
366
- */
367
- HtmlTag.prototype.hasClass = function (cssClass) {
368
- return (' ' + this.getClass() + ' ').indexOf(' ' + cssClass + ' ') !== -1;
369
- };
370
- /**
371
- * Sets the inner HTML for the tag.
372
- *
373
- * @param {String} html The inner HTML to set.
374
- * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained.
375
- */
376
- HtmlTag.prototype.setInnerHTML = function (html) {
377
- this.innerHTML = html;
378
- return this;
379
- };
380
- /**
381
- * Backwards compatibility method name.
382
- *
383
- * @param {String} html The inner HTML to set.
384
- * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained.
385
- */
386
- HtmlTag.prototype.setInnerHtml = function (html) {
387
- return this.setInnerHTML(html);
388
- };
389
- /**
390
- * Retrieves the inner HTML for the tag.
391
- *
392
- * @return {String}
393
- */
394
- HtmlTag.prototype.getInnerHTML = function () {
395
- return this.innerHTML || '';
396
- };
397
- /**
398
- * Backward compatibility method name.
399
- *
400
- * @return {String}
401
- */
402
- HtmlTag.prototype.getInnerHtml = function () {
403
- return this.getInnerHTML();
404
- };
405
- /**
406
- * Override of superclass method used to generate the HTML string for the tag.
407
- *
408
- * @return {String}
409
- */
410
- HtmlTag.prototype.toAnchorString = function () {
411
- var tagName = this.getTagName(),
412
- attrsStr = this.buildAttrsStr();
413
- attrsStr = attrsStr ? ' ' + attrsStr : ''; // prepend a space if there are actually attributes
414
- return ['<', tagName, attrsStr, '>', this.getInnerHtml(), '</', tagName, '>'].join('');
415
- };
416
- /**
417
- * Support method for {@link #toAnchorString}, returns the string space-separated key="value" pairs, used to populate
418
- * the stringified HtmlTag.
419
- *
420
- * @protected
421
- * @return {String} Example return: `attr1="value1" attr2="value2"`
422
- */
423
- HtmlTag.prototype.buildAttrsStr = function () {
424
- if (!this.attrs) return ''; // no `attrs` Object (map) has been set, return empty string
425
- var attrs = this.getAttrs(),
426
- attrsArr = [];
427
- for (var prop in attrs) {
428
- if (attrs.hasOwnProperty(prop)) {
429
- attrsArr.push(prop + '="' + attrs[prop] + '"');
430
- }
431
- }
432
- return attrsArr.join(' ');
433
- };
434
- return HtmlTag;
435
- }();
436
-
437
- /**
438
- * Date: 2015-10-05
439
- * Author: Kasper Søfren <soefritz@gmail.com> (https://github.com/kafoso)
440
- *
441
- * A truncation feature, where the ellipsis will be placed at a section within
442
- * the URL making it still somewhat human readable.
443
- *
444
- * @param {String} url A URL.
445
- * @param {Number} truncateLen The maximum length of the truncated output URL string.
446
- * @param {String} ellipsisChars The characters to place within the url, e.g. "...".
447
- * @return {String} The truncated URL.
448
- */
449
- function truncateSmart(url, truncateLen, ellipsisChars) {
450
- var ellipsisLengthBeforeParsing;
451
- var ellipsisLength;
452
- if (ellipsisChars == null) {
453
- ellipsisChars = '&hellip;';
454
- ellipsisLength = 3;
455
- ellipsisLengthBeforeParsing = 8;
456
- } else {
457
- ellipsisLength = ellipsisChars.length;
458
- ellipsisLengthBeforeParsing = ellipsisChars.length;
459
- }
460
- var parse_url = function (url) {
461
- // Functionality inspired by PHP function of same name
462
- var urlObj = {};
463
- var urlSub = url;
464
- var match = urlSub.match(/^([a-z]+):\/\//i);
465
- if (match) {
466
- urlObj.scheme = match[1];
467
- urlSub = urlSub.substr(match[0].length);
468
- }
469
- match = urlSub.match(/^(.*?)(?=(\?|#|\/|$))/i);
470
- if (match) {
471
- urlObj.host = match[1];
472
- urlSub = urlSub.substr(match[0].length);
473
- }
474
- match = urlSub.match(/^\/(.*?)(?=(\?|#|$))/i);
475
- if (match) {
476
- urlObj.path = match[1];
477
- urlSub = urlSub.substr(match[0].length);
478
- }
479
- match = urlSub.match(/^\?(.*?)(?=(#|$))/i);
480
- if (match) {
481
- urlObj.query = match[1];
482
- urlSub = urlSub.substr(match[0].length);
483
- }
484
- match = urlSub.match(/^#(.*?)$/i);
485
- if (match) {
486
- urlObj.fragment = match[1];
487
- //urlSub = urlSub.substr(match[0].length); -- not used. Uncomment if adding another block.
488
- }
489
-
490
- return urlObj;
491
- };
492
- var buildUrl = function (urlObj) {
493
- var url = '';
494
- if (urlObj.scheme && urlObj.host) {
495
- url += urlObj.scheme + '://';
496
- }
497
- if (urlObj.host) {
498
- url += urlObj.host;
499
- }
500
- if (urlObj.path) {
501
- url += '/' + urlObj.path;
502
- }
503
- if (urlObj.query) {
504
- url += '?' + urlObj.query;
505
- }
506
- if (urlObj.fragment) {
507
- url += '#' + urlObj.fragment;
508
- }
509
- return url;
510
- };
511
- var buildSegment = function (segment, remainingAvailableLength) {
512
- var remainingAvailableLengthHalf = remainingAvailableLength / 2,
513
- startOffset = Math.ceil(remainingAvailableLengthHalf),
514
- endOffset = -1 * Math.floor(remainingAvailableLengthHalf),
515
- end = '';
516
- if (endOffset < 0) {
517
- end = segment.substr(endOffset);
518
- }
519
- return segment.substr(0, startOffset) + ellipsisChars + end;
520
- };
521
- if (url.length <= truncateLen) {
522
- return url;
523
- }
524
- var availableLength = truncateLen - ellipsisLength;
525
- var urlObj = parse_url(url);
526
- // Clean up the URL
527
- if (urlObj.query) {
528
- var matchQuery = urlObj.query.match(/^(.*?)(?=(\?|\#))(.*?)$/i);
529
- if (matchQuery) {
530
- // Malformed URL; two or more "?". Removed any content behind the 2nd.
531
- urlObj.query = urlObj.query.substr(0, matchQuery[1].length);
532
- url = buildUrl(urlObj);
533
- }
534
- }
535
- if (url.length <= truncateLen) {
536
- return url;
537
- }
538
- if (urlObj.host) {
539
- urlObj.host = urlObj.host.replace(/^www\./, '');
540
- url = buildUrl(urlObj);
541
- }
542
- if (url.length <= truncateLen) {
543
- return url;
544
- }
545
- // Process and build the URL
546
- var str = '';
547
- if (urlObj.host) {
548
- str += urlObj.host;
549
- }
550
- if (str.length >= availableLength) {
551
- if (urlObj.host.length == truncateLen) {
552
- return (urlObj.host.substr(0, truncateLen - ellipsisLength) + ellipsisChars).substr(0, availableLength + ellipsisLengthBeforeParsing);
553
- }
554
- return buildSegment(str, availableLength).substr(0, availableLength + ellipsisLengthBeforeParsing);
555
- }
556
- var pathAndQuery = '';
557
- if (urlObj.path) {
558
- pathAndQuery += '/' + urlObj.path;
559
- }
560
- if (urlObj.query) {
561
- pathAndQuery += '?' + urlObj.query;
562
- }
563
- if (pathAndQuery) {
564
- if ((str + pathAndQuery).length >= availableLength) {
565
- if ((str + pathAndQuery).length == truncateLen) {
566
- return (str + pathAndQuery).substr(0, truncateLen);
567
- }
568
- var remainingAvailableLength = availableLength - str.length;
569
- return (str + buildSegment(pathAndQuery, remainingAvailableLength)).substr(0, availableLength + ellipsisLengthBeforeParsing);
570
- } else {
571
- str += pathAndQuery;
572
- }
573
- }
574
- if (urlObj.fragment) {
575
- var fragment = '#' + urlObj.fragment;
576
- if ((str + fragment).length >= availableLength) {
577
- if ((str + fragment).length == truncateLen) {
578
- return (str + fragment).substr(0, truncateLen);
579
- }
580
- var remainingAvailableLength2 = availableLength - str.length;
581
- return (str + buildSegment(fragment, remainingAvailableLength2)).substr(0, availableLength + ellipsisLengthBeforeParsing);
582
- } else {
583
- str += fragment;
584
- }
585
- }
586
- if (urlObj.scheme && urlObj.host) {
587
- var scheme = urlObj.scheme + '://';
588
- if ((str + scheme).length < availableLength) {
589
- return (scheme + str).substr(0, truncateLen);
590
- }
591
- }
592
- if (str.length <= truncateLen) {
593
- return str;
594
- }
595
- var end = '';
596
- if (availableLength > 0) {
597
- end = str.substr(-1 * Math.floor(availableLength / 2));
598
- }
599
- return (str.substr(0, Math.ceil(availableLength / 2)) + ellipsisChars + end).substr(0, availableLength + ellipsisLengthBeforeParsing);
600
- }
601
-
602
- /**
603
- * Date: 2015-10-05
604
- * Author: Kasper Søfren <soefritz@gmail.com> (https://github.com/kafoso)
605
- *
606
- * A truncation feature, where the ellipsis will be placed in the dead-center of the URL.
607
- *
608
- * @param {String} url A URL.
609
- * @param {Number} truncateLen The maximum length of the truncated output URL string.
610
- * @param {String} ellipsisChars The characters to place within the url, e.g. "..".
611
- * @return {String} The truncated URL.
612
- */
613
- function truncateMiddle(url, truncateLen, ellipsisChars) {
614
- if (url.length <= truncateLen) {
615
- return url;
616
- }
617
- var ellipsisLengthBeforeParsing;
618
- var ellipsisLength;
619
- if (ellipsisChars == null) {
620
- ellipsisChars = '&hellip;';
621
- ellipsisLengthBeforeParsing = 8;
622
- ellipsisLength = 3;
623
- } else {
624
- ellipsisLengthBeforeParsing = ellipsisChars.length;
625
- ellipsisLength = ellipsisChars.length;
626
- }
627
- var availableLength = truncateLen - ellipsisLength;
628
- var end = '';
629
- if (availableLength > 0) {
630
- end = url.substr(-1 * Math.floor(availableLength / 2));
631
- }
632
- return (url.substr(0, Math.ceil(availableLength / 2)) + ellipsisChars + end).substr(0, availableLength + ellipsisLengthBeforeParsing);
633
- }
634
-
635
- /**
636
- * A truncation feature where the ellipsis will be placed at the end of the URL.
637
- *
638
- * @param {String} anchorText
639
- * @param {Number} truncateLen The maximum length of the truncated output URL string.
640
- * @param {String} ellipsisChars The characters to place within the url, e.g. "..".
641
- * @return {String} The truncated URL.
642
- */
643
- function truncateEnd(anchorText, truncateLen, ellipsisChars) {
644
- return ellipsis(anchorText, truncateLen, ellipsisChars);
645
- }
646
-
647
- /**
648
- * @protected
649
- * @class Autolinker.AnchorTagBuilder
650
- * @extends Object
651
- *
652
- * Builds anchor (&lt;a&gt;) tags for the Autolinker utility when a match is
653
- * found.
654
- *
655
- * Normally this class is instantiated, configured, and used internally by an
656
- * {@link Autolinker} instance, but may actually be used indirectly in a
657
- * {@link Autolinker#replaceFn replaceFn} to create {@link Autolinker.HtmlTag HtmlTag}
658
- * instances which may be modified before returning from the
659
- * {@link Autolinker#replaceFn replaceFn}. For example:
660
- *
661
- * var html = Autolinker.link( "Test google.com", {
662
- * replaceFn : function( match ) {
663
- * var tag = match.buildTag(); // returns an {@link Autolinker.HtmlTag} instance
664
- * tag.setAttr( 'rel', 'nofollow' );
665
- *
666
- * return tag;
667
- * }
668
- * } );
669
- *
670
- * // generated html:
671
- * // Test <a href="http://google.com" target="_blank" rel="nofollow">google.com</a>
672
- */
673
- var AnchorTagBuilder = /** @class */function () {
674
- /**
675
- * @method constructor
676
- * @param {Object} [cfg] The configuration options for the AnchorTagBuilder instance, specified in an Object (map).
677
- */
678
- function AnchorTagBuilder(cfg) {
679
- if (cfg === void 0) {
680
- cfg = {};
681
- }
682
- /**
683
- * @cfg {Boolean} newWindow
684
- * @inheritdoc Autolinker#newWindow
685
- */
686
- this.newWindow = false; // default value just to get the above doc comment in the ES5 output and documentation generator
687
- /**
688
- * @cfg {Object} truncate
689
- * @inheritdoc Autolinker#truncate
690
- */
691
- this.truncate = {}; // default value just to get the above doc comment in the ES5 output and documentation generator
692
- /**
693
- * @cfg {String} className
694
- * @inheritdoc Autolinker#className
695
- */
696
- this.className = ''; // default value just to get the above doc comment in the ES5 output and documentation generator
697
- this.newWindow = cfg.newWindow || false;
698
- this.truncate = cfg.truncate || {};
699
- this.className = cfg.className || '';
700
- }
701
- /**
702
- * Generates the actual anchor (&lt;a&gt;) tag to use in place of the
703
- * matched text, via its `match` object.
704
- *
705
- * @param {Autolinker.match.Match} match The Match instance to generate an
706
- * anchor tag from.
707
- * @return {Autolinker.HtmlTag} The HtmlTag instance for the anchor tag.
708
- */
709
- AnchorTagBuilder.prototype.build = function (match) {
710
- return new HtmlTag({
711
- tagName: 'a',
712
- attrs: this.createAttrs(match),
713
- innerHtml: this.processAnchorText(match.getAnchorText())
714
- });
715
- };
716
- /**
717
- * Creates the Object (map) of the HTML attributes for the anchor (&lt;a&gt;)
718
- * tag being generated.
719
- *
720
- * @protected
721
- * @param {Autolinker.match.Match} match The Match instance to generate an
722
- * anchor tag from.
723
- * @return {Object} A key/value Object (map) of the anchor tag's attributes.
724
- */
725
- AnchorTagBuilder.prototype.createAttrs = function (match) {
726
- var attrs = {
727
- href: match.getAnchorHref() // we'll always have the `href` attribute
728
- };
729
-
730
- var cssClass = this.createCssClass(match);
731
- if (cssClass) {
732
- attrs['class'] = cssClass;
733
- }
734
- if (this.newWindow) {
735
- attrs['target'] = '_blank';
736
- attrs['rel'] = 'noopener noreferrer'; // Issue #149. See https://mathiasbynens.github.io/rel-noopener/
737
- }
738
-
739
- if (this.truncate) {
740
- if (this.truncate.length && this.truncate.length < match.getAnchorText().length) {
741
- attrs['title'] = match.getAnchorHref();
742
- }
743
- }
744
- return attrs;
745
- };
746
- /**
747
- * Creates the CSS class that will be used for a given anchor tag, based on
748
- * the `matchType` and the {@link #className} config.
749
- *
750
- * Example returns:
751
- *
752
- * - "" // no {@link #className}
753
- * - "myLink myLink-url" // url match
754
- * - "myLink myLink-email" // email match
755
- * - "myLink myLink-phone" // phone match
756
- * - "myLink myLink-hashtag" // hashtag match
757
- * - "myLink myLink-mention myLink-twitter" // mention match with Twitter service
758
- *
759
- * @protected
760
- * @param {Autolinker.match.Match} match The Match instance to generate an
761
- * anchor tag from.
762
- * @return {String} The CSS class string for the link. Example return:
763
- * "myLink myLink-url". If no {@link #className} was configured, returns
764
- * an empty string.
765
- */
766
- AnchorTagBuilder.prototype.createCssClass = function (match) {
767
- var className = this.className;
768
- if (!className) {
769
- return '';
770
- } else {
771
- var returnClasses = [className],
772
- cssClassSuffixes = match.getCssClassSuffixes();
773
- for (var i = 0, len = cssClassSuffixes.length; i < len; i++) {
774
- returnClasses.push(className + '-' + cssClassSuffixes[i]);
775
- }
776
- return returnClasses.join(' ');
777
- }
778
- };
779
- /**
780
- * Processes the `anchorText` by truncating the text according to the
781
- * {@link #truncate} config.
782
- *
783
- * @private
784
- * @param {String} anchorText The anchor tag's text (i.e. what will be
785
- * displayed).
786
- * @return {String} The processed `anchorText`.
787
- */
788
- AnchorTagBuilder.prototype.processAnchorText = function (anchorText) {
789
- anchorText = this.doTruncate(anchorText);
790
- return anchorText;
791
- };
792
- /**
793
- * Performs the truncation of the `anchorText` based on the {@link #truncate}
794
- * option. If the `anchorText` is longer than the length specified by the
795
- * {@link #truncate} option, the truncation is performed based on the
796
- * `location` property. See {@link #truncate} for details.
797
- *
798
- * @private
799
- * @param {String} anchorText The anchor tag's text (i.e. what will be
800
- * displayed).
801
- * @return {String} The truncated anchor text.
802
- */
803
- AnchorTagBuilder.prototype.doTruncate = function (anchorText) {
804
- var truncate = this.truncate;
805
- if (!truncate || !truncate.length) return anchorText;
806
- var truncateLength = truncate.length,
807
- truncateLocation = truncate.location;
808
- if (truncateLocation === 'smart') {
809
- return truncateSmart(anchorText, truncateLength);
810
- } else if (truncateLocation === 'middle') {
811
- return truncateMiddle(anchorText, truncateLength);
812
- } else {
813
- return truncateEnd(anchorText, truncateLength);
814
- }
815
- };
816
- return AnchorTagBuilder;
817
- }();
818
-
819
- /**
820
- * @abstract
821
- * @class Autolinker.match.Match
822
- *
823
- * Represents a match found in an input string which should be Autolinked. A Match object is what is provided in a
824
- * {@link Autolinker#replaceFn replaceFn}, and may be used to query for details about the match.
825
- *
826
- * For example:
827
- *
828
- * var input = "..."; // string with URLs, Email Addresses, and Mentions (Twitter, Instagram, Soundcloud)
829
- *
830
- * var linkedText = Autolinker.link( input, {
831
- * replaceFn : function( match ) {
832
- * console.log( "href = ", match.getAnchorHref() );
833
- * console.log( "text = ", match.getAnchorText() );
834
- *
835
- * switch( match.getType() ) {
836
- * case 'url' :
837
- * console.log( "url: ", match.getUrl() );
838
- *
839
- * case 'email' :
840
- * console.log( "email: ", match.getEmail() );
841
- *
842
- * case 'mention' :
843
- * console.log( "mention: ", match.getMention() );
844
- * }
845
- * }
846
- * } );
847
- *
848
- * See the {@link Autolinker} class for more details on using the {@link Autolinker#replaceFn replaceFn}.
849
- */
850
- var Match = /** @class */function () {
851
- /**
852
- * @member Autolinker.match.Match
853
- * @method constructor
854
- * @param {Object} cfg The configuration properties for the Match
855
- * instance, specified in an Object (map).
856
- */
857
- function Match(cfg) {
858
- /**
859
- * @cfg {Autolinker.AnchorTagBuilder} tagBuilder (required)
860
- *
861
- * Reference to the AnchorTagBuilder instance to use to generate an anchor
862
- * tag for the Match.
863
- */
864
- // @ts-ignore
865
- this.__jsduckDummyDocProp = null; // property used just to get the above doc comment into the ES5 output and documentation generator
866
- /**
867
- * @cfg {String} matchedText (required)
868
- *
869
- * The original text that was matched by the {@link Autolinker.matcher.Matcher}.
870
- */
871
- this.matchedText = ''; // default value just to get the above doc comment in the ES5 output and documentation generator
872
- /**
873
- * @cfg {Number} offset (required)
874
- *
875
- * The offset of where the match was made in the input string.
876
- */
877
- this.offset = 0; // default value just to get the above doc comment in the ES5 output and documentation generator
878
- this.tagBuilder = cfg.tagBuilder;
879
- this.matchedText = cfg.matchedText;
880
- this.offset = cfg.offset;
881
- }
882
- /**
883
- * Returns the original text that was matched.
884
- *
885
- * @return {String}
886
- */
887
- Match.prototype.getMatchedText = function () {
888
- return this.matchedText;
889
- };
890
- /**
891
- * Sets the {@link #offset} of where the match was made in the input string.
892
- *
893
- * A {@link Autolinker.matcher.Matcher} will be fed only HTML text nodes,
894
- * and will therefore set an original offset that is relative to the HTML
895
- * text node itself. However, we want this offset to be relative to the full
896
- * HTML input string, and thus if using {@link Autolinker#parse} (rather
897
- * than calling a {@link Autolinker.matcher.Matcher} directly), then this
898
- * offset is corrected after the Matcher itself has done its job.
899
- *
900
- * @param {Number} offset
901
- */
902
- Match.prototype.setOffset = function (offset) {
903
- this.offset = offset;
904
- };
905
- /**
906
- * Returns the offset of where the match was made in the input string. This
907
- * is the 0-based index of the match.
908
- *
909
- * @return {Number}
910
- */
911
- Match.prototype.getOffset = function () {
912
- return this.offset;
913
- };
914
- /**
915
- * Returns the CSS class suffix(es) for this match.
916
- *
917
- * A CSS class suffix is appended to the {@link Autolinker#className} in
918
- * the {@link Autolinker.AnchorTagBuilder} when a match is translated into
919
- * an anchor tag.
920
- *
921
- * For example, if {@link Autolinker#className} was configured as 'myLink',
922
- * and this method returns `[ 'url' ]`, the final class name of the element
923
- * will become: 'myLink myLink-url'.
924
- *
925
- * The match may provide multiple CSS class suffixes to be appended to the
926
- * {@link Autolinker#className} in order to facilitate better styling
927
- * options for different match criteria. See {@link Autolinker.match.Mention}
928
- * for an example.
929
- *
930
- * By default, this method returns a single array with the match's
931
- * {@link #getType type} name, but may be overridden by subclasses.
932
- *
933
- * @return {String[]}
934
- */
935
- Match.prototype.getCssClassSuffixes = function () {
936
- return [this.getType()];
937
- };
938
- /**
939
- * Builds and returns an {@link Autolinker.HtmlTag} instance based on the
940
- * Match.
941
- *
942
- * This can be used to easily generate anchor tags from matches, and either
943
- * return their HTML string, or modify them before doing so.
944
- *
945
- * Example Usage:
946
- *
947
- * var tag = match.buildTag();
948
- * tag.addClass( 'cordova-link' );
949
- * tag.setAttr( 'target', '_system' );
950
- *
951
- * tag.toAnchorString(); // <a href="http://google.com" class="cordova-link" target="_system">Google</a>
952
- *
953
- * Example Usage in {@link Autolinker#replaceFn}:
954
- *
955
- * var html = Autolinker.link( "Test google.com", {
956
- * replaceFn : function( match ) {
957
- * var tag = match.buildTag(); // returns an {@link Autolinker.HtmlTag} instance
958
- * tag.setAttr( 'rel', 'nofollow' );
959
- *
960
- * return tag;
961
- * }
962
- * } );
963
- *
964
- * // generated html:
965
- * // Test <a href="http://google.com" target="_blank" rel="nofollow">google.com</a>
966
- */
967
- Match.prototype.buildTag = function () {
968
- return this.tagBuilder.build(this);
969
- };
970
- return Match;
971
- }();
972
-
973
- /******************************************************************************
974
- Copyright (c) Microsoft Corporation.
975
-
976
- Permission to use, copy, modify, and/or distribute this software for any
977
- purpose with or without fee is hereby granted.
978
-
979
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
980
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
981
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
982
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
983
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
984
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
985
- PERFORMANCE OF THIS SOFTWARE.
986
- ***************************************************************************** */
987
- /* global Reflect, Promise, SuppressedError, Symbol */
988
-
989
- var extendStatics = function (d, b) {
990
- extendStatics = Object.setPrototypeOf || {
991
- __proto__: []
992
- } instanceof Array && function (d, b) {
993
- d.__proto__ = b;
994
- } || function (d, b) {
995
- for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];
996
- };
997
- return extendStatics(d, b);
998
- };
999
- function __extends(d, b) {
1000
- if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
1001
- extendStatics(d, b);
1002
- function __() {
1003
- this.constructor = d;
1004
- }
1005
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
1006
- }
1007
- var __assign = function () {
1008
- __assign = Object.assign || function __assign(t) {
1009
- for (var s, i = 1, n = arguments.length; i < n; i++) {
1010
- s = arguments[i];
1011
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
1012
- }
1013
- return t;
1014
- };
1015
- return __assign.apply(this, arguments);
1016
- };
1017
- var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
1018
- var e = new Error(message);
1019
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
1020
- };
1021
-
1022
- /**
1023
- * @class Autolinker.match.Email
1024
- * @extends Autolinker.match.Match
1025
- *
1026
- * Represents a Email match found in an input string which should be Autolinked.
1027
- *
1028
- * See this class's superclass ({@link Autolinker.match.Match}) for more details.
1029
- */
1030
- var EmailMatch = /** @class */function (_super) {
1031
- __extends(EmailMatch, _super);
1032
- /**
1033
- * @method constructor
1034
- * @param {Object} cfg The configuration properties for the Match
1035
- * instance, specified in an Object (map).
1036
- */
1037
- function EmailMatch(cfg) {
1038
- var _this = _super.call(this, cfg) || this;
1039
- /**
1040
- * @cfg {String} email (required)
1041
- *
1042
- * The email address that was matched.
1043
- */
1044
- _this.email = ''; // default value just to get the above doc comment in the ES5 output and documentation generator
1045
- _this.email = cfg.email;
1046
- return _this;
1047
- }
1048
- /**
1049
- * Returns a string name for the type of match that this class represents.
1050
- * For the case of EmailMatch, returns 'email'.
1051
- *
1052
- * @return {String}
1053
- */
1054
- EmailMatch.prototype.getType = function () {
1055
- return 'email';
1056
- };
1057
- /**
1058
- * Returns the email address that was matched.
1059
- *
1060
- * @return {String}
1061
- */
1062
- EmailMatch.prototype.getEmail = function () {
1063
- return this.email;
1064
- };
1065
- /**
1066
- * Returns the anchor href that should be generated for the match.
1067
- *
1068
- * @return {String}
1069
- */
1070
- EmailMatch.prototype.getAnchorHref = function () {
1071
- return 'mailto:' + this.email;
1072
- };
1073
- /**
1074
- * Returns the anchor text that should be generated for the match.
1075
- *
1076
- * @return {String}
1077
- */
1078
- EmailMatch.prototype.getAnchorText = function () {
1079
- return this.email;
1080
- };
1081
- return EmailMatch;
1082
- }(Match);
1083
-
1084
- /**
1085
- * @class Autolinker.match.Hashtag
1086
- * @extends Autolinker.match.Match
1087
- *
1088
- * Represents a Hashtag match found in an input string which should be
1089
- * Autolinked.
1090
- *
1091
- * See this class's superclass ({@link Autolinker.match.Match}) for more
1092
- * details.
1093
- */
1094
- var HashtagMatch = /** @class */function (_super) {
1095
- __extends(HashtagMatch, _super);
1096
- /**
1097
- * @method constructor
1098
- * @param {Object} cfg The configuration properties for the Match
1099
- * instance, specified in an Object (map).
1100
- */
1101
- function HashtagMatch(cfg) {
1102
- var _this = _super.call(this, cfg) || this;
1103
- /**
1104
- * @cfg {String} serviceName
1105
- *
1106
- * The service to point hashtag matches to. See {@link Autolinker#hashtag}
1107
- * for available values.
1108
- */
1109
- _this.serviceName = ''; // default value just to get the above doc comment in the ES5 output and documentation generator
1110
- /**
1111
- * @cfg {String} hashtag (required)
1112
- *
1113
- * The HashtagMatch that was matched, without the '#'.
1114
- */
1115
- _this.hashtag = ''; // default value just to get the above doc comment in the ES5 output and documentation generator
1116
- _this.serviceName = cfg.serviceName;
1117
- _this.hashtag = cfg.hashtag;
1118
- return _this;
1119
- }
1120
- /**
1121
- * Returns a string name for the type of match that this class represents.
1122
- * For the case of HashtagMatch, returns 'hashtag'.
1123
- *
1124
- * @return {String}
1125
- */
1126
- HashtagMatch.prototype.getType = function () {
1127
- return 'hashtag';
1128
- };
1129
- /**
1130
- * Returns the configured {@link #serviceName} to point the HashtagMatch to.
1131
- * Ex: 'facebook', 'twitter'.
1132
- *
1133
- * @return {String}
1134
- */
1135
- HashtagMatch.prototype.getServiceName = function () {
1136
- return this.serviceName;
1137
- };
1138
- /**
1139
- * Returns the matched hashtag, without the '#' character.
1140
- *
1141
- * @return {String}
1142
- */
1143
- HashtagMatch.prototype.getHashtag = function () {
1144
- return this.hashtag;
1145
- };
1146
- /**
1147
- * Returns the anchor href that should be generated for the match.
1148
- *
1149
- * @return {String}
1150
- */
1151
- HashtagMatch.prototype.getAnchorHref = function () {
1152
- var serviceName = this.serviceName,
1153
- hashtag = this.hashtag;
1154
- switch (serviceName) {
1155
- case 'twitter':
1156
- return 'https://twitter.com/hashtag/' + hashtag;
1157
- case 'facebook':
1158
- return 'https://www.facebook.com/hashtag/' + hashtag;
1159
- case 'instagram':
1160
- return 'https://instagram.com/explore/tags/' + hashtag;
1161
- case 'tiktok':
1162
- return 'https://www.tiktok.com/tag/' + hashtag;
1163
- default:
1164
- // Shouldn't happen because Autolinker's constructor should block any invalid values, but just in case.
1165
- throw new Error('Unknown service name to point hashtag to: ' + serviceName);
1166
- }
1167
- };
1168
- /**
1169
- * Returns the anchor text that should be generated for the match.
1170
- *
1171
- * @return {String}
1172
- */
1173
- HashtagMatch.prototype.getAnchorText = function () {
1174
- return '#' + this.hashtag;
1175
- };
1176
- return HashtagMatch;
1177
- }(Match);
1178
-
1179
- /**
1180
- * @class Autolinker.match.Mention
1181
- * @extends Autolinker.match.Match
1182
- *
1183
- * Represents a Mention match found in an input string which should be Autolinked.
1184
- *
1185
- * See this class's superclass ({@link Autolinker.match.Match}) for more details.
1186
- */
1187
- var MentionMatch = /** @class */function (_super) {
1188
- __extends(MentionMatch, _super);
1189
- /**
1190
- * @method constructor
1191
- * @param {Object} cfg The configuration properties for the Match
1192
- * instance, specified in an Object (map).
1193
- */
1194
- function MentionMatch(cfg) {
1195
- var _this = _super.call(this, cfg) || this;
1196
- /**
1197
- * @cfg {String} serviceName
1198
- *
1199
- * The service to point mention matches to. See {@link Autolinker#mention}
1200
- * for available values.
1201
- */
1202
- _this.serviceName = 'twitter'; // default value just to get the above doc comment in the ES5 output and documentation generator
1203
- /**
1204
- * @cfg {String} mention (required)
1205
- *
1206
- * The Mention that was matched, without the '@' character.
1207
- */
1208
- _this.mention = ''; // default value just to get the above doc comment in the ES5 output and documentation generator
1209
- _this.mention = cfg.mention;
1210
- _this.serviceName = cfg.serviceName;
1211
- return _this;
1212
- }
1213
- /**
1214
- * Returns a string name for the type of match that this class represents.
1215
- * For the case of MentionMatch, returns 'mention'.
1216
- *
1217
- * @return {String}
1218
- */
1219
- MentionMatch.prototype.getType = function () {
1220
- return 'mention';
1221
- };
1222
- /**
1223
- * Returns the mention, without the '@' character.
1224
- *
1225
- * @return {String}
1226
- */
1227
- MentionMatch.prototype.getMention = function () {
1228
- return this.mention;
1229
- };
1230
- /**
1231
- * Returns the configured {@link #serviceName} to point the mention to.
1232
- * Ex: 'instagram', 'twitter', 'soundcloud'.
1233
- *
1234
- * @return {String}
1235
- */
1236
- MentionMatch.prototype.getServiceName = function () {
1237
- return this.serviceName;
1238
- };
1239
- /**
1240
- * Returns the anchor href that should be generated for the match.
1241
- *
1242
- * @return {String}
1243
- */
1244
- MentionMatch.prototype.getAnchorHref = function () {
1245
- switch (this.serviceName) {
1246
- case 'twitter':
1247
- return 'https://twitter.com/' + this.mention;
1248
- case 'instagram':
1249
- return 'https://instagram.com/' + this.mention;
1250
- case 'soundcloud':
1251
- return 'https://soundcloud.com/' + this.mention;
1252
- case 'tiktok':
1253
- return 'https://www.tiktok.com/@' + this.mention;
1254
- default:
1255
- // Shouldn't happen because Autolinker's constructor should block any invalid values, but just in case.
1256
- throw new Error('Unknown service name to point mention to: ' + this.serviceName);
1257
- }
1258
- };
1259
- /**
1260
- * Returns the anchor text that should be generated for the match.
1261
- *
1262
- * @return {String}
1263
- */
1264
- MentionMatch.prototype.getAnchorText = function () {
1265
- return '@' + this.mention;
1266
- };
1267
- /**
1268
- * Returns the CSS class suffixes that should be used on a tag built with
1269
- * the match. See {@link Autolinker.match.Match#getCssClassSuffixes} for
1270
- * details.
1271
- *
1272
- * @return {String[]}
1273
- */
1274
- MentionMatch.prototype.getCssClassSuffixes = function () {
1275
- var cssClassSuffixes = _super.prototype.getCssClassSuffixes.call(this),
1276
- serviceName = this.getServiceName();
1277
- if (serviceName) {
1278
- cssClassSuffixes.push(serviceName);
1279
- }
1280
- return cssClassSuffixes;
1281
- };
1282
- return MentionMatch;
1283
- }(Match);
1284
-
1285
- /**
1286
- * @class Autolinker.match.Phone
1287
- * @extends Autolinker.match.Match
1288
- *
1289
- * Represents a Phone number match found in an input string which should be
1290
- * Autolinked.
1291
- *
1292
- * See this class's superclass ({@link Autolinker.match.Match}) for more
1293
- * details.
1294
- */
1295
- var PhoneMatch = /** @class */function (_super) {
1296
- __extends(PhoneMatch, _super);
1297
- /**
1298
- * @method constructor
1299
- * @param {Object} cfg The configuration properties for the Match
1300
- * instance, specified in an Object (map).
1301
- */
1302
- function PhoneMatch(cfg) {
1303
- var _this = _super.call(this, cfg) || this;
1304
- /**
1305
- * @protected
1306
- * @property {String} number (required)
1307
- *
1308
- * The phone number that was matched, without any delimiter characters.
1309
- *
1310
- * Note: This is a string to allow for prefixed 0's.
1311
- */
1312
- _this.number = ''; // default value just to get the above doc comment in the ES5 output and documentation generator
1313
- /**
1314
- * @protected
1315
- * @property {Boolean} plusSign (required)
1316
- *
1317
- * `true` if the matched phone number started with a '+' sign. We'll include
1318
- * it in the `tel:` URL if so, as this is needed for international numbers.
1319
- *
1320
- * Ex: '+1 (123) 456 7879'
1321
- */
1322
- _this.plusSign = false; // default value just to get the above doc comment in the ES5 output and documentation generator
1323
- _this.number = cfg.number;
1324
- _this.plusSign = cfg.plusSign;
1325
- return _this;
1326
- }
1327
- /**
1328
- * Returns a string name for the type of match that this class represents.
1329
- * For the case of PhoneMatch, returns 'phone'.
1330
- *
1331
- * @return {String}
1332
- */
1333
- PhoneMatch.prototype.getType = function () {
1334
- return 'phone';
1335
- };
1336
- /**
1337
- * Returns the phone number that was matched as a string, without any
1338
- * delimiter characters.
1339
- *
1340
- * Note: This is a string to allow for prefixed 0's.
1341
- *
1342
- * @return {String}
1343
- */
1344
- PhoneMatch.prototype.getPhoneNumber = function () {
1345
- return this.number;
1346
- };
1347
- /**
1348
- * Alias of {@link #getPhoneNumber}, returns the phone number that was
1349
- * matched as a string, without any delimiter characters.
1350
- *
1351
- * Note: This is a string to allow for prefixed 0's.
1352
- *
1353
- * @return {String}
1354
- */
1355
- PhoneMatch.prototype.getNumber = function () {
1356
- return this.getPhoneNumber();
1357
- };
1358
- /**
1359
- * Returns the anchor href that should be generated for the match.
1360
- *
1361
- * @return {String}
1362
- */
1363
- PhoneMatch.prototype.getAnchorHref = function () {
1364
- return 'tel:' + (this.plusSign ? '+' : '') + this.number;
1365
- };
1366
- /**
1367
- * Returns the anchor text that should be generated for the match.
1368
- *
1369
- * @return {String}
1370
- */
1371
- PhoneMatch.prototype.getAnchorText = function () {
1372
- return this.matchedText;
1373
- };
1374
- return PhoneMatch;
1375
- }(Match);
1376
-
1377
- /**
1378
- * @class Autolinker.match.Url
1379
- * @extends Autolinker.match.Match
1380
- *
1381
- * Represents a Url match found in an input string which should be Autolinked.
1382
- *
1383
- * See this class's superclass ({@link Autolinker.match.Match}) for more details.
1384
- */
1385
- var UrlMatch = /** @class */function (_super) {
1386
- __extends(UrlMatch, _super);
1387
- /**
1388
- * @method constructor
1389
- * @param {Object} cfg The configuration properties for the Match
1390
- * instance, specified in an Object (map).
1391
- */
1392
- function UrlMatch(cfg) {
1393
- var _this = _super.call(this, cfg) || this;
1394
- /**
1395
- * @cfg {String} url (required)
1396
- *
1397
- * The url that was matched.
1398
- */
1399
- _this.url = ''; // default value just to get the above doc comment in the ES5 output and documentation generator
1400
- /**
1401
- * @cfg {"scheme"/"www"/"tld"} urlMatchType (required)
1402
- *
1403
- * The type of URL match that this class represents. This helps to determine
1404
- * if the match was made in the original text with a prefixed scheme (ex:
1405
- * 'http://www.google.com'), a prefixed 'www' (ex: 'www.google.com'), or
1406
- * was matched by a known top-level domain (ex: 'google.com').
1407
- */
1408
- _this.urlMatchType = 'scheme'; // default value just to get the above doc comment in the ES5 output and documentation generator
1409
- /**
1410
- * @cfg {Boolean} protocolUrlMatch (required)
1411
- *
1412
- * `true` if the URL is a match which already has a protocol (i.e.
1413
- * 'http://'), `false` if the match was from a 'www' or known TLD match.
1414
- */
1415
- _this.protocolUrlMatch = false; // default value just to get the above doc comment in the ES5 output and documentation generator
1416
- /**
1417
- * @cfg {Boolean} protocolRelativeMatch (required)
1418
- *
1419
- * `true` if the URL is a protocol-relative match. A protocol-relative match
1420
- * is a URL that starts with '//', and will be either http:// or https://
1421
- * based on the protocol that the site is loaded under.
1422
- */
1423
- _this.protocolRelativeMatch = false; // default value just to get the above doc comment in the ES5 output and documentation generator
1424
- /**
1425
- * @cfg {Object} stripPrefix (required)
1426
- *
1427
- * The Object form of {@link Autolinker#cfg-stripPrefix}.
1428
- */
1429
- _this.stripPrefix = {
1430
- scheme: true,
1431
- www: true
1432
- }; // default value just to get the above doc comment in the ES5 output and documentation generator
1433
- /**
1434
- * @cfg {Boolean} stripTrailingSlash (required)
1435
- * @inheritdoc Autolinker#cfg-stripTrailingSlash
1436
- */
1437
- _this.stripTrailingSlash = true; // default value just to get the above doc comment in the ES5 output and documentation generator
1438
- /**
1439
- * @cfg {Boolean} decodePercentEncoding (required)
1440
- * @inheritdoc Autolinker#cfg-decodePercentEncoding
1441
- */
1442
- _this.decodePercentEncoding = true; // default value just to get the above doc comment in the ES5 output and documentation generator
1443
- /**
1444
- * @private
1445
- * @property {RegExp} schemePrefixRegex
1446
- *
1447
- * A regular expression used to remove the 'http://' or 'https://' from
1448
- * URLs.
1449
- */
1450
- _this.schemePrefixRegex = /^(https?:\/\/)?/i;
1451
- /**
1452
- * @private
1453
- * @property {RegExp} wwwPrefixRegex
1454
- *
1455
- * A regular expression used to remove the 'www.' from URLs.
1456
- */
1457
- _this.wwwPrefixRegex = /^(https?:\/\/)?(www\.)?/i;
1458
- /**
1459
- * @private
1460
- * @property {RegExp} protocolRelativeRegex
1461
- *
1462
- * The regular expression used to remove the protocol-relative '//' from the {@link #url} string, for purposes
1463
- * of {@link #getAnchorText}. A protocol-relative URL is, for example, "//yahoo.com"
1464
- */
1465
- _this.protocolRelativeRegex = /^\/\//;
1466
- /**
1467
- * @private
1468
- * @property {Boolean} protocolPrepended
1469
- *
1470
- * Will be set to `true` if the 'http://' protocol has been prepended to the {@link #url} (because the
1471
- * {@link #url} did not have a protocol)
1472
- */
1473
- _this.protocolPrepended = false;
1474
- _this.urlMatchType = cfg.urlMatchType;
1475
- _this.url = cfg.url;
1476
- _this.protocolUrlMatch = cfg.protocolUrlMatch;
1477
- _this.protocolRelativeMatch = cfg.protocolRelativeMatch;
1478
- _this.stripPrefix = cfg.stripPrefix;
1479
- _this.stripTrailingSlash = cfg.stripTrailingSlash;
1480
- _this.decodePercentEncoding = cfg.decodePercentEncoding;
1481
- return _this;
1482
- }
1483
- /**
1484
- * Returns a string name for the type of match that this class represents.
1485
- * For the case of UrlMatch, returns 'url'.
1486
- *
1487
- * @return {String}
1488
- */
1489
- UrlMatch.prototype.getType = function () {
1490
- return 'url';
1491
- };
1492
- /**
1493
- * Returns a string name for the type of URL match that this class
1494
- * represents.
1495
- *
1496
- * This helps to determine if the match was made in the original text with a
1497
- * prefixed scheme (ex: 'http://www.google.com'), a prefixed 'www' (ex:
1498
- * 'www.google.com'), or was matched by a known top-level domain (ex:
1499
- * 'google.com').
1500
- *
1501
- * @return {"scheme"/"www"/"tld"}
1502
- */
1503
- UrlMatch.prototype.getUrlMatchType = function () {
1504
- return this.urlMatchType;
1505
- };
1506
- /**
1507
- * Returns the url that was matched, assuming the protocol to be 'http://' if the original
1508
- * match was missing a protocol.
1509
- *
1510
- * @return {String}
1511
- */
1512
- UrlMatch.prototype.getUrl = function () {
1513
- var url = this.url;
1514
- // if the url string doesn't begin with a protocol, assume 'http://'
1515
- if (!this.protocolRelativeMatch && !this.protocolUrlMatch && !this.protocolPrepended) {
1516
- url = this.url = 'http://' + url;
1517
- this.protocolPrepended = true;
1518
- }
1519
- return url;
1520
- };
1521
- /**
1522
- * Returns the anchor href that should be generated for the match.
1523
- *
1524
- * @return {String}
1525
- */
1526
- UrlMatch.prototype.getAnchorHref = function () {
1527
- var url = this.getUrl();
1528
- return url.replace(/&amp;/g, '&'); // any &amp;'s in the URL should be converted back to '&' if they were displayed as &amp; in the source html
1529
- };
1530
- /**
1531
- * Returns the anchor text that should be generated for the match.
1532
- *
1533
- * @return {String}
1534
- */
1535
- UrlMatch.prototype.getAnchorText = function () {
1536
- var anchorText = this.getMatchedText();
1537
- if (this.protocolRelativeMatch) {
1538
- // Strip off any protocol-relative '//' from the anchor text
1539
- anchorText = this.stripProtocolRelativePrefix(anchorText);
1540
- }
1541
- if (this.stripPrefix.scheme) {
1542
- anchorText = this.stripSchemePrefix(anchorText);
1543
- }
1544
- if (this.stripPrefix.www) {
1545
- anchorText = this.stripWwwPrefix(anchorText);
1546
- }
1547
- if (this.stripTrailingSlash) {
1548
- anchorText = this.removeTrailingSlash(anchorText); // remove trailing slash, if there is one
1549
- }
1550
-
1551
- if (this.decodePercentEncoding) {
1552
- anchorText = this.removePercentEncoding(anchorText);
1553
- }
1554
- return anchorText;
1555
- };
1556
- // ---------------------------------------
1557
- // Utility Functionality
1558
- /**
1559
- * Strips the scheme prefix (such as "http://" or "https://") from the given
1560
- * `url`.
1561
- *
1562
- * @private
1563
- * @param {String} url The text of the anchor that is being generated, for
1564
- * which to strip off the url scheme.
1565
- * @return {String} The `url`, with the scheme stripped.
1566
- */
1567
- UrlMatch.prototype.stripSchemePrefix = function (url) {
1568
- return url.replace(this.schemePrefixRegex, '');
1569
- };
1570
- /**
1571
- * Strips the 'www' prefix from the given `url`.
1572
- *
1573
- * @private
1574
- * @param {String} url The text of the anchor that is being generated, for
1575
- * which to strip off the 'www' if it exists.
1576
- * @return {String} The `url`, with the 'www' stripped.
1577
- */
1578
- UrlMatch.prototype.stripWwwPrefix = function (url) {
1579
- return url.replace(this.wwwPrefixRegex, '$1'); // leave any scheme ($1), it one exists
1580
- };
1581
- /**
1582
- * Strips any protocol-relative '//' from the anchor text.
1583
- *
1584
- * @private
1585
- * @param {String} text The text of the anchor that is being generated, for which to strip off the
1586
- * protocol-relative prefix (such as stripping off "//")
1587
- * @return {String} The `anchorText`, with the protocol-relative prefix stripped.
1588
- */
1589
- UrlMatch.prototype.stripProtocolRelativePrefix = function (text) {
1590
- return text.replace(this.protocolRelativeRegex, '');
1591
- };
1592
- /**
1593
- * Removes any trailing slash from the given `anchorText`, in preparation for the text to be displayed.
1594
- *
1595
- * @private
1596
- * @param {String} anchorText The text of the anchor that is being generated, for which to remove any trailing
1597
- * slash ('/') that may exist.
1598
- * @return {String} The `anchorText`, with the trailing slash removed.
1599
- */
1600
- UrlMatch.prototype.removeTrailingSlash = function (anchorText) {
1601
- if (anchorText.charAt(anchorText.length - 1) === '/') {
1602
- anchorText = anchorText.slice(0, -1);
1603
- }
1604
- return anchorText;
1605
- };
1606
- /**
1607
- * Decodes percent-encoded characters from the given `anchorText`, in
1608
- * preparation for the text to be displayed.
1609
- *
1610
- * @private
1611
- * @param {String} anchorText The text of the anchor that is being
1612
- * generated, for which to decode any percent-encoded characters.
1613
- * @return {String} The `anchorText`, with the percent-encoded characters
1614
- * decoded.
1615
- */
1616
- UrlMatch.prototype.removePercentEncoding = function (anchorText) {
1617
- // First, convert a few of the known % encodings to the corresponding
1618
- // HTML entities that could accidentally be interpretted as special
1619
- // HTML characters
1620
- var preProcessedEntityAnchorText = anchorText.replace(/%22/gi, '&quot;') // " char
1621
- .replace(/%26/gi, '&amp;') // & char
1622
- .replace(/%27/gi, '&#39;') // ' char
1623
- .replace(/%3C/gi, '&lt;') // < char
1624
- .replace(/%3E/gi, '&gt;'); // > char
1625
- try {
1626
- // Now attempt to decode the rest of the anchor text
1627
- return decodeURIComponent(preProcessedEntityAnchorText);
1628
- } catch (e) {
1629
- // Invalid % escape sequence in the anchor text
1630
- return preProcessedEntityAnchorText;
1631
- }
1632
- };
1633
- return UrlMatch;
1634
- }(Match);
1635
-
1636
- /**
1637
- * @abstract
1638
- * @class Autolinker.matcher.Matcher
1639
- *
1640
- * An abstract class and interface for individual matchers to find matches in
1641
- * an input string with linkified versions of them.
1642
- *
1643
- * Note that Matchers do not take HTML into account - they must be fed the text
1644
- * nodes of any HTML string, which is handled by {@link Autolinker#parse}.
1645
- */
1646
- var Matcher = /** @class */function () {
1647
- /**
1648
- * @method constructor
1649
- * @param {Object} cfg The configuration properties for the Matcher
1650
- * instance, specified in an Object (map).
1651
- */
1652
- function Matcher(cfg) {
1653
- /**
1654
- * @cfg {Autolinker.AnchorTagBuilder} tagBuilder (required)
1655
- *
1656
- * Reference to the AnchorTagBuilder instance to use to generate HTML tags
1657
- * for {@link Autolinker.match.Match Matches}.
1658
- */
1659
- // @ts-ignore
1660
- this.__jsduckDummyDocProp = null; // property used just to get the above doc comment into the ES5 output and documentation generator
1661
- this.tagBuilder = cfg.tagBuilder;
1662
- }
1663
- return Matcher;
1664
- }();
1665
-
1666
- /*
1667
- * This file builds and stores a library of the common regular expressions used
1668
- * by the Autolinker utility.
1669
- *
1670
- * Other regular expressions may exist ad-hoc, but these are generally the
1671
- * regular expressions that are shared between source files.
1672
- */
1673
- /**
1674
- * Regular expression to match upper and lowercase ASCII letters
1675
- */
1676
- var letterRe = /[A-Za-z]/;
1677
- /**
1678
- * Regular expression to match ASCII digits
1679
- */
1680
- var digitRe = /[\d]/;
1681
- /**
1682
- * Regular expression to match everything *except* ASCII digits
1683
- */
1684
- var nonDigitRe = /[\D]/;
1685
- /**
1686
- * Regular expression to match whitespace
1687
- */
1688
- var whitespaceRe = /\s/;
1689
- /**
1690
- * Regular expression to match quote characters
1691
- */
1692
- var quoteRe = /['"]/;
1693
- /**
1694
- * Regular expression to match the range of ASCII control characters (0-31), and
1695
- * the backspace char (127)
1696
- */
1697
- var controlCharsRe = /[\x00-\x1F\x7F]/;
1698
- /**
1699
- * The string form of a regular expression that would match all of the
1700
- * alphabetic ("letter") chars in the unicode character set when placed in a
1701
- * RegExp character class (`[]`). This includes all international alphabetic
1702
- * characters.
1703
- *
1704
- * These would be the characters matched by unicode regex engines `\p{L}`
1705
- * escape ("all letters").
1706
- *
1707
- * Taken from the XRegExp library: http://xregexp.com/ (thanks @https://github.com/slevithan)
1708
- * Specifically: http://xregexp.com/v/3.2.0/xregexp-all.js, the 'Letter'
1709
- * regex's bmp
1710
- *
1711
- * VERY IMPORTANT: This set of characters is defined inside of a Regular
1712
- * Expression literal rather than a string literal to prevent UglifyJS from
1713
- * compressing the unicode escape sequences into their actual unicode
1714
- * characters. If Uglify compresses these into the unicode characters
1715
- * themselves, this results in the error "Range out of order in character
1716
- * class" when these characters are used inside of a Regular Expression
1717
- * character class (`[]`). See usages of this const. Alternatively, we can set
1718
- * the UglifyJS option `ascii_only` to true for the build, but that doesn't
1719
- * help others who are pulling in Autolinker into their own build and running
1720
- * UglifyJS themselves.
1721
- */
1722
- // prettier-ignore
1723
- 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
1724
- /**
1725
- * The string form of a regular expression that would match all emoji characters
1726
- * Based on the emoji regex defined in this article: https://thekevinscott.com/emojis-in-javascript/
1727
- */
1728
- 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;
1729
- /**
1730
- * The string form of a regular expression that would match all of the
1731
- * combining mark characters in the unicode character set when placed in a
1732
- * RegExp character class (`[]`).
1733
- *
1734
- * These would be the characters matched by unicode regex engines `\p{M}`
1735
- * escape ("all marks").
1736
- *
1737
- * Taken from the XRegExp library: http://xregexp.com/ (thanks @https://github.com/slevithan)
1738
- * Specifically: http://xregexp.com/v/3.2.0/xregexp-all.js, the 'Mark'
1739
- * regex's bmp
1740
- *
1741
- * VERY IMPORTANT: This set of characters is defined inside of a Regular
1742
- * Expression literal rather than a string literal to prevent UglifyJS from
1743
- * compressing the unicode escape sequences into their actual unicode
1744
- * characters. If Uglify compresses these into the unicode characters
1745
- * themselves, this results in the error "Range out of order in character
1746
- * class" when these characters are used inside of a Regular Expression
1747
- * character class (`[]`). See usages of this const. Alternatively, we can set
1748
- * the UglifyJS option `ascii_only` to true for the build, but that doesn't
1749
- * help others who are pulling in Autolinker into their own build and running
1750
- * UglifyJS themselves.
1751
- */
1752
- // prettier-ignore
1753
- 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
1754
- /**
1755
- * The string form of a regular expression that would match all of the
1756
- * alphabetic ("letter") chars, emoji, and combining marks in the unicode character set
1757
- * when placed in a RegExp character class (`[]`). This includes all
1758
- * international alphabetic characters.
1759
- *
1760
- * These would be the characters matched by unicode regex engines `\p{L}\p{M}`
1761
- * escapes and emoji characters.
1762
- */
1763
- var alphaCharsAndMarksStr = alphaCharsStr + emojiStr + marksStr;
1764
- /**
1765
- * The string form of a regular expression that would match all of the
1766
- * decimal number chars in the unicode character set when placed in a RegExp
1767
- * character class (`[]`).
1768
- *
1769
- * These would be the characters matched by unicode regex engines `\p{Nd}`
1770
- * escape ("all decimal numbers")
1771
- *
1772
- * Taken from the XRegExp library: http://xregexp.com/ (thanks @https://github.com/slevithan)
1773
- * Specifically: http://xregexp.com/v/3.2.0/xregexp-all.js, the 'Decimal_Number'
1774
- * regex's bmp
1775
- *
1776
- * VERY IMPORTANT: This set of characters is defined inside of a Regular
1777
- * Expression literal rather than a string literal to prevent UglifyJS from
1778
- * compressing the unicode escape sequences into their actual unicode
1779
- * characters. If Uglify compresses these into the unicode characters
1780
- * themselves, this results in the error "Range out of order in character
1781
- * class" when these characters are used inside of a Regular Expression
1782
- * character class (`[]`). See usages of this const. Alternatively, we can set
1783
- * the UglifyJS option `ascii_only` to true for the build, but that doesn't
1784
- * help others who are pulling in Autolinker into their own build and running
1785
- * UglifyJS themselves.
1786
- */
1787
- // prettier-ignore
1788
- 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
1789
- /**
1790
- * The string form of a regular expression that would match all of the
1791
- * letters and decimal number chars in the unicode character set when placed in
1792
- * a RegExp character class (`[]`).
1793
- *
1794
- * These would be the characters matched by unicode regex engines
1795
- * `[\p{L}\p{Nd}]` escape ("all letters and decimal numbers")
1796
- */
1797
- var alphaNumericCharsStr = alphaCharsAndMarksStr + decimalNumbersStr;
1798
- /**
1799
- * The string form of a regular expression that would match all of the
1800
- * letters, combining marks, and decimal number chars in the unicode character
1801
- * set when placed in a RegExp character class (`[]`).
1802
- *
1803
- * These would be the characters matched by unicode regex engines
1804
- * `[\p{L}\p{M}\p{Nd}]` escape ("all letters, combining marks, and decimal
1805
- * numbers")
1806
- */
1807
- var alphaNumericAndMarksCharsStr = alphaCharsAndMarksStr + decimalNumbersStr;
1808
- /**
1809
- * The regular expression that will match a single letter of the
1810
- * {@link #alphaNumericAndMarksCharsStr}.
1811
- */
1812
- var alphaNumericAndMarksCharRe = new RegExp("[".concat(alphaNumericAndMarksCharsStr, "]"));
1813
- // Simplified IP regular expression
1814
- var ipStr = '(?:[' + decimalNumbersStr + ']{1,3}\\.){3}[' + decimalNumbersStr + ']{1,3}';
1815
- // Protected domain label which do not allow "-" or "_" character on the beginning and the end of a single label
1816
- // prettier-ignore
1817
- var domainLabelStr = '[' + alphaNumericAndMarksCharsStr + '](?:[' + alphaNumericAndMarksCharsStr + '\\-_]{0,61}[' + alphaNumericAndMarksCharsStr + '])?';
1818
- var getDomainLabelStr = function (group) {
1819
- return '(?=(' + domainLabelStr + '))\\' + group;
1820
- };
1821
- /**
1822
- * A function to match domain names of a URL or email address.
1823
- * Ex: 'google', 'yahoo', 'some-other-company', etc.
1824
- */
1825
- // prettier-ignore
1826
- var getDomainNameStr = function (group) {
1827
- return '(?:' + getDomainLabelStr(group) + '(?:\\.' + getDomainLabelStr(group + 1) + '){0,126}|' + ipStr + ')';
1828
- };
1829
- /**
1830
- * A regular expression that is simply the character class of the characters
1831
- * that may be used in a domain name, minus the '-' or '.'
1832
- */
1833
- var domainNameCharRegex = alphaNumericAndMarksCharRe;
1834
-
1835
- // NOTE: THIS IS A GENERATED FILE
1836
- // To update with the latest TLD list, run `npm run update-tld-regex`
1837
- var tldRegex = /(?:xn--vermgensberatung-pwb|xn--vermgensberater-ctb|xn--clchc0ea0b2g2a9gcd|xn--w4r85el8fhu5dnra|northwesternmutual|travelersinsurance|vermögensberatung|xn--5su34j936bgsg|xn--bck1b9a5dre4c|xn--mgbah1a3hjkrd|xn--mgbai9azgqp6j|xn--mgberp4a5d4ar|xn--xkc2dl3a5ee0h|vermögensberater|xn--fzys8d69uvgm|xn--mgba7c0bbn0a|xn--mgbcpq6gpa1a|xn--xkc2al3hye2a|americanexpress|kerryproperties|sandvikcoromant|xn--i1b6b1a6a2e|xn--kcrx77d1x4a|xn--lgbbat1ad8j|xn--mgba3a4f16a|xn--mgbaakc7dvf|xn--mgbc0a9azcg|xn--nqv7fs00ema|americanfamily|bananarepublic|cancerresearch|cookingchannel|kerrylogistics|weatherchannel|xn--54b7fta0cc|xn--6qq986b3xl|xn--80aqecdr1a|xn--b4w605ferd|xn--fiq228c5hs|xn--h2breg3eve|xn--jlq480n2rg|xn--jlq61u9w7b|xn--mgba3a3ejt|xn--mgbaam7a8h|xn--mgbayh7gpa|xn--mgbbh1a71e|xn--mgbca7dzdo|xn--mgbi4ecexp|xn--mgbx4cd0ab|xn--rvc1e0am3e|international|lifeinsurance|travelchannel|wolterskluwer|xn--cckwcxetd|xn--eckvdtc9d|xn--fpcrj9c3d|xn--fzc2c9e2c|xn--h2brj9c8c|xn--tiq49xqyj|xn--yfro4i67o|xn--ygbi2ammx|construction|lplfinancial|scholarships|versicherung|xn--3e0b707e|xn--45br5cyl|xn--4dbrk0ce|xn--80adxhks|xn--80asehdb|xn--8y0a063a|xn--gckr3f0f|xn--mgb9awbf|xn--mgbab2bd|xn--mgbgu82a|xn--mgbpl2fh|xn--mgbt3dhd|xn--mk1bu44c|xn--ngbc5azd|xn--ngbe9e0a|xn--ogbpf8fl|xn--qcka1pmc|accountants|barclaycard|blackfriday|blockbuster|bridgestone|calvinklein|contractors|creditunion|engineering|enterprises|foodnetwork|investments|kerryhotels|lamborghini|motorcycles|olayangroup|photography|playstation|productions|progressive|redumbrella|williamhill|xn--11b4c3d|xn--1ck2e1b|xn--1qqw23a|xn--2scrj9c|xn--3bst00m|xn--3ds443g|xn--3hcrj9c|xn--42c2d9a|xn--45brj9c|xn--55qw42g|xn--6frz82g|xn--80ao21a|xn--9krt00a|xn--cck2b3b|xn--czr694b|xn--d1acj3b|xn--efvy88h|xn--fct429k|xn--fjq720a|xn--flw351e|xn--g2xx48c|xn--gecrj9c|xn--gk3at1e|xn--h2brj9c|xn--hxt814e|xn--imr513n|xn--j6w193g|xn--jvr189m|xn--kprw13d|xn--kpry57d|xn--mgbbh1a|xn--mgbtx2b|xn--mix891f|xn--nyqy26a|xn--otu796d|xn--pgbs0dh|xn--q9jyb4c|xn--rhqv96g|xn--rovu88b|xn--s9brj9c|xn--ses554g|xn--t60b56a|xn--vuq861b|xn--w4rs40l|xn--xhq521b|xn--zfr164b|சிங்கப்பூர்|accountant|apartments|associates|basketball|bnpparibas|boehringer|capitalone|consulting|creditcard|cuisinella|eurovision|extraspace|foundation|healthcare|immobilien|industries|management|mitsubishi|nextdirect|properties|protection|prudential|realestate|republican|restaurant|schaeffler|tatamotors|technology|university|vlaanderen|volkswagen|xn--30rr7y|xn--3pxu8k|xn--45q11c|xn--4gbrim|xn--55qx5d|xn--5tzm5g|xn--80aswg|xn--90a3ac|xn--9dbq2a|xn--9et52u|xn--c2br7g|xn--cg4bki|xn--czrs0t|xn--czru2d|xn--fiq64b|xn--fiqs8s|xn--fiqz9s|xn--io0a7i|xn--kput3i|xn--mxtq1m|xn--o3cw4h|xn--pssy2u|xn--q7ce6a|xn--unup4y|xn--wgbh1c|xn--wgbl6a|xn--y9a3aq|accenture|alfaromeo|allfinanz|amsterdam|analytics|aquarelle|barcelona|bloomberg|christmas|community|directory|education|equipment|fairwinds|financial|firestone|fresenius|frontdoor|furniture|goldpoint|hisamitsu|homedepot|homegoods|homesense|institute|insurance|kuokgroup|lancaster|landrover|lifestyle|marketing|marshalls|melbourne|microsoft|panasonic|passagens|pramerica|richardli|shangrila|solutions|statebank|statefarm|stockholm|travelers|vacations|xn--90ais|xn--c1avg|xn--d1alf|xn--e1a4c|xn--fhbei|xn--j1aef|xn--j1amh|xn--l1acc|xn--ngbrx|xn--nqv7f|xn--p1acf|xn--qxa6a|xn--tckwe|xn--vhquv|yodobashi|موريتانيا|abudhabi|airforce|allstate|attorney|barclays|barefoot|bargains|baseball|boutique|bradesco|broadway|brussels|builders|business|capetown|catering|catholic|cipriani|cityeats|cleaning|clinique|clothing|commbank|computer|delivery|deloitte|democrat|diamonds|discount|discover|download|engineer|ericsson|etisalat|exchange|feedback|fidelity|firmdale|football|frontier|goodyear|grainger|graphics|guardian|hdfcbank|helsinki|holdings|hospital|infiniti|ipiranga|istanbul|jpmorgan|lighting|lundbeck|marriott|maserati|mckinsey|memorial|merckmsd|mortgage|observer|partners|pharmacy|pictures|plumbing|property|redstone|reliance|saarland|samsclub|security|services|shopping|showtime|softbank|software|stcgroup|supplies|training|vanguard|ventures|verisign|woodside|xn--90ae|xn--node|xn--p1ai|xn--qxam|yokohama|السعودية|abogado|academy|agakhan|alibaba|android|athleta|auction|audible|auspost|avianca|banamex|bauhaus|bentley|bestbuy|booking|brother|bugatti|capital|caravan|careers|channel|charity|chintai|citadel|clubmed|college|cologne|comcast|company|compare|contact|cooking|corsica|country|coupons|courses|cricket|cruises|dentist|digital|domains|exposed|express|farmers|fashion|ferrari|ferrero|finance|fishing|fitness|flights|florist|flowers|forsale|frogans|fujitsu|gallery|genting|godaddy|grocery|guitars|hamburg|hangout|hitachi|holiday|hosting|hoteles|hotmail|hyundai|ismaili|jewelry|juniper|kitchen|komatsu|lacaixa|lanxess|lasalle|latrobe|leclerc|limited|lincoln|markets|monster|netbank|netflix|network|neustar|okinawa|oldnavy|organic|origins|philips|pioneer|politie|realtor|recipes|rentals|reviews|rexroth|samsung|sandvik|schmidt|schwarz|science|shiksha|singles|staples|storage|support|surgery|systems|temasek|theater|theatre|tickets|tiffany|toshiba|trading|walmart|wanggou|watches|weather|website|wedding|whoswho|windows|winners|xfinity|yamaxun|youtube|zuerich|католик|اتصالات|البحرين|الجزائر|العليان|پاکستان|كاثوليك|இந்தியா|abarth|abbott|abbvie|africa|agency|airbus|airtel|alipay|alsace|alstom|amazon|anquan|aramco|author|bayern|beauty|berlin|bharti|bostik|boston|broker|camera|career|casino|center|chanel|chrome|church|circle|claims|clinic|coffee|comsec|condos|coupon|credit|cruise|dating|datsun|dealer|degree|dental|design|direct|doctor|dunlop|dupont|durban|emerck|energy|estate|events|expert|family|flickr|futbol|gallup|garden|george|giving|global|google|gratis|health|hermes|hiphop|hockey|hotels|hughes|imamat|insure|intuit|jaguar|joburg|juegos|kaufen|kinder|kindle|kosher|lancia|latino|lawyer|lefrak|living|locker|london|luxury|madrid|maison|makeup|market|mattel|mobile|monash|mormon|moscow|museum|mutual|nagoya|natura|nissan|nissay|norton|nowruz|office|olayan|online|oracle|orange|otsuka|pfizer|photos|physio|pictet|quebec|racing|realty|reisen|repair|report|review|rocher|rogers|ryukyu|safety|sakura|sanofi|school|schule|search|secure|select|shouji|soccer|social|stream|studio|supply|suzuki|swatch|sydney|taipei|taobao|target|tattoo|tennis|tienda|tjmaxx|tkmaxx|toyota|travel|unicom|viajes|viking|villas|virgin|vision|voting|voyage|vuelos|walter|webcam|xihuan|yachts|yandex|zappos|москва|онлайн|ابوظبي|ارامكو|الاردن|المغرب|امارات|فلسطين|مليسيا|भारतम्|இலங்கை|ファッション|actor|adult|aetna|amfam|amica|apple|archi|audio|autos|azure|baidu|beats|bible|bingo|black|boats|bosch|build|canon|cards|chase|cheap|cisco|citic|click|cloud|coach|codes|crown|cymru|dabur|dance|deals|delta|drive|dubai|earth|edeka|email|epson|faith|fedex|final|forex|forum|gallo|games|gifts|gives|glass|globo|gmail|green|gripe|group|gucci|guide|homes|honda|horse|house|hyatt|ikano|irish|jetzt|koeln|kyoto|lamer|lease|legal|lexus|lilly|linde|lipsy|loans|locus|lotte|lotto|macys|mango|media|miami|money|movie|music|nexus|nikon|ninja|nokia|nowtv|omega|osaka|paris|parts|party|phone|photo|pizza|place|poker|praxi|press|prime|promo|quest|radio|rehab|reise|ricoh|rocks|rodeo|rugby|salon|sener|seven|sharp|shell|shoes|skype|sling|smart|smile|solar|space|sport|stada|store|study|style|sucks|swiss|tatar|tires|tirol|tmall|today|tokyo|tools|toray|total|tours|trade|trust|tunes|tushu|ubank|vegas|video|vodka|volvo|wales|watch|weber|weibo|works|world|xerox|yahoo|ישראל|ایران|بازار|بھارت|سودان|سورية|همراه|भारोत|संगठन|বাংলা|భారత్|ഭാരതം|嘉里大酒店|aarp|able|adac|aero|akdn|ally|amex|arab|army|arpa|arte|asda|asia|audi|auto|baby|band|bank|bbva|beer|best|bike|bing|blog|blue|bofa|bond|book|buzz|cafe|call|camp|care|cars|casa|case|cash|cbre|cern|chat|citi|city|club|cool|coop|cyou|data|date|dclk|deal|dell|desi|diet|dish|docs|dvag|erni|fage|fail|fans|farm|fast|fiat|fido|film|fire|fish|flir|food|ford|free|fund|game|gbiz|gent|ggee|gift|gmbh|gold|golf|goog|guge|guru|hair|haus|hdfc|help|here|hgtv|host|hsbc|icbc|ieee|imdb|immo|info|itau|java|jeep|jobs|jprs|kddi|kids|kiwi|kpmg|kred|land|lego|lgbt|lidl|life|like|limo|link|live|loan|loft|love|ltda|luxe|maif|meet|meme|menu|mini|mint|mobi|moda|moto|name|navy|news|next|nico|nike|ollo|open|page|pars|pccw|pics|ping|pink|play|plus|pohl|porn|post|prod|prof|qpon|read|reit|rent|rest|rich|room|rsvp|ruhr|safe|sale|sarl|save|saxo|scot|seat|seek|sexy|shaw|shia|shop|show|silk|sina|site|skin|sncf|sohu|song|sony|spot|star|surf|talk|taxi|team|tech|teva|tiaa|tips|town|toys|tube|vana|visa|viva|vivo|vote|voto|wang|weir|wien|wiki|wine|work|xbox|yoga|zara|zero|zone|дети|сайт|بارت|بيتك|ڀارت|تونس|شبكة|عراق|عمان|موقع|भारत|ভারত|ভাৰত|ਭਾਰਤ|ભારત|ଭାରତ|ಭಾರತ|ලංකා|アマゾン|グーグル|クラウド|ポイント|组织机构|電訊盈科|香格里拉|aaa|abb|abc|aco|ads|aeg|afl|aig|anz|aol|app|art|aws|axa|bar|bbc|bbt|bcg|bcn|bet|bid|bio|biz|bms|bmw|bom|boo|bot|box|buy|bzh|cab|cal|cam|car|cat|cba|cbn|cbs|ceo|cfa|cfd|com|cpa|crs|dad|day|dds|dev|dhl|diy|dnp|dog|dot|dtv|dvr|eat|eco|edu|esq|eus|fan|fit|fly|foo|fox|frl|ftr|fun|fyi|gal|gap|gay|gdn|gea|gle|gmo|gmx|goo|gop|got|gov|hbo|hiv|hkt|hot|how|ibm|ice|icu|ifm|inc|ing|ink|int|ist|itv|jcb|jio|jll|jmp|jnj|jot|joy|kfh|kia|kim|kpn|krd|lat|law|lds|llc|llp|lol|lpl|ltd|man|map|mba|med|men|mil|mit|mlb|mls|mma|moe|moi|mom|mov|msd|mtn|mtr|nab|nba|nec|net|new|nfl|ngo|nhk|now|nra|nrw|ntt|nyc|obi|one|ong|onl|ooo|org|ott|ovh|pay|pet|phd|pid|pin|pnc|pro|pru|pub|pwc|red|ren|ril|rio|rip|run|rwe|sap|sas|sbi|sbs|sca|scb|ses|sew|sex|sfr|ski|sky|soy|spa|srl|stc|tab|tax|tci|tdk|tel|thd|tjx|top|trv|tui|tvs|ubs|uno|uol|ups|vet|vig|vin|vip|wed|win|wme|wow|wtc|wtf|xin|xxx|xyz|you|yun|zip|бел|ком|қаз|мкд|мон|орг|рус|срб|укр|հայ|קום|عرب|قطر|كوم|مصر|कॉम|नेट|คอม|ไทย|ລາວ|ストア|セール|みんな|中文网|亚马逊|天主教|我爱你|新加坡|淡马锡|诺基亚|飞利浦|ac|ad|ae|af|ag|ai|al|am|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cw|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|za|zm|zw|ελ|ευ|бг|ею|рф|გე|닷넷|닷컴|삼성|한국|コム|世界|中信|中国|中國|企业|佛山|信息|健康|八卦|公司|公益|台湾|台灣|商城|商店|商标|嘉里|在线|大拿|娱乐|家電|广东|微博|慈善|手机|招聘|政务|政府|新闻|时尚|書籍|机构|游戏|澳門|点看|移动|网址|网店|网站|网络|联通|谷歌|购物|通販|集团|食品|餐厅|香港)/;
1838
-
1839
- // For debugging: search for other "For debugging" lines
1840
- // import CliTable from 'cli-table';
1841
- // RegExp objects which are shared by all instances of EmailMatcher. These are
1842
- // here to avoid re-instantiating the RegExp objects if `Autolinker.link()` is
1843
- // called multiple times, thus instantiating EmailMatcher and its RegExp
1844
- // objects each time (which is very expensive - see https://github.com/gregjacobs/Autolinker.js/issues/314).
1845
- // See descriptions of the properties where they are used for details about them
1846
- var localPartCharRegex = new RegExp("[".concat(alphaNumericAndMarksCharsStr, "!#$%&'*+/=?^_`{|}~-]"));
1847
- var strictTldRegex = new RegExp("^".concat(tldRegex.source, "$"));
1848
- /**
1849
- * @class Autolinker.matcher.Email
1850
- * @extends Autolinker.matcher.Matcher
1851
- *
1852
- * Matcher to find email matches in an input string.
1853
- *
1854
- * See this class's superclass ({@link Autolinker.matcher.Matcher}) for more details.
1855
- */
1856
- var EmailMatcher = /** @class */function (_super) {
1857
- __extends(EmailMatcher, _super);
1858
- function EmailMatcher() {
1859
- var _this = _super !== null && _super.apply(this, arguments) || this;
1860
- /**
1861
- * Valid characters that can be used in the "local" part of an email address,
1862
- * i.e. the "name" part of "name@site.com"
1863
- */
1864
- _this.localPartCharRegex = localPartCharRegex;
1865
- /**
1866
- * Stricter TLD regex which adds a beginning and end check to ensure
1867
- * the string is a valid TLD
1868
- */
1869
- _this.strictTldRegex = strictTldRegex;
1870
- return _this;
1871
- }
1872
- /**
1873
- * @inheritdoc
1874
- */
1875
- EmailMatcher.prototype.parseMatches = function (text) {
1876
- var tagBuilder = this.tagBuilder,
1877
- localPartCharRegex = this.localPartCharRegex,
1878
- strictTldRegex = this.strictTldRegex,
1879
- matches = [],
1880
- len = text.length,
1881
- noCurrentEmailMatch = new CurrentEmailMatch();
1882
- // for matching a 'mailto:' prefix
1883
- var mailtoTransitions = {
1884
- m: 'a',
1885
- a: 'i',
1886
- i: 'l',
1887
- l: 't',
1888
- t: 'o',
1889
- o: ':'
1890
- };
1891
- var charIdx = 0,
1892
- state = 0 /* NonEmailMatch */,
1893
- currentEmailMatch = noCurrentEmailMatch;
1894
- // For debugging: search for other "For debugging" lines
1895
- // const table = new CliTable( {
1896
- // head: [ 'charIdx', 'char', 'state', 'charIdx', 'currentEmailAddress.idx', 'hasDomainDot' ]
1897
- // } );
1898
- while (charIdx < len) {
1899
- var char = text.charAt(charIdx);
1900
- // For debugging: search for other "For debugging" lines
1901
- // table.push(
1902
- // [ charIdx, char, State[ state ], charIdx, currentEmailAddress.idx, currentEmailAddress.hasDomainDot ]
1903
- // );
1904
- switch (state) {
1905
- case 0 /* NonEmailMatch */:
1906
- stateNonEmailAddress(char);
1907
- break;
1908
- case 1 /* Mailto */:
1909
- stateMailTo(text.charAt(charIdx - 1), char);
1910
- break;
1911
- case 2 /* LocalPart */:
1912
- stateLocalPart(char);
1913
- break;
1914
- case 3 /* LocalPartDot */:
1915
- stateLocalPartDot(char);
1916
- break;
1917
- case 4 /* AtSign */:
1918
- stateAtSign(char);
1919
- break;
1920
- case 5 /* DomainChar */:
1921
- stateDomainChar(char);
1922
- break;
1923
- case 6 /* DomainHyphen */:
1924
- stateDomainHyphen(char);
1925
- break;
1926
- case 7 /* DomainDot */:
1927
- stateDomainDot(char);
1928
- break;
1929
- default:
1930
- throwUnhandledCaseError(state);
1931
- }
1932
- // For debugging: search for other "For debugging" lines
1933
- // table.push(
1934
- // [ charIdx, char, State[ state ], charIdx, currentEmailAddress.idx, currentEmailAddress.hasDomainDot ]
1935
- // );
1936
- charIdx++;
1937
- }
1938
- // Capture any valid match at the end of the string
1939
- captureMatchIfValidAndReset();
1940
- // For debugging: search for other "For debugging" lines
1941
- //console.log( '\n' + table.toString() );
1942
- return matches;
1943
- // Handles the state when we're not in an email address
1944
- function stateNonEmailAddress(char) {
1945
- if (char === 'm') {
1946
- beginEmailMatch(1 /* Mailto */);
1947
- } else if (localPartCharRegex.test(char)) {
1948
- beginEmailMatch();
1949
- } else ;
1950
- }
1951
- // Handles if we're reading a 'mailto:' prefix on the string
1952
- function stateMailTo(prevChar, char) {
1953
- if (prevChar === ':') {
1954
- // We've reached the end of the 'mailto:' prefix
1955
- if (localPartCharRegex.test(char)) {
1956
- state = 2 /* LocalPart */;
1957
- currentEmailMatch = new CurrentEmailMatch(__assign(__assign({}, currentEmailMatch), {
1958
- hasMailtoPrefix: true
1959
- }));
1960
- } else {
1961
- // we've matched 'mailto:' but didn't get anything meaningful
1962
- // immediately afterwards (for example, we encountered a
1963
- // space character, or an '@' character which formed 'mailto:@'
1964
- resetToNonEmailMatchState();
1965
- }
1966
- } else if (mailtoTransitions[prevChar] === char) ; else if (localPartCharRegex.test(char)) {
1967
- // We we're reading a prefix of 'mailto:', but encountered a
1968
- // different character that didn't continue the prefix
1969
- state = 2 /* LocalPart */;
1970
- } else if (char === '.') {
1971
- // We we're reading a prefix of 'mailto:', but encountered a
1972
- // dot character
1973
- state = 3 /* LocalPartDot */;
1974
- } else if (char === '@') {
1975
- // We we're reading a prefix of 'mailto:', but encountered a
1976
- // an @ character
1977
- state = 4 /* AtSign */;
1978
- } else {
1979
- // not an email address character, return to "NonEmailAddress" state
1980
- resetToNonEmailMatchState();
1981
- }
1982
- }
1983
- // Handles the state when we're currently in the "local part" of an
1984
- // email address (as opposed to the "domain part")
1985
- function stateLocalPart(char) {
1986
- if (char === '.') {
1987
- state = 3 /* LocalPartDot */;
1988
- } else if (char === '@') {
1989
- state = 4 /* AtSign */;
1990
- } else if (localPartCharRegex.test(char)) ; else {
1991
- // not an email address character, return to "NonEmailAddress" state
1992
- resetToNonEmailMatchState();
1993
- }
1994
- }
1995
- // Handles the state where we've read
1996
- function stateLocalPartDot(char) {
1997
- if (char === '.') {
1998
- // We read a second '.' in a row, not a valid email address
1999
- // local part
2000
- resetToNonEmailMatchState();
2001
- } else if (char === '@') {
2002
- // We read the '@' character immediately after a dot ('.'), not
2003
- // an email address
2004
- resetToNonEmailMatchState();
2005
- } else if (localPartCharRegex.test(char)) {
2006
- state = 2 /* LocalPart */;
2007
- } else {
2008
- // Anything else, not an email address
2009
- resetToNonEmailMatchState();
2010
- }
2011
- }
2012
- function stateAtSign(char) {
2013
- if (domainNameCharRegex.test(char)) {
2014
- state = 5 /* DomainChar */;
2015
- } else {
2016
- // Anything else, not an email address
2017
- resetToNonEmailMatchState();
2018
- }
2019
- }
2020
- function stateDomainChar(char) {
2021
- if (char === '.') {
2022
- state = 7 /* DomainDot */;
2023
- } else if (char === '-') {
2024
- state = 6 /* DomainHyphen */;
2025
- } else if (domainNameCharRegex.test(char)) ; else {
2026
- // Anything else, we potentially matched if the criteria has
2027
- // been met
2028
- captureMatchIfValidAndReset();
2029
- }
2030
- }
2031
- function stateDomainHyphen(char) {
2032
- if (char === '-' || char === '.') {
2033
- // Not valid to have two hyphens ("--") or hypen+dot ("-.")
2034
- captureMatchIfValidAndReset();
2035
- } else if (domainNameCharRegex.test(char)) {
2036
- state = 5 /* DomainChar */;
2037
- } else {
2038
- // Anything else
2039
- captureMatchIfValidAndReset();
2040
- }
2041
- }
2042
- function stateDomainDot(char) {
2043
- if (char === '.' || char === '-') {
2044
- // not valid to have two dots ("..") or dot+hypen (".-")
2045
- captureMatchIfValidAndReset();
2046
- } else if (domainNameCharRegex.test(char)) {
2047
- state = 5 /* DomainChar */;
2048
- // After having read a '.' and then a valid domain character,
2049
- // we now know that the domain part of the email is valid, and
2050
- // we have found at least a partial EmailMatch (however, the
2051
- // email address may have additional characters from this point)
2052
- currentEmailMatch = new CurrentEmailMatch(__assign(__assign({}, currentEmailMatch), {
2053
- hasDomainDot: true
2054
- }));
2055
- } else {
2056
- // Anything else
2057
- captureMatchIfValidAndReset();
2058
- }
2059
- }
2060
- function beginEmailMatch(newState) {
2061
- if (newState === void 0) {
2062
- newState = 2 /* LocalPart */;
2063
- }
2064
- state = newState;
2065
- currentEmailMatch = new CurrentEmailMatch({
2066
- idx: charIdx
2067
- });
2068
- }
2069
- function resetToNonEmailMatchState() {
2070
- state = 0 /* NonEmailMatch */;
2071
- currentEmailMatch = noCurrentEmailMatch;
2072
- }
2073
- /*
2074
- * Captures the current email address as an EmailMatch if it's valid,
2075
- * and resets the state to read another email address.
2076
- */
2077
- function captureMatchIfValidAndReset() {
2078
- if (currentEmailMatch.hasDomainDot) {
2079
- // we need at least one dot in the domain to be considered a valid email address
2080
- var matchedText = text.slice(currentEmailMatch.idx, charIdx);
2081
- // If we read a '.' or '-' char that ended the email address
2082
- // (valid domain name characters, but only valid email address
2083
- // characters if they are followed by something else), strip
2084
- // it off now
2085
- if (/[-.]$/.test(matchedText)) {
2086
- matchedText = matchedText.slice(0, -1);
2087
- }
2088
- var emailAddress = currentEmailMatch.hasMailtoPrefix ? matchedText.slice('mailto:'.length) : matchedText;
2089
- // if the email address has a valid TLD, add it to the list of matches
2090
- if (doesEmailHaveValidTld(emailAddress)) {
2091
- matches.push(new EmailMatch({
2092
- tagBuilder: tagBuilder,
2093
- matchedText: matchedText,
2094
- offset: currentEmailMatch.idx,
2095
- email: emailAddress
2096
- }));
2097
- }
2098
- }
2099
- resetToNonEmailMatchState();
2100
- /**
2101
- * Determines if the given email address has a valid TLD or not
2102
- * @param {string} emailAddress - email address
2103
- * @return {Boolean} - true is email have valid TLD, false otherwise
2104
- */
2105
- function doesEmailHaveValidTld(emailAddress) {
2106
- var emailAddressTld = emailAddress.split('.').pop() || '';
2107
- var emailAddressNormalized = emailAddressTld.toLowerCase();
2108
- var isValidTld = strictTldRegex.test(emailAddressNormalized);
2109
- return isValidTld;
2110
- }
2111
- }
2112
- };
2113
- return EmailMatcher;
2114
- }(Matcher);
2115
- var CurrentEmailMatch = /** @class */function () {
2116
- function CurrentEmailMatch(cfg) {
2117
- if (cfg === void 0) {
2118
- cfg = {};
2119
- }
2120
- this.idx = cfg.idx !== undefined ? cfg.idx : -1;
2121
- this.hasMailtoPrefix = !!cfg.hasMailtoPrefix;
2122
- this.hasDomainDot = !!cfg.hasDomainDot;
2123
- }
2124
- return CurrentEmailMatch;
2125
- }();
2126
-
2127
- /**
2128
- * @private
2129
- * @class Autolinker.matcher.UrlMatchValidator
2130
- * @singleton
2131
- *
2132
- * Used by Autolinker to filter out false URL positives from the
2133
- * {@link Autolinker.matcher.Url UrlMatcher}.
2134
- *
2135
- * Due to the limitations of regular expressions (including the missing feature
2136
- * of look-behinds in JS regular expressions), we cannot always determine the
2137
- * validity of a given match. This class applies a bit of additional logic to
2138
- * filter out any false positives that have been matched by the
2139
- * {@link Autolinker.matcher.Url UrlMatcher}.
2140
- */
2141
- var UrlMatchValidator = /** @class */function () {
2142
- function UrlMatchValidator() {}
2143
- /**
2144
- * Determines if a given URL match found by the {@link Autolinker.matcher.Url UrlMatcher}
2145
- * is valid. Will return `false` for:
2146
- *
2147
- * 1) URL matches which do not have at least have one period ('.') in the
2148
- * domain name (effectively skipping over matches like "abc:def").
2149
- * However, URL matches with a protocol will be allowed (ex: 'http://localhost')
2150
- * 2) URL matches which do not have at least one word character in the
2151
- * domain name (effectively skipping over matches like "git:1.0").
2152
- * However, URL matches with a protocol will be allowed (ex: 'intra-net://271219.76')
2153
- * 3) A protocol-relative url match (a URL beginning with '//') whose
2154
- * previous character is a word character (effectively skipping over
2155
- * strings like "abc//google.com")
2156
- *
2157
- * Otherwise, returns `true`.
2158
- *
2159
- * @param {String} urlMatch The matched URL, if there was one. Will be an
2160
- * empty string if the match is not a URL match.
2161
- * @param {String} protocolUrlMatch The match URL string for a protocol
2162
- * match. Ex: 'http://yahoo.com'. This is used to match something like
2163
- * 'http://localhost', where we won't double check that the domain name
2164
- * has at least one '.' in it.
2165
- * @return {Boolean} `true` if the match given is valid and should be
2166
- * processed, or `false` if the match is invalid and/or should just not be
2167
- * processed.
2168
- */
2169
- UrlMatchValidator.isValid = function (urlMatch, protocolUrlMatch) {
2170
- if (protocolUrlMatch && !this.isValidUriScheme(protocolUrlMatch) || this.urlMatchDoesNotHaveProtocolOrDot(urlMatch, protocolUrlMatch) ||
2171
- // 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')
2172
- this.urlMatchDoesNotHaveAtLeastOneWordChar(urlMatch, protocolUrlMatch) &&
2173
- // At least one letter character must exist in the domain name after a protocol match. Ex: skip over something like "git:1.0"
2174
- !this.isValidIpAddress(urlMatch) ||
2175
- // Except if it's an IP address
2176
- this.containsMultipleDots(urlMatch)) {
2177
- return false;
2178
- }
2179
- return true;
2180
- };
2181
- UrlMatchValidator.isValidIpAddress = function (uriSchemeMatch) {
2182
- var newRegex = new RegExp(this.hasFullProtocolRegex.source + this.ipRegex.source);
2183
- var uriScheme = uriSchemeMatch.match(newRegex);
2184
- return uriScheme !== null;
2185
- };
2186
- UrlMatchValidator.containsMultipleDots = function (urlMatch) {
2187
- var stringBeforeSlash = urlMatch;
2188
- if (this.hasFullProtocolRegex.test(urlMatch)) {
2189
- stringBeforeSlash = urlMatch.split('://')[1];
2190
- }
2191
- return stringBeforeSlash.split('/')[0].indexOf('..') > -1;
2192
- };
2193
- /**
2194
- * Determines if the URI scheme is a valid scheme to be autolinked. Returns
2195
- * `false` if the scheme is 'javascript:' or 'vbscript:'
2196
- *
2197
- * @private
2198
- * @param {String} uriSchemeMatch The match URL string for a full URI scheme
2199
- * match. Ex: 'http://yahoo.com' or 'mailto:a@a.com'.
2200
- * @return {Boolean} `true` if the scheme is a valid one, `false` otherwise.
2201
- */
2202
- UrlMatchValidator.isValidUriScheme = function (uriSchemeMatch) {
2203
- var uriSchemeMatchArr = uriSchemeMatch.match(this.uriSchemeRegex),
2204
- uriScheme = uriSchemeMatchArr && uriSchemeMatchArr[0].toLowerCase();
2205
- return uriScheme !== 'javascript:' && uriScheme !== 'vbscript:';
2206
- };
2207
- /**
2208
- * Determines if a URL match does not have either:
2209
- *
2210
- * a) a full protocol (i.e. 'http://'), or
2211
- * b) at least one dot ('.') in the domain name (for a non-full-protocol
2212
- * match).
2213
- *
2214
- * Either situation is considered an invalid URL (ex: 'git:d' does not have
2215
- * either the '://' part, or at least one dot in the domain name. If the
2216
- * match was 'git:abc.com', we would consider this valid.)
2217
- *
2218
- * @private
2219
- * @param {String} urlMatch The matched URL, if there was one. Will be an
2220
- * empty string if the match is not a URL match.
2221
- * @param {String} protocolUrlMatch The match URL string for a protocol
2222
- * match. Ex: 'http://yahoo.com'. This is used to match something like
2223
- * 'http://localhost', where we won't double check that the domain name
2224
- * has at least one '.' in it.
2225
- * @return {Boolean} `true` if the URL match does not have a full protocol,
2226
- * or at least one dot ('.') in a non-full-protocol match.
2227
- */
2228
- UrlMatchValidator.urlMatchDoesNotHaveProtocolOrDot = function (urlMatch, protocolUrlMatch) {
2229
- return !!urlMatch && (!protocolUrlMatch || !this.hasFullProtocolRegex.test(protocolUrlMatch)) && urlMatch.indexOf('.') === -1;
2230
- };
2231
- /**
2232
- * Determines if a URL match does not have either:
2233
- *
2234
- * a) a full protocol (i.e. 'http://'), or
2235
- * b) at least one word character after the protocol (i.e. in the domain name)
2236
- *
2237
- * At least one letter character must exist in the domain name after a
2238
- * protocol match. Ex: skip over something like "git:1.0"
2239
- *
2240
- * @private
2241
- * @param {String} urlMatch The matched URL, if there was one. Will be an
2242
- * empty string if the match is not a URL match.
2243
- * @param {String} protocolUrlMatch The match URL string for a protocol
2244
- * match. Ex: 'http://yahoo.com'. This is used to know whether or not we
2245
- * have a protocol in the URL string, in order to check for a word
2246
- * character after the protocol separator (':').
2247
- * @return {Boolean} `true` if the URL match does not have a full protocol, or
2248
- * at least one word character in it, `false` otherwise.
2249
- */
2250
- UrlMatchValidator.urlMatchDoesNotHaveAtLeastOneWordChar = function (urlMatch, protocolUrlMatch) {
2251
- if (urlMatch && protocolUrlMatch) {
2252
- return !this.hasFullProtocolRegex.test(protocolUrlMatch) && !this.hasWordCharAfterProtocolRegex.test(urlMatch);
2253
- } else {
2254
- return false;
2255
- }
2256
- };
2257
- /**
2258
- * Regex to test for a full protocol, with the two trailing slashes. Ex: 'http://'
2259
- *
2260
- * @private
2261
- * @property {RegExp} hasFullProtocolRegex
2262
- */
2263
- UrlMatchValidator.hasFullProtocolRegex = /^[A-Za-z][-.+A-Za-z0-9]*:\/\//;
2264
- /**
2265
- * Regex to find the URI scheme, such as 'mailto:'.
2266
- *
2267
- * This is used to filter out 'javascript:' and 'vbscript:' schemes.
2268
- *
2269
- * @private
2270
- * @property {RegExp} uriSchemeRegex
2271
- */
2272
- UrlMatchValidator.uriSchemeRegex = /^[A-Za-z][-.+A-Za-z0-9]*:/;
2273
- /**
2274
- * Regex to determine if at least one word char exists after the protocol (i.e. after the ':')
2275
- *
2276
- * @private
2277
- * @property {RegExp} hasWordCharAfterProtocolRegex
2278
- */
2279
- UrlMatchValidator.hasWordCharAfterProtocolRegex = new RegExp(':[^\\s]*?[' + alphaCharsStr + ']');
2280
- /**
2281
- * Regex to determine if the string is a valid IP address
2282
- *
2283
- * @private
2284
- * @property {RegExp} ipRegex
2285
- */
2286
- 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]*)?\/?$/;
2287
- return UrlMatchValidator;
2288
- }();
2289
-
2290
- // RegExp objects which are shared by all instances of UrlMatcher. These are
2291
- // here to avoid re-instantiating the RegExp objects if `Autolinker.link()` is
2292
- // called multiple times, thus instantiating UrlMatcher and its RegExp
2293
- // objects each time (which is very expensive - see https://github.com/gregjacobs/Autolinker.js/issues/314).
2294
- // See descriptions of the properties where they are used for details about them
2295
- // prettier-ignore
2296
- var matcherRegex = function () {
2297
- var schemeRegex = /(?:[A-Za-z][-.+A-Za-z0-9]{0,63}:(?![A-Za-z][-.+A-Za-z0-9]{0,63}:\/\/)(?!\d+\/?)(?:\/\/)?)/,
2298
- // 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)
2299
- wwwRegex = /(?:www\.)/,
2300
- // starting with 'www.'
2301
- // Allow optional path, query string, and hash anchor, not ending in the following characters: "?!:,.;"
2302
- // http://blog.codinghorror.com/the-problem-with-urls/
2303
- urlSuffixRegex = new RegExp('[/?#](?:[' + alphaNumericAndMarksCharsStr + '\\-+&@#/%=~_()|\'$*\\[\\]{}?!:,.;^\u2713]*[' + alphaNumericAndMarksCharsStr + '\\-+&@#/%=~_()|\'$*\\[\\]{}\u2713])?');
2304
- 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
2305
- ].join(""), 'gi');
2306
- }();
2307
- var wordCharRegExp = new RegExp('[' + alphaNumericAndMarksCharsStr + ']');
2308
- /**
2309
- * @class Autolinker.matcher.Url
2310
- * @extends Autolinker.matcher.Matcher
2311
- *
2312
- * Matcher to find URL matches in an input string.
2313
- *
2314
- * See this class's superclass ({@link Autolinker.matcher.Matcher}) for more details.
2315
- */
2316
- var UrlMatcher = /** @class */function (_super) {
2317
- __extends(UrlMatcher, _super);
2318
- /**
2319
- * @method constructor
2320
- * @param {Object} cfg The configuration properties for the Match instance,
2321
- * specified in an Object (map).
2322
- */
2323
- function UrlMatcher(cfg) {
2324
- var _this = _super.call(this, cfg) || this;
2325
- /**
2326
- * @cfg {Object} stripPrefix (required)
2327
- *
2328
- * The Object form of {@link Autolinker#cfg-stripPrefix}.
2329
- */
2330
- _this.stripPrefix = {
2331
- scheme: true,
2332
- www: true
2333
- }; // default value just to get the above doc comment in the ES5 output and documentation generator
2334
- /**
2335
- * @cfg {Boolean} stripTrailingSlash (required)
2336
- * @inheritdoc Autolinker#stripTrailingSlash
2337
- */
2338
- _this.stripTrailingSlash = true; // default value just to get the above doc comment in the ES5 output and documentation generator
2339
- /**
2340
- * @cfg {Boolean} decodePercentEncoding (required)
2341
- * @inheritdoc Autolinker#decodePercentEncoding
2342
- */
2343
- _this.decodePercentEncoding = true; // default value just to get the above doc comment in the ES5 output and documentation generator
2344
- /**
2345
- * @protected
2346
- * @property {RegExp} matcherRegex
2347
- *
2348
- * The regular expression to match URLs with an optional scheme, port
2349
- * number, path, query string, and hash anchor.
2350
- *
2351
- * Example matches:
2352
- *
2353
- * http://google.com
2354
- * www.google.com
2355
- * google.com/path/to/file?q1=1&q2=2#myAnchor
2356
- *
2357
- *
2358
- * This regular expression will have the following capturing groups:
2359
- *
2360
- * 1. Group that matches a scheme-prefixed URL (i.e. 'http://google.com').
2361
- * This is used to match scheme URLs with just a single word, such as
2362
- * 'http://localhost', where we won't double check that the domain name
2363
- * has at least one dot ('.') in it.
2364
- * 2. Group that matches a 'www.' prefixed URL. This is only matched if the
2365
- * 'www.' text was not prefixed by a scheme (i.e.: not prefixed by
2366
- * 'http://', 'ftp:', etc.)
2367
- * 3. A protocol-relative ('//') match for the case of a 'www.' prefixed
2368
- * URL. Will be an empty string if it is not a protocol-relative match.
2369
- * We need to know the character before the '//' in order to determine
2370
- * if it is a valid match or the // was in a string we don't want to
2371
- * auto-link.
2372
- * 4. Group that matches a known TLD (top level domain), when a scheme
2373
- * or 'www.'-prefixed domain is not matched.
2374
- * 5. A protocol-relative ('//') match for the case of a known TLD prefixed
2375
- * URL. Will be an empty string if it is not a protocol-relative match.
2376
- * See #3 for more info.
2377
- */
2378
- _this.matcherRegex = matcherRegex;
2379
- /**
2380
- * A regular expression to use to check the character before a protocol-relative
2381
- * URL match. We don't want to match a protocol-relative URL if it is part
2382
- * of another word.
2383
- *
2384
- * For example, we want to match something like "Go to: //google.com",
2385
- * but we don't want to match something like "abc//google.com"
2386
- *
2387
- * This regular expression is used to test the character before the '//'.
2388
- *
2389
- * @protected
2390
- * @type {RegExp} wordCharRegExp
2391
- */
2392
- _this.wordCharRegExp = wordCharRegExp;
2393
- _this.stripPrefix = cfg.stripPrefix;
2394
- _this.stripTrailingSlash = cfg.stripTrailingSlash;
2395
- _this.decodePercentEncoding = cfg.decodePercentEncoding;
2396
- return _this;
2397
- }
2398
- /**
2399
- * @inheritdoc
2400
- */
2401
- UrlMatcher.prototype.parseMatches = function (text) {
2402
- var matcherRegex = this.matcherRegex,
2403
- stripPrefix = this.stripPrefix,
2404
- stripTrailingSlash = this.stripTrailingSlash,
2405
- decodePercentEncoding = this.decodePercentEncoding,
2406
- tagBuilder = this.tagBuilder,
2407
- matches = [],
2408
- match;
2409
- var _loop_1 = function () {
2410
- var matchStr = match[0],
2411
- schemeUrlMatch = match[1],
2412
- wwwUrlMatch = match[4],
2413
- wwwProtocolRelativeMatch = match[5],
2414
- //tldUrlMatch = match[ 8 ], -- not needed at the moment
2415
- tldProtocolRelativeMatch = match[9],
2416
- offset = match.index,
2417
- protocolRelativeMatch = wwwProtocolRelativeMatch || tldProtocolRelativeMatch,
2418
- prevChar = text.charAt(offset - 1);
2419
- if (!UrlMatchValidator.isValid(matchStr, schemeUrlMatch)) {
2420
- return "continue";
2421
- }
2422
- // If the match is preceded by an '@' character, then it is either
2423
- // an email address or a username. Skip these types of matches.
2424
- if (offset > 0 && prevChar === '@') {
2425
- return "continue";
2426
- }
2427
- // If it's a protocol-relative '//' match, but the character before the '//'
2428
- // was a word character (i.e. a letter/number), then we found the '//' in the
2429
- // middle of another word (such as "asdf//asdf.com"). In this case, skip the
2430
- // match.
2431
- if (offset > 0 && protocolRelativeMatch && this_1.wordCharRegExp.test(prevChar)) {
2432
- return "continue";
2433
- }
2434
- // If the URL ends with a question mark, don't include the question
2435
- // mark as part of the URL. We'll assume the question mark was the
2436
- // end of a sentence, such as: "Going to google.com?"
2437
- if (/\?$/.test(matchStr)) {
2438
- matchStr = matchStr.substr(0, matchStr.length - 1);
2439
- }
2440
- // Handle a closing parenthesis or square bracket at the end of the
2441
- // match, and exclude it if there is not a matching open parenthesis
2442
- // or square bracket in the match itself.
2443
- if (this_1.matchHasUnbalancedClosingParen(matchStr)) {
2444
- matchStr = matchStr.substr(0, matchStr.length - 1); // remove the trailing ")"
2445
- } else {
2446
- // Handle an invalid character after the TLD
2447
- var pos = this_1.matchHasInvalidCharAfterTld(matchStr, schemeUrlMatch);
2448
- if (pos > -1) {
2449
- matchStr = matchStr.substr(0, pos); // remove the trailing invalid chars
2450
- }
2451
- }
2452
- // The autolinker accepts many characters in a url's scheme (like `fake://test.com`).
2453
- // However, in cases where a URL is missing whitespace before an obvious link,
2454
- // (for example: `nowhitespacehttp://www.test.com`), we only want the match to start
2455
- // at the http:// part. We will check if the match contains a common scheme and then
2456
- // shift the match to start from there.
2457
- var foundCommonScheme = ['http://', 'https://'].find(function (commonScheme) {
2458
- return !!schemeUrlMatch && schemeUrlMatch.indexOf(commonScheme) !== -1;
2459
- });
2460
- if (foundCommonScheme) {
2461
- // If we found an overmatched URL, we want to find the index
2462
- // of where the match should start and shift the match to
2463
- // start from the beginning of the common scheme
2464
- var indexOfSchemeStart = matchStr.indexOf(foundCommonScheme);
2465
- matchStr = matchStr.substr(indexOfSchemeStart);
2466
- schemeUrlMatch = schemeUrlMatch.substr(indexOfSchemeStart);
2467
- offset = offset + indexOfSchemeStart;
2468
- }
2469
- var urlMatchType = schemeUrlMatch ? 'scheme' : wwwUrlMatch ? 'www' : 'tld',
2470
- protocolUrlMatch = !!schemeUrlMatch;
2471
- matches.push(new UrlMatch({
2472
- tagBuilder: tagBuilder,
2473
- matchedText: matchStr,
2474
- offset: offset,
2475
- urlMatchType: urlMatchType,
2476
- url: matchStr,
2477
- protocolUrlMatch: protocolUrlMatch,
2478
- protocolRelativeMatch: !!protocolRelativeMatch,
2479
- stripPrefix: stripPrefix,
2480
- stripTrailingSlash: stripTrailingSlash,
2481
- decodePercentEncoding: decodePercentEncoding
2482
- }));
2483
- };
2484
- var this_1 = this;
2485
- while ((match = matcherRegex.exec(text)) !== null) {
2486
- _loop_1();
2487
- }
2488
- return matches;
2489
- };
2490
- /**
2491
- * Determines if a match found has an unmatched closing parenthesis,
2492
- * square bracket or curly bracket. If so, the symbol will be removed
2493
- * from the match itself, and appended after the generated anchor tag.
2494
- *
2495
- * A match may have an extra closing parenthesis at the end of the match
2496
- * because the regular expression must include parenthesis for URLs such as
2497
- * "wikipedia.com/something_(disambiguation)", which should be auto-linked.
2498
- *
2499
- * However, an extra parenthesis *will* be included when the URL itself is
2500
- * wrapped in parenthesis, such as in the case of:
2501
- * "(wikipedia.com/something_(disambiguation))"
2502
- * In this case, the last closing parenthesis should *not* be part of the
2503
- * URL itself, and this method will return `true`.
2504
- *
2505
- * For square brackets in URLs such as in PHP arrays, the same behavior as
2506
- * parenthesis discussed above should happen:
2507
- * "[http://www.example.com/foo.php?bar[]=1&bar[]=2&bar[]=3]"
2508
- * The closing square bracket should not be part of the URL itself, and this
2509
- * method will return `true`.
2510
- *
2511
- * @protected
2512
- * @param {String} matchStr The full match string from the {@link #matcherRegex}.
2513
- * @return {Boolean} `true` if there is an unbalanced closing parenthesis or
2514
- * square bracket at the end of the `matchStr`, `false` otherwise.
2515
- */
2516
- UrlMatcher.prototype.matchHasUnbalancedClosingParen = function (matchStr) {
2517
- var endChar = matchStr.charAt(matchStr.length - 1);
2518
- var startChar;
2519
- if (endChar === ')') {
2520
- startChar = '(';
2521
- } else if (endChar === ']') {
2522
- startChar = '[';
2523
- } else if (endChar === '}') {
2524
- startChar = '{';
2525
- } else {
2526
- return false; // not a close parenthesis or square bracket
2527
- }
2528
- // Find if there are the same number of open braces as close braces in
2529
- // the URL string, minus the last character (which we have already
2530
- // determined to be either ')', ']' or '}'
2531
- var numOpenBraces = 0;
2532
- for (var i = 0, len = matchStr.length - 1; i < len; i++) {
2533
- var char = matchStr.charAt(i);
2534
- if (char === startChar) {
2535
- numOpenBraces++;
2536
- } else if (char === endChar) {
2537
- numOpenBraces = Math.max(numOpenBraces - 1, 0);
2538
- }
2539
- }
2540
- // If the number of open braces matches the number of close braces in
2541
- // the URL minus the last character, then the match has *unbalanced*
2542
- // braces because of the last character. Example of unbalanced braces
2543
- // from the regex match:
2544
- // "http://example.com?a[]=1]"
2545
- if (numOpenBraces === 0) {
2546
- return true;
2547
- }
2548
- return false;
2549
- };
2550
- /**
2551
- * Determine if there's an invalid character after the TLD in a URL. Valid
2552
- * characters after TLD are ':/?#'. Exclude scheme matched URLs from this
2553
- * check.
2554
- *
2555
- * @protected
2556
- * @param {String} urlMatch The matched URL, if there was one. Will be an
2557
- * empty string if the match is not a URL match.
2558
- * @param {String} schemeUrlMatch The match URL string for a scheme
2559
- * match. Ex: 'http://yahoo.com'. This is used to match something like
2560
- * 'http://localhost', where we won't double check that the domain name
2561
- * has at least one '.' in it.
2562
- * @return {Number} the position where the invalid character was found. If
2563
- * no such character was found, returns -1
2564
- */
2565
- UrlMatcher.prototype.matchHasInvalidCharAfterTld = function (urlMatch, schemeUrlMatch) {
2566
- if (!urlMatch) {
2567
- return -1;
2568
- }
2569
- var offset = 0;
2570
- if (schemeUrlMatch) {
2571
- offset = urlMatch.indexOf(':');
2572
- urlMatch = urlMatch.slice(offset);
2573
- }
2574
- // prettier-ignore
2575
- var re = new RegExp("^((.?\/\/)?[-." + alphaNumericAndMarksCharsStr + "]*[-" + alphaNumericAndMarksCharsStr + "]\\.[-" + alphaNumericAndMarksCharsStr + "]+)");
2576
- var res = re.exec(urlMatch);
2577
- if (res === null) {
2578
- return -1;
2579
- }
2580
- offset += res[1].length;
2581
- urlMatch = urlMatch.slice(res[1].length);
2582
- if (/^[^-.A-Za-z0-9:\/?#]/.test(urlMatch)) {
2583
- return offset;
2584
- }
2585
- return -1;
2586
- };
2587
- return UrlMatcher;
2588
- }(Matcher);
2589
-
2590
- // For debugging: search for other "For debugging" lines
2591
- // import CliTable from 'cli-table';
2592
- var hashtagTextCharRe = new RegExp("[_".concat(alphaNumericAndMarksCharsStr, "]"));
2593
- /**
2594
- * @class Autolinker.matcher.Hashtag
2595
- * @extends Autolinker.matcher.Matcher
2596
- *
2597
- * Matcher to find HashtagMatch matches in an input string.
2598
- */
2599
- var HashtagMatcher = /** @class */function (_super) {
2600
- __extends(HashtagMatcher, _super);
2601
- /**
2602
- * @method constructor
2603
- * @param {Object} cfg The configuration properties for the Match instance,
2604
- * specified in an Object (map).
2605
- */
2606
- function HashtagMatcher(cfg) {
2607
- var _this = _super.call(this, cfg) || this;
2608
- /**
2609
- * @cfg {String} service
2610
- *
2611
- * A string for the service name to have hashtags (ex: "#myHashtag")
2612
- * auto-linked to. The currently-supported values are:
2613
- *
2614
- * - 'twitter'
2615
- * - 'facebook'
2616
- * - 'instagram'
2617
- * - 'tiktok'
2618
- */
2619
- _this.serviceName = 'twitter'; // default value just to get the above doc comment in the ES5 output and documentation generator
2620
- _this.serviceName = cfg.serviceName;
2621
- return _this;
2622
- }
2623
- /**
2624
- * @inheritdoc
2625
- */
2626
- HashtagMatcher.prototype.parseMatches = function (text) {
2627
- var tagBuilder = this.tagBuilder;
2628
- var serviceName = this.serviceName;
2629
- var matches = [];
2630
- var len = text.length;
2631
- var charIdx = 0,
2632
- hashCharIdx = -1,
2633
- state = 0 /* None */;
2634
- // For debugging: search for other "For debugging" lines
2635
- // const table = new CliTable( {
2636
- // head: [ 'charIdx', 'char', 'state', 'charIdx', 'currentEmailAddress.idx', 'hasDomainDot' ]
2637
- // } );
2638
- while (charIdx < len) {
2639
- var char = text.charAt(charIdx);
2640
- // For debugging: search for other "For debugging" lines
2641
- // table.push(
2642
- // [ charIdx, char, State[ state ], charIdx, currentEmailAddress.idx, currentEmailAddress.hasDomainDot ]
2643
- // );
2644
- switch (state) {
2645
- case 0 /* None */:
2646
- stateNone(char);
2647
- break;
2648
- case 1 /* NonHashtagWordChar */:
2649
- stateNonHashtagWordChar(char);
2650
- break;
2651
- case 2 /* HashtagHashChar */:
2652
- stateHashtagHashChar(char);
2653
- break;
2654
- case 3 /* HashtagTextChar */:
2655
- stateHashtagTextChar(char);
2656
- break;
2657
- default:
2658
- throwUnhandledCaseError(state);
2659
- }
2660
- // For debugging: search for other "For debugging" lines
2661
- // table.push(
2662
- // [ charIdx, char, State[ state ], charIdx, currentEmailAddress.idx, currentEmailAddress.hasDomainDot ]
2663
- // );
2664
- charIdx++;
2665
- }
2666
- // Capture any valid match at the end of the string
2667
- captureMatchIfValid();
2668
- // For debugging: search for other "For debugging" lines
2669
- //console.log( '\n' + table.toString() );
2670
- return matches;
2671
- // Handles the state when we're not in a hashtag or any word
2672
- function stateNone(char) {
2673
- if (char === '#') {
2674
- state = 2 /* HashtagHashChar */;
2675
- hashCharIdx = charIdx;
2676
- } else if (alphaNumericAndMarksCharRe.test(char)) {
2677
- state = 1 /* NonHashtagWordChar */;
2678
- } else ;
2679
- }
2680
- // Handles the state when we've encountered a word character but are not
2681
- // in a hashtag. This is used to distinguish between a standalone
2682
- // hashtag such as '#Stuff' vs a hash char that is part of a word like
2683
- // 'asdf#stuff' (the latter of which would not be a match)
2684
- function stateNonHashtagWordChar(char) {
2685
- if (alphaNumericAndMarksCharRe.test(char)) ; else {
2686
- state = 0 /* None */;
2687
- }
2688
- }
2689
- // Handles the state when we've just encountered a '#' character
2690
- function stateHashtagHashChar(char) {
2691
- if (hashtagTextCharRe.test(char)) {
2692
- // '#' char with valid hash text char following
2693
- state = 3 /* HashtagTextChar */;
2694
- } else if (alphaNumericAndMarksCharRe.test(char)) {
2695
- state = 1 /* NonHashtagWordChar */;
2696
- } else {
2697
- state = 0 /* None */;
2698
- }
2699
- }
2700
- // Handles the state when we're currently in the hash tag's text chars
2701
- function stateHashtagTextChar(char) {
2702
- if (hashtagTextCharRe.test(char)) ; else {
2703
- captureMatchIfValid();
2704
- hashCharIdx = -1;
2705
- if (alphaNumericAndMarksCharRe.test(char)) {
2706
- state = 1 /* NonHashtagWordChar */;
2707
- } else {
2708
- state = 0 /* None */;
2709
- }
2710
- }
2711
- }
2712
- /*
2713
- * Captures the current hashtag as a HashtagMatch if it's valid.
2714
- */
2715
- function captureMatchIfValid() {
2716
- if (hashCharIdx > -1 && charIdx - hashCharIdx <= 140) {
2717
- // Max length of 140 for a hashtag ('#' char + 139 word chars)
2718
- var matchedText = text.slice(hashCharIdx, charIdx);
2719
- var match = new HashtagMatch({
2720
- tagBuilder: tagBuilder,
2721
- matchedText: matchedText,
2722
- offset: hashCharIdx,
2723
- serviceName: serviceName,
2724
- hashtag: matchedText.slice(1)
2725
- });
2726
- matches.push(match);
2727
- }
2728
- }
2729
- };
2730
- return HashtagMatcher;
2731
- }(Matcher);
2732
- var hashtagServices = ['twitter', 'facebook', 'instagram', 'tiktok'];
2733
-
2734
- // RegExp objects which are shared by all instances of PhoneMatcher. These are
2735
- // here to avoid re-instantiating the RegExp objects if `Autolinker.link()` is
2736
- // called multiple times, thus instantiating PhoneMatcher and its RegExp
2737
- // objects each time (which is very expensive - see https://github.com/gregjacobs/Autolinker.js/issues/314).
2738
- // See descriptions of the properties where they are used for details about them
2739
- // Over the years, many people have added to this regex, but it should have been
2740
- // split up by country. Maybe one day we can break this down.
2741
- var mostPhoneNumbers = /(?:(?:(?:(\+)?\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]+#?)*/;
2742
- // Regex for Japanese phone numbers
2743
- var japanesePhoneRe = /(0([1-9]{1}-?[1-9]\d{3}|[1-9]{2}-?\d{3}|[1-9]{2}\d{1}-?\d{2}|[1-9]{2}\d{2}-?\d{1})-?\d{4}|0[789]0-?\d{4}-?\d{4}|050-?\d{4}-?\d{4})/;
2744
- // Combined regex
2745
- var phoneMatcherRegex = new RegExp("".concat(mostPhoneNumbers.source, "|").concat(japanesePhoneRe.source), 'g');
2746
- /**
2747
- * @class Autolinker.matcher.Phone
2748
- * @extends Autolinker.matcher.Matcher
2749
- *
2750
- * Matcher to find Phone number matches in an input string.
2751
- *
2752
- * See this class's superclass ({@link Autolinker.matcher.Matcher}) for more
2753
- * details.
2754
- */
2755
- var PhoneMatcher = /** @class */function (_super) {
2756
- __extends(PhoneMatcher, _super);
2757
- function PhoneMatcher() {
2758
- var _this = _super !== null && _super.apply(this, arguments) || this;
2759
- /**
2760
- * The regular expression to match Phone numbers. Example matches:
2761
- *
2762
- * (123) 456-7890
2763
- * 123 456 7890
2764
- * 123-456-7890
2765
- * +18004441234,,;,10226420346#
2766
- * +1 (800) 444 1234
2767
- * 10226420346#
2768
- * 1-800-444-1234,1022,64,20346#
2769
- *
2770
- * This regular expression has the following capturing groups:
2771
- *
2772
- * 1 or 2. The prefixed '+' sign, if there is one.
2773
- *
2774
- * @protected
2775
- * @property {RegExp} matcherRegex
2776
- */
2777
- _this.matcherRegex = phoneMatcherRegex;
2778
- return _this;
2779
- }
2780
- /**
2781
- * @inheritdoc
2782
- */
2783
- PhoneMatcher.prototype.parseMatches = function (text) {
2784
- var matcherRegex = this.matcherRegex,
2785
- tagBuilder = this.tagBuilder,
2786
- matches = [],
2787
- match;
2788
- while ((match = matcherRegex.exec(text)) !== null) {
2789
- // Remove non-numeric values from phone number string
2790
- var matchedText = match[0],
2791
- cleanNumber = matchedText.replace(/[^0-9,;#]/g, ''),
2792
- // strip out non-digit characters exclude comma semicolon and #
2793
- plusSign = !!(match[1] || match[2]),
2794
- // match[ 1 ] or match[ 2 ] is the prefixed plus sign, if there is one
2795
- before = match.index == 0 ? '' : text.substr(match.index - 1, 1),
2796
- after = text.substr(match.index + matchedText.length, 1),
2797
- contextClear = !before.match(/\d/) && !after.match(/\d/);
2798
- if (this.testMatch(match[3]) && this.testMatch(matchedText) && contextClear) {
2799
- matches.push(new PhoneMatch({
2800
- tagBuilder: tagBuilder,
2801
- matchedText: matchedText,
2802
- offset: match.index,
2803
- number: cleanNumber,
2804
- plusSign: plusSign
2805
- }));
2806
- }
2807
- }
2808
- return matches;
2809
- };
2810
- PhoneMatcher.prototype.testMatch = function (text) {
2811
- return nonDigitRe.test(text);
2812
- };
2813
- return PhoneMatcher;
2814
- }(Matcher);
2815
-
2816
- // RegExp objects which are shared by all instances of MentionMatcher. These are
2817
- // here to avoid re-instantiating the RegExp objects if `Autolinker.link()` is
2818
- // called multiple times, thus instantiating MentionMatcher and its RegExp
2819
- // objects each time (which is very expensive - see https://github.com/gregjacobs/Autolinker.js/issues/314).
2820
- // See descriptions of the properties where they are used for details about them
2821
- var twitterRegex = new RegExp("@[_".concat(alphaNumericAndMarksCharsStr, "]{1,50}(?![_").concat(alphaNumericAndMarksCharsStr, "])"), 'g'); // lookahead used to make sure we don't match something above 50 characters
2822
- var instagramRegex = new RegExp("@[_.".concat(alphaNumericAndMarksCharsStr, "]{1,30}(?![_").concat(alphaNumericAndMarksCharsStr, "])"), 'g'); // lookahead used to make sure we don't match something above 30 characters
2823
- var soundcloudRegex = new RegExp("@[-_.".concat(alphaNumericAndMarksCharsStr, "]{1,50}(?![-_").concat(alphaNumericAndMarksCharsStr, "])"), 'g'); // lookahead used to make sure we don't match something above 50 characters
2824
- // TikTok usernames are 1-24 characters containing letters, numbers, underscores
2825
- // and periods, but cannot end in a period: https://support.tiktok.com/en/getting-started/setting-up-your-profile/changing-your-username
2826
- var tiktokRegex = new RegExp("@[_.".concat(alphaNumericAndMarksCharsStr, "]{1,23}[_").concat(alphaNumericAndMarksCharsStr, "](?![_").concat(alphaNumericAndMarksCharsStr, "])"), 'g'); // lookahead used to make sure we don't match something above 24 characters
2827
- var nonWordCharRegex = new RegExp('[^' + alphaNumericAndMarksCharsStr + ']');
2828
- /**
2829
- * @class Autolinker.matcher.Mention
2830
- * @extends Autolinker.matcher.Matcher
2831
- *
2832
- * Matcher to find/replace username matches in an input string.
2833
- */
2834
- var MentionMatcher = /** @class */function (_super) {
2835
- __extends(MentionMatcher, _super);
2836
- /**
2837
- * @method constructor
2838
- * @param {Object} cfg The configuration properties for the Match instance,
2839
- * specified in an Object (map).
2840
- */
2841
- function MentionMatcher(cfg) {
2842
- var _this = _super.call(this, cfg) || this;
2843
- /**
2844
- * @cfg {'twitter'/'instagram'/'soundcloud'} protected
2845
- *
2846
- * The name of service to link @mentions to.
2847
- *
2848
- * Valid values are: 'twitter', 'instagram', 'soundcloud', or 'tiktok'
2849
- */
2850
- _this.serviceName = 'twitter'; // default value just to get the above doc comment in the ES5 output and documentation generator
2851
- /**
2852
- * Hash of regular expression to match username handles. Example match:
2853
- *
2854
- * @asdf
2855
- *
2856
- * @private
2857
- * @property {Object} matcherRegexes
2858
- */
2859
- _this.matcherRegexes = {
2860
- twitter: twitterRegex,
2861
- instagram: instagramRegex,
2862
- soundcloud: soundcloudRegex,
2863
- tiktok: tiktokRegex
2864
- };
2865
- /**
2866
- * The regular expression to use to check the character before a username match to
2867
- * make sure we didn't accidentally match an email address.
2868
- *
2869
- * For example, the string "asdf@asdf.com" should not match "@asdf" as a username.
2870
- *
2871
- * @private
2872
- * @property {RegExp} nonWordCharRegex
2873
- */
2874
- _this.nonWordCharRegex = nonWordCharRegex;
2875
- _this.serviceName = cfg.serviceName;
2876
- return _this;
2877
- }
2878
- /**
2879
- * @inheritdoc
2880
- */
2881
- MentionMatcher.prototype.parseMatches = function (text) {
2882
- var serviceName = this.serviceName,
2883
- matcherRegex = this.matcherRegexes[this.serviceName],
2884
- nonWordCharRegex = this.nonWordCharRegex,
2885
- tagBuilder = this.tagBuilder,
2886
- matches = [],
2887
- match;
2888
- if (!matcherRegex) {
2889
- return matches;
2890
- }
2891
- while ((match = matcherRegex.exec(text)) !== null) {
2892
- var offset = match.index,
2893
- prevChar = text.charAt(offset - 1);
2894
- // If we found the match at the beginning of the string, or we found the match
2895
- // and there is a whitespace char in front of it (meaning it is not an email
2896
- // address), then it is a username match.
2897
- if (offset === 0 || nonWordCharRegex.test(prevChar)) {
2898
- var matchedText = match[0].replace(/\.+$/g, ''),
2899
- // strip off trailing .
2900
- mention = matchedText.slice(1); // strip off the '@' character at the beginning
2901
- matches.push(new MentionMatch({
2902
- tagBuilder: tagBuilder,
2903
- matchedText: matchedText,
2904
- offset: offset,
2905
- serviceName: serviceName,
2906
- mention: mention
2907
- }));
2908
- }
2909
- }
2910
- return matches;
2911
- };
2912
- return MentionMatcher;
2913
- }(Matcher);
2914
-
2915
- // For debugging: search for other "For debugging" lines
2916
- // import CliTable from 'cli-table';
2917
- /**
2918
- * Parses an HTML string, calling the callbacks to notify of tags and text.
2919
- *
2920
- * ## History
2921
- *
2922
- * This file previously used a regular expression to find html tags in the input
2923
- * text. Unfortunately, we ran into a bunch of catastrophic backtracking issues
2924
- * with certain input text, causing Autolinker to either hang or just take a
2925
- * really long time to parse the string.
2926
- *
2927
- * The current code is intended to be a O(n) algorithm that walks through
2928
- * the string in one pass, and tries to be as cheap as possible. We don't need
2929
- * to implement the full HTML spec, but rather simply determine where the string
2930
- * looks like an HTML tag, and where it looks like text (so that we can autolink
2931
- * that).
2932
- *
2933
- * This state machine parser is intended just to be a simple but performant
2934
- * parser of HTML for the subset of requirements we have. We simply need to:
2935
- *
2936
- * 1. Determine where HTML tags are
2937
- * 2. Determine the tag name (Autolinker specifically only cares about <a>,
2938
- * <script>, and <style> tags, so as not to link any text within them)
2939
- *
2940
- * We don't need to:
2941
- *
2942
- * 1. Create a parse tree
2943
- * 2. Auto-close tags with invalid markup
2944
- * 3. etc.
2945
- *
2946
- * The other intention behind this is that we didn't want to add external
2947
- * dependencies on the Autolinker utility which would increase its size. For
2948
- * instance, adding htmlparser2 adds 125kb to the minified output file,
2949
- * increasing its final size from 47kb to 172kb (at the time of writing). It
2950
- * also doesn't work exactly correctly, treating the string "<3 blah blah blah"
2951
- * as an HTML tag.
2952
- *
2953
- * Reference for HTML spec:
2954
- *
2955
- * https://www.w3.org/TR/html51/syntax.html#sec-tokenization
2956
- *
2957
- * @param {String} html The HTML to parse
2958
- * @param {Object} callbacks
2959
- * @param {Function} callbacks.onOpenTag Callback function to call when an open
2960
- * tag is parsed. Called with the tagName as its argument.
2961
- * @param {Function} callbacks.onCloseTag Callback function to call when a close
2962
- * tag is parsed. Called with the tagName as its argument. If a self-closing
2963
- * tag is found, `onCloseTag` is called immediately after `onOpenTag`.
2964
- * @param {Function} callbacks.onText Callback function to call when text (i.e
2965
- * not an HTML tag) is parsed. Called with the text (string) as its first
2966
- * argument, and offset (number) into the string as its second.
2967
- */
2968
- function parseHtml(html, _a) {
2969
- var onOpenTag = _a.onOpenTag,
2970
- onCloseTag = _a.onCloseTag,
2971
- onText = _a.onText,
2972
- onComment = _a.onComment,
2973
- onDoctype = _a.onDoctype;
2974
- var noCurrentTag = new CurrentTag();
2975
- var charIdx = 0,
2976
- len = html.length,
2977
- state = 0 /* Data */,
2978
- currentDataIdx = 0,
2979
- // where the current data start index is
2980
- currentTag = noCurrentTag; // describes the current tag that is being read
2981
- // For debugging: search for other "For debugging" lines
2982
- // const table = new CliTable( {
2983
- // head: [ 'charIdx', 'char', 'state', 'currentDataIdx', 'currentOpenTagIdx', 'tag.type' ]
2984
- // } );
2985
- while (charIdx < len) {
2986
- var char = html.charAt(charIdx);
2987
- // For debugging: search for other "For debugging" lines
2988
- // ALSO: Temporarily remove the 'const' keyword on the State enum
2989
- // table.push(
2990
- // [ charIdx, char, State[ state ], currentDataIdx, currentTag.idx, currentTag.idx === -1 ? '' : currentTag.type ]
2991
- // );
2992
- switch (state) {
2993
- case 0 /* Data */:
2994
- stateData(char);
2995
- break;
2996
- case 1 /* TagOpen */:
2997
- stateTagOpen(char);
2998
- break;
2999
- case 2 /* EndTagOpen */:
3000
- stateEndTagOpen(char);
3001
- break;
3002
- case 3 /* TagName */:
3003
- stateTagName(char);
3004
- break;
3005
- case 4 /* BeforeAttributeName */:
3006
- stateBeforeAttributeName(char);
3007
- break;
3008
- case 5 /* AttributeName */:
3009
- stateAttributeName(char);
3010
- break;
3011
- case 6 /* AfterAttributeName */:
3012
- stateAfterAttributeName(char);
3013
- break;
3014
- case 7 /* BeforeAttributeValue */:
3015
- stateBeforeAttributeValue(char);
3016
- break;
3017
- case 8 /* AttributeValueDoubleQuoted */:
3018
- stateAttributeValueDoubleQuoted(char);
3019
- break;
3020
- case 9 /* AttributeValueSingleQuoted */:
3021
- stateAttributeValueSingleQuoted(char);
3022
- break;
3023
- case 10 /* AttributeValueUnquoted */:
3024
- stateAttributeValueUnquoted(char);
3025
- break;
3026
- case 11 /* AfterAttributeValueQuoted */:
3027
- stateAfterAttributeValueQuoted(char);
3028
- break;
3029
- case 12 /* SelfClosingStartTag */:
3030
- stateSelfClosingStartTag(char);
3031
- break;
3032
- case 13 /* MarkupDeclarationOpenState */:
3033
- stateMarkupDeclarationOpen();
3034
- break;
3035
- case 14 /* CommentStart */:
3036
- stateCommentStart(char);
3037
- break;
3038
- case 15 /* CommentStartDash */:
3039
- stateCommentStartDash(char);
3040
- break;
3041
- case 16 /* Comment */:
3042
- stateComment(char);
3043
- break;
3044
- case 17 /* CommentEndDash */:
3045
- stateCommentEndDash(char);
3046
- break;
3047
- case 18 /* CommentEnd */:
3048
- stateCommentEnd(char);
3049
- break;
3050
- case 19 /* CommentEndBang */:
3051
- stateCommentEndBang(char);
3052
- break;
3053
- case 20 /* Doctype */:
3054
- stateDoctype(char);
3055
- break;
3056
- default:
3057
- throwUnhandledCaseError(state);
3058
- }
3059
- // For debugging: search for other "For debugging" lines
3060
- // ALSO: Temporarily remove the 'const' keyword on the State enum
3061
- // table.push(
3062
- // [ charIdx, char, State[ state ], currentDataIdx, currentTag.idx, currentTag.idx === -1 ? '' : currentTag.type ]
3063
- // );
3064
- charIdx++;
3065
- }
3066
- if (currentDataIdx < charIdx) {
3067
- emitText();
3068
- }
3069
- // For debugging: search for other "For debugging" lines
3070
- // console.log( '\n' + table.toString() );
3071
- // Called when non-tags are being read (i.e. the text around HTML †ags)
3072
- // https://www.w3.org/TR/html51/syntax.html#data-state
3073
- function stateData(char) {
3074
- if (char === '<') {
3075
- startNewTag();
3076
- }
3077
- }
3078
- // Called after a '<' is read from the Data state
3079
- // https://www.w3.org/TR/html51/syntax.html#tag-open-state
3080
- function stateTagOpen(char) {
3081
- if (char === '!') {
3082
- state = 13 /* MarkupDeclarationOpenState */;
3083
- } else if (char === '/') {
3084
- state = 2 /* EndTagOpen */;
3085
- currentTag = new CurrentTag(__assign(__assign({}, currentTag), {
3086
- isClosing: true
3087
- }));
3088
- } else if (char === '<') {
3089
- // start of another tag (ignore the previous, incomplete one)
3090
- startNewTag();
3091
- } else if (letterRe.test(char)) {
3092
- // tag name start (and no '/' read)
3093
- state = 3 /* TagName */;
3094
- currentTag = new CurrentTag(__assign(__assign({}, currentTag), {
3095
- isOpening: true
3096
- }));
3097
- } else {
3098
- // Any other
3099
- state = 0 /* Data */;
3100
- currentTag = noCurrentTag;
3101
- }
3102
- }
3103
- // After a '<x', '</x' sequence is read (where 'x' is a letter character),
3104
- // this is to continue reading the tag name
3105
- // https://www.w3.org/TR/html51/syntax.html#tag-name-state
3106
- function stateTagName(char) {
3107
- if (whitespaceRe.test(char)) {
3108
- currentTag = new CurrentTag(__assign(__assign({}, currentTag), {
3109
- name: captureTagName()
3110
- }));
3111
- state = 4 /* BeforeAttributeName */;
3112
- } else if (char === '<') {
3113
- // start of another tag (ignore the previous, incomplete one)
3114
- startNewTag();
3115
- } else if (char === '/') {
3116
- currentTag = new CurrentTag(__assign(__assign({}, currentTag), {
3117
- name: captureTagName()
3118
- }));
3119
- state = 12 /* SelfClosingStartTag */;
3120
- } else if (char === '>') {
3121
- currentTag = new CurrentTag(__assign(__assign({}, currentTag), {
3122
- name: captureTagName()
3123
- }));
3124
- emitTagAndPreviousTextNode(); // resets to Data state as well
3125
- } else if (!letterRe.test(char) && !digitRe.test(char) && char !== ':') {
3126
- // Anything else that does not form an html tag. Note: the colon
3127
- // character is accepted for XML namespaced tags
3128
- resetToDataState();
3129
- } else ;
3130
- }
3131
- // Called after the '/' is read from a '</' sequence
3132
- // https://www.w3.org/TR/html51/syntax.html#end-tag-open-state
3133
- function stateEndTagOpen(char) {
3134
- if (char === '>') {
3135
- // parse error. Encountered "</>". Skip it without treating as a tag
3136
- resetToDataState();
3137
- } else if (letterRe.test(char)) {
3138
- state = 3 /* TagName */;
3139
- } else {
3140
- // some other non-tag-like character, don't treat this as a tag
3141
- resetToDataState();
3142
- }
3143
- }
3144
- // https://www.w3.org/TR/html51/syntax.html#before-attribute-name-state
3145
- function stateBeforeAttributeName(char) {
3146
- if (whitespaceRe.test(char)) ; else if (char === '/') {
3147
- state = 12 /* SelfClosingStartTag */;
3148
- } else if (char === '>') {
3149
- emitTagAndPreviousTextNode(); // resets to Data state as well
3150
- } else if (char === '<') {
3151
- // start of another tag (ignore the previous, incomplete one)
3152
- startNewTag();
3153
- } else if (char === "=" || quoteRe.test(char) || controlCharsRe.test(char)) {
3154
- // "Parse error" characters that, according to the spec, should be
3155
- // appended to the attribute name, but we'll treat these characters
3156
- // as not forming a real HTML tag
3157
- resetToDataState();
3158
- } else {
3159
- // Any other char, start of a new attribute name
3160
- state = 5 /* AttributeName */;
3161
- }
3162
- }
3163
- // https://www.w3.org/TR/html51/syntax.html#attribute-name-state
3164
- function stateAttributeName(char) {
3165
- if (whitespaceRe.test(char)) {
3166
- state = 6 /* AfterAttributeName */;
3167
- } else if (char === '/') {
3168
- state = 12 /* SelfClosingStartTag */;
3169
- } else if (char === '=') {
3170
- state = 7 /* BeforeAttributeValue */;
3171
- } else if (char === '>') {
3172
- emitTagAndPreviousTextNode(); // resets to Data state as well
3173
- } else if (char === '<') {
3174
- // start of another tag (ignore the previous, incomplete one)
3175
- startNewTag();
3176
- } else if (quoteRe.test(char)) {
3177
- // "Parse error" characters that, according to the spec, should be
3178
- // appended to the attribute name, but we'll treat these characters
3179
- // as not forming a real HTML tag
3180
- resetToDataState();
3181
- } else ;
3182
- }
3183
- // https://www.w3.org/TR/html51/syntax.html#after-attribute-name-state
3184
- function stateAfterAttributeName(char) {
3185
- if (whitespaceRe.test(char)) ; else if (char === '/') {
3186
- state = 12 /* SelfClosingStartTag */;
3187
- } else if (char === '=') {
3188
- state = 7 /* BeforeAttributeValue */;
3189
- } else if (char === '>') {
3190
- emitTagAndPreviousTextNode();
3191
- } else if (char === '<') {
3192
- // start of another tag (ignore the previous, incomplete one)
3193
- startNewTag();
3194
- } else if (quoteRe.test(char)) {
3195
- // "Parse error" characters that, according to the spec, should be
3196
- // appended to the attribute name, but we'll treat these characters
3197
- // as not forming a real HTML tag
3198
- resetToDataState();
3199
- } else {
3200
- // Any other character, start a new attribute in the current tag
3201
- state = 5 /* AttributeName */;
3202
- }
3203
- }
3204
- // https://www.w3.org/TR/html51/syntax.html#before-attribute-value-state
3205
- function stateBeforeAttributeValue(char) {
3206
- if (whitespaceRe.test(char)) ; else if (char === "\"") {
3207
- state = 8 /* AttributeValueDoubleQuoted */;
3208
- } else if (char === "'") {
3209
- state = 9 /* AttributeValueSingleQuoted */;
3210
- } else if (/[>=`]/.test(char)) {
3211
- // Invalid chars after an '=' for an attribute value, don't count
3212
- // the current tag as an HTML tag
3213
- resetToDataState();
3214
- } else if (char === '<') {
3215
- // start of another tag (ignore the previous, incomplete one)
3216
- startNewTag();
3217
- } else {
3218
- // Any other character, consider it an unquoted attribute value
3219
- state = 10 /* AttributeValueUnquoted */;
3220
- }
3221
- }
3222
- // https://www.w3.org/TR/html51/syntax.html#attribute-value-double-quoted-state
3223
- function stateAttributeValueDoubleQuoted(char) {
3224
- if (char === "\"") {
3225
- // end the current double-quoted attribute
3226
- state = 11 /* AfterAttributeValueQuoted */;
3227
- }
3228
- }
3229
- // https://www.w3.org/TR/html51/syntax.html#attribute-value-single-quoted-state
3230
- function stateAttributeValueSingleQuoted(char) {
3231
- if (char === "'") {
3232
- // end the current single-quoted attribute
3233
- state = 11 /* AfterAttributeValueQuoted */;
3234
- }
3235
- }
3236
- // https://www.w3.org/TR/html51/syntax.html#attribute-value-unquoted-state
3237
- function stateAttributeValueUnquoted(char) {
3238
- if (whitespaceRe.test(char)) {
3239
- state = 4 /* BeforeAttributeName */;
3240
- } else if (char === '>') {
3241
- emitTagAndPreviousTextNode();
3242
- } else if (char === '<') {
3243
- // start of another tag (ignore the previous, incomplete one)
3244
- startNewTag();
3245
- } else ;
3246
- }
3247
- // https://www.w3.org/TR/html51/syntax.html#after-attribute-value-quoted-state
3248
- function stateAfterAttributeValueQuoted(char) {
3249
- if (whitespaceRe.test(char)) {
3250
- state = 4 /* BeforeAttributeName */;
3251
- } else if (char === '/') {
3252
- state = 12 /* SelfClosingStartTag */;
3253
- } else if (char === '>') {
3254
- emitTagAndPreviousTextNode();
3255
- } else if (char === '<') {
3256
- // start of another tag (ignore the previous, incomplete one)
3257
- startNewTag();
3258
- } else {
3259
- // Any other character, "parse error". Spec says to switch to the
3260
- // BeforeAttributeState and re-consume the character, as it may be
3261
- // the start of a new attribute name
3262
- state = 4 /* BeforeAttributeName */;
3263
- reconsumeCurrentCharacter();
3264
- }
3265
- }
3266
- // A '/' has just been read in the current tag (presumably for '/>'), and
3267
- // this handles the next character
3268
- // https://www.w3.org/TR/html51/syntax.html#self-closing-start-tag-state
3269
- function stateSelfClosingStartTag(char) {
3270
- if (char === '>') {
3271
- currentTag = new CurrentTag(__assign(__assign({}, currentTag), {
3272
- isClosing: true
3273
- }));
3274
- emitTagAndPreviousTextNode(); // resets to Data state as well
3275
- } else {
3276
- state = 4 /* BeforeAttributeName */;
3277
- }
3278
- }
3279
- // https://www.w3.org/TR/html51/syntax.html#markup-declaration-open-state
3280
- // (HTML Comments or !DOCTYPE)
3281
- function stateMarkupDeclarationOpen(char) {
3282
- if (html.substr(charIdx, 2) === '--') {
3283
- // html comment
3284
- charIdx += 2; // "consume" characters
3285
- currentTag = new CurrentTag(__assign(__assign({}, currentTag), {
3286
- type: 'comment'
3287
- }));
3288
- state = 14 /* CommentStart */;
3289
- } else if (html.substr(charIdx, 7).toUpperCase() === 'DOCTYPE') {
3290
- charIdx += 7; // "consume" characters
3291
- currentTag = new CurrentTag(__assign(__assign({}, currentTag), {
3292
- type: 'doctype'
3293
- }));
3294
- state = 20 /* Doctype */;
3295
- } else {
3296
- // At this point, the spec specifies that the state machine should
3297
- // enter the "bogus comment" state, in which case any character(s)
3298
- // after the '<!' that were read should become an HTML comment up
3299
- // until the first '>' that is read (or EOF). Instead, we'll assume
3300
- // that a user just typed '<!' as part of text data
3301
- resetToDataState();
3302
- }
3303
- }
3304
- // Handles after the sequence '<!--' has been read
3305
- // https://www.w3.org/TR/html51/syntax.html#comment-start-state
3306
- function stateCommentStart(char) {
3307
- if (char === '-') {
3308
- // We've read the sequence '<!---' at this point (3 dashes)
3309
- state = 15 /* CommentStartDash */;
3310
- } else if (char === '>') {
3311
- // At this point, we'll assume the comment wasn't a real comment
3312
- // so we'll just emit it as data. We basically read the sequence
3313
- // '<!-->'
3314
- resetToDataState();
3315
- } else {
3316
- // Any other char, take it as part of the comment
3317
- state = 16 /* Comment */;
3318
- }
3319
- }
3320
- // We've read the sequence '<!---' at this point (3 dashes)
3321
- // https://www.w3.org/TR/html51/syntax.html#comment-start-dash-state
3322
- function stateCommentStartDash(char) {
3323
- if (char === '-') {
3324
- // We've read '<!----' (4 dashes) at this point
3325
- state = 18 /* CommentEnd */;
3326
- } else if (char === '>') {
3327
- // At this point, we'll assume the comment wasn't a real comment
3328
- // so we'll just emit it as data. We basically read the sequence
3329
- // '<!--->'
3330
- resetToDataState();
3331
- } else {
3332
- // Anything else, take it as a valid comment
3333
- state = 16 /* Comment */;
3334
- }
3335
- }
3336
- // Currently reading the comment's text (data)
3337
- // https://www.w3.org/TR/html51/syntax.html#comment-state
3338
- function stateComment(char) {
3339
- if (char === '-') {
3340
- state = 17 /* CommentEndDash */;
3341
- }
3342
- }
3343
- // When we we've read the first dash inside a comment, it may signal the
3344
- // end of the comment if we read another dash
3345
- // https://www.w3.org/TR/html51/syntax.html#comment-end-dash-state
3346
- function stateCommentEndDash(char) {
3347
- if (char === '-') {
3348
- state = 18 /* CommentEnd */;
3349
- } else {
3350
- // Wasn't a dash, must still be part of the comment
3351
- state = 16 /* Comment */;
3352
- }
3353
- }
3354
- // After we've read two dashes inside a comment, it may signal the end of
3355
- // the comment if we then read a '>' char
3356
- // https://www.w3.org/TR/html51/syntax.html#comment-end-state
3357
- function stateCommentEnd(char) {
3358
- if (char === '>') {
3359
- emitTagAndPreviousTextNode();
3360
- } else if (char === '!') {
3361
- state = 19 /* CommentEndBang */;
3362
- } else if (char === '-') ; else {
3363
- // Anything else, switch back to the comment state since we didn't
3364
- // read the full "end comment" sequence (i.e. '-->')
3365
- state = 16 /* Comment */;
3366
- }
3367
- }
3368
- // We've read the sequence '--!' inside of a comment
3369
- // https://www.w3.org/TR/html51/syntax.html#comment-end-bang-state
3370
- function stateCommentEndBang(char) {
3371
- if (char === '-') {
3372
- // We read the sequence '--!-' inside of a comment. The last dash
3373
- // could signify that the comment is going to close
3374
- state = 17 /* CommentEndDash */;
3375
- } else if (char === '>') {
3376
- // End of comment with the sequence '--!>'
3377
- emitTagAndPreviousTextNode();
3378
- } else {
3379
- // The '--!' was not followed by a '>', continue reading the
3380
- // comment's text
3381
- state = 16 /* Comment */;
3382
- }
3383
- }
3384
- /**
3385
- * For DOCTYPES in particular, we don't care about the attributes. Just
3386
- * advance to the '>' character and emit the tag, unless we find a '<'
3387
- * character in which case we'll start a new tag.
3388
- *
3389
- * Example doctype tag:
3390
- * <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
3391
- *
3392
- * Actual spec: https://www.w3.org/TR/html51/syntax.html#doctype-state
3393
- */
3394
- function stateDoctype(char) {
3395
- if (char === '>') {
3396
- emitTagAndPreviousTextNode();
3397
- } else if (char === '<') {
3398
- startNewTag();
3399
- } else ;
3400
- }
3401
- /**
3402
- * Resets the state back to the Data state, and removes the current tag.
3403
- *
3404
- * We'll generally run this function whenever a "parse error" is
3405
- * encountered, where the current tag that is being read no longer looks
3406
- * like a real HTML tag.
3407
- */
3408
- function resetToDataState() {
3409
- state = 0 /* Data */;
3410
- currentTag = noCurrentTag;
3411
- }
3412
- /**
3413
- * Starts a new HTML tag at the current index, ignoring any previous HTML
3414
- * tag that was being read.
3415
- *
3416
- * We'll generally run this function whenever we read a new '<' character,
3417
- * including when we read a '<' character inside of an HTML tag that we were
3418
- * previously reading.
3419
- */
3420
- function startNewTag() {
3421
- state = 1 /* TagOpen */;
3422
- currentTag = new CurrentTag({
3423
- idx: charIdx
3424
- });
3425
- }
3426
- /**
3427
- * Once we've decided to emit an open tag, that means we can also emit the
3428
- * text node before it.
3429
- */
3430
- function emitTagAndPreviousTextNode() {
3431
- var textBeforeTag = html.slice(currentDataIdx, currentTag.idx);
3432
- if (textBeforeTag) {
3433
- // the html tag was the first element in the html string, or two
3434
- // tags next to each other, in which case we should not emit a text
3435
- // node
3436
- onText(textBeforeTag, currentDataIdx);
3437
- }
3438
- if (currentTag.type === 'comment') {
3439
- onComment(currentTag.idx);
3440
- } else if (currentTag.type === 'doctype') {
3441
- onDoctype(currentTag.idx);
3442
- } else {
3443
- if (currentTag.isOpening) {
3444
- onOpenTag(currentTag.name, currentTag.idx);
3445
- }
3446
- if (currentTag.isClosing) {
3447
- // note: self-closing tags will emit both opening and closing
3448
- onCloseTag(currentTag.name, currentTag.idx);
3449
- }
3450
- }
3451
- // Since we just emitted a tag, reset to the data state for the next char
3452
- resetToDataState();
3453
- currentDataIdx = charIdx + 1;
3454
- }
3455
- function emitText() {
3456
- var text = html.slice(currentDataIdx, charIdx);
3457
- onText(text, currentDataIdx);
3458
- currentDataIdx = charIdx + 1;
3459
- }
3460
- /**
3461
- * Captures the tag name from the start of the tag to the current character
3462
- * index, and converts it to lower case
3463
- */
3464
- function captureTagName() {
3465
- var startIdx = currentTag.idx + (currentTag.isClosing ? 2 : 1);
3466
- return html.slice(startIdx, charIdx).toLowerCase();
3467
- }
3468
- /**
3469
- * Causes the main loop to re-consume the current character, such as after
3470
- * encountering a "parse error" that changed state and needs to reconsume
3471
- * the same character in that new state.
3472
- */
3473
- function reconsumeCurrentCharacter() {
3474
- charIdx--;
3475
- }
3476
- }
3477
- var CurrentTag = /** @class */function () {
3478
- function CurrentTag(cfg) {
3479
- if (cfg === void 0) {
3480
- cfg = {};
3481
- }
3482
- this.idx = cfg.idx !== undefined ? cfg.idx : -1;
3483
- this.type = cfg.type || 'tag';
3484
- this.name = cfg.name || '';
3485
- this.isOpening = !!cfg.isOpening;
3486
- this.isClosing = !!cfg.isClosing;
3487
- }
3488
- return CurrentTag;
3489
- }();
3490
-
3491
- /**
3492
- * @class Autolinker
3493
- * @extends Object
3494
- *
3495
- * Utility class used to process a given string of text, and wrap the matches in
3496
- * the appropriate anchor (&lt;a&gt;) tags to turn them into links.
3497
- *
3498
- * Any of the configuration options may be provided in an Object provided
3499
- * to the Autolinker constructor, which will configure how the {@link #link link()}
3500
- * method will process the links.
3501
- *
3502
- * For example:
3503
- *
3504
- * var autolinker = new Autolinker( {
3505
- * newWindow : false,
3506
- * truncate : 30
3507
- * } );
3508
- *
3509
- * var html = autolinker.link( "Joe went to www.yahoo.com" );
3510
- * // produces: 'Joe went to <a href="http://www.yahoo.com">yahoo.com</a>'
3511
- *
3512
- *
3513
- * The {@link #static-link static link()} method may also be used to inline
3514
- * options into a single call, which may be more convenient for one-off uses.
3515
- * For example:
3516
- *
3517
- * var html = Autolinker.link( "Joe went to www.yahoo.com", {
3518
- * newWindow : false,
3519
- * truncate : 30
3520
- * } );
3521
- * // produces: 'Joe went to <a href="http://www.yahoo.com">yahoo.com</a>'
3522
- *
3523
- *
3524
- * ## Custom Replacements of Links
3525
- *
3526
- * If the configuration options do not provide enough flexibility, a {@link #replaceFn}
3527
- * may be provided to fully customize the output of Autolinker. This function is
3528
- * called once for each URL/Email/Phone#/Hashtag/Mention (Twitter, Instagram, Soundcloud)
3529
- * match that is encountered.
3530
- *
3531
- * For example:
3532
- *
3533
- * var input = "..."; // string with URLs, Email Addresses, Phone #s, Hashtags, and Mentions (Twitter, Instagram, Soundcloud)
3534
- *
3535
- * var linkedText = Autolinker.link( input, {
3536
- * replaceFn : function( match ) {
3537
- * console.log( "href = ", match.getAnchorHref() );
3538
- * console.log( "text = ", match.getAnchorText() );
3539
- *
3540
- * switch( match.getType() ) {
3541
- * case 'url' :
3542
- * console.log( "url: ", match.getUrl() );
3543
- *
3544
- * if( match.getUrl().indexOf( 'mysite.com' ) === -1 ) {
3545
- * var tag = match.buildTag(); // returns an `Autolinker.HtmlTag` instance, which provides mutator methods for easy changes
3546
- * tag.setAttr( 'rel', 'nofollow' );
3547
- * tag.addClass( 'external-link' );
3548
- *
3549
- * return tag;
3550
- *
3551
- * } else {
3552
- * return true; // let Autolinker perform its normal anchor tag replacement
3553
- * }
3554
- *
3555
- * case 'email' :
3556
- * var email = match.getEmail();
3557
- * console.log( "email: ", email );
3558
- *
3559
- * if( email === "my@own.address" ) {
3560
- * return false; // don't auto-link this particular email address; leave as-is
3561
- * } else {
3562
- * return; // no return value will have Autolinker perform its normal anchor tag replacement (same as returning `true`)
3563
- * }
3564
- *
3565
- * case 'phone' :
3566
- * var phoneNumber = match.getPhoneNumber();
3567
- * console.log( phoneNumber );
3568
- *
3569
- * return '<a href="http://newplace.to.link.phone.numbers.to/">' + phoneNumber + '</a>';
3570
- *
3571
- * case 'hashtag' :
3572
- * var hashtag = match.getHashtag();
3573
- * console.log( hashtag );
3574
- *
3575
- * return '<a href="http://newplace.to.link.hashtag.handles.to/">' + hashtag + '</a>';
3576
- *
3577
- * case 'mention' :
3578
- * var mention = match.getMention();
3579
- * console.log( mention );
3580
- *
3581
- * return '<a href="http://newplace.to.link.mention.to/">' + mention + '</a>';
3582
- * }
3583
- * }
3584
- * } );
3585
- *
3586
- *
3587
- * The function may return the following values:
3588
- *
3589
- * - `true` (Boolean): Allow Autolinker to replace the match as it normally
3590
- * would.
3591
- * - `false` (Boolean): Do not replace the current match at all - leave as-is.
3592
- * - Any String: If a string is returned from the function, the string will be
3593
- * used directly as the replacement HTML for the match.
3594
- * - An {@link Autolinker.HtmlTag} instance, which can be used to build/modify
3595
- * an HTML tag before writing out its HTML text.
3596
- */
3597
- var Autolinker = /** @class */function () {
3598
- /**
3599
- * @method constructor
3600
- * @param {Object} [cfg] The configuration options for the Autolinker instance,
3601
- * specified in an Object (map).
3602
- */
3603
- function Autolinker(cfg) {
3604
- if (cfg === void 0) {
3605
- cfg = {};
3606
- }
3607
- /**
3608
- * The Autolinker version number exposed on the instance itself.
3609
- *
3610
- * Ex: 0.25.1
3611
- */
3612
- this.version = Autolinker.version;
3613
- /**
3614
- * @cfg {Boolean/Object} [urls]
3615
- *
3616
- * `true` if URLs should be automatically linked, `false` if they should not
3617
- * be. Defaults to `true`.
3618
- *
3619
- * Examples:
3620
- *
3621
- * urls: true
3622
- *
3623
- * // or
3624
- *
3625
- * urls: {
3626
- * schemeMatches : true,
3627
- * wwwMatches : true,
3628
- * tldMatches : true
3629
- * }
3630
- *
3631
- * As shown above, this option also accepts an Object form with 3 properties
3632
- * to allow for more customization of what exactly gets linked. All default
3633
- * to `true`:
3634
- *
3635
- * @cfg {Boolean} [urls.schemeMatches] `true` to match URLs found prefixed
3636
- * with a scheme, i.e. `http://google.com`, or `other+scheme://google.com`,
3637
- * `false` to prevent these types of matches.
3638
- * @cfg {Boolean} [urls.wwwMatches] `true` to match urls found prefixed with
3639
- * `'www.'`, i.e. `www.google.com`. `false` to prevent these types of
3640
- * matches. Note that if the URL had a prefixed scheme, and
3641
- * `schemeMatches` is true, it will still be linked.
3642
- * @cfg {Boolean} [urls.tldMatches] `true` to match URLs with known top
3643
- * level domains (.com, .net, etc.) that are not prefixed with a scheme or
3644
- * `'www.'`. This option attempts to match anything that looks like a URL
3645
- * in the given text. Ex: `google.com`, `asdf.org/?page=1`, etc. `false`
3646
- * to prevent these types of matches.
3647
- */
3648
- this.urls = {}; // default value just to get the above doc comment in the ES5 output and documentation generator
3649
- /**
3650
- * @cfg {Boolean} [email=true]
3651
- *
3652
- * `true` if email addresses should be automatically linked, `false` if they
3653
- * should not be.
3654
- */
3655
- this.email = true; // default value just to get the above doc comment in the ES5 output and documentation generator
3656
- /**
3657
- * @cfg {Boolean} [phone=true]
3658
- *
3659
- * `true` if Phone numbers ("(555)555-5555") should be automatically linked,
3660
- * `false` if they should not be.
3661
- */
3662
- this.phone = true; // default value just to get the above doc comment in the ES5 output and documentation generator
3663
- /**
3664
- * @cfg {Boolean/String} [hashtag=false]
3665
- *
3666
- * A string for the service name to have hashtags (ex: "#myHashtag")
3667
- * auto-linked to. The currently-supported values are:
3668
- *
3669
- * - 'twitter'
3670
- * - 'facebook'
3671
- * - 'instagram'
3672
- *
3673
- * Pass `false` to skip auto-linking of hashtags.
3674
- */
3675
- this.hashtag = false; // default value just to get the above doc comment in the ES5 output and documentation generator
3676
- /**
3677
- * @cfg {String/Boolean} [mention=false]
3678
- *
3679
- * A string for the service name to have mentions (ex: "@myuser")
3680
- * auto-linked to. The currently supported values are:
3681
- *
3682
- * - 'twitter'
3683
- * - 'instagram'
3684
- * - 'soundcloud'
3685
- *
3686
- * Defaults to `false` to skip auto-linking of mentions.
3687
- */
3688
- this.mention = false; // default value just to get the above doc comment in the ES5 output and documentation generator
3689
- /**
3690
- * @cfg {Boolean} [newWindow=true]
3691
- *
3692
- * `true` if the links should open in a new window, `false` otherwise.
3693
- */
3694
- this.newWindow = true; // default value just to get the above doc comment in the ES5 output and documentation generator
3695
- /**
3696
- * @cfg {Boolean/Object} [stripPrefix=true]
3697
- *
3698
- * `true` if 'http://' (or 'https://') and/or the 'www.' should be stripped
3699
- * from the beginning of URL links' text, `false` otherwise. Defaults to
3700
- * `true`.
3701
- *
3702
- * Examples:
3703
- *
3704
- * stripPrefix: true
3705
- *
3706
- * // or
3707
- *
3708
- * stripPrefix: {
3709
- * scheme : true,
3710
- * www : true
3711
- * }
3712
- *
3713
- * As shown above, this option also accepts an Object form with 2 properties
3714
- * to allow for more customization of what exactly is prevented from being
3715
- * displayed. Both default to `true`:
3716
- *
3717
- * @cfg {Boolean} [stripPrefix.scheme] `true` to prevent the scheme part of
3718
- * a URL match from being displayed to the user. Example:
3719
- * `'http://google.com'` will be displayed as `'google.com'`. `false` to
3720
- * not strip the scheme. NOTE: Only an `'http://'` or `'https://'` scheme
3721
- * will be removed, so as not to remove a potentially dangerous scheme
3722
- * (such as `'file://'` or `'javascript:'`)
3723
- * @cfg {Boolean} [stripPrefix.www] www (Boolean): `true` to prevent the
3724
- * `'www.'` part of a URL match from being displayed to the user. Ex:
3725
- * `'www.google.com'` will be displayed as `'google.com'`. `false` to not
3726
- * strip the `'www'`.
3727
- */
3728
- this.stripPrefix = {
3729
- scheme: true,
3730
- www: true
3731
- }; // default value just to get the above doc comment in the ES5 output and documentation generator
3732
- /**
3733
- * @cfg {Boolean} [stripTrailingSlash=true]
3734
- *
3735
- * `true` to remove the trailing slash from URL matches, `false` to keep
3736
- * the trailing slash.
3737
- *
3738
- * Example when `true`: `http://google.com/` will be displayed as
3739
- * `http://google.com`.
3740
- */
3741
- this.stripTrailingSlash = true; // default value just to get the above doc comment in the ES5 output and documentation generator
3742
- /**
3743
- * @cfg {Boolean} [decodePercentEncoding=true]
3744
- *
3745
- * `true` to decode percent-encoded characters in URL matches, `false` to keep
3746
- * the percent-encoded characters.
3747
- *
3748
- * Example when `true`: `https://en.wikipedia.org/wiki/San_Jos%C3%A9` will
3749
- * be displayed as `https://en.wikipedia.org/wiki/San_José`.
3750
- */
3751
- this.decodePercentEncoding = true; // default value just to get the above doc comment in the ES5 output and documentation generator
3752
- /**
3753
- * @cfg {Number/Object} [truncate=0]
3754
- *
3755
- * ## Number Form
3756
- *
3757
- * A number for how many characters matched text should be truncated to
3758
- * inside the text of a link. If the matched text is over this number of
3759
- * characters, it will be truncated to this length by adding a two period
3760
- * ellipsis ('..') to the end of the string.
3761
- *
3762
- * For example: A url like 'http://www.yahoo.com/some/long/path/to/a/file'
3763
- * truncated to 25 characters might look something like this:
3764
- * 'yahoo.com/some/long/pat..'
3765
- *
3766
- * Example Usage:
3767
- *
3768
- * truncate: 25
3769
- *
3770
- *
3771
- * Defaults to `0` for "no truncation."
3772
- *
3773
- *
3774
- * ## Object Form
3775
- *
3776
- * An Object may also be provided with two properties: `length` (Number) and
3777
- * `location` (String). `location` may be one of the following: 'end'
3778
- * (default), 'middle', or 'smart'.
3779
- *
3780
- * Example Usage:
3781
- *
3782
- * truncate: { length: 25, location: 'middle' }
3783
- *
3784
- * @cfg {Number} [truncate.length=0] How many characters to allow before
3785
- * truncation will occur. Defaults to `0` for "no truncation."
3786
- * @cfg {"end"/"middle"/"smart"} [truncate.location="end"]
3787
- *
3788
- * - 'end' (default): will truncate up to the number of characters, and then
3789
- * add an ellipsis at the end. Ex: 'yahoo.com/some/long/pat..'
3790
- * - 'middle': will truncate and add the ellipsis in the middle. Ex:
3791
- * 'yahoo.com/s..th/to/a/file'
3792
- * - 'smart': for URLs where the algorithm attempts to strip out unnecessary
3793
- * parts first (such as the 'www.', then URL scheme, hash, etc.),
3794
- * attempting to make the URL human-readable before looking for a good
3795
- * point to insert the ellipsis if it is still too long. Ex:
3796
- * 'yahoo.com/some..to/a/file'. For more details, see
3797
- * {@link Autolinker.truncate.TruncateSmart}.
3798
- */
3799
- this.truncate = {
3800
- length: 0,
3801
- location: 'end'
3802
- }; // default value just to get the above doc comment in the ES5 output and documentation generator
3803
- /**
3804
- * @cfg {String} className
3805
- *
3806
- * A CSS class name to add to the generated links. This class will be added
3807
- * to all links, as well as this class plus match suffixes for styling
3808
- * url/email/phone/hashtag/mention links differently.
3809
- *
3810
- * For example, if this config is provided as "myLink", then:
3811
- *
3812
- * - URL links will have the CSS classes: "myLink myLink-url"
3813
- * - Email links will have the CSS classes: "myLink myLink-email", and
3814
- * - Phone links will have the CSS classes: "myLink myLink-phone"
3815
- * - Hashtag links will have the CSS classes: "myLink myLink-hashtag"
3816
- * - Mention links will have the CSS classes: "myLink myLink-mention myLink-[type]"
3817
- * where [type] is either "instagram", "twitter" or "soundcloud"
3818
- */
3819
- this.className = ''; // default value just to get the above doc comment in the ES5 output and documentation generator
3820
- /**
3821
- * @cfg {Function} replaceFn
3822
- *
3823
- * A function to individually process each match found in the input string.
3824
- *
3825
- * See the class's description for usage.
3826
- *
3827
- * The `replaceFn` can be called with a different context object (`this`
3828
- * reference) using the {@link #context} cfg.
3829
- *
3830
- * This function is called with the following parameter:
3831
- *
3832
- * @cfg {Autolinker.match.Match} replaceFn.match The Match instance which
3833
- * can be used to retrieve information about the match that the `replaceFn`
3834
- * is currently processing. See {@link Autolinker.match.Match} subclasses
3835
- * for details.
3836
- */
3837
- this.replaceFn = null; // default value just to get the above doc comment in the ES5 output and documentation generator
3838
- /**
3839
- * @cfg {Object} context
3840
- *
3841
- * The context object (`this` reference) to call the `replaceFn` with.
3842
- *
3843
- * Defaults to this Autolinker instance.
3844
- */
3845
- this.context = undefined; // default value just to get the above doc comment in the ES5 output and documentation generator
3846
- /**
3847
- * @cfg {Boolean} [sanitizeHtml=false]
3848
- *
3849
- * `true` to HTML-encode the start and end brackets of existing HTML tags found
3850
- * in the input string. This will escape `<` and `>` characters to `&lt;` and
3851
- * `&gt;`, respectively.
3852
- *
3853
- * Setting this to `true` will prevent XSS (Cross-site Scripting) attacks,
3854
- * but will remove the significance of existing HTML tags in the input string. If
3855
- * you would like to maintain the significance of existing HTML tags while also
3856
- * making the output HTML string safe, leave this option as `false` and use a
3857
- * tool like https://github.com/cure53/DOMPurify (or others) on the input string
3858
- * before running Autolinker.
3859
- */
3860
- this.sanitizeHtml = false; // default value just to get the above doc comment in the ES5 output and documentation generator
3861
- /**
3862
- * @private
3863
- * @property {Autolinker.matcher.Matcher[]} matchers
3864
- *
3865
- * The {@link Autolinker.matcher.Matcher} instances for this Autolinker
3866
- * instance.
3867
- *
3868
- * This is lazily created in {@link #getMatchers}.
3869
- */
3870
- this.matchers = null;
3871
- /**
3872
- * @private
3873
- * @property {Autolinker.AnchorTagBuilder} tagBuilder
3874
- *
3875
- * The AnchorTagBuilder instance used to build match replacement anchor tags.
3876
- * Note: this is lazily instantiated in the {@link #getTagBuilder} method.
3877
- */
3878
- this.tagBuilder = null;
3879
- // Note: when `this.something` is used in the rhs of these assignments,
3880
- // it refers to the default values set above the constructor
3881
- this.urls = this.normalizeUrlsCfg(cfg.urls);
3882
- this.email = typeof cfg.email === 'boolean' ? cfg.email : this.email;
3883
- this.phone = typeof cfg.phone === 'boolean' ? cfg.phone : this.phone;
3884
- this.hashtag = cfg.hashtag || this.hashtag;
3885
- this.mention = cfg.mention || this.mention;
3886
- this.newWindow = typeof cfg.newWindow === 'boolean' ? cfg.newWindow : this.newWindow;
3887
- this.stripPrefix = this.normalizeStripPrefixCfg(cfg.stripPrefix);
3888
- this.stripTrailingSlash = typeof cfg.stripTrailingSlash === 'boolean' ? cfg.stripTrailingSlash : this.stripTrailingSlash;
3889
- this.decodePercentEncoding = typeof cfg.decodePercentEncoding === 'boolean' ? cfg.decodePercentEncoding : this.decodePercentEncoding;
3890
- this.sanitizeHtml = cfg.sanitizeHtml || false;
3891
- // Validate the value of the `mention` cfg
3892
- var mention = this.mention;
3893
- if (mention !== false && ['twitter', 'instagram', 'soundcloud', 'tiktok'].indexOf(mention) === -1) {
3894
- throw new Error("invalid `mention` cfg '".concat(mention, "' - see docs"));
3895
- }
3896
- // Validate the value of the `hashtag` cfg
3897
- var hashtag = this.hashtag;
3898
- if (hashtag !== false && hashtagServices.indexOf(hashtag) === -1) {
3899
- throw new Error("invalid `hashtag` cfg '".concat(hashtag, "' - see docs"));
3900
- }
3901
- this.truncate = this.normalizeTruncateCfg(cfg.truncate);
3902
- this.className = cfg.className || this.className;
3903
- this.replaceFn = cfg.replaceFn || this.replaceFn;
3904
- this.context = cfg.context || this;
3905
- }
3906
- /**
3907
- * Automatically links URLs, Email addresses, Phone Numbers, Twitter handles,
3908
- * Hashtags, and Mentions found in the given chunk of HTML. Does not link URLs
3909
- * found within HTML tags.
3910
- *
3911
- * For instance, if given the text: `You should go to http://www.yahoo.com`,
3912
- * then the result will be `You should go to &lt;a href="http://www.yahoo.com"&gt;http://www.yahoo.com&lt;/a&gt;`
3913
- *
3914
- * Example:
3915
- *
3916
- * var linkedText = Autolinker.link( "Go to google.com", { newWindow: false } );
3917
- * // Produces: "Go to <a href="http://google.com">google.com</a>"
3918
- *
3919
- * @static
3920
- * @param {String} textOrHtml The HTML or text to find matches within (depending
3921
- * on if the {@link #urls}, {@link #email}, {@link #phone}, {@link #mention},
3922
- * {@link #hashtag}, and {@link #mention} options are enabled).
3923
- * @param {Object} [options] Any of the configuration options for the Autolinker
3924
- * class, specified in an Object (map). See the class description for an
3925
- * example call.
3926
- * @return {String} The HTML text, with matches automatically linked.
3927
- */
3928
- Autolinker.link = function (textOrHtml, options) {
3929
- var autolinker = new Autolinker(options);
3930
- return autolinker.link(textOrHtml);
3931
- };
3932
- /**
3933
- * Parses the input `textOrHtml` looking for URLs, email addresses, phone
3934
- * numbers, username handles, and hashtags (depending on the configuration
3935
- * of the Autolinker instance), and returns an array of {@link Autolinker.match.Match}
3936
- * objects describing those matches (without making any replacements).
3937
- *
3938
- * Note that if parsing multiple pieces of text, it is slightly more efficient
3939
- * to create an Autolinker instance, and use the instance-level {@link #parse}
3940
- * method.
3941
- *
3942
- * Example:
3943
- *
3944
- * var matches = Autolinker.parse( "Hello google.com, I am asdf@asdf.com", {
3945
- * urls: true,
3946
- * email: true
3947
- * } );
3948
- *
3949
- * console.log( matches.length ); // 2
3950
- * console.log( matches[ 0 ].getType() ); // 'url'
3951
- * console.log( matches[ 0 ].getUrl() ); // 'google.com'
3952
- * console.log( matches[ 1 ].getType() ); // 'email'
3953
- * console.log( matches[ 1 ].getEmail() ); // 'asdf@asdf.com'
3954
- *
3955
- * @static
3956
- * @param {String} textOrHtml The HTML or text to find matches within
3957
- * (depending on if the {@link #urls}, {@link #email}, {@link #phone},
3958
- * {@link #hashtag}, and {@link #mention} options are enabled).
3959
- * @param {Object} [options] Any of the configuration options for the Autolinker
3960
- * class, specified in an Object (map). See the class description for an
3961
- * example call.
3962
- * @return {Autolinker.match.Match[]} The array of Matches found in the
3963
- * given input `textOrHtml`.
3964
- */
3965
- Autolinker.parse = function (textOrHtml, options) {
3966
- var autolinker = new Autolinker(options);
3967
- return autolinker.parse(textOrHtml);
3968
- };
3969
- /**
3970
- * Normalizes the {@link #urls} config into an Object with 3 properties:
3971
- * `schemeMatches`, `wwwMatches`, and `tldMatches`, all Booleans.
3972
- *
3973
- * See {@link #urls} config for details.
3974
- *
3975
- * @private
3976
- * @param {Boolean/Object} urls
3977
- * @return {Object}
3978
- */
3979
- Autolinker.prototype.normalizeUrlsCfg = function (urls) {
3980
- if (urls == null) urls = true; // default to `true`
3981
- if (typeof urls === 'boolean') {
3982
- return {
3983
- schemeMatches: urls,
3984
- wwwMatches: urls,
3985
- tldMatches: urls
3986
- };
3987
- } else {
3988
- // object form
3989
- return {
3990
- schemeMatches: typeof urls.schemeMatches === 'boolean' ? urls.schemeMatches : true,
3991
- wwwMatches: typeof urls.wwwMatches === 'boolean' ? urls.wwwMatches : true,
3992
- tldMatches: typeof urls.tldMatches === 'boolean' ? urls.tldMatches : true
3993
- };
3994
- }
3995
- };
3996
- /**
3997
- * Normalizes the {@link #stripPrefix} config into an Object with 2
3998
- * properties: `scheme`, and `www` - both Booleans.
3999
- *
4000
- * See {@link #stripPrefix} config for details.
4001
- *
4002
- * @private
4003
- * @param {Boolean/Object} stripPrefix
4004
- * @return {Object}
4005
- */
4006
- Autolinker.prototype.normalizeStripPrefixCfg = function (stripPrefix) {
4007
- if (stripPrefix == null) stripPrefix = true; // default to `true`
4008
- if (typeof stripPrefix === 'boolean') {
4009
- return {
4010
- scheme: stripPrefix,
4011
- www: stripPrefix
4012
- };
4013
- } else {
4014
- // object form
4015
- return {
4016
- scheme: typeof stripPrefix.scheme === 'boolean' ? stripPrefix.scheme : true,
4017
- www: typeof stripPrefix.www === 'boolean' ? stripPrefix.www : true
4018
- };
4019
- }
4020
- };
4021
- /**
4022
- * Normalizes the {@link #truncate} config into an Object with 2 properties:
4023
- * `length` (Number), and `location` (String).
4024
- *
4025
- * See {@link #truncate} config for details.
4026
- *
4027
- * @private
4028
- * @param {Number/Object} truncate
4029
- * @return {Object}
4030
- */
4031
- Autolinker.prototype.normalizeTruncateCfg = function (truncate) {
4032
- if (typeof truncate === 'number') {
4033
- return {
4034
- length: truncate,
4035
- location: 'end'
4036
- };
4037
- } else {
4038
- // object, or undefined/null
4039
- return defaults(truncate || {}, {
4040
- length: Number.POSITIVE_INFINITY,
4041
- location: 'end'
4042
- });
4043
- }
4044
- };
4045
- /**
4046
- * Parses the input `textOrHtml` looking for URLs, email addresses, phone
4047
- * numbers, username handles, and hashtags (depending on the configuration
4048
- * of the Autolinker instance), and returns an array of {@link Autolinker.match.Match}
4049
- * objects describing those matches (without making any replacements).
4050
- *
4051
- * This method is used by the {@link #link} method, but can also be used to
4052
- * simply do parsing of the input in order to discover what kinds of links
4053
- * there are and how many.
4054
- *
4055
- * Example usage:
4056
- *
4057
- * var autolinker = new Autolinker( {
4058
- * urls: true,
4059
- * email: true
4060
- * } );
4061
- *
4062
- * var matches = autolinker.parse( "Hello google.com, I am asdf@asdf.com" );
4063
- *
4064
- * console.log( matches.length ); // 2
4065
- * console.log( matches[ 0 ].getType() ); // 'url'
4066
- * console.log( matches[ 0 ].getUrl() ); // 'google.com'
4067
- * console.log( matches[ 1 ].getType() ); // 'email'
4068
- * console.log( matches[ 1 ].getEmail() ); // 'asdf@asdf.com'
4069
- *
4070
- * @param {String} textOrHtml The HTML or text to find matches within
4071
- * (depending on if the {@link #urls}, {@link #email}, {@link #phone},
4072
- * {@link #hashtag}, and {@link #mention} options are enabled).
4073
- * @return {Autolinker.match.Match[]} The array of Matches found in the
4074
- * given input `textOrHtml`.
4075
- */
4076
- Autolinker.prototype.parse = function (textOrHtml) {
4077
- var _this = this;
4078
- var skipTagNames = ['a', 'style', 'script'],
4079
- skipTagsStackCount = 0,
4080
- // 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
4081
- matches = [];
4082
- // Find all matches within the `textOrHtml` (but not matches that are
4083
- // already nested within <a>, <style> and <script> tags)
4084
- parseHtml(textOrHtml, {
4085
- onOpenTag: function (tagName) {
4086
- if (skipTagNames.indexOf(tagName) >= 0) {
4087
- skipTagsStackCount++;
4088
- }
4089
- },
4090
- onText: function (text, offset) {
4091
- // Only process text nodes that are not within an <a>, <style> or <script> tag
4092
- if (skipTagsStackCount === 0) {
4093
- // "Walk around" common HTML entities. An '&nbsp;' (for example)
4094
- // could be at the end of a URL, but we don't want to
4095
- // include the trailing '&' in the URL. See issue #76
4096
- // TODO: Handle HTML entities separately in parseHtml() and
4097
- // don't emit them as "text" except for &amp; entities
4098
- var htmlCharacterEntitiesRegex = /(&nbsp;|&#160;|&lt;|&#60;|&gt;|&#62;|&quot;|&#34;|&#39;)/gi;
4099
- var textSplit = splitAndCapture(text, htmlCharacterEntitiesRegex);
4100
- var currentOffset_1 = offset;
4101
- textSplit.forEach(function (splitText, i) {
4102
- // even number matches are text, odd numbers are html entities
4103
- if (i % 2 === 0) {
4104
- var textNodeMatches = _this.parseText(splitText, currentOffset_1);
4105
- matches.push.apply(matches, textNodeMatches);
4106
- }
4107
- currentOffset_1 += splitText.length;
4108
- });
4109
- }
4110
- },
4111
- onCloseTag: function (tagName) {
4112
- if (skipTagNames.indexOf(tagName) >= 0) {
4113
- skipTagsStackCount = Math.max(skipTagsStackCount - 1, 0); // attempt to handle extraneous </a> tags by making sure the stack count never goes below 0
4114
- }
4115
- },
4116
-
4117
- onComment: function (offset) {},
4118
- onDoctype: function (offset) {} // no need to process doctype nodes
4119
- });
4120
- // After we have found all matches, remove subsequent matches that
4121
- // overlap with a previous match. This can happen for instance with URLs,
4122
- // where the url 'google.com/#link' would match '#link' as a hashtag.
4123
- matches = this.compactMatches(matches);
4124
- // And finally, remove matches for match types that have been turned
4125
- // off. We needed to have all match types turned on initially so that
4126
- // things like hashtags could be filtered out if they were really just
4127
- // part of a URL match (for instance, as a named anchor).
4128
- matches = this.removeUnwantedMatches(matches);
4129
- return matches;
4130
- };
4131
- /**
4132
- * After we have found all matches, we need to remove matches that overlap
4133
- * with a previous match. This can happen for instance with URLs, where the
4134
- * url 'google.com/#link' would match '#link' as a hashtag. Because the
4135
- * '#link' part is contained in a larger match that comes before the HashTag
4136
- * match, we'll remove the HashTag match.
4137
- *
4138
- * @private
4139
- * @param {Autolinker.match.Match[]} matches
4140
- * @return {Autolinker.match.Match[]}
4141
- */
4142
- Autolinker.prototype.compactMatches = function (matches) {
4143
- // First, the matches need to be sorted in order of offset
4144
- matches.sort(function (a, b) {
4145
- return a.getOffset() - b.getOffset();
4146
- });
4147
- var i = 0;
4148
- while (i < matches.length - 1) {
4149
- var match = matches[i],
4150
- offset = match.getOffset(),
4151
- matchedTextLength = match.getMatchedText().length,
4152
- endIdx = offset + matchedTextLength;
4153
- if (i + 1 < matches.length) {
4154
- // Remove subsequent matches that equal offset with current match
4155
- if (matches[i + 1].getOffset() === offset) {
4156
- var removeIdx = matches[i + 1].getMatchedText().length > matchedTextLength ? i : i + 1;
4157
- matches.splice(removeIdx, 1);
4158
- continue;
4159
- }
4160
- // Remove subsequent matches that overlap with the current match
4161
- if (matches[i + 1].getOffset() < endIdx) {
4162
- matches.splice(i + 1, 1);
4163
- continue;
4164
- }
4165
- }
4166
- i++;
4167
- }
4168
- return matches;
4169
- };
4170
- /**
4171
- * Removes matches for matchers that were turned off in the options. For
4172
- * example, if {@link #hashtag hashtags} were not to be matched, we'll
4173
- * remove them from the `matches` array here.
4174
- *
4175
- * Note: we *must* use all Matchers on the input string, and then filter
4176
- * them out later. For example, if the options were `{ url: false, hashtag: true }`,
4177
- * we wouldn't want to match the text '#link' as a HashTag inside of the text
4178
- * 'google.com/#link'. The way the algorithm works is that we match the full
4179
- * URL first (which prevents the accidental HashTag match), and then we'll
4180
- * simply throw away the URL match.
4181
- *
4182
- * @private
4183
- * @param {Autolinker.match.Match[]} matches The array of matches to remove
4184
- * the unwanted matches from. Note: this array is mutated for the
4185
- * removals.
4186
- * @return {Autolinker.match.Match[]} The mutated input `matches` array.
4187
- */
4188
- Autolinker.prototype.removeUnwantedMatches = function (matches) {
4189
- if (!this.hashtag) remove(matches, function (match) {
4190
- return match.getType() === 'hashtag';
4191
- });
4192
- if (!this.email) remove(matches, function (match) {
4193
- return match.getType() === 'email';
4194
- });
4195
- if (!this.phone) remove(matches, function (match) {
4196
- return match.getType() === 'phone';
4197
- });
4198
- if (!this.mention) remove(matches, function (match) {
4199
- return match.getType() === 'mention';
4200
- });
4201
- if (!this.urls.schemeMatches) {
4202
- remove(matches, function (m) {
4203
- return m.getType() === 'url' && m.getUrlMatchType() === 'scheme';
4204
- });
4205
- }
4206
- if (!this.urls.wwwMatches) {
4207
- remove(matches, function (m) {
4208
- return m.getType() === 'url' && m.getUrlMatchType() === 'www';
4209
- });
4210
- }
4211
- if (!this.urls.tldMatches) {
4212
- remove(matches, function (m) {
4213
- return m.getType() === 'url' && m.getUrlMatchType() === 'tld';
4214
- });
4215
- }
4216
- return matches;
4217
- };
4218
- /**
4219
- * Parses the input `text` looking for URLs, email addresses, phone
4220
- * numbers, username handles, and hashtags (depending on the configuration
4221
- * of the Autolinker instance), and returns an array of {@link Autolinker.match.Match}
4222
- * objects describing those matches.
4223
- *
4224
- * This method processes a **non-HTML string**, and is used to parse and
4225
- * match within the text nodes of an HTML string. This method is used
4226
- * internally by {@link #parse}.
4227
- *
4228
- * @private
4229
- * @param {String} text The text to find matches within (depending on if the
4230
- * {@link #urls}, {@link #email}, {@link #phone},
4231
- * {@link #hashtag}, and {@link #mention} options are enabled). This must be a non-HTML string.
4232
- * @param {Number} [offset=0] The offset of the text node within the
4233
- * original string. This is used when parsing with the {@link #parse}
4234
- * method to generate correct offsets within the {@link Autolinker.match.Match}
4235
- * instances, but may be omitted if calling this method publicly.
4236
- * @return {Autolinker.match.Match[]} The array of Matches found in the
4237
- * given input `text`.
4238
- */
4239
- Autolinker.prototype.parseText = function (text, offset) {
4240
- if (offset === void 0) {
4241
- offset = 0;
4242
- }
4243
- offset = offset || 0;
4244
- var matchers = this.getMatchers(),
4245
- matches = [];
4246
- for (var i = 0, numMatchers = matchers.length; i < numMatchers; i++) {
4247
- var textMatches = matchers[i].parseMatches(text);
4248
- // Correct the offset of each of the matches. They are originally
4249
- // the offset of the match within the provided text node, but we
4250
- // need to correct them to be relative to the original HTML input
4251
- // string (i.e. the one provided to #parse).
4252
- for (var j = 0, numTextMatches = textMatches.length; j < numTextMatches; j++) {
4253
- textMatches[j].setOffset(offset + textMatches[j].getOffset());
4254
- }
4255
- matches.push.apply(matches, textMatches);
4256
- }
4257
- return matches;
4258
- };
4259
- /**
4260
- * Automatically links URLs, Email addresses, Phone numbers, Hashtags,
4261
- * and Mentions (Twitter, Instagram, Soundcloud) found in the given chunk of HTML. Does not link
4262
- * URLs found within HTML tags.
4263
- *
4264
- * For instance, if given the text: `You should go to http://www.yahoo.com`,
4265
- * then the result will be `You should go to
4266
- * &lt;a href="http://www.yahoo.com"&gt;http://www.yahoo.com&lt;/a&gt;`
4267
- *
4268
- * This method finds the text around any HTML elements in the input
4269
- * `textOrHtml`, which will be the text that is processed. Any original HTML
4270
- * elements will be left as-is, as well as the text that is already wrapped
4271
- * in anchor (&lt;a&gt;) tags.
4272
- *
4273
- * @param {String} textOrHtml The HTML or text to autolink matches within
4274
- * (depending on if the {@link #urls}, {@link #email}, {@link #phone}, {@link #hashtag}, and {@link #mention} options are enabled).
4275
- * @return {String} The HTML, with matches automatically linked.
4276
- */
4277
- Autolinker.prototype.link = function (textOrHtml) {
4278
- if (!textOrHtml) {
4279
- return '';
4280
- } // handle `null` and `undefined` (for JavaScript users that don't have TypeScript support)
4281
- /* We would want to sanitize the start and end characters of a tag
4282
- * before processing the string in order to avoid an XSS scenario.
4283
- * This behaviour can be changed by toggling the sanitizeHtml option.
4284
- */
4285
- if (this.sanitizeHtml) {
4286
- textOrHtml = textOrHtml.replace(/</g, '&lt;').replace(/>/g, '&gt;');
4287
- }
4288
- var matches = this.parse(textOrHtml),
4289
- newHtml = [],
4290
- lastIndex = 0;
4291
- for (var i = 0, len = matches.length; i < len; i++) {
4292
- var match = matches[i];
4293
- newHtml.push(textOrHtml.substring(lastIndex, match.getOffset()));
4294
- newHtml.push(this.createMatchReturnVal(match));
4295
- lastIndex = match.getOffset() + match.getMatchedText().length;
4296
- }
4297
- newHtml.push(textOrHtml.substring(lastIndex)); // handle the text after the last match
4298
- return newHtml.join('');
4299
- };
4300
- /**
4301
- * Creates the return string value for a given match in the input string.
4302
- *
4303
- * This method handles the {@link #replaceFn}, if one was provided.
4304
- *
4305
- * @private
4306
- * @param {Autolinker.match.Match} match The Match object that represents
4307
- * the match.
4308
- * @return {String} The string that the `match` should be replaced with.
4309
- * This is usually the anchor tag string, but may be the `matchStr` itself
4310
- * if the match is not to be replaced.
4311
- */
4312
- Autolinker.prototype.createMatchReturnVal = function (match) {
4313
- // Handle a custom `replaceFn` being provided
4314
- var replaceFnResult;
4315
- if (this.replaceFn) {
4316
- replaceFnResult = this.replaceFn.call(this.context, match); // Autolinker instance is the context
4317
- }
4318
-
4319
- if (typeof replaceFnResult === 'string') {
4320
- return replaceFnResult; // `replaceFn` returned a string, use that
4321
- } else if (replaceFnResult === false) {
4322
- return match.getMatchedText(); // no replacement for the match
4323
- } else if (replaceFnResult instanceof HtmlTag) {
4324
- return replaceFnResult.toAnchorString();
4325
- } else {
4326
- // replaceFnResult === true, or no/unknown return value from function
4327
- // Perform Autolinker's default anchor tag generation
4328
- var anchorTag = match.buildTag(); // returns an Autolinker.HtmlTag instance
4329
- return anchorTag.toAnchorString();
4330
- }
4331
- };
4332
- /**
4333
- * Lazily instantiates and returns the {@link Autolinker.matcher.Matcher}
4334
- * instances for this Autolinker instance.
4335
- *
4336
- * @private
4337
- * @return {Autolinker.matcher.Matcher[]}
4338
- */
4339
- Autolinker.prototype.getMatchers = function () {
4340
- if (!this.matchers) {
4341
- var tagBuilder = this.getTagBuilder();
4342
- var matchers = [new HashtagMatcher({
4343
- tagBuilder: tagBuilder,
4344
- serviceName: this.hashtag
4345
- }), new EmailMatcher({
4346
- tagBuilder: tagBuilder
4347
- }), new PhoneMatcher({
4348
- tagBuilder: tagBuilder
4349
- }), new MentionMatcher({
4350
- tagBuilder: tagBuilder,
4351
- serviceName: this.mention
4352
- }), new UrlMatcher({
4353
- tagBuilder: tagBuilder,
4354
- stripPrefix: this.stripPrefix,
4355
- stripTrailingSlash: this.stripTrailingSlash,
4356
- decodePercentEncoding: this.decodePercentEncoding
4357
- })];
4358
- return this.matchers = matchers;
4359
- } else {
4360
- return this.matchers;
4361
- }
4362
- };
4363
- /**
4364
- * Returns the {@link #tagBuilder} instance for this Autolinker instance,
4365
- * lazily instantiating it if it does not yet exist.
4366
- *
4367
- * @private
4368
- * @return {Autolinker.AnchorTagBuilder}
4369
- */
4370
- Autolinker.prototype.getTagBuilder = function () {
4371
- var tagBuilder = this.tagBuilder;
4372
- if (!tagBuilder) {
4373
- tagBuilder = this.tagBuilder = new AnchorTagBuilder({
4374
- newWindow: this.newWindow,
4375
- truncate: this.truncate,
4376
- className: this.className
4377
- });
4378
- }
4379
- return tagBuilder;
4380
- };
4381
- // NOTE: must be 'export default' here for UMD module
4382
- /**
4383
- * @static
4384
- * @property {String} version
4385
- *
4386
- * The Autolinker version number in the form major.minor.patch
4387
- *
4388
- * Ex: 3.15.0
4389
- */
4390
- Autolinker.version = version;
4391
- /**
4392
- * For backwards compatibility with Autolinker 1.x, the AnchorTagBuilder
4393
- * class is provided as a static on the Autolinker class.
4394
- */
4395
- Autolinker.AnchorTagBuilder = AnchorTagBuilder;
4396
- /**
4397
- * For backwards compatibility with Autolinker 1.x, the HtmlTag class is
4398
- * provided as a static on the Autolinker class.
4399
- */
4400
- Autolinker.HtmlTag = HtmlTag;
4401
- /**
4402
- * For backwards compatibility with Autolinker 1.x, the Matcher classes are
4403
- * provided as statics on the Autolinker class.
4404
- */
4405
- Autolinker.matcher = {
4406
- Email: EmailMatcher,
4407
- Hashtag: HashtagMatcher,
4408
- Matcher: Matcher,
4409
- Mention: MentionMatcher,
4410
- Phone: PhoneMatcher,
4411
- Url: UrlMatcher
4412
- };
4413
- /**
4414
- * For backwards compatibility with Autolinker 1.x, the Match classes are
4415
- * provided as statics on the Autolinker class.
4416
- */
4417
- Autolinker.match = {
4418
- Email: EmailMatch,
4419
- Hashtag: HashtagMatch,
4420
- Match: Match,
4421
- Mention: MentionMatch,
4422
- Phone: PhoneMatch,
4423
- Url: UrlMatch
4424
- };
4425
- return Autolinker;
4426
- }();
4427
-
4428
- export { Autolinker };
4429
- //# sourceMappingURL=autolinker.js.map