diff --git a/docs/rules/text-encoding-identifier-case.md b/docs/rules/text-encoding-identifier-case.md index aa59c2f1df..fc1d00ea64 100644 --- a/docs/rules/text-encoding-identifier-case.md +++ b/docs/rules/text-encoding-identifier-case.md @@ -4,12 +4,14 @@ ✅ *This rule is part of the [recommended](https://github.com/sindresorhus/eslint-plugin-unicorn#recommended-config) config.* -💡 *This rule provides [suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions).* +🔧💡 *This rule is [auto-fixable](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) and provides [suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions).* - Enforce `'utf8'` for [UTF-8](https://en.wikipedia.org/wiki/UTF-8) encoding. - Enforce `'ascii'` for [ASCII](https://en.wikipedia.org/wiki/ASCII) encoding. +This rule only auto-fix encoding in `fs.readFile()` and `fs.readFileSync()`. + ## Fail ```js diff --git a/readme.md b/readme.md index 939012d484..84c6be653f 100644 --- a/readme.md +++ b/readme.md @@ -150,7 +150,7 @@ Each rule has emojis denoting: | [require-post-message-target-origin](docs/rules/require-post-message-target-origin.md) | Enforce using the `targetOrigin` argument with `window.postMessage()`. | | | 💡 | | [string-content](docs/rules/string-content.md) | Enforce better string content. | | 🔧 | 💡 | | [template-indent](docs/rules/template-indent.md) | Fix whitespace-insensitive template indentation. | ✅ | 🔧 | | -| [text-encoding-identifier-case](docs/rules/text-encoding-identifier-case.md) | Enforce consistent case for text encoding identifiers. | ✅ | | 💡 | +| [text-encoding-identifier-case](docs/rules/text-encoding-identifier-case.md) | Enforce consistent case for text encoding identifiers. | ✅ | 🔧 | 💡 | | [throw-new-error](docs/rules/throw-new-error.md) | Require `new` when throwing an error. | ✅ | 🔧 | | diff --git a/rules/text-encoding-identifier-case.js b/rules/text-encoding-identifier-case.js index b5dc9d67e0..23a76531f2 100644 --- a/rules/text-encoding-identifier-case.js +++ b/rules/text-encoding-identifier-case.js @@ -19,6 +19,19 @@ const getReplacement = encoding => { } }; +// `fs.{readFile,readFileSync}()` +const isFsReadFileEncoding = node => + node.parent.type === 'CallExpression' + && !node.parent.optional + && node.parent.arguments[1] === node + && node.parent.arguments[0] + && node.parent.arguments[0].type !== 'SpreadElement' + && node.parent.callee.type === 'MemberExpression' + && !node.parent.callee.optional + && !node.parent.callee.computed + && node.parent.callee.property.type === 'Identifier' + && (node.parent.callee.property.name === 'readFile' || node.parent.callee.property.name === 'readFileSync'); + /** @param {import('eslint').Rule.RuleContext} context */ const create = () => ({ Literal(node) { @@ -39,19 +52,29 @@ const create = () => ({ replacement, }; - return { + /** @param {import('eslint').Rule.RuleFixer} fixer */ + const fix = fixer => replaceStringLiteral(fixer, node, replacement); + + const problem = { node, messageId: MESSAGE_ID_ERROR, data: messageData, - suggest: [ - { - messageId: MESSAGE_ID_SUGGESTION, - data: messageData, - /** @param {import('eslint').Rule.RuleFixer} fixer */ - fix: fixer => replaceStringLiteral(fixer, node, replacement), - }, - ], }; + + if (isFsReadFileEncoding(node)) { + problem.fix = fix; + return problem; + } + + problem.suggest = [ + { + messageId: MESSAGE_ID_SUGGESTION, + data: messageData, + fix: fixer => replaceStringLiteral(fixer, node, replacement), + }, + ]; + + return problem; }, }); @@ -63,6 +86,7 @@ module.exports = { docs: { description: 'Enforce consistent case for text encoding identifiers.', }, + fixable: 'code', hasSuggestions: true, messages, }, diff --git a/test/snapshots/text-encoding-identifier-case.mjs.md b/test/snapshots/text-encoding-identifier-case.mjs.md index 15980fd03d..de592321d8 100644 --- a/test/snapshots/text-encoding-identifier-case.mjs.md +++ b/test/snapshots/text-encoding-identifier-case.mjs.md @@ -75,15 +75,207 @@ Generated by [AVA](https://avajs.dev). ` ## Invalid #6 - 1 | await fs.readFile(file, "UTF-8",) + 1 | fs.readFile?.(file, "UTF-8") > Error 1/1 `␊ - > 1 | await fs.readFile(file, "UTF-8",)␊ - | ^^^^^^^ Prefer \`utf8\` over \`UTF-8\`.␊ + > 1 | fs.readFile?.(file, "UTF-8")␊ + | ^^^^^^^ Prefer \`utf8\` over \`UTF-8\`.␊ ␊ --------------------------------------------------------------------------------␊ Suggestion 1/1: Replace \`UTF-8\` with \`utf8\`.␊ + 1 | fs.readFile?.(file, "utf8")␊ + ` + +## Invalid #7 + 1 | fs?.readFile(file, "UTF-8") + +> Error 1/1 + + `␊ + > 1 | fs?.readFile(file, "UTF-8")␊ + | ^^^^^^^ Prefer \`utf8\` over \`UTF-8\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`UTF-8\` with \`utf8\`.␊ + 1 | fs?.readFile(file, "utf8")␊ + ` + +## Invalid #8 + 1 | readFile(file, "UTF-8") + +> Error 1/1 + + `␊ + > 1 | readFile(file, "UTF-8")␊ + | ^^^^^^^ Prefer \`utf8\` over \`UTF-8\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`UTF-8\` with \`utf8\`.␊ + 1 | readFile(file, "utf8")␊ + ` + +## Invalid #9 + 1 | fs.readFile(...file, "UTF-8") + +> Error 1/1 + + `␊ + > 1 | fs.readFile(...file, "UTF-8")␊ + | ^^^^^^^ Prefer \`utf8\` over \`UTF-8\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`UTF-8\` with \`utf8\`.␊ + 1 | fs.readFile(...file, "utf8")␊ + ` + +## Invalid #10 + 1 | new fs.readFile(file, "UTF-8") + +> Error 1/1 + + `␊ + > 1 | new fs.readFile(file, "UTF-8")␊ + | ^^^^^^^ Prefer \`utf8\` over \`UTF-8\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`UTF-8\` with \`utf8\`.␊ + 1 | new fs.readFile(file, "utf8")␊ + ` + +## Invalid #11 + 1 | fs.readFile(file, {encoding: "UTF-8"}) + +> Error 1/1 + + `␊ + > 1 | fs.readFile(file, {encoding: "UTF-8"})␊ + | ^^^^^^^ Prefer \`utf8\` over \`UTF-8\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`UTF-8\` with \`utf8\`.␊ + 1 | fs.readFile(file, {encoding: "utf8"})␊ + ` + +## Invalid #12 + 1 | fs.readFile("UTF-8") + +> Error 1/1 + + `␊ + > 1 | fs.readFile("UTF-8")␊ + | ^^^^^^^ Prefer \`utf8\` over \`UTF-8\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`UTF-8\` with \`utf8\`.␊ + 1 | fs.readFile("utf8")␊ + ` + +## Invalid #13 + 1 | fs.readFile(file, "UTF-8", () => {}) + +> Output + + `␊ + 1 | fs.readFile(file, "utf8", () => {})␊ + ` + +> Error 1/1 + + `␊ + > 1 | fs.readFile(file, "UTF-8", () => {})␊ + | ^^^^^^^ Prefer \`utf8\` over \`UTF-8\`.␊ + ` + +## Invalid #14 + 1 | fs.readFileSync(file, "UTF-8") + +> Output + + `␊ + 1 | fs.readFileSync(file, "utf8")␊ + ` + +> Error 1/1 + + `␊ + > 1 | fs.readFileSync(file, "UTF-8")␊ + | ^^^^^^^ Prefer \`utf8\` over \`UTF-8\`.␊ + ` + +## Invalid #15 + 1 | fs[readFile](file, "UTF-8") + +> Error 1/1 + + `␊ + > 1 | fs[readFile](file, "UTF-8")␊ + | ^^^^^^^ Prefer \`utf8\` over \`UTF-8\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`UTF-8\` with \`utf8\`.␊ + 1 | fs[readFile](file, "utf8")␊ + ` + +## Invalid #16 + 1 | fs["readFile"](file, "UTF-8") + +> Error 1/1 + + `␊ + > 1 | fs["readFile"](file, "UTF-8")␊ + | ^^^^^^^ Prefer \`utf8\` over \`UTF-8\`.␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace \`UTF-8\` with \`utf8\`.␊ + 1 | fs["readFile"](file, "utf8")␊ + ` + +## Invalid #17 + 1 | await fs.readFile(file, "UTF-8",) + +> Output + + `␊ 1 | await fs.readFile(file, "utf8",)␊ ` + +> Error 1/1 + + `␊ + > 1 | await fs.readFile(file, "UTF-8",)␊ + | ^^^^^^^ Prefer \`utf8\` over \`UTF-8\`.␊ + ` + +## Invalid #18 + 1 | fs.promises.readFile(file, "UTF-8",) + +> Output + + `␊ + 1 | fs.promises.readFile(file, "utf8",)␊ + ` + +> Error 1/1 + + `␊ + > 1 | fs.promises.readFile(file, "UTF-8",)␊ + | ^^^^^^^ Prefer \`utf8\` over \`UTF-8\`.␊ + ` + +## Invalid #19 + 1 | whatever.readFile(file, "UTF-8",) + +> Output + + `␊ + 1 | whatever.readFile(file, "utf8",)␊ + ` + +> Error 1/1 + + `␊ + > 1 | whatever.readFile(file, "UTF-8",)␊ + | ^^^^^^^ Prefer \`utf8\` over \`UTF-8\`.␊ + ` diff --git a/test/snapshots/text-encoding-identifier-case.mjs.snap b/test/snapshots/text-encoding-identifier-case.mjs.snap index 4dbb487666..a3d0ae8d8e 100644 Binary files a/test/snapshots/text-encoding-identifier-case.mjs.snap and b/test/snapshots/text-encoding-identifier-case.mjs.snap differ diff --git a/test/text-encoding-identifier-case.mjs b/test/text-encoding-identifier-case.mjs index 16102eaca9..155641af6e 100644 --- a/test/text-encoding-identifier-case.mjs +++ b/test/text-encoding-identifier-case.mjs @@ -19,6 +19,19 @@ test.snapshot({ '\'utf-8\'', '"Utf8"', '"ASCII"', + 'fs.readFile?.(file, "UTF-8")', + 'fs?.readFile(file, "UTF-8")', + 'readFile(file, "UTF-8")', + 'fs.readFile(...file, "UTF-8")', + 'new fs.readFile(file, "UTF-8")', + 'fs.readFile(file, {encoding: "UTF-8"})', + 'fs.readFile("UTF-8")', + 'fs.readFile(file, "UTF-8", () => {})', + 'fs.readFileSync(file, "UTF-8")', + 'fs[readFile](file, "UTF-8")', + 'fs["readFile"](file, "UTF-8")', 'await fs.readFile(file, "UTF-8",)', + 'fs.promises.readFile(file, "UTF-8",)', + 'whatever.readFile(file, "UTF-8",)', ], });