From f7458e606cd7f92787b67f69c26f9e92e63ec0d0 Mon Sep 17 00:00:00 2001 From: Henry Lin Date: Sun, 20 Aug 2023 11:14:13 +0800 Subject: [PATCH] Fix dash escape at the end of the entire char class --- src/helper.ts | 38 +++++++++++++++++++++++++ src/modifiers/CharacterClassModifier.ts | 35 ++++++----------------- 2 files changed, 46 insertions(+), 27 deletions(-) diff --git a/src/helper.ts b/src/helper.ts index e996600..c84aad3 100644 --- a/src/helper.ts +++ b/src/helper.ts @@ -176,3 +176,41 @@ export function wrapIfNeeded(regExp: string): string { } return `(?:${regExp})`; } + +export function escapeForCharClass(option: string): string { + if (option.startsWith('-')) { + option = '\\-' + option.substring(1); + } + let charEscaped = false; + for (let i = 0; i < option.length; i++) { + const char = option[i]; + if (charEscaped) { + charEscaped = false; + } else if (char === '\\' || char === '-') { + if (i === option.length - 1) { + // escape characters at the end of the string + option = option.slice(0, -1) + '\\' + char; + break; + } else { + charEscaped = true; + } + } else if (char === ']' || char === '^') { + // escape this character + option = option.substring(0, i) + '\\' + option.substring(i); + charEscaped = true; + } + } + return option; +} + +export function countTail(str: string, char: string): number { + let count = 0; + for (let i = str.length - 1; i >= 0; i--) { + if (str[i] === char) { + count++; + } else { + break; + } + } + return count; +} diff --git a/src/modifiers/CharacterClassModifier.ts b/src/modifiers/CharacterClassModifier.ts index 5eb8a8e..5a83dbb 100644 --- a/src/modifiers/CharacterClassModifier.ts +++ b/src/modifiers/CharacterClassModifier.ts @@ -1,30 +1,5 @@ import { RegExpModifier } from '../types'; - -function escapeForCharClass(option: string): string { - if (option.startsWith('-')) { - option = '\\-' + option.substring(1); - } - let charEscaped = false; - for (let i = 0; i < option.length; i++) { - const char = option[i]; - if (charEscaped) { - charEscaped = false; - } else if (char === '\\' || char === '-') { - if (i === option.length - 1) { - // escape backslash at the end of the string - option = option.substring(0, option.length - 1) + '\\' + char; - break; - } else { - charEscaped = true; - } - } else if (char === ']' || char === '^') { - // escape this character - option = option.substring(0, i) + '\\' + option.substring(i); - charEscaped = true; - } - } - return option; -} +import { countTail, escapeForCharClass } from '../helper'; export default class CharacterClassModifier implements RegExpModifier { private readonly options: string[] = []; @@ -47,7 +22,13 @@ export default class CharacterClassModifier implements RegExpModifier { combined = '-' + combined.substring(2); } if (combined.endsWith('\\-')) { - combined = combined.substring(0, combined.length - 2) + '-'; + const before = countTail(combined.slice(0, -2), '\\'); + if (before % 2 === 0) { + combined = combined.slice(0, -2) + '-'; + } + } + if (countTail(combined, '\\') % 2 === 1) { + combined += '\\'; } return [`[${this.negative ? '^' : ''}${combined}]`, regExp]; }