Skip to content

Commit

Permalink
prefer-dom-node-text-content: Check destructuring, Use suggestion i…
Browse files Browse the repository at this point in the history
…nstead of auto-fix (#1417)
  • Loading branch information
fisker committed Jul 13, 2021
1 parent 741484a commit c4bfc42
Show file tree
Hide file tree
Showing 6 changed files with 276 additions and 32 deletions.
21 changes: 19 additions & 2 deletions docs/rules/prefer-dom-node-text-content.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,35 @@
# Prefer `.textContent` over `.innerText`

Enforces the use of `.textContent` over `.innerText` for DOM nodes. There are [some advantages of using `.textContent`](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent), like performance and more predictable behavior when updating it.
Enforces the use of `.textContent` over `.innerText` for DOM nodes.

This rule is fixable.
There are [some advantages of using `.textContent`](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent), like performance and more predictable behavior when updating it.

Note that there are [differences](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent#differences_from_innertext) between them.

## Fail

```js
const text = foo.innerText;
```

```js
const {innerText} = foo;
```

```js
foo.innerText = '🦄';
```

## Pass

```js
const text = foo.textContent;
```

```js
const {textContent} = foo;
```

```js
foo.textContent = '🦄';
```
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ Each rule has emojis denoting:
| [prefer-dom-node-append](docs/rules/prefer-dom-node-append.md) | Prefer `Node#append()` over `Node#appendChild()`. || 🔧 | |
| [prefer-dom-node-dataset](docs/rules/prefer-dom-node-dataset.md) | Prefer using `.dataset` on DOM elements over `.setAttribute(…)`. || 🔧 | |
| [prefer-dom-node-remove](docs/rules/prefer-dom-node-remove.md) | Prefer `childNode.remove()` over `parentNode.removeChild(childNode)`. || 🔧 | 💡 |
| [prefer-dom-node-text-content](docs/rules/prefer-dom-node-text-content.md) | Prefer `.textContent` over `.innerText`. || 🔧 | |
| [prefer-dom-node-text-content](docs/rules/prefer-dom-node-text-content.md) | Prefer `.textContent` over `.innerText`. || | 💡 |
| [prefer-includes](docs/rules/prefer-includes.md) | Prefer `.includes()` over `.indexOf()` and `Array#some()` when checking for existence or non-existence. || 🔧 | 💡 |
| [prefer-keyboard-event-key](docs/rules/prefer-keyboard-event-key.md) | Prefer `KeyboardEvent#key` over `KeyboardEvent#keyCode`. || 🔧 | |
| [prefer-math-trunc](docs/rules/prefer-math-trunc.md) | Enforce the use of `Math.trunc` instead of bitwise operators. || 🔧 | 💡 |
Expand Down
46 changes: 39 additions & 7 deletions rules/prefer-dom-node-text-content.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,52 @@
'use strict';
const {memberExpressionSelector} = require('./selectors/index.js');

const MESSAGE_ID = 'prefer-dom-node-text-content';
const ERROR = 'error';
const SUGGESTION = 'suggestion';
const messages = {
[MESSAGE_ID]: 'Prefer `.textContent` over `.innerText`.',
[ERROR]: 'Prefer `.textContent` over `.innerText`.',
[SUGGESTION]: 'Switch to `.textContent`.',
};

const selector = `${memberExpressionSelector('innerText')} > .property`;
const memberExpressionPropertySelector = `${memberExpressionSelector('innerText')} > .property`;
const destructuringSelector = [
'ObjectPattern',
' > ',
'Property.properties',
'[kind="init"]',
'[computed!=true]',
' > ',
'Identifier.key',
'[name="innerText"]',
].join('');

const create = () => {
return {
[selector](node) {
[memberExpressionPropertySelector](node) {
return {
node,
messageId: MESSAGE_ID,
fix: fixer => fixer.replaceText(node, 'textContent'),
messageId: ERROR,
suggest: [
{
messageId: SUGGESTION,
fix: fixer => fixer.replaceText(node, 'textContent'),
},
],
};
},
[destructuringSelector](node) {
return {
node,
messageId: ERROR,
suggest: [
{
messageId: SUGGESTION,
fix: fixer => fixer.replaceText(
node,
node.parent.shorthand ? 'textContent: innerText' : 'textContent',
),
},
],
};
},
};
Expand All @@ -27,7 +59,7 @@ module.exports = {
docs: {
description: 'Prefer `.textContent` over `.innerText`.',
},
fixable: 'code',
messages,
hasSuggestions: true,
},
};
39 changes: 17 additions & 22 deletions test/prefer-dom-node-text-content.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,31 @@ import {getTester} from './utils/test.mjs';

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

const errors = [
{
message: 'Prefer `.textContent` over `.innerText`.',
},
];

test({
test.snapshot({
valid: [
'innerText;',
'node.textContent;',
'node[innerText];',
'innerText = true;',
'node[\'innerText\'];',
'innerText.textContent',
'const [innerText] = node;',
'[innerText] = node;',
'const {[innerText]: text} = node;',
'({[innerText]: text} = node);',
'const foo = {innerText}',
'const foo = {innerText: text}',
],
invalid: [
{
code: 'node.innerText;',
output: 'node.textContent;',
errors,
},
{
code: 'node.innerText = \'foo\';',
output: 'node.textContent = \'foo\';',
errors,
},
{
code: 'innerText.innerText;',
output: 'innerText.textContent;',
errors,
},
'node.innerText;',
'node.innerText = \'foo\';',
'innerText.innerText;',
'const {innerText} = node;',
'const {innerText,} = node;',
'const {innerText: text} = node;',
'({innerText} = node);',
'({innerText: text} = node);',
'function foo({innerText}) {return innerText}',
'for (const [{innerText}] of elements);',
],
});
200 changes: 200 additions & 0 deletions test/snapshots/prefer-dom-node-text-content.mjs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
# Snapshot report for `test/prefer-dom-node-text-content.mjs`

The actual snapshot is saved in `prefer-dom-node-text-content.mjs.snap`.

Generated by [AVA](https://avajs.dev).

## Invalid #1
1 | node.innerText;

> Error 1/1
`␊
> 1 | node.innerText;␊
| ^^^^^^^^^ Prefer \`.textContent\` over \`.innerText\`.␊
--------------------------------------------------------------------------------␊
Suggestion 1/1: Switch to \`.textContent\`.␊
1 | node.textContent;␊
`

## Invalid #2
1 | node.innerText = 'foo';

> Error 1/1
`␊
> 1 | node.innerText = 'foo';␊
| ^^^^^^^^^ Prefer \`.textContent\` over \`.innerText\`.␊
--------------------------------------------------------------------------------␊
Suggestion 1/1: Switch to \`.textContent\`.␊
1 | node.textContent = 'foo';␊
`

## Invalid #3
1 | innerText.innerText;

> Error 1/1
`␊
> 1 | innerText.innerText;␊
| ^^^^^^^^^ Prefer \`.textContent\` over \`.innerText\`.␊
--------------------------------------------------------------------------------␊
Suggestion 1/1: Switch to \`.textContent\`.␊
1 | innerText.textContent;␊
`

## Invalid #4
1 | const {innerText} = node;

> Error 1/2
`␊
> 1 | const {innerText} = node;␊
| ^^^^^^^^^ Prefer \`.textContent\` over \`.innerText\`.␊
--------------------------------------------------------------------------------␊
Suggestion 1/1: Switch to \`.textContent\`.␊
1 | const {textContent: innerText} = node;␊
`

> Error 2/2
`␊
> 1 | const {innerText} = node;␊
| ^^^^^^^^^ Prefer \`.textContent\` over \`.innerText\`.␊
--------------------------------------------------------------------------------␊
Suggestion 1/1: Switch to \`.textContent\`.␊
1 | const {textContent: innerText} = node;␊
`

## Invalid #5
1 | const {innerText,} = node;

> Error 1/2
`␊
> 1 | const {innerText,} = node;␊
| ^^^^^^^^^ Prefer \`.textContent\` over \`.innerText\`.␊
--------------------------------------------------------------------------------␊
Suggestion 1/1: Switch to \`.textContent\`.␊
1 | const {textContent: innerText,} = node;␊
`

> Error 2/2
`␊
> 1 | const {innerText,} = node;␊
| ^^^^^^^^^ Prefer \`.textContent\` over \`.innerText\`.␊
--------------------------------------------------------------------------------␊
Suggestion 1/1: Switch to \`.textContent\`.␊
1 | const {textContent: innerText,} = node;␊
`

## Invalid #6
1 | const {innerText: text} = node;

> Error 1/1
`␊
> 1 | const {innerText: text} = node;␊
| ^^^^^^^^^ Prefer \`.textContent\` over \`.innerText\`.␊
--------------------------------------------------------------------------------␊
Suggestion 1/1: Switch to \`.textContent\`.␊
1 | const {textContent: text} = node;␊
`

## Invalid #7
1 | ({innerText} = node);

> Error 1/2
`␊
> 1 | ({innerText} = node);␊
| ^^^^^^^^^ Prefer \`.textContent\` over \`.innerText\`.␊
--------------------------------------------------------------------------------␊
Suggestion 1/1: Switch to \`.textContent\`.␊
1 | ({textContent: innerText} = node);␊
`

> Error 2/2
`␊
> 1 | ({innerText} = node);␊
| ^^^^^^^^^ Prefer \`.textContent\` over \`.innerText\`.␊
--------------------------------------------------------------------------------␊
Suggestion 1/1: Switch to \`.textContent\`.␊
1 | ({textContent: innerText} = node);␊
`

## Invalid #8
1 | ({innerText: text} = node);

> Error 1/1
`␊
> 1 | ({innerText: text} = node);␊
| ^^^^^^^^^ Prefer \`.textContent\` over \`.innerText\`.␊
--------------------------------------------------------------------------------␊
Suggestion 1/1: Switch to \`.textContent\`.␊
1 | ({textContent: text} = node);␊
`

## Invalid #9
1 | function foo({innerText}) {return innerText}

> Error 1/2
`␊
> 1 | function foo({innerText}) {return innerText}␊
| ^^^^^^^^^ Prefer \`.textContent\` over \`.innerText\`.␊
--------------------------------------------------------------------------------␊
Suggestion 1/1: Switch to \`.textContent\`.␊
1 | function foo({textContent: innerText}) {return innerText}␊
`

> Error 2/2
`␊
> 1 | function foo({innerText}) {return innerText}␊
| ^^^^^^^^^ Prefer \`.textContent\` over \`.innerText\`.␊
--------------------------------------------------------------------------------␊
Suggestion 1/1: Switch to \`.textContent\`.␊
1 | function foo({textContent: innerText}) {return innerText}␊
`

## Invalid #10
1 | for (const [{innerText}] of elements);

> Error 1/2
`␊
> 1 | for (const [{innerText}] of elements);␊
| ^^^^^^^^^ Prefer \`.textContent\` over \`.innerText\`.␊
--------------------------------------------------------------------------------␊
Suggestion 1/1: Switch to \`.textContent\`.␊
1 | for (const [{textContent: innerText}] of elements);␊
`

> Error 2/2
`␊
> 1 | for (const [{innerText}] of elements);␊
| ^^^^^^^^^ Prefer \`.textContent\` over \`.innerText\`.␊
--------------------------------------------------------------------------------␊
Suggestion 1/1: Switch to \`.textContent\`.␊
1 | for (const [{textContent: innerText}] of elements);␊
`
Binary file added test/snapshots/prefer-dom-node-text-content.mjs.snap
Binary file not shown.

0 comments on commit c4bfc42

Please sign in to comment.