@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/README.md CHANGED
@@ -121,10 +121,11 @@ const inputData =
121
121
  "description" : {"en":"Service description", "el":"Περιγραφή υπηρεσίας"},
122
122
  "url" : "https://gov.cy",
123
123
  "manifest": "/manifest.json",
124
- "matomo": {
125
- "url": "//wp.matomo.dits.dmrid.gov.cy/",
126
- "siteId": "1234"
127
- },
124
+ "matomo": {
125
+ "url": "//wp.matomo.dits.dmrid.gov.cy/",
126
+ "siteId": "1234",
127
+ "userId": "already-hashed-stable-id"
128
+ },
128
129
  "cdn" : {
129
130
  "dist" : "https://cdn.jsdelivr.net/gh/gov-cy/govcy-design-system@3.0.0/dist",
130
131
  "cssIntegrity" : "sha384-1zLHWOtnS0hOIz5mVEPZp0UH5gUE6eo0CQcCGA3sF2TyYhHyKOd3Ni8Iy/NjEASU",
@@ -251,10 +252,11 @@ const inputData =
251
252
  "description" : {"en":"Service description", "el":"Περιγραφή υπηρεσίας"},
252
253
  "url" : "https://gov.cy",
253
254
  "manifest": "manifest.json",
254
- "matomo": {
255
- "url": "//wp.matomo.dits.dmrid.gov.cy/",
256
- "siteId": "1234"
257
- },
255
+ "matomo": {
256
+ "url": "//wp.matomo.dits.dmrid.gov.cy/",
257
+ "siteId": "1234",
258
+ "userId": "already-hashed-stable-id"
259
+ },
258
260
  "cdn" : {
259
261
  "dist" : "https://cdn.jsdelivr.net/gh/gov-cy/govcy-design-system@3.0.0/dist",
260
262
  "cssIntegrity" : "sha384-1zLHWOtnS0hOIz5mVEPZp0UH5gUE6eo0CQcCGA3sF2TyYhHyKOd3Ni8Iy/NjEASU",
@@ -436,7 +438,7 @@ The `inputData` object has the following structure:
436
438
  - **site.description**: the description of the site. It is used in the `<meta name="description"`, `<meta property="og:description"` and `<meta property="twitter:description"` tags of the head.
437
439
  - **site.url**: the URL of the site. It is used in the `<meta property="og:url"` and `<meta property="twitter:url"` tags of the head.
438
440
  - **site.manifest**: the manifest of the site. It is used to add the manifest location to the page.
439
- - **site.matomo**: the matomo data. It is used to add the Matomo code to the page. If you don't want to use Matomo tracking, you can remove this value. Use `site.matomo.url` to define the URL of the Matomo server and `site.matomo.siteId` to define the site ID to be tracked.
441
+ - **site.matomo**: the matomo data. It is used to add the Matomo code to the page. If you don't want to use Matomo tracking, you can remove this value. Use `site.matomo.url` to define the URL of the Matomo server and `site.matomo.siteId` to define the site ID to be tracked. Use `site.matomo.userId` only for authenticated users, when the consuming application can provide a stable unique identifier that has already been pseudonymized, for example a SHA-256/base64 or HMAC-SHA256 value based on an internal ID. Do not pass personally identifiable information such as email, full name or username. If the user is not authenticated, omit `site.matomo.userId`.
440
442
  - **site.cdn.dist**: the CDN of the site. It is used to define the URL of the CDN used for the CSS and JS files. If you need to change the version of the CDN, you can do it by changing this value (in this case you will need to change the `site.cdn.cssIntegrity` and `site.cdn.jsIntegrity` values as well)
441
443
  - **site.cdn.cssIntegrity**: the integrity of the CSS file. It is used to define the integrity of the CSS file. If you need to change the version of the CDN, you will need to change this value. https://www.srihash.org/ can help you generate the integrity value.
442
444
  - **site.cdn.jsIntegrity**: the integrity of the JS file. It is used to define the integrity of the JS file. If you need to change the version of the CDN, you will need to change this value. https://www.srihash.org/ can help you generate the integrity value.
@@ -8071,6 +8071,15 @@ var GovcyFrontendRendererBrowser = (function () {
8071
8071
  function decodeHTML(str, mode = DecodingMode.Legacy) {
8072
8072
  return htmlDecoder(str, mode);
8073
8073
  }
8074
+ /**
8075
+ * Decodes an HTML string, requiring all entities to be terminated by a semicolon.
8076
+ *
8077
+ * @param str The string to decode.
8078
+ * @returns The decoded string.
8079
+ */
8080
+ function decodeHTMLStrict(str) {
8081
+ return htmlDecoder(str, DecodingMode.Strict);
8082
+ }
8074
8083
 
8075
8084
  // Utilities
8076
8085
  //
@@ -8250,6 +8259,10 @@ var GovcyFrontendRendererBrowser = (function () {
8250
8259
  return P.test(ch) || regex.test(ch)
8251
8260
  }
8252
8261
 
8262
+ function isPunctCharCode (code) {
8263
+ return isPunctChar(fromCodePoint(code))
8264
+ }
8265
+
8253
8266
  // Markdown ASCII punctuation characters.
8254
8267
  //
8255
8268
  // !, ", #, $, %, &, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ?, @, [, \, ], ^, _, `, {, |, }, or ~
@@ -8311,6 +8324,7 @@ var GovcyFrontendRendererBrowser = (function () {
8311
8324
  // (remove this when node v10 is no longer supported).
8312
8325
  //
8313
8326
  if ('ẞ'.toLowerCase() === 'Ṿ') {
8327
+ /* c8 ignore next 2 */
8314
8328
  str = str.replace(/ẞ/g, 'ß');
8315
8329
  }
8316
8330
 
@@ -8349,6 +8363,28 @@ var GovcyFrontendRendererBrowser = (function () {
8349
8363
  return str.toLowerCase().toUpperCase()
8350
8364
  }
8351
8365
 
8366
+ function isAsciiTrimmable (c) {
8367
+ return c === 0x20 || c === 0x09 || c === 0x0a || c === 0x0d
8368
+ }
8369
+
8370
+ // "Light" .trim() for blocks (headers, paragraphs), where unicode spaces
8371
+ // should be preserved.
8372
+ function asciiTrim (str) {
8373
+ let start = 0;
8374
+ for (; start < str.length; start++) {
8375
+ if (!isAsciiTrimmable(str.charCodeAt(start))) {
8376
+ break
8377
+ }
8378
+ }
8379
+ let end = str.length - 1;
8380
+ for (; end >= start; end--) {
8381
+ if (!isAsciiTrimmable(str.charCodeAt(end))) {
8382
+ break
8383
+ }
8384
+ }
8385
+ return str.slice(start, end + 1)
8386
+ }
8387
+
8352
8388
  // Re-export libraries commonly used in both markdown-it and its plugins,
8353
8389
  // so plugins won't have to depend on them explicitly, which reduces their
8354
8390
  // bundled size (e.g. a browser build).
@@ -8358,6 +8394,7 @@ var GovcyFrontendRendererBrowser = (function () {
8358
8394
  var utils$2 = /*#__PURE__*/Object.freeze({
8359
8395
  __proto__: null,
8360
8396
  arrayReplaceAt: arrayReplaceAt,
8397
+ asciiTrim: asciiTrim,
8361
8398
  assign: assign$1,
8362
8399
  escapeHtml: escapeHtml,
8363
8400
  escapeRE: escapeRE$1,
@@ -8365,6 +8402,7 @@ var GovcyFrontendRendererBrowser = (function () {
8365
8402
  has: has,
8366
8403
  isMdAsciiPunct: isMdAsciiPunct,
8367
8404
  isPunctChar: isPunctChar,
8405
+ isPunctCharCode: isPunctCharCode,
8368
8406
  isSpace: isSpace,
8369
8407
  isString: isString$1,
8370
8408
  isValidEntityCode: isValidEntityCode,
@@ -9728,14 +9766,36 @@ var GovcyFrontendRendererBrowser = (function () {
9728
9766
  const QUOTE_RE = /['"]/g;
9729
9767
  const APOSTROPHE = '\u2019'; /* ’ */
9730
9768
 
9731
- function replaceAt (str, index, ch) {
9732
- return str.slice(0, index) + ch + str.slice(index + 1)
9769
+ function addReplacement (replacements, tokenIdx, pos, ch) {
9770
+ if (!replacements[tokenIdx]) {
9771
+ replacements[tokenIdx] = [];
9772
+ }
9773
+
9774
+ replacements[tokenIdx].push({ pos, ch });
9775
+ }
9776
+
9777
+ function applyReplacements (str, replacements) {
9778
+ let result = '';
9779
+ let lastPos = 0;
9780
+
9781
+ replacements.sort((a, b) => a.pos - b.pos);
9782
+
9783
+ for (let i = 0; i < replacements.length; i++) {
9784
+ const replacement = replacements[i];
9785
+
9786
+ result += str.slice(lastPos, replacement.pos) + replacement.ch;
9787
+ lastPos = replacement.pos + 1;
9788
+ }
9789
+
9790
+ return result + str.slice(lastPos)
9733
9791
  }
9734
9792
 
9735
9793
  function process_inlines (tokens, state) {
9736
9794
  let j;
9737
9795
 
9738
9796
  const stack = [];
9797
+ // token index -> list of replacements in the original token content
9798
+ const replacements = {};
9739
9799
 
9740
9800
  for (let i = 0; i < tokens.length; i++) {
9741
9801
  const token = tokens[i];
@@ -9749,9 +9809,9 @@ var GovcyFrontendRendererBrowser = (function () {
9749
9809
 
9750
9810
  if (token.type !== 'text') { continue }
9751
9811
 
9752
- let text = token.content;
9812
+ const text = token.content;
9753
9813
  let pos = 0;
9754
- let max = text.length;
9814
+ const max = text.length;
9755
9815
 
9756
9816
  /* eslint no-labels:0,block-scoped-var:0 */
9757
9817
  OUTER:
@@ -9799,8 +9859,8 @@ var GovcyFrontendRendererBrowser = (function () {
9799
9859
  }
9800
9860
  }
9801
9861
 
9802
- const isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar));
9803
- const isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar));
9862
+ const isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctCharCode(lastChar);
9863
+ const isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctCharCode(nextChar);
9804
9864
 
9805
9865
  const isLastWhiteSpace = isWhiteSpace(lastChar);
9806
9866
  const isNextWhiteSpace = isWhiteSpace(nextChar);
@@ -9843,7 +9903,7 @@ var GovcyFrontendRendererBrowser = (function () {
9843
9903
  if (!canOpen && !canClose) {
9844
9904
  // middle of word
9845
9905
  if (isSingle) {
9846
- token.content = replaceAt(token.content, t.index, APOSTROPHE);
9906
+ addReplacement(replacements, i, t.index, APOSTROPHE);
9847
9907
  }
9848
9908
  continue
9849
9909
  }
@@ -9866,18 +9926,8 @@ var GovcyFrontendRendererBrowser = (function () {
9866
9926
  closeQuote = state.md.options.quotes[1];
9867
9927
  }
9868
9928
 
9869
- // replace token.content *before* tokens[item.token].content,
9870
- // because, if they are pointing at the same token, replaceAt
9871
- // could mess up indices when quote length != 1
9872
- token.content = replaceAt(token.content, t.index, closeQuote);
9873
- tokens[item.token].content = replaceAt(
9874
- tokens[item.token].content, item.pos, openQuote);
9875
-
9876
- pos += closeQuote.length - 1;
9877
- if (item.token === i) { pos += openQuote.length - 1; }
9878
-
9879
- text = token.content;
9880
- max = text.length;
9929
+ addReplacement(replacements, i, t.index, closeQuote);
9930
+ addReplacement(replacements, item.token, item.pos, openQuote);
9881
9931
 
9882
9932
  stack.length = j;
9883
9933
  continue OUTER
@@ -9893,10 +9943,14 @@ var GovcyFrontendRendererBrowser = (function () {
9893
9943
  level: thisLevel
9894
9944
  });
9895
9945
  } else if (canClose && isSingle) {
9896
- token.content = replaceAt(token.content, t.index, APOSTROPHE);
9946
+ addReplacement(replacements, i, t.index, APOSTROPHE);
9897
9947
  }
9898
9948
  }
9899
9949
  }
9950
+
9951
+ Object.keys(replacements).forEach(function (tokenIdx) {
9952
+ tokens[tokenIdx].content = applyReplacements(tokens[tokenIdx].content, replacements[tokenIdx]);
9953
+ });
9900
9954
  }
9901
9955
 
9902
9956
  function smartquotes (state) {
@@ -11500,11 +11554,22 @@ var GovcyFrontendRendererBrowser = (function () {
11500
11554
 
11501
11555
  let nextLine = startLine + 1;
11502
11556
 
11557
+ // Block types 6 and 7 (the only ones whose end condition is a blank line)
11558
+ // have `/^$/` as their closing regexp. For all other types (1-5, e.g.
11559
+ // `<!--` comments), a blank line is regular content and must not terminate
11560
+ // the block - it ends only when its closing sequence is found.
11561
+ const endsOnBlankLine = HTML_SEQUENCES[i][1].test('');
11562
+
11503
11563
  // If we are here - we detected HTML block.
11504
11564
  // Let's roll down till block end.
11505
11565
  if (!HTML_SEQUENCES[i][1].test(lineText)) {
11506
11566
  for (; nextLine < endLine; nextLine++) {
11507
- if (state.sCount[nextLine] < state.blkIndent) { break }
11567
+ if (state.sCount[nextLine] < state.blkIndent) {
11568
+ // An outdented blank line shouldn't end a block that doesn't end on a
11569
+ // blank line (e.g. a `<!--` comment inside a list item). Such blocks
11570
+ // must continue until their closing sequence regardless of indent.
11571
+ if (endsOnBlankLine || !state.isEmpty(nextLine)) { break }
11572
+ }
11508
11573
 
11509
11574
  pos = state.bMarks[nextLine] + state.tShift[nextLine];
11510
11575
  max = state.eMarks[nextLine];
@@ -11567,7 +11632,7 @@ var GovcyFrontendRendererBrowser = (function () {
11567
11632
  token_o.map = [startLine, state.line];
11568
11633
 
11569
11634
  const token_i = state.push('inline', '', 0);
11570
- token_i.content = state.src.slice(pos, max).trim();
11635
+ token_i.content = asciiTrim(state.src.slice(pos, max));
11571
11636
  token_i.map = [startLine, state.line];
11572
11637
  token_i.children = [];
11573
11638
 
@@ -11579,6 +11644,7 @@ var GovcyFrontendRendererBrowser = (function () {
11579
11644
 
11580
11645
  // lheading (---, ===)
11581
11646
 
11647
+
11582
11648
  function lheading (state, startLine, endLine/*, silent */) {
11583
11649
  const terminatorRules = state.md.block.ruler.getRules('paragraph');
11584
11650
 
@@ -11636,10 +11702,11 @@ var GovcyFrontendRendererBrowser = (function () {
11636
11702
 
11637
11703
  if (!level) {
11638
11704
  // Didn't find valid underline
11705
+ state.parentType = oldParentType;
11639
11706
  return false
11640
11707
  }
11641
11708
 
11642
- const content = state.getLines(startLine, nextLine, state.blkIndent, false).trim();
11709
+ const content = asciiTrim(state.getLines(startLine, nextLine, state.blkIndent, false));
11643
11710
 
11644
11711
  state.line = nextLine + 1;
11645
11712
 
@@ -11662,6 +11729,7 @@ var GovcyFrontendRendererBrowser = (function () {
11662
11729
 
11663
11730
  // Paragraph
11664
11731
 
11732
+
11665
11733
  function paragraph (state, startLine, endLine) {
11666
11734
  const terminatorRules = state.md.block.ruler.getRules('paragraph');
11667
11735
  const oldParentType = state.parentType;
@@ -11688,7 +11756,7 @@ var GovcyFrontendRendererBrowser = (function () {
11688
11756
  if (terminate) { break }
11689
11757
  }
11690
11758
 
11691
- const content = state.getLines(startLine, nextLine, state.blkIndent, false).trim();
11759
+ const content = asciiTrim(state.getLines(startLine, nextLine, state.blkIndent, false));
11692
11760
 
11693
11761
  state.line = nextLine;
11694
11762
 
@@ -11915,8 +11983,30 @@ var GovcyFrontendRendererBrowser = (function () {
11915
11983
  const max = this.posMax;
11916
11984
  const marker = this.src.charCodeAt(start);
11917
11985
 
11918
- // treat beginning of the line as a whitespace
11919
- const lastChar = start > 0 ? this.src.charCodeAt(start - 1) : 0x20;
11986
+ // Astral characters below are combined manually, because .codePointAt()
11987
+ // does not guarantee numeric type output. And we don't wish JIT cache issues.
11988
+ // The broken surrogate pairs are evaluated as U+FFFD to prevent possible
11989
+ // crashes.
11990
+
11991
+ let lastChar;
11992
+ if (start === 0) {
11993
+ // treat beginning of the line as a whitespace
11994
+ lastChar = 0x20;
11995
+ } else if (start === 1) {
11996
+ lastChar = this.src.charCodeAt(0);
11997
+ if ((lastChar & 0xF800) === 0xD800) { lastChar = 0xFFFD; }
11998
+ } else {
11999
+ lastChar = this.src.charCodeAt(start - 1);
12000
+ if ((lastChar & 0xFC00) === 0xDC00) {
12001
+ // low surrogate => add high one, replace broken pair with U+FFFD
12002
+ const highSurr = this.src.charCodeAt(start - 2);
12003
+ lastChar = (highSurr & 0xFC00) === 0xD800
12004
+ ? 0x10000 + ((highSurr - 0xD800) << 10) + (lastChar - 0xDC00)
12005
+ : 0xFFFD;
12006
+ } else if ((lastChar & 0xFC00) === 0xD800) {
12007
+ lastChar = 0xFFFD;
12008
+ }
12009
+ }
11920
12010
 
11921
12011
  let pos = start;
11922
12012
  while (pos < max && this.src.charCodeAt(pos) === marker) { pos++; }
@@ -11924,10 +12014,19 @@ var GovcyFrontendRendererBrowser = (function () {
11924
12014
  const count = pos - start;
11925
12015
 
11926
12016
  // treat end of the line as a whitespace
11927
- const nextChar = pos < max ? this.src.charCodeAt(pos) : 0x20;
12017
+ let nextChar = pos < max ? this.src.charCodeAt(pos) : 0x20;
12018
+ if ((nextChar & 0xFC00) === 0xD800) {
12019
+ // high surrogate => add low one, replace broken pair with U+FFFD
12020
+ const lowSurr = this.src.charCodeAt(pos + 1);
12021
+ nextChar = (lowSurr & 0xFC00) === 0xDC00
12022
+ ? 0x10000 + ((nextChar - 0xD800) << 10) + (lowSurr - 0xDC00)
12023
+ : 0xFFFD;
12024
+ } else if ((nextChar & 0xFC00) === 0xDC00) {
12025
+ nextChar = 0xFFFD;
12026
+ }
11928
12027
 
11929
- const isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar));
11930
- const isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar));
12028
+ const isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctCharCode(lastChar);
12029
+ const isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctCharCode(nextChar);
11931
12030
 
11932
12031
  const isLastWhiteSpace = isWhiteSpace(lastChar);
11933
12032
  const isNextWhiteSpace = isWhiteSpace(nextChar);
@@ -12954,7 +13053,7 @@ var GovcyFrontendRendererBrowser = (function () {
12954
13053
  } else {
12955
13054
  const match = state.src.slice(pos).match(NAMED_RE);
12956
13055
  if (match) {
12957
- const decoded = decodeHTML(match[0]);
13056
+ const decoded = decodeHTMLStrict(match[0]);
12958
13057
  if (decoded !== match[0]) {
12959
13058
  if (!silent) {
12960
13059
  const token = state.push('text_special', '', 0);
@@ -13616,11 +13715,6 @@ var GovcyFrontendRendererBrowser = (function () {
13616
13715
  // DON'T try to make PRs with changes. Extend TLDs with LinkifyIt.tlds() instead
13617
13716
  const tlds_default = 'biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф'.split('|');
13618
13717
 
13619
- function resetScanCache (self) {
13620
- self.__index__ = -1;
13621
- self.__text_cache__ = '';
13622
- }
13623
-
13624
13718
  function createValidator (re) {
13625
13719
  return function (text, pos) {
13626
13720
  const tail = text.slice(pos);
@@ -13659,8 +13753,11 @@ var GovcyFrontendRendererBrowser = (function () {
13659
13753
  function untpl (tpl) { return tpl.replace('%TLDS%', re.src_tlds) }
13660
13754
 
13661
13755
  re.email_fuzzy = RegExp(untpl(re.tpl_email_fuzzy), 'i');
13756
+ re.email_fuzzy_global = RegExp(untpl(re.tpl_email_fuzzy), 'ig');
13662
13757
  re.link_fuzzy = RegExp(untpl(re.tpl_link_fuzzy), 'i');
13758
+ re.link_fuzzy_global = RegExp(untpl(re.tpl_link_fuzzy), 'ig');
13663
13759
  re.link_no_ip_fuzzy = RegExp(untpl(re.tpl_link_no_ip_fuzzy), 'i');
13760
+ re.link_no_ip_fuzzy_global = RegExp(untpl(re.tpl_link_no_ip_fuzzy), 'ig');
13664
13761
  re.host_fuzzy_test = RegExp(untpl(re.tpl_host_fuzzy_test), 'i');
13665
13762
 
13666
13763
  //
@@ -13754,12 +13851,6 @@ var GovcyFrontendRendererBrowser = (function () {
13754
13851
  '(' + self.re.schema_test.source + ')|(' + self.re.host_fuzzy_test.source + ')|@',
13755
13852
  'i'
13756
13853
  );
13757
-
13758
- //
13759
- // Cleanup
13760
- //
13761
-
13762
- resetScanCache(self);
13763
13854
  }
13764
13855
 
13765
13856
  /**
@@ -13767,55 +13858,45 @@ var GovcyFrontendRendererBrowser = (function () {
13767
13858
  *
13768
13859
  * Match result. Single element of array, returned by [[LinkifyIt#match]]
13769
13860
  **/
13770
- function Match (self, shift) {
13771
- const start = self.__index__;
13772
- const end = self.__last_index__;
13773
- const text = self.__text_cache__.slice(start, end);
13861
+ function Match (text, schema, index, lastIndex) {
13862
+ const raw = text.slice(index, lastIndex);
13774
13863
 
13775
13864
  /**
13776
13865
  * Match#schema -> String
13777
13866
  *
13778
13867
  * Prefix (protocol) for matched string.
13779
13868
  **/
13780
- this.schema = self.__schema__.toLowerCase();
13869
+ this.schema = schema.toLowerCase();
13781
13870
  /**
13782
13871
  * Match#index -> Number
13783
13872
  *
13784
13873
  * First position of matched string.
13785
13874
  **/
13786
- this.index = start + shift;
13875
+ this.index = index;
13787
13876
  /**
13788
13877
  * Match#lastIndex -> Number
13789
13878
  *
13790
13879
  * Next position after matched string.
13791
13880
  **/
13792
- this.lastIndex = end + shift;
13881
+ this.lastIndex = lastIndex;
13793
13882
  /**
13794
13883
  * Match#raw -> String
13795
13884
  *
13796
13885
  * Matched string.
13797
13886
  **/
13798
- this.raw = text;
13887
+ this.raw = raw;
13799
13888
  /**
13800
13889
  * Match#text -> String
13801
13890
  *
13802
13891
  * Notmalized text of matched string.
13803
13892
  **/
13804
- this.text = text;
13893
+ this.text = raw;
13805
13894
  /**
13806
13895
  * Match#url -> String
13807
13896
  *
13808
13897
  * Normalized url of matched string.
13809
13898
  **/
13810
- this.url = text;
13811
- }
13812
-
13813
- function createMatch (self, shift) {
13814
- const match = new Match(self, shift);
13815
-
13816
- self.__compiled__[match.schema].normalize(match, self);
13817
-
13818
- return match
13899
+ this.url = raw;
13819
13900
  }
13820
13901
 
13821
13902
  /**
@@ -13870,12 +13951,6 @@ var GovcyFrontendRendererBrowser = (function () {
13870
13951
 
13871
13952
  this.__opts__ = assign({}, defaultOptions$1, options);
13872
13953
 
13873
- // Cache last tested result. Used to skip repeating steps on next `match` call.
13874
- this.__index__ = -1;
13875
- this.__last_index__ = -1; // Next scan position
13876
- this.__schema__ = '';
13877
- this.__text_cache__ = '';
13878
-
13879
13954
  this.__schemas__ = assign({}, defaultSchemas, schemas);
13880
13955
  this.__compiled__ = {};
13881
13956
 
@@ -13917,69 +13992,38 @@ var GovcyFrontendRendererBrowser = (function () {
13917
13992
  * Searches linkifiable pattern and returns `true` on success or `false` on fail.
13918
13993
  **/
13919
13994
  LinkifyIt.prototype.test = function test (text) {
13920
- // Reset scan cache
13921
- this.__text_cache__ = text;
13922
- this.__index__ = -1;
13923
-
13924
13995
  if (!text.length) { return false }
13925
13996
 
13926
- let m, ml, me, len, shift, next, re, tld_pos, at_pos;
13997
+ let m, re;
13927
13998
 
13928
13999
  // try to scan for link with schema - that's the most simple rule
13929
14000
  if (this.re.schema_test.test(text)) {
13930
14001
  re = this.re.schema_search;
13931
14002
  re.lastIndex = 0;
13932
14003
  while ((m = re.exec(text)) !== null) {
13933
- len = this.testSchemaAt(text, m[2], re.lastIndex);
13934
- if (len) {
13935
- this.__schema__ = m[2];
13936
- this.__index__ = m.index + m[1].length;
13937
- this.__last_index__ = m.index + m[0].length + len;
13938
- break
13939
- }
14004
+ if (this.testSchemaAt(text, m[2], re.lastIndex)) { return true }
13940
14005
  }
13941
14006
  }
13942
14007
 
13943
14008
  if (this.__opts__.fuzzyLink && this.__compiled__['http:']) {
13944
14009
  // guess schemaless links
13945
- tld_pos = text.search(this.re.host_fuzzy_test);
13946
- if (tld_pos >= 0) {
13947
- // if tld is located after found link - no need to check fuzzy pattern
13948
- if (this.__index__ < 0 || tld_pos < this.__index__) {
13949
- if ((ml = text.match(this.__opts__.fuzzyIP ? this.re.link_fuzzy : this.re.link_no_ip_fuzzy)) !== null) {
13950
- shift = ml.index + ml[1].length;
13951
-
13952
- if (this.__index__ < 0 || shift < this.__index__) {
13953
- this.__schema__ = '';
13954
- this.__index__ = shift;
13955
- this.__last_index__ = ml.index + ml[0].length;
13956
- }
13957
- }
14010
+ if (text.search(this.re.host_fuzzy_test) >= 0) {
14011
+ if (text.match(this.__opts__.fuzzyIP ? this.re.link_fuzzy : this.re.link_no_ip_fuzzy) !== null) {
14012
+ return true
13958
14013
  }
13959
14014
  }
13960
14015
  }
13961
14016
 
13962
14017
  if (this.__opts__.fuzzyEmail && this.__compiled__['mailto:']) {
13963
14018
  // guess schemaless emails
13964
- at_pos = text.indexOf('@');
13965
- if (at_pos >= 0) {
14019
+ if (text.indexOf('@') >= 0) {
13966
14020
  // We can't skip this check, because this cases are possible:
13967
14021
  // 192.168.1.1@gmail.com, my.in@example.com
13968
- if ((me = text.match(this.re.email_fuzzy)) !== null) {
13969
- shift = me.index + me[1].length;
13970
- next = me.index + me[0].length;
13971
-
13972
- if (this.__index__ < 0 || shift < this.__index__ ||
13973
- (shift === this.__index__ && next > this.__last_index__)) {
13974
- this.__schema__ = 'mailto:';
13975
- this.__index__ = shift;
13976
- this.__last_index__ = next;
13977
- }
13978
- }
14022
+ if (text.match(this.re.email_fuzzy) !== null) { return true }
13979
14023
  }
13980
14024
  }
13981
14025
 
13982
- return this.__index__ >= 0
14026
+ return false
13983
14027
  };
13984
14028
 
13985
14029
  /**
@@ -14028,23 +14072,88 @@ var GovcyFrontendRendererBrowser = (function () {
14028
14072
  **/
14029
14073
  LinkifyIt.prototype.match = function match (text) {
14030
14074
  const result = [];
14031
- let shift = 0;
14075
+ const type_schemed = [];
14076
+ const type_fuzzy_link = [];
14077
+ const type_fuzzy_email = [];
14078
+ let m, len, re;
14079
+
14080
+ function choose (a, b) {
14081
+ if (!a) { return b }
14082
+ if (!b) { return a }
14083
+ if (a.index !== b.index) { return a.index < b.index ? a : b }
14084
+ return a.lastIndex >= b.lastIndex ? a : b
14085
+ }
14086
+
14087
+ if (!text.length) { return null }
14088
+
14089
+ // scan for links with schema
14090
+ if (this.re.schema_test.test(text)) {
14091
+ re = this.re.schema_search;
14092
+ re.lastIndex = 0;
14093
+ while ((m = re.exec(text)) !== null) {
14094
+ len = this.testSchemaAt(text, m[2], re.lastIndex);
14095
+ if (len) {
14096
+ type_schemed.push({
14097
+ schema: m[2],
14098
+ index: m.index + m[1].length,
14099
+ lastIndex: m.index + m[0].length + len
14100
+ });
14101
+ }
14102
+ }
14103
+ }
14104
+
14105
+ if (this.__opts__.fuzzyLink && this.__compiled__['http:']) {
14106
+ re = this.__opts__.fuzzyIP ? this.re.link_fuzzy_global : this.re.link_no_ip_fuzzy_global;
14107
+ re.lastIndex = 0;
14108
+ while ((m = re.exec(text)) !== null) {
14109
+ type_fuzzy_link.push({
14110
+ schema: '',
14111
+ index: m.index + m[1].length,
14112
+ lastIndex: m.index + m[0].length
14113
+ });
14114
+ }
14115
+ }
14032
14116
 
14033
- // Try to take previous element from cache, if .test() called before
14034
- if (this.__index__ >= 0 && this.__text_cache__ === text) {
14035
- result.push(createMatch(this, shift));
14036
- shift = this.__last_index__;
14117
+ if (this.__opts__.fuzzyEmail && this.__compiled__['mailto:']) {
14118
+ re = this.re.email_fuzzy_global;
14119
+ re.lastIndex = 0;
14120
+ while ((m = re.exec(text)) !== null) {
14121
+ type_fuzzy_email.push({
14122
+ schema: 'mailto:',
14123
+ index: m.index + m[1].length,
14124
+ lastIndex: m.index + m[0].length
14125
+ });
14126
+ }
14037
14127
  }
14038
14128
 
14039
- // Cut head if cache was used
14040
- let tail = shift ? text.slice(shift) : text;
14129
+ const indexes = [0, 0, 0];
14130
+ let lastIndex = 0;
14131
+
14132
+ for (;;) {
14133
+ const candidates = [
14134
+ type_schemed[indexes[0]],
14135
+ type_fuzzy_email[indexes[1]],
14136
+ type_fuzzy_link[indexes[2]]
14137
+ ];
14138
+
14139
+ const candidate = choose(choose(candidates[0], candidates[1]), candidates[2]);
14041
14140
 
14042
- // Scan string until end reached
14043
- while (this.test(tail)) {
14044
- result.push(createMatch(this, shift));
14141
+ if (!candidate) { break }
14045
14142
 
14046
- tail = tail.slice(this.__last_index__);
14047
- shift += this.__last_index__;
14143
+ if (candidate === candidates[0]) {
14144
+ indexes[0]++;
14145
+ } else if (candidate === candidates[1]) {
14146
+ indexes[1]++;
14147
+ } else {
14148
+ indexes[2]++;
14149
+ }
14150
+
14151
+ if (candidate.index < lastIndex) { continue }
14152
+
14153
+ const match = new Match(text, candidate.schema, candidate.index, candidate.lastIndex);
14154
+ this.__compiled__[match.schema].normalize(match, this);
14155
+ result.push(match);
14156
+ lastIndex = candidate.lastIndex;
14048
14157
  }
14049
14158
 
14050
14159
  if (result.length) {
@@ -14061,10 +14170,6 @@ var GovcyFrontendRendererBrowser = (function () {
14061
14170
  * of the string, and null otherwise.
14062
14171
  **/
14063
14172
  LinkifyIt.prototype.matchAtStart = function matchAtStart (text) {
14064
- // Reset scan cache
14065
- this.__text_cache__ = text;
14066
- this.__index__ = -1;
14067
-
14068
14173
  if (!text.length) return null
14069
14174
 
14070
14175
  const m = this.re.schema_at_start.exec(text);
@@ -14073,11 +14178,10 @@ var GovcyFrontendRendererBrowser = (function () {
14073
14178
  const len = this.testSchemaAt(text, m[2], m[0].length);
14074
14179
  if (!len) return null
14075
14180
 
14076
- this.__schema__ = m[2];
14077
- this.__index__ = m.index + m[1].length;
14078
- this.__last_index__ = m.index + m[0].length + len;
14181
+ const match = new Match(text, m[2], m.index + m[1].length, m.index + m[0].length + len);
14079
14182
 
14080
- return createMatch(this, 0)
14183
+ this.__compiled__[match.schema].normalize(match, this);
14184
+ return match
14081
14185
  };
14082
14186
 
14083
14187
  /** chainable
@@ -15129,7 +15233,7 @@ var GovcyFrontendRendererBrowser = (function () {
15129
15233
  * ```javascript
15130
15234
  * var md = require('markdown-it')()
15131
15235
  * .set({ html: true, breaks: true })
15132
- * .set({ typographer, true });
15236
+ * .set({ typographer: true });
15133
15237
  * ```
15134
15238
  *
15135
15239
  * __Note:__ To achieve the best possible performance, don't modify a