Skip to content

Commit 16bdfe1

Browse files
Add whatwgEncoding option to text-encoding-identifier-case
1 parent dbe2bb2 commit 16bdfe1

File tree

5 files changed

+287
-7
lines changed

5 files changed

+287
-7
lines changed

docs/rules/text-encoding-identifier-case.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,15 @@ await fs.readFile(file, 'ascii');
3939
```js
4040
const string = buffer.toString('utf8');
4141
```
42+
43+
## Options
44+
45+
### whatwgEncoding
46+
47+
Type: `boolean`\
48+
Default: `false`
49+
50+
- `false` (default)
51+
- Prefer `utf8` without a dash (Node.js style)
52+
- `true`
53+
- Prefer `utf-8` with a dash (WHATWG standard, required for HTML)

rules/text-encoding-identifier-case.js

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ const messages = {
77
[MESSAGE_ID_SUGGESTION]: 'Replace `{{value}}` with `{{replacement}}`.',
88
};
99

10-
const getReplacement = encoding => {
10+
const getReplacement = (encoding, whatwgEncoding) => {
1111
switch (encoding.toLowerCase()) {
1212
// eslint-disable-next-line unicorn/text-encoding-identifier-case
1313
case 'utf-8':
1414
case 'utf8': {
15-
return 'utf8';
15+
// eslint-disable-next-line unicorn/text-encoding-identifier-case
16+
return whatwgEncoding ? 'utf-8' : 'utf8';
1617
}
1718

1819
case 'ascii': {
@@ -35,8 +36,12 @@ const isFsReadFileEncoding = node =>
3536
&& (node.parent.callee.property.name === 'readFile' || node.parent.callee.property.name === 'readFileSync');
3637

3738
/** @param {import('eslint').Rule.RuleContext} context */
38-
const create = () => ({
39-
Literal(node) {
39+
const create = context => {
40+
const {
41+
whatwgEncoding,
42+
} = context.options[0];
43+
44+
context.on('Literal', node => {
4045
if (typeof node.value !== 'string') {
4146
return;
4247
}
@@ -59,7 +64,7 @@ const create = () => ({
5964
const {raw} = node;
6065
const value = raw.slice(1, -1);
6166

62-
const replacement = getReplacement(value);
67+
const replacement = getReplacement(value, whatwgEncoding);
6368
if (!replacement || replacement === value) {
6469
return;
6570
}
@@ -89,8 +94,20 @@ const create = () => ({
8994
];
9095

9196
return problem;
97+
});
98+
};
99+
100+
const schema = [
101+
{
102+
type: 'object',
103+
additionalProperties: false,
104+
properties: {
105+
whatwgEncoding: {
106+
type: 'boolean',
107+
},
108+
},
92109
},
93-
});
110+
];
94111

95112
/** @type {import('eslint').Rule.RuleModule} */
96113
const config = {
@@ -103,6 +120,10 @@ const config = {
103120
},
104121
fixable: 'code',
105122
hasSuggestions: true,
123+
schema,
124+
defaultOptions: [{
125+
whatwgEncoding: false,
126+
}],
106127
messages,
107128
},
108129
};

test/snapshots/text-encoding-identifier-case.js.md

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,232 @@ Generated by [AVA](https://avajs.dev).
375375
| ^^^^^^^ Prefer \`utf8\` over \`UTF-8\`.␊
376376
`
377377

378+
## invalid(1): "UTF-8" /* undefined */
379+
380+
> Input
381+
382+
`␊
383+
1 | "UTF-8"␊
384+
2 | /* undefined */␊
385+
`
386+
387+
> Options
388+
389+
`␊
390+
[␊
391+
{␊
392+
"whatwgEncoding": true␊
393+
}␊
394+
]␊
395+
`
396+
397+
> Error 1/1
398+
399+
`␊
400+
> 1 | "UTF-8"␊
401+
| ^^^^^^^ Prefer \`utf-8\` over \`UTF-8\`.␊
402+
2 | /* undefined */␊
403+
404+
--------------------------------------------------------------------------------␊
405+
Suggestion 1/1: Replace \`UTF-8\` with \`utf-8\`.␊
406+
1 | "utf-8"␊
407+
2 | /* undefined */␊
408+
`
409+
410+
## invalid(2): "UTF8" /* undefined */
411+
412+
> Input
413+
414+
`␊
415+
1 | "UTF8"␊
416+
2 | /* undefined */␊
417+
`
418+
419+
> Options
420+
421+
`␊
422+
[␊
423+
{␊
424+
"whatwgEncoding": true␊
425+
}␊
426+
]␊
427+
`
428+
429+
> Error 1/1
430+
431+
`␊
432+
> 1 | "UTF8"␊
433+
| ^^^^^^ Prefer \`utf-8\` over \`UTF8\`.␊
434+
2 | /* undefined */␊
435+
436+
--------------------------------------------------------------------------------␊
437+
Suggestion 1/1: Replace \`UTF8\` with \`utf-8\`.␊
438+
1 | "utf-8"␊
439+
2 | /* undefined */␊
440+
`
441+
442+
## invalid(3): "utf8" /* undefined */
443+
444+
> Input
445+
446+
`␊
447+
1 | "utf8"␊
448+
2 | /* undefined */␊
449+
`
450+
451+
> Options
452+
453+
`␊
454+
[␊
455+
{␊
456+
"whatwgEncoding": true␊
457+
}␊
458+
]␊
459+
`
460+
461+
> Error 1/1
462+
463+
`␊
464+
> 1 | "utf8"␊
465+
| ^^^^^^ Prefer \`utf-8\` over \`utf8\`.␊
466+
2 | /* undefined */␊
467+
468+
--------------------------------------------------------------------------------␊
469+
Suggestion 1/1: Replace \`utf8\` with \`utf-8\`.␊
470+
1 | "utf-8"␊
471+
2 | /* undefined */␊
472+
`
473+
474+
## invalid(4): 'utf8' /* undefined */
475+
476+
> Input
477+
478+
`␊
479+
1 | 'utf8'␊
480+
2 | /* undefined */␊
481+
`
482+
483+
> Options
484+
485+
`␊
486+
[␊
487+
{␊
488+
"whatwgEncoding": true␊
489+
}␊
490+
]␊
491+
`
492+
493+
> Error 1/1
494+
495+
`␊
496+
> 1 | 'utf8'␊
497+
| ^^^^^^ Prefer \`utf-8\` over \`utf8\`.␊
498+
2 | /* undefined */␊
499+
500+
--------------------------------------------------------------------------------␊
501+
Suggestion 1/1: Replace \`utf8\` with \`utf-8\`.␊
502+
1 | 'utf-8'␊
503+
2 | /* undefined */␊
504+
`
505+
506+
## invalid(5): "Utf8" /* undefined */
507+
508+
> Input
509+
510+
`␊
511+
1 | "Utf8"␊
512+
2 | /* undefined */␊
513+
`
514+
515+
> Options
516+
517+
`␊
518+
[␊
519+
{␊
520+
"whatwgEncoding": true␊
521+
}␊
522+
]␊
523+
`
524+
525+
> Error 1/1
526+
527+
`␊
528+
> 1 | "Utf8"␊
529+
| ^^^^^^ Prefer \`utf-8\` over \`Utf8\`.␊
530+
2 | /* undefined */␊
531+
532+
--------------------------------------------------------------------------------␊
533+
Suggestion 1/1: Replace \`Utf8\` with \`utf-8\`.␊
534+
1 | "utf-8"␊
535+
2 | /* undefined */␊
536+
`
537+
538+
## invalid(6): "ASCII" /* undefined */
539+
540+
> Input
541+
542+
`␊
543+
1 | "ASCII"␊
544+
2 | /* undefined */␊
545+
`
546+
547+
> Options
548+
549+
`␊
550+
[␊
551+
{␊
552+
"whatwgEncoding": true␊
553+
}␊
554+
]␊
555+
`
556+
557+
> Error 1/1
558+
559+
`␊
560+
> 1 | "ASCII"␊
561+
| ^^^^^^^ Prefer \`ascii\` over \`ASCII\`.␊
562+
2 | /* undefined */␊
563+
564+
--------------------------------------------------------------------------------␊
565+
Suggestion 1/1: Replace \`ASCII\` with \`ascii\`.␊
566+
1 | "ascii"␊
567+
2 | /* undefined */␊
568+
`
569+
570+
## invalid(7): whatever.readFile(file, "utf8",) /* undefined */
571+
572+
> Input
573+
574+
`␊
575+
1 | whatever.readFile(file, "utf8",)␊
576+
2 | /* undefined */␊
577+
`
578+
579+
> Options
580+
581+
`␊
582+
[␊
583+
{␊
584+
"whatwgEncoding": true␊
585+
}␊
586+
]␊
587+
`
588+
589+
> Output
590+
591+
`␊
592+
1 | whatever.readFile(file, "utf-8",)␊
593+
2 | /* undefined */␊
594+
`
595+
596+
> Error 1/1
597+
598+
`␊
599+
> 1 | whatever.readFile(file, "utf8",)␊
600+
| ^^^^^^ Prefer \`utf-8\` over \`utf8\`.␊
601+
2 | /* undefined */␊
602+
`
603+
378604
## invalid(1): <not-meta charset="utf-8" />
379605

380606
> Input
283 Bytes
Binary file not shown.

test/text-encoding-identifier-case.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {getTester} from './utils/test.js';
1+
import {getTester, avoidTestTitleConflict} from './utils/test.js';
22

33
const {test} = getTester(import.meta);
44

@@ -36,6 +36,27 @@ test.snapshot({
3636
],
3737
});
3838

39+
// 'whatwgEncoding'
40+
test.snapshot(avoidTestTitleConflict({
41+
valid: [
42+
'`UTF-8`',
43+
'"utf-8"',
44+
'" uTf8 "',
45+
'\'utf-8\'',
46+
'const utf8 = 1',
47+
].map(code => ({code, options: [{whatwgEncoding: true}]})),
48+
invalid: [
49+
'"UTF-8"',
50+
'"UTF8"',
51+
'"utf8"',
52+
'\'utf8\'',
53+
'"Utf8"',
54+
'"ASCII"',
55+
56+
'whatever.readFile(file, "utf8",)',
57+
].map(code => ({code, options: [{whatwgEncoding: true}]})),
58+
}));
59+
3960
// JSX
4061
test.snapshot({
4162
testerOptions: {

0 commit comments

Comments
 (0)