Skip to content

Commit 2310b50

Browse files
authored
prefer-string-replace-all: Preserve escape (#2667)
1 parent f51aeb9 commit 2310b50

File tree

5 files changed

+169
-49
lines changed

5 files changed

+169
-49
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ jobs:
5454
env:
5555
AVA_FORCE_CI: not-ci
5656
- run: git diff --exit-code
57-
- uses: codecov/codecov-action@v4
57+
- uses: codecov/codecov-action@v5
5858
with:
5959
fail_ci_if_error: true
6060
disable_search: true

rules/prefer-string-replace-all.js

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import {getStaticValue} from '@eslint-community/eslint-utils';
22
import regjsparser from 'regjsparser';
3-
import escapeString from './utils/escape-string.js';
43
import {isRegexLiteral, isNewExpression, isMethodCall} from './ast/index.js';
54

65
const {parse: parseRegExp} = regjsparser;
@@ -11,6 +10,8 @@ const messages = {
1110
[MESSAGE_ID_USE_STRING]: 'This pattern can be replaced with {{replacement}}.',
1211
};
1312

13+
const QUOTE = '\'';
14+
1415
function getPatternReplacement(node) {
1516
if (!isRegexLiteral(node)) {
1617
return;
@@ -39,10 +40,38 @@ function getPatternReplacement(node) {
3940
return;
4041
}
4142

42-
// TODO: Preserve escape
43-
const string = String.fromCodePoint(...parts.map(part => part.codePoint));
43+
return QUOTE
44+
+ parts.map(part => {
45+
const {kind, codePoint, raw} = part;
46+
47+
if (kind === 'controlLetter') {
48+
if (codePoint === 13) {
49+
return String.raw`\r`;
50+
}
51+
52+
if (codePoint === 10) {
53+
return String.raw`\n`;
54+
}
55+
56+
if (codePoint === 9) {
57+
return String.raw`\t`;
58+
}
59+
60+
return `\\u{${codePoint.toString(16)}}`;
61+
}
62+
63+
let character = raw;
64+
if (kind === 'identifier') {
65+
character = character.slice(1);
66+
}
67+
68+
if (character === QUOTE || character === '\\') {
69+
return `\\${character}`;
70+
}
4471

45-
return escapeString(string);
72+
return character;
73+
}).join('')
74+
+ QUOTE;
4675
}
4776

4877
const isRegExpWithGlobalFlag = (node, scope) => {

test/prefer-string-replace-all.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ test.snapshot({
7878
String.raw`foo.replace(/\u{61}/g, bar)`,
7979
String.raw`foo.replace(/\u{61}/gu, bar)`,
8080
String.raw`foo.replace(/\u{61}/gv, bar)`,
81+
String.raw`str.replace(/\u200B/g, '')`,
82+
String.raw`str.replace(/\x20/g, '')`,
8183
'foo.replace(/]/g, "bar")',
8284
// Extra flag
8385
'foo.replace(/a/gi, bar)',
@@ -94,7 +96,12 @@ test.snapshot({
9496
'foo.replace(/a{1}/g, _)',
9597
String.raw`foo.replace(/\u0022/g, _)`,
9698
String.raw`foo.replace(/\u0027/g, _)`,
97-
String.raw`foo.replace(/\cM\cj/g, _)`,
99+
100+
// `\r\n\t`
101+
String.raw`foo.replace(/\cM\cj\cI/g, _)`,
102+
String.raw`foo.replace(/\x0d\x0a\x09/g, _)`,
103+
String.raw`foo.replace(/\u000d\u000a\u0009/g, _)`,
104+
98105
String.raw`foo.replace(/\x22/g, _)`,
99106
String.raw`foo.replace(/\x27/g, _)`,
100107
String.raw`foo.replace(/\uD83D\ude00/g, _)`,

0 commit comments

Comments
 (0)