@adguard/agtree 2.1.1 → 2.1.3

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/agtree.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /*
2
- * AGTree v2.1.1 (build date: Thu, 19 Sep 2024 13:27:19 GMT)
2
+ * AGTree v2.1.3 (build date: Mon, 21 Oct 2024 08:22:25 GMT)
3
3
  * (c) 2024 Adguard Software Ltd.
4
4
  * Released under the MIT license
5
5
  * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme
@@ -3415,9 +3415,12 @@ declare const SPECIAL_REGEX_SYMBOLS: Set<string>;
3415
3415
  */
3416
3416
  declare class RegExpUtils {
3417
3417
  /**
3418
- * Checks whether a string is a RegExp pattern.
3418
+ * Checks whether a string possibly is a RegExp pattern.
3419
3419
  * Flags are not supported.
3420
3420
  *
3421
+ * Note: it does not perform a full validation of the pattern,
3422
+ * it just checks if the string starts and ends with a slash.
3423
+ *
3421
3424
  * @param pattern - Pattern to check
3422
3425
  * @returns `true` if the string is a RegExp pattern, `false` otherwise
3423
3426
  */
package/dist/agtree.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*
2
- * AGTree v2.1.1 (build date: Thu, 19 Sep 2024 13:27:19 GMT)
2
+ * AGTree v2.1.3 (build date: Mon, 21 Oct 2024 08:22:25 GMT)
3
3
  * (c) 2024 Adguard Software Ltd.
4
4
  * Released under the MIT license
5
5
  * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme
@@ -343,10 +343,11 @@ class StringUtils {
343
343
  * @param searchedCharacter - Searched character
344
344
  * @param start - Start index
345
345
  * @param escapeCharacter - Escape character, \ by default
346
+ * @param end - End index (excluded)
346
347
  * @returns Index or -1 if the character not found
347
348
  */
348
- static findNextUnescapedCharacter(pattern, searchedCharacter, start = 0, escapeCharacter = ESCAPE_CHARACTER) {
349
- for (let i = start; i < pattern.length; i += 1) {
349
+ static findNextUnescapedCharacter(pattern, searchedCharacter, start = 0, escapeCharacter = ESCAPE_CHARACTER, end = pattern.length) {
350
+ for (let i = start; i < end; i += 1) {
350
351
  // The searched character cannot be preceded by an escape
351
352
  if (pattern[i] === searchedCharacter && pattern[i - 1] !== escapeCharacter) {
352
353
  return i;
@@ -361,10 +362,11 @@ class StringUtils {
361
362
  * @param searchedCharacter - Searched character
362
363
  * @param start - Start index
363
364
  * @param escapeCharacter - Escape character, \ by default
365
+ * @param end - End index (Included)
364
366
  * @returns Index or -1 if the character not found
365
367
  */
366
- static findNextUnescapedCharacterBackwards(pattern, searchedCharacter, start = pattern.length - 1, escapeCharacter = ESCAPE_CHARACTER) {
367
- for (let i = start; i >= 0; i -= 1) {
368
+ static findNextUnescapedCharacterBackwards(pattern, searchedCharacter, start = pattern.length - 1, escapeCharacter = ESCAPE_CHARACTER, end = 0) {
369
+ for (let i = start; i >= end; i -= 1) {
368
370
  // The searched character cannot be preceded by an escape
369
371
  if (pattern[i] === searchedCharacter && pattern[i - 1] !== escapeCharacter) {
370
372
  return i;
@@ -7052,9 +7054,6 @@ class UboParameterListParser extends ParameterListParser {
7052
7054
  // Next non-whitespace character after the closing quote should be the separator
7053
7055
  const nextSeparatorIndex = StringUtils.skipWS(raw, possibleClosingQuoteIndex + 1);
7054
7056
  if (nextSeparatorIndex === length) {
7055
- if (requireQuotes) {
7056
- throw new AdblockSyntaxError('Expected separator, got end of string', baseOffset + nextSeparatorIndex, baseOffset + length);
7057
- }
7058
7057
  // If the separator is not found, the param end is the end of the string
7059
7058
  paramEnd = StringUtils.skipWSBack(raw, length - 1) + 1;
7060
7059
  offset = length;
@@ -7068,9 +7067,41 @@ class UboParameterListParser extends ParameterListParser {
7068
7067
  if (requireQuotes) {
7069
7068
  throw new AdblockSyntaxError(`Expected separator, got: '${raw[nextSeparatorIndex]}'`, baseOffset + nextSeparatorIndex, baseOffset + length);
7070
7069
  }
7071
- // Param end should be the last separator before the quote
7072
- offset = StringUtils.findNextUnescapedCharacterBackwards(raw, separator, possibleClosingQuoteIndex) + 1;
7073
- paramEnd = StringUtils.skipWSBack(raw, offset - 2) + 1;
7070
+ /**
7071
+ * At that point found `possibleClosingQuoteIndex` is wrong
7072
+ * | is `offset`
7073
+ * ~ is `possibleClosingQuoteIndex`
7074
+ * ^ is `nextSeparatorIndex`
7075
+ *
7076
+ * Example 1: "abc, ').cba='1'"
7077
+ * | ~^
7078
+ * Example 2: "abc, ').cba, '1'"
7079
+ * | ~^
7080
+ * Example 3: "abc, ').cba='1', cba"
7081
+ * | ~^
7082
+ *
7083
+ * Search for separator before `possibleClosingQuoteIndex`
7084
+ */
7085
+ const separatorIndexBeforeQuote = StringUtils.findNextUnescapedCharacterBackwards(raw, separator, possibleClosingQuoteIndex, ESCAPE_CHARACTER, offset + 1);
7086
+ if (separatorIndexBeforeQuote !== -1) {
7087
+ // Found separator before (Example 2)
7088
+ paramEnd = StringUtils.skipWSBack(raw, separatorIndexBeforeQuote - 1) + 1;
7089
+ offset = separatorIndexBeforeQuote + 1;
7090
+ }
7091
+ else {
7092
+ // Didn't found separator before, search after
7093
+ const separatorIndexAfterQuote = StringUtils.findNextUnescapedCharacter(raw, separator, possibleClosingQuoteIndex);
7094
+ if (separatorIndexAfterQuote !== -1) {
7095
+ // We found separator after (Example 3)
7096
+ paramEnd = StringUtils.skipWSBack(raw, separatorIndexAfterQuote - 1) + 1;
7097
+ offset = separatorIndexAfterQuote + 1;
7098
+ }
7099
+ else {
7100
+ // If the separator is not found, the param end is the end of the string (Example 1)
7101
+ paramEnd = StringUtils.skipWSBack(raw, length - 1) + 1;
7102
+ offset = length;
7103
+ }
7104
+ }
7074
7105
  }
7075
7106
  }
7076
7107
  else {
@@ -11566,20 +11597,22 @@ const SPECIAL_REGEX_SYMBOLS = new Set([
11566
11597
  */
11567
11598
  class RegExpUtils {
11568
11599
  /**
11569
- * Checks whether a string is a RegExp pattern.
11600
+ * Checks whether a string possibly is a RegExp pattern.
11570
11601
  * Flags are not supported.
11571
11602
  *
11603
+ * Note: it does not perform a full validation of the pattern,
11604
+ * it just checks if the string starts and ends with a slash.
11605
+ *
11572
11606
  * @param pattern - Pattern to check
11573
11607
  * @returns `true` if the string is a RegExp pattern, `false` otherwise
11574
11608
  */
11575
11609
  static isRegexPattern(pattern) {
11576
11610
  const trimmedPattern = pattern.trim();
11577
11611
  // Avoid false positives
11578
- if (trimmedPattern.length > REGEX_MARKER.length * 2 && trimmedPattern.startsWith(REGEX_MARKER)) {
11579
- const last = StringUtils.findNextUnescapedCharacter(trimmedPattern, REGEX_MARKER, REGEX_MARKER.length);
11580
- return last === trimmedPattern.length - 1;
11581
- }
11582
- return false;
11612
+ return trimmedPattern.length > REGEX_MARKER.length * 2
11613
+ && trimmedPattern.startsWith(REGEX_MARKER)
11614
+ && trimmedPattern.endsWith(REGEX_MARKER)
11615
+ && trimmedPattern[REGEX_MARKER.length - 2] !== ESCAPE_CHARACTER;
11583
11616
  }
11584
11617
  /**
11585
11618
  * Negates a RegExp pattern. Technically, this method wraps the pattern in `^((?!` and `).)*$`.
@@ -15615,7 +15648,7 @@ class RuleCategorizer {
15615
15648
  }
15616
15649
  }
15617
15650
 
15618
- const version = "2.1.1";
15651
+ const version = "2.1.3";
15619
15652
 
15620
15653
  /**
15621
15654
  * @file AGTree version
package/dist/agtree.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /*
2
- * AGTree v2.1.1 (build date: Thu, 19 Sep 2024 13:27:19 GMT)
2
+ * AGTree v2.1.3 (build date: Mon, 21 Oct 2024 08:22:25 GMT)
3
3
  * (c) 2024 Adguard Software Ltd.
4
4
  * Released under the MIT license
5
5
  * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme
@@ -323,10 +323,11 @@ class StringUtils {
323
323
  * @param searchedCharacter - Searched character
324
324
  * @param start - Start index
325
325
  * @param escapeCharacter - Escape character, \ by default
326
+ * @param end - End index (excluded)
326
327
  * @returns Index or -1 if the character not found
327
328
  */
328
- static findNextUnescapedCharacter(pattern, searchedCharacter, start = 0, escapeCharacter = ESCAPE_CHARACTER) {
329
- for (let i = start; i < pattern.length; i += 1) {
329
+ static findNextUnescapedCharacter(pattern, searchedCharacter, start = 0, escapeCharacter = ESCAPE_CHARACTER, end = pattern.length) {
330
+ for (let i = start; i < end; i += 1) {
330
331
  // The searched character cannot be preceded by an escape
331
332
  if (pattern[i] === searchedCharacter && pattern[i - 1] !== escapeCharacter) {
332
333
  return i;
@@ -341,10 +342,11 @@ class StringUtils {
341
342
  * @param searchedCharacter - Searched character
342
343
  * @param start - Start index
343
344
  * @param escapeCharacter - Escape character, \ by default
345
+ * @param end - End index (Included)
344
346
  * @returns Index or -1 if the character not found
345
347
  */
346
- static findNextUnescapedCharacterBackwards(pattern, searchedCharacter, start = pattern.length - 1, escapeCharacter = ESCAPE_CHARACTER) {
347
- for (let i = start; i >= 0; i -= 1) {
348
+ static findNextUnescapedCharacterBackwards(pattern, searchedCharacter, start = pattern.length - 1, escapeCharacter = ESCAPE_CHARACTER, end = 0) {
349
+ for (let i = start; i >= end; i -= 1) {
348
350
  // The searched character cannot be preceded by an escape
349
351
  if (pattern[i] === searchedCharacter && pattern[i - 1] !== escapeCharacter) {
350
352
  return i;
@@ -7032,9 +7034,6 @@ class UboParameterListParser extends ParameterListParser {
7032
7034
  // Next non-whitespace character after the closing quote should be the separator
7033
7035
  const nextSeparatorIndex = StringUtils.skipWS(raw, possibleClosingQuoteIndex + 1);
7034
7036
  if (nextSeparatorIndex === length) {
7035
- if (requireQuotes) {
7036
- throw new AdblockSyntaxError('Expected separator, got end of string', baseOffset + nextSeparatorIndex, baseOffset + length);
7037
- }
7038
7037
  // If the separator is not found, the param end is the end of the string
7039
7038
  paramEnd = StringUtils.skipWSBack(raw, length - 1) + 1;
7040
7039
  offset = length;
@@ -7048,9 +7047,41 @@ class UboParameterListParser extends ParameterListParser {
7048
7047
  if (requireQuotes) {
7049
7048
  throw new AdblockSyntaxError(`Expected separator, got: '${raw[nextSeparatorIndex]}'`, baseOffset + nextSeparatorIndex, baseOffset + length);
7050
7049
  }
7051
- // Param end should be the last separator before the quote
7052
- offset = StringUtils.findNextUnescapedCharacterBackwards(raw, separator, possibleClosingQuoteIndex) + 1;
7053
- paramEnd = StringUtils.skipWSBack(raw, offset - 2) + 1;
7050
+ /**
7051
+ * At that point found `possibleClosingQuoteIndex` is wrong
7052
+ * | is `offset`
7053
+ * ~ is `possibleClosingQuoteIndex`
7054
+ * ^ is `nextSeparatorIndex`
7055
+ *
7056
+ * Example 1: "abc, ').cba='1'"
7057
+ * | ~^
7058
+ * Example 2: "abc, ').cba, '1'"
7059
+ * | ~^
7060
+ * Example 3: "abc, ').cba='1', cba"
7061
+ * | ~^
7062
+ *
7063
+ * Search for separator before `possibleClosingQuoteIndex`
7064
+ */
7065
+ const separatorIndexBeforeQuote = StringUtils.findNextUnescapedCharacterBackwards(raw, separator, possibleClosingQuoteIndex, ESCAPE_CHARACTER, offset + 1);
7066
+ if (separatorIndexBeforeQuote !== -1) {
7067
+ // Found separator before (Example 2)
7068
+ paramEnd = StringUtils.skipWSBack(raw, separatorIndexBeforeQuote - 1) + 1;
7069
+ offset = separatorIndexBeforeQuote + 1;
7070
+ }
7071
+ else {
7072
+ // Didn't found separator before, search after
7073
+ const separatorIndexAfterQuote = StringUtils.findNextUnescapedCharacter(raw, separator, possibleClosingQuoteIndex);
7074
+ if (separatorIndexAfterQuote !== -1) {
7075
+ // We found separator after (Example 3)
7076
+ paramEnd = StringUtils.skipWSBack(raw, separatorIndexAfterQuote - 1) + 1;
7077
+ offset = separatorIndexAfterQuote + 1;
7078
+ }
7079
+ else {
7080
+ // If the separator is not found, the param end is the end of the string (Example 1)
7081
+ paramEnd = StringUtils.skipWSBack(raw, length - 1) + 1;
7082
+ offset = length;
7083
+ }
7084
+ }
7054
7085
  }
7055
7086
  }
7056
7087
  else {
@@ -11546,20 +11577,22 @@ const SPECIAL_REGEX_SYMBOLS = new Set([
11546
11577
  */
11547
11578
  class RegExpUtils {
11548
11579
  /**
11549
- * Checks whether a string is a RegExp pattern.
11580
+ * Checks whether a string possibly is a RegExp pattern.
11550
11581
  * Flags are not supported.
11551
11582
  *
11583
+ * Note: it does not perform a full validation of the pattern,
11584
+ * it just checks if the string starts and ends with a slash.
11585
+ *
11552
11586
  * @param pattern - Pattern to check
11553
11587
  * @returns `true` if the string is a RegExp pattern, `false` otherwise
11554
11588
  */
11555
11589
  static isRegexPattern(pattern) {
11556
11590
  const trimmedPattern = pattern.trim();
11557
11591
  // Avoid false positives
11558
- if (trimmedPattern.length > REGEX_MARKER.length * 2 && trimmedPattern.startsWith(REGEX_MARKER)) {
11559
- const last = StringUtils.findNextUnescapedCharacter(trimmedPattern, REGEX_MARKER, REGEX_MARKER.length);
11560
- return last === trimmedPattern.length - 1;
11561
- }
11562
- return false;
11592
+ return trimmedPattern.length > REGEX_MARKER.length * 2
11593
+ && trimmedPattern.startsWith(REGEX_MARKER)
11594
+ && trimmedPattern.endsWith(REGEX_MARKER)
11595
+ && trimmedPattern[REGEX_MARKER.length - 2] !== ESCAPE_CHARACTER;
11563
11596
  }
11564
11597
  /**
11565
11598
  * Negates a RegExp pattern. Technically, this method wraps the pattern in `^((?!` and `).)*$`.
@@ -15595,7 +15628,7 @@ class RuleCategorizer {
15595
15628
  }
15596
15629
  }
15597
15630
 
15598
- const version = "2.1.1";
15631
+ const version = "2.1.3";
15599
15632
 
15600
15633
  /**
15601
15634
  * @file AGTree version
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adguard/agtree",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "description": "Tool set for working with adblock filter lists",
5
5
  "keywords": [
6
6
  "adblock",