Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[New] Add suggestions to no-unescaped-entities #3831

Merged
merged 1 commit into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange

### Added
* add type generation ([#3830][] @voxpelli)
* [`no-unescaped-entities`]: add suggestions ([#3831][] @StyleShit)

[#3831]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3831
[#3830]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3830

## [7.36.1] - 2024.09.12
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ module.exports = [
| [no-string-refs](docs/rules/no-string-refs.md) | Disallow using string references | ☑️ | | | | |
| [no-this-in-sfc](docs/rules/no-this-in-sfc.md) | Disallow `this` from being used in stateless functional components | | | | | |
| [no-typos](docs/rules/no-typos.md) | Disallow common typos | | | | | |
| [no-unescaped-entities](docs/rules/no-unescaped-entities.md) | Disallow unescaped HTML entities from appearing in markup | ☑️ | | | | |
| [no-unescaped-entities](docs/rules/no-unescaped-entities.md) | Disallow unescaped HTML entities from appearing in markup | ☑️ | | | 💡 | |
| [no-unknown-property](docs/rules/no-unknown-property.md) | Disallow usage of unknown DOM property | ☑️ | | 🔧 | | |
| [no-unsafe](docs/rules/no-unsafe.md) | Disallow usage of unsafe lifecycle methods | | ☑️ | | | |
| [no-unstable-nested-components](docs/rules/no-unstable-nested-components.md) | Disallow creating unstable components inside components | | | | | |
Expand Down
2 changes: 2 additions & 0 deletions docs/rules/no-unescaped-entities.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

💼 This rule is enabled in the ☑️ `recommended` [config](https://github.com/jsx-eslint/eslint-plugin-react/#shareable-configs).

💡 This rule is manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions).

<!-- end auto-generated rule header -->

This rule prevents characters that you may have meant as JSX escape characters
Expand Down
22 changes: 22 additions & 0 deletions lib/rules/no-unescaped-entities.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const docsUrl = require('../util/docsUrl');
const getSourceCode = require('../util/eslint').getSourceCode;
const jsxUtil = require('../util/jsx');
const report = require('../util/report');
const getMessageData = require('../util/message');

// ------------------------------------------------------------------------------
// Rule Definition
Expand All @@ -34,11 +35,13 @@ const DEFAULTS = [{
const messages = {
unescapedEntity: 'HTML entity, `{{entity}}` , must be escaped.',
unescapedEntityAlts: '`{{entity}}` can be escaped with {{alts}}.',
replaceWithAlt: 'Replace with `{{alt}}`.',
};

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
meta: {
hasSuggestions: true,
docs: {
description: 'Disallow unescaped HTML entities from appearing in markup',
category: 'Possible Errors',
Expand Down Expand Up @@ -117,6 +120,25 @@ module.exports = {
entity: entities[j].char,
alts: entities[j].alternatives.map((alt) => `\`${alt}\``).join(', '),
},
suggest: entities[j].alternatives.map((alt) => Object.assign(
getMessageData('replaceWithAlt', messages.replaceWithAlt),
{
data: { alt },
fix(fixer) {
const lineToChange = i - node.loc.start.line;

const newText = node.raw.split('\n').map((line, idx) => {
if (idx === lineToChange) {
return line.slice(0, index) + alt + line.slice(index + 1);
}

return line;
}).join('\n');

return fixer.replaceText(node, newText);
},
}
)),
});
}
}
Expand Down
Loading