@gov-cy/govcy-frontend-renderer 1.29.0 → 1.30.0

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.
package/dist/index.cjs CHANGED
@@ -14479,6 +14479,15 @@ getDecoder(xmlDecodeTree);
14479
14479
  function decodeHTML(str, mode = DecodingMode.Legacy) {
14480
14480
  return htmlDecoder(str, mode);
14481
14481
  }
14482
+ /**
14483
+ * Decodes an HTML string, requiring all entities to be terminated by a semicolon.
14484
+ *
14485
+ * @param str The string to decode.
14486
+ * @returns The decoded string.
14487
+ */
14488
+ function decodeHTMLStrict(str) {
14489
+ return htmlDecoder(str, DecodingMode.Strict);
14490
+ }
14482
14491
 
14483
14492
  // Utilities
14484
14493
  //
@@ -14658,6 +14667,10 @@ function isPunctChar (ch) {
14658
14667
  return P.test(ch) || regex.test(ch)
14659
14668
  }
14660
14669
 
14670
+ function isPunctCharCode (code) {
14671
+ return isPunctChar(fromCodePoint(code))
14672
+ }
14673
+
14661
14674
  // Markdown ASCII punctuation characters.
14662
14675
  //
14663
14676
  // !, ", #, $, %, &, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ?, @, [, \, ], ^, _, `, {, |, }, or ~
@@ -14719,6 +14732,7 @@ function normalizeReference (str) {
14719
14732
  // (remove this when node v10 is no longer supported).
14720
14733
  //
14721
14734
  if ('ẞ'.toLowerCase() === 'Ṿ') {
14735
+ /* c8 ignore next 2 */
14722
14736
  str = str.replace(/ẞ/g, 'ß');
14723
14737
  }
14724
14738
 
@@ -14757,6 +14771,28 @@ function normalizeReference (str) {
14757
14771
  return str.toLowerCase().toUpperCase()
14758
14772
  }
14759
14773
 
14774
+ function isAsciiTrimmable (c) {
14775
+ return c === 0x20 || c === 0x09 || c === 0x0a || c === 0x0d
14776
+ }
14777
+
14778
+ // "Light" .trim() for blocks (headers, paragraphs), where unicode spaces
14779
+ // should be preserved.
14780
+ function asciiTrim (str) {
14781
+ let start = 0;
14782
+ for (; start < str.length; start++) {
14783
+ if (!isAsciiTrimmable(str.charCodeAt(start))) {
14784
+ break
14785
+ }
14786
+ }
14787
+ let end = str.length - 1;
14788
+ for (; end >= start; end--) {
14789
+ if (!isAsciiTrimmable(str.charCodeAt(end))) {
14790
+ break
14791
+ }
14792
+ }
14793
+ return str.slice(start, end + 1)
14794
+ }
14795
+
14760
14796
  // Re-export libraries commonly used in both markdown-it and its plugins,
14761
14797
  // so plugins won't have to depend on them explicitly, which reduces their
14762
14798
  // bundled size (e.g. a browser build).
@@ -14766,6 +14802,7 @@ const lib = { mdurl, ucmicro };
14766
14802
  var utils$2 = /*#__PURE__*/Object.freeze({
14767
14803
  __proto__: null,
14768
14804
  arrayReplaceAt: arrayReplaceAt,
14805
+ asciiTrim: asciiTrim,
14769
14806
  assign: assign$1,
14770
14807
  escapeHtml: escapeHtml,
14771
14808
  escapeRE: escapeRE$1,
@@ -14773,6 +14810,7 @@ var utils$2 = /*#__PURE__*/Object.freeze({
14773
14810
  has: has,
14774
14811
  isMdAsciiPunct: isMdAsciiPunct,
14775
14812
  isPunctChar: isPunctChar,
14813
+ isPunctCharCode: isPunctCharCode,
14776
14814
  isSpace: isSpace,
14777
14815
  isString: isString$1,
14778
14816
  isValidEntityCode: isValidEntityCode,
@@ -16136,14 +16174,36 @@ const QUOTE_TEST_RE = /['"]/;
16136
16174
  const QUOTE_RE = /['"]/g;
16137
16175
  const APOSTROPHE = '\u2019'; /* ’ */
16138
16176
 
16139
- function replaceAt (str, index, ch) {
16140
- return str.slice(0, index) + ch + str.slice(index + 1)
16177
+ function addReplacement (replacements, tokenIdx, pos, ch) {
16178
+ if (!replacements[tokenIdx]) {
16179
+ replacements[tokenIdx] = [];
16180
+ }
16181
+
16182
+ replacements[tokenIdx].push({ pos, ch });
16183
+ }
16184
+
16185
+ function applyReplacements (str, replacements) {
16186
+ let result = '';
16187
+ let lastPos = 0;
16188
+
16189
+ replacements.sort((a, b) => a.pos - b.pos);
16190
+
16191
+ for (let i = 0; i < replacements.length; i++) {
16192
+ const replacement = replacements[i];
16193
+
16194
+ result += str.slice(lastPos, replacement.pos) + replacement.ch;
16195
+ lastPos = replacement.pos + 1;
16196
+ }
16197
+
16198
+ return result + str.slice(lastPos)
16141
16199
  }
16142
16200
 
16143
16201
  function process_inlines (tokens, state) {
16144
16202
  let j;
16145
16203
 
16146
16204
  const stack = [];
16205
+ // token index -> list of replacements in the original token content
16206
+ const replacements = {};
16147
16207
 
16148
16208
  for (let i = 0; i < tokens.length; i++) {
16149
16209
  const token = tokens[i];
@@ -16157,9 +16217,9 @@ function process_inlines (tokens, state) {
16157
16217
 
16158
16218
  if (token.type !== 'text') { continue }
16159
16219
 
16160
- let text = token.content;
16220
+ const text = token.content;
16161
16221
  let pos = 0;
16162
- let max = text.length;
16222
+ const max = text.length;
16163
16223
 
16164
16224
  /* eslint no-labels:0,block-scoped-var:0 */
16165
16225
  OUTER:
@@ -16207,8 +16267,8 @@ function process_inlines (tokens, state) {
16207
16267
  }
16208
16268
  }
16209
16269
 
16210
- const isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar));
16211
- const isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar));
16270
+ const isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctCharCode(lastChar);
16271
+ const isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctCharCode(nextChar);
16212
16272
 
16213
16273
  const isLastWhiteSpace = isWhiteSpace(lastChar);
16214
16274
  const isNextWhiteSpace = isWhiteSpace(nextChar);
@@ -16251,7 +16311,7 @@ function process_inlines (tokens, state) {
16251
16311
  if (!canOpen && !canClose) {
16252
16312
  // middle of word
16253
16313
  if (isSingle) {
16254
- token.content = replaceAt(token.content, t.index, APOSTROPHE);
16314
+ addReplacement(replacements, i, t.index, APOSTROPHE);
16255
16315
  }
16256
16316
  continue
16257
16317
  }
@@ -16274,18 +16334,8 @@ function process_inlines (tokens, state) {
16274
16334
  closeQuote = state.md.options.quotes[1];
16275
16335
  }
16276
16336
 
16277
- // replace token.content *before* tokens[item.token].content,
16278
- // because, if they are pointing at the same token, replaceAt
16279
- // could mess up indices when quote length != 1
16280
- token.content = replaceAt(token.content, t.index, closeQuote);
16281
- tokens[item.token].content = replaceAt(
16282
- tokens[item.token].content, item.pos, openQuote);
16283
-
16284
- pos += closeQuote.length - 1;
16285
- if (item.token === i) { pos += openQuote.length - 1; }
16286
-
16287
- text = token.content;
16288
- max = text.length;
16337
+ addReplacement(replacements, i, t.index, closeQuote);
16338
+ addReplacement(replacements, item.token, item.pos, openQuote);
16289
16339
 
16290
16340
  stack.length = j;
16291
16341
  continue OUTER
@@ -16301,10 +16351,14 @@ function process_inlines (tokens, state) {
16301
16351
  level: thisLevel
16302
16352
  });
16303
16353
  } else if (canClose && isSingle) {
16304
- token.content = replaceAt(token.content, t.index, APOSTROPHE);
16354
+ addReplacement(replacements, i, t.index, APOSTROPHE);
16305
16355
  }
16306
16356
  }
16307
16357
  }
16358
+
16359
+ Object.keys(replacements).forEach(function (tokenIdx) {
16360
+ tokens[tokenIdx].content = applyReplacements(tokens[tokenIdx].content, replacements[tokenIdx]);
16361
+ });
16308
16362
  }
16309
16363
 
16310
16364
  function smartquotes (state) {
@@ -17908,11 +17962,22 @@ function html_block (state, startLine, endLine, silent) {
17908
17962
 
17909
17963
  let nextLine = startLine + 1;
17910
17964
 
17965
+ // Block types 6 and 7 (the only ones whose end condition is a blank line)
17966
+ // have `/^$/` as their closing regexp. For all other types (1-5, e.g.
17967
+ // `<!--` comments), a blank line is regular content and must not terminate
17968
+ // the block - it ends only when its closing sequence is found.
17969
+ const endsOnBlankLine = HTML_SEQUENCES[i][1].test('');
17970
+
17911
17971
  // If we are here - we detected HTML block.
17912
17972
  // Let's roll down till block end.
17913
17973
  if (!HTML_SEQUENCES[i][1].test(lineText)) {
17914
17974
  for (; nextLine < endLine; nextLine++) {
17915
- if (state.sCount[nextLine] < state.blkIndent) { break }
17975
+ if (state.sCount[nextLine] < state.blkIndent) {
17976
+ // An outdented blank line shouldn't end a block that doesn't end on a
17977
+ // blank line (e.g. a `<!--` comment inside a list item). Such blocks
17978
+ // must continue until their closing sequence regardless of indent.
17979
+ if (endsOnBlankLine || !state.isEmpty(nextLine)) { break }
17980
+ }
17916
17981
 
17917
17982
  pos = state.bMarks[nextLine] + state.tShift[nextLine];
17918
17983
  max = state.eMarks[nextLine];
@@ -17975,7 +18040,7 @@ function heading (state, startLine, endLine, silent) {
17975
18040
  token_o.map = [startLine, state.line];
17976
18041
 
17977
18042
  const token_i = state.push('inline', '', 0);
17978
- token_i.content = state.src.slice(pos, max).trim();
18043
+ token_i.content = asciiTrim(state.src.slice(pos, max));
17979
18044
  token_i.map = [startLine, state.line];
17980
18045
  token_i.children = [];
17981
18046
 
@@ -17987,6 +18052,7 @@ function heading (state, startLine, endLine, silent) {
17987
18052
 
17988
18053
  // lheading (---, ===)
17989
18054
 
18055
+
17990
18056
  function lheading (state, startLine, endLine/*, silent */) {
17991
18057
  const terminatorRules = state.md.block.ruler.getRules('paragraph');
17992
18058
 
@@ -18044,10 +18110,11 @@ function lheading (state, startLine, endLine/*, silent */) {
18044
18110
 
18045
18111
  if (!level) {
18046
18112
  // Didn't find valid underline
18113
+ state.parentType = oldParentType;
18047
18114
  return false
18048
18115
  }
18049
18116
 
18050
- const content = state.getLines(startLine, nextLine, state.blkIndent, false).trim();
18117
+ const content = asciiTrim(state.getLines(startLine, nextLine, state.blkIndent, false));
18051
18118
 
18052
18119
  state.line = nextLine + 1;
18053
18120
 
@@ -18070,6 +18137,7 @@ function lheading (state, startLine, endLine/*, silent */) {
18070
18137
 
18071
18138
  // Paragraph
18072
18139
 
18140
+
18073
18141
  function paragraph (state, startLine, endLine) {
18074
18142
  const terminatorRules = state.md.block.ruler.getRules('paragraph');
18075
18143
  const oldParentType = state.parentType;
@@ -18096,7 +18164,7 @@ function paragraph (state, startLine, endLine) {
18096
18164
  if (terminate) { break }
18097
18165
  }
18098
18166
 
18099
- const content = state.getLines(startLine, nextLine, state.blkIndent, false).trim();
18167
+ const content = asciiTrim(state.getLines(startLine, nextLine, state.blkIndent, false));
18100
18168
 
18101
18169
  state.line = nextLine;
18102
18170
 
@@ -18323,8 +18391,30 @@ StateInline.prototype.scanDelims = function (start, canSplitWord) {
18323
18391
  const max = this.posMax;
18324
18392
  const marker = this.src.charCodeAt(start);
18325
18393
 
18326
- // treat beginning of the line as a whitespace
18327
- const lastChar = start > 0 ? this.src.charCodeAt(start - 1) : 0x20;
18394
+ // Astral characters below are combined manually, because .codePointAt()
18395
+ // does not guarantee numeric type output. And we don't wish JIT cache issues.
18396
+ // The broken surrogate pairs are evaluated as U+FFFD to prevent possible
18397
+ // crashes.
18398
+
18399
+ let lastChar;
18400
+ if (start === 0) {
18401
+ // treat beginning of the line as a whitespace
18402
+ lastChar = 0x20;
18403
+ } else if (start === 1) {
18404
+ lastChar = this.src.charCodeAt(0);
18405
+ if ((lastChar & 0xF800) === 0xD800) { lastChar = 0xFFFD; }
18406
+ } else {
18407
+ lastChar = this.src.charCodeAt(start - 1);
18408
+ if ((lastChar & 0xFC00) === 0xDC00) {
18409
+ // low surrogate => add high one, replace broken pair with U+FFFD
18410
+ const highSurr = this.src.charCodeAt(start - 2);
18411
+ lastChar = (highSurr & 0xFC00) === 0xD800
18412
+ ? 0x10000 + ((highSurr - 0xD800) << 10) + (lastChar - 0xDC00)
18413
+ : 0xFFFD;
18414
+ } else if ((lastChar & 0xFC00) === 0xD800) {
18415
+ lastChar = 0xFFFD;
18416
+ }
18417
+ }
18328
18418
 
18329
18419
  let pos = start;
18330
18420
  while (pos < max && this.src.charCodeAt(pos) === marker) { pos++; }
@@ -18332,10 +18422,19 @@ StateInline.prototype.scanDelims = function (start, canSplitWord) {
18332
18422
  const count = pos - start;
18333
18423
 
18334
18424
  // treat end of the line as a whitespace
18335
- const nextChar = pos < max ? this.src.charCodeAt(pos) : 0x20;
18425
+ let nextChar = pos < max ? this.src.charCodeAt(pos) : 0x20;
18426
+ if ((nextChar & 0xFC00) === 0xD800) {
18427
+ // high surrogate => add low one, replace broken pair with U+FFFD
18428
+ const lowSurr = this.src.charCodeAt(pos + 1);
18429
+ nextChar = (lowSurr & 0xFC00) === 0xDC00
18430
+ ? 0x10000 + ((nextChar - 0xD800) << 10) + (lowSurr - 0xDC00)
18431
+ : 0xFFFD;
18432
+ } else if ((nextChar & 0xFC00) === 0xDC00) {
18433
+ nextChar = 0xFFFD;
18434
+ }
18336
18435
 
18337
- const isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar));
18338
- const isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar));
18436
+ const isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctCharCode(lastChar);
18437
+ const isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctCharCode(nextChar);
18339
18438
 
18340
18439
  const isLastWhiteSpace = isWhiteSpace(lastChar);
18341
18440
  const isNextWhiteSpace = isWhiteSpace(nextChar);
@@ -19362,7 +19461,7 @@ function entity (state, silent) {
19362
19461
  } else {
19363
19462
  const match = state.src.slice(pos).match(NAMED_RE);
19364
19463
  if (match) {
19365
- const decoded = decodeHTML(match[0]);
19464
+ const decoded = decodeHTMLStrict(match[0]);
19366
19465
  if (decoded !== match[0]) {
19367
19466
  if (!silent) {
19368
19467
  const token = state.push('text_special', '', 0);
@@ -20024,11 +20123,6 @@ const tlds_2ch_src_re = 'a[cdefgilmnoqrstuwxz]|b[abdefghijmnorstvwyz]|c[acdfghik
20024
20123
  // DON'T try to make PRs with changes. Extend TLDs with LinkifyIt.tlds() instead
20025
20124
  const tlds_default = 'biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф'.split('|');
20026
20125
 
20027
- function resetScanCache (self) {
20028
- self.__index__ = -1;
20029
- self.__text_cache__ = '';
20030
- }
20031
-
20032
20126
  function createValidator (re) {
20033
20127
  return function (text, pos) {
20034
20128
  const tail = text.slice(pos);
@@ -20067,8 +20161,11 @@ function compile (self) {
20067
20161
  function untpl (tpl) { return tpl.replace('%TLDS%', re.src_tlds) }
20068
20162
 
20069
20163
  re.email_fuzzy = RegExp(untpl(re.tpl_email_fuzzy), 'i');
20164
+ re.email_fuzzy_global = RegExp(untpl(re.tpl_email_fuzzy), 'ig');
20070
20165
  re.link_fuzzy = RegExp(untpl(re.tpl_link_fuzzy), 'i');
20166
+ re.link_fuzzy_global = RegExp(untpl(re.tpl_link_fuzzy), 'ig');
20071
20167
  re.link_no_ip_fuzzy = RegExp(untpl(re.tpl_link_no_ip_fuzzy), 'i');
20168
+ re.link_no_ip_fuzzy_global = RegExp(untpl(re.tpl_link_no_ip_fuzzy), 'ig');
20072
20169
  re.host_fuzzy_test = RegExp(untpl(re.tpl_host_fuzzy_test), 'i');
20073
20170
 
20074
20171
  //
@@ -20162,12 +20259,6 @@ function compile (self) {
20162
20259
  '(' + self.re.schema_test.source + ')|(' + self.re.host_fuzzy_test.source + ')|@',
20163
20260
  'i'
20164
20261
  );
20165
-
20166
- //
20167
- // Cleanup
20168
- //
20169
-
20170
- resetScanCache(self);
20171
20262
  }
20172
20263
 
20173
20264
  /**
@@ -20175,55 +20266,45 @@ function compile (self) {
20175
20266
  *
20176
20267
  * Match result. Single element of array, returned by [[LinkifyIt#match]]
20177
20268
  **/
20178
- function Match (self, shift) {
20179
- const start = self.__index__;
20180
- const end = self.__last_index__;
20181
- const text = self.__text_cache__.slice(start, end);
20269
+ function Match (text, schema, index, lastIndex) {
20270
+ const raw = text.slice(index, lastIndex);
20182
20271
 
20183
20272
  /**
20184
20273
  * Match#schema -> String
20185
20274
  *
20186
20275
  * Prefix (protocol) for matched string.
20187
20276
  **/
20188
- this.schema = self.__schema__.toLowerCase();
20277
+ this.schema = schema.toLowerCase();
20189
20278
  /**
20190
20279
  * Match#index -> Number
20191
20280
  *
20192
20281
  * First position of matched string.
20193
20282
  **/
20194
- this.index = start + shift;
20283
+ this.index = index;
20195
20284
  /**
20196
20285
  * Match#lastIndex -> Number
20197
20286
  *
20198
20287
  * Next position after matched string.
20199
20288
  **/
20200
- this.lastIndex = end + shift;
20289
+ this.lastIndex = lastIndex;
20201
20290
  /**
20202
20291
  * Match#raw -> String
20203
20292
  *
20204
20293
  * Matched string.
20205
20294
  **/
20206
- this.raw = text;
20295
+ this.raw = raw;
20207
20296
  /**
20208
20297
  * Match#text -> String
20209
20298
  *
20210
20299
  * Notmalized text of matched string.
20211
20300
  **/
20212
- this.text = text;
20301
+ this.text = raw;
20213
20302
  /**
20214
20303
  * Match#url -> String
20215
20304
  *
20216
20305
  * Normalized url of matched string.
20217
20306
  **/
20218
- this.url = text;
20219
- }
20220
-
20221
- function createMatch (self, shift) {
20222
- const match = new Match(self, shift);
20223
-
20224
- self.__compiled__[match.schema].normalize(match, self);
20225
-
20226
- return match
20307
+ this.url = raw;
20227
20308
  }
20228
20309
 
20229
20310
  /**
@@ -20278,12 +20359,6 @@ function LinkifyIt (schemas, options) {
20278
20359
 
20279
20360
  this.__opts__ = assign({}, defaultOptions$1, options);
20280
20361
 
20281
- // Cache last tested result. Used to skip repeating steps on next `match` call.
20282
- this.__index__ = -1;
20283
- this.__last_index__ = -1; // Next scan position
20284
- this.__schema__ = '';
20285
- this.__text_cache__ = '';
20286
-
20287
20362
  this.__schemas__ = assign({}, defaultSchemas, schemas);
20288
20363
  this.__compiled__ = {};
20289
20364
 
@@ -20325,69 +20400,38 @@ LinkifyIt.prototype.set = function set (options) {
20325
20400
  * Searches linkifiable pattern and returns `true` on success or `false` on fail.
20326
20401
  **/
20327
20402
  LinkifyIt.prototype.test = function test (text) {
20328
- // Reset scan cache
20329
- this.__text_cache__ = text;
20330
- this.__index__ = -1;
20331
-
20332
20403
  if (!text.length) { return false }
20333
20404
 
20334
- let m, ml, me, len, shift, next, re, tld_pos, at_pos;
20405
+ let m, re;
20335
20406
 
20336
20407
  // try to scan for link with schema - that's the most simple rule
20337
20408
  if (this.re.schema_test.test(text)) {
20338
20409
  re = this.re.schema_search;
20339
20410
  re.lastIndex = 0;
20340
20411
  while ((m = re.exec(text)) !== null) {
20341
- len = this.testSchemaAt(text, m[2], re.lastIndex);
20342
- if (len) {
20343
- this.__schema__ = m[2];
20344
- this.__index__ = m.index + m[1].length;
20345
- this.__last_index__ = m.index + m[0].length + len;
20346
- break
20347
- }
20412
+ if (this.testSchemaAt(text, m[2], re.lastIndex)) { return true }
20348
20413
  }
20349
20414
  }
20350
20415
 
20351
20416
  if (this.__opts__.fuzzyLink && this.__compiled__['http:']) {
20352
20417
  // guess schemaless links
20353
- tld_pos = text.search(this.re.host_fuzzy_test);
20354
- if (tld_pos >= 0) {
20355
- // if tld is located after found link - no need to check fuzzy pattern
20356
- if (this.__index__ < 0 || tld_pos < this.__index__) {
20357
- if ((ml = text.match(this.__opts__.fuzzyIP ? this.re.link_fuzzy : this.re.link_no_ip_fuzzy)) !== null) {
20358
- shift = ml.index + ml[1].length;
20359
-
20360
- if (this.__index__ < 0 || shift < this.__index__) {
20361
- this.__schema__ = '';
20362
- this.__index__ = shift;
20363
- this.__last_index__ = ml.index + ml[0].length;
20364
- }
20365
- }
20418
+ if (text.search(this.re.host_fuzzy_test) >= 0) {
20419
+ if (text.match(this.__opts__.fuzzyIP ? this.re.link_fuzzy : this.re.link_no_ip_fuzzy) !== null) {
20420
+ return true
20366
20421
  }
20367
20422
  }
20368
20423
  }
20369
20424
 
20370
20425
  if (this.__opts__.fuzzyEmail && this.__compiled__['mailto:']) {
20371
20426
  // guess schemaless emails
20372
- at_pos = text.indexOf('@');
20373
- if (at_pos >= 0) {
20427
+ if (text.indexOf('@') >= 0) {
20374
20428
  // We can't skip this check, because this cases are possible:
20375
20429
  // 192.168.1.1@gmail.com, my.in@example.com
20376
- if ((me = text.match(this.re.email_fuzzy)) !== null) {
20377
- shift = me.index + me[1].length;
20378
- next = me.index + me[0].length;
20379
-
20380
- if (this.__index__ < 0 || shift < this.__index__ ||
20381
- (shift === this.__index__ && next > this.__last_index__)) {
20382
- this.__schema__ = 'mailto:';
20383
- this.__index__ = shift;
20384
- this.__last_index__ = next;
20385
- }
20386
- }
20430
+ if (text.match(this.re.email_fuzzy) !== null) { return true }
20387
20431
  }
20388
20432
  }
20389
20433
 
20390
- return this.__index__ >= 0
20434
+ return false
20391
20435
  };
20392
20436
 
20393
20437
  /**
@@ -20436,23 +20480,88 @@ LinkifyIt.prototype.testSchemaAt = function testSchemaAt (text, schema, pos) {
20436
20480
  **/
20437
20481
  LinkifyIt.prototype.match = function match (text) {
20438
20482
  const result = [];
20439
- let shift = 0;
20483
+ const type_schemed = [];
20484
+ const type_fuzzy_link = [];
20485
+ const type_fuzzy_email = [];
20486
+ let m, len, re;
20440
20487
 
20441
- // Try to take previous element from cache, if .test() called before
20442
- if (this.__index__ >= 0 && this.__text_cache__ === text) {
20443
- result.push(createMatch(this, shift));
20444
- shift = this.__last_index__;
20488
+ function choose (a, b) {
20489
+ if (!a) { return b }
20490
+ if (!b) { return a }
20491
+ if (a.index !== b.index) { return a.index < b.index ? a : b }
20492
+ return a.lastIndex >= b.lastIndex ? a : b
20445
20493
  }
20446
20494
 
20447
- // Cut head if cache was used
20448
- let tail = shift ? text.slice(shift) : text;
20495
+ if (!text.length) { return null }
20449
20496
 
20450
- // Scan string until end reached
20451
- while (this.test(tail)) {
20452
- result.push(createMatch(this, shift));
20497
+ // scan for links with schema
20498
+ if (this.re.schema_test.test(text)) {
20499
+ re = this.re.schema_search;
20500
+ re.lastIndex = 0;
20501
+ while ((m = re.exec(text)) !== null) {
20502
+ len = this.testSchemaAt(text, m[2], re.lastIndex);
20503
+ if (len) {
20504
+ type_schemed.push({
20505
+ schema: m[2],
20506
+ index: m.index + m[1].length,
20507
+ lastIndex: m.index + m[0].length + len
20508
+ });
20509
+ }
20510
+ }
20511
+ }
20453
20512
 
20454
- tail = tail.slice(this.__last_index__);
20455
- shift += this.__last_index__;
20513
+ if (this.__opts__.fuzzyLink && this.__compiled__['http:']) {
20514
+ re = this.__opts__.fuzzyIP ? this.re.link_fuzzy_global : this.re.link_no_ip_fuzzy_global;
20515
+ re.lastIndex = 0;
20516
+ while ((m = re.exec(text)) !== null) {
20517
+ type_fuzzy_link.push({
20518
+ schema: '',
20519
+ index: m.index + m[1].length,
20520
+ lastIndex: m.index + m[0].length
20521
+ });
20522
+ }
20523
+ }
20524
+
20525
+ if (this.__opts__.fuzzyEmail && this.__compiled__['mailto:']) {
20526
+ re = this.re.email_fuzzy_global;
20527
+ re.lastIndex = 0;
20528
+ while ((m = re.exec(text)) !== null) {
20529
+ type_fuzzy_email.push({
20530
+ schema: 'mailto:',
20531
+ index: m.index + m[1].length,
20532
+ lastIndex: m.index + m[0].length
20533
+ });
20534
+ }
20535
+ }
20536
+
20537
+ const indexes = [0, 0, 0];
20538
+ let lastIndex = 0;
20539
+
20540
+ for (;;) {
20541
+ const candidates = [
20542
+ type_schemed[indexes[0]],
20543
+ type_fuzzy_email[indexes[1]],
20544
+ type_fuzzy_link[indexes[2]]
20545
+ ];
20546
+
20547
+ const candidate = choose(choose(candidates[0], candidates[1]), candidates[2]);
20548
+
20549
+ if (!candidate) { break }
20550
+
20551
+ if (candidate === candidates[0]) {
20552
+ indexes[0]++;
20553
+ } else if (candidate === candidates[1]) {
20554
+ indexes[1]++;
20555
+ } else {
20556
+ indexes[2]++;
20557
+ }
20558
+
20559
+ if (candidate.index < lastIndex) { continue }
20560
+
20561
+ const match = new Match(text, candidate.schema, candidate.index, candidate.lastIndex);
20562
+ this.__compiled__[match.schema].normalize(match, this);
20563
+ result.push(match);
20564
+ lastIndex = candidate.lastIndex;
20456
20565
  }
20457
20566
 
20458
20567
  if (result.length) {
@@ -20469,10 +20578,6 @@ LinkifyIt.prototype.match = function match (text) {
20469
20578
  * of the string, and null otherwise.
20470
20579
  **/
20471
20580
  LinkifyIt.prototype.matchAtStart = function matchAtStart (text) {
20472
- // Reset scan cache
20473
- this.__text_cache__ = text;
20474
- this.__index__ = -1;
20475
-
20476
20581
  if (!text.length) return null
20477
20582
 
20478
20583
  const m = this.re.schema_at_start.exec(text);
@@ -20481,11 +20586,10 @@ LinkifyIt.prototype.matchAtStart = function matchAtStart (text) {
20481
20586
  const len = this.testSchemaAt(text, m[2], m[0].length);
20482
20587
  if (!len) return null
20483
20588
 
20484
- this.__schema__ = m[2];
20485
- this.__index__ = m.index + m[1].length;
20486
- this.__last_index__ = m.index + m[0].length + len;
20589
+ const match = new Match(text, m[2], m.index + m[1].length, m.index + m[0].length + len);
20487
20590
 
20488
- return createMatch(this, 0)
20591
+ this.__compiled__[match.schema].normalize(match, this);
20592
+ return match
20489
20593
  };
20490
20594
 
20491
20595
  /** chainable
@@ -21537,7 +21641,7 @@ function MarkdownIt (presetName, options) {
21537
21641
  * ```javascript
21538
21642
  * var md = require('markdown-it')()
21539
21643
  * .set({ html: true, breaks: true })
21540
- * .set({ typographer, true });
21644
+ * .set({ typographer: true });
21541
21645
  * ```
21542
21646
  *
21543
21647
  * __Note:__ To achieve the best possible performance, don't modify a