Skip to content

Commit

Permalink
Add prefer-blob-reading-methods rule (#2065)
Browse files Browse the repository at this point in the history
Co-authored-by: fisker <lionkay@gmail.com>
  • Loading branch information
NotWoods and fisker committed Apr 17, 2023
1 parent d90f337 commit 2bb1a04
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 0 deletions.
1 change: 1 addition & 0 deletions configs/recommended.js
Expand Up @@ -75,6 +75,7 @@ module.exports = {
'unicorn/prefer-array-some': 'error',
// TODO: Enable this by default when targeting a Node.js version that supports `Array#at`.
'unicorn/prefer-at': 'off',
'unicorn/prefer-blob-reading-methods': 'error',
'unicorn/prefer-code-point': 'error',
'unicorn/prefer-date-now': 'error',
'unicorn/prefer-default-parameters': 'error',
Expand Down
45 changes: 45 additions & 0 deletions docs/rules/prefer-blob-reading-methods.md
@@ -0,0 +1,45 @@
# Prefer `Blob#arrayBuffer()` over `FileReader#readAsArrayBuffer(…)` and `Blob#text()` over `FileReader#readAsText(…)`

💼 This rule is enabled in the ✅ `recommended` [config](https://github.com/sindresorhus/eslint-plugin-unicorn#preset-configs).

<!-- end auto-generated rule header -->
<!-- Do not manually modify this header. Run: `npm run fix:eslint-docs` -->

`FileReader` predates promises, and the newer [`Blob#arrayBuffer()`](https://developer.mozilla.org/en-US/docs/Web/API/Blob/arrayBuffer) and [`Blob#text()`](https://developer.mozilla.org/en-US/docs/Web/API/Blob/text) methods are much cleaner and easier to use.

## Fail

```js
const arrayBuffer = await new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.addEventListener('load', () => {
resolve(fileReader.result);
});
fileReader.addEventListener('error', () => {
reject(fileReader.error);
});
fileReader.readAsArrayBuffer(blob);
});
```

```js
fileReader.readAsText(blob);
```

## Pass

```js
const arrayBuffer = await blob.arrayBuffer();
```

```js
const text = await blob.text();
```

```js
fileReader.readAsText(blob, 'ascii');
```

```js
fileReader.readAsDataURL(blob);
```
1 change: 1 addition & 0 deletions readme.md
Expand Up @@ -116,6 +116,7 @@ If you don't use the preset, ensure you use the same `env` and `parserOptions` c
| [prefer-array-index-of](docs/rules/prefer-array-index-of.md) | Prefer `Array#{indexOf,lastIndexOf}()` over `Array#{findIndex,findLastIndex}()` when looking for the index of an item. || 🔧 | 💡 |
| [prefer-array-some](docs/rules/prefer-array-some.md) | Prefer `.some(…)` over `.filter(…).length` check and `.{find,findLast}(…)`. || 🔧 | 💡 |
| [prefer-at](docs/rules/prefer-at.md) | Prefer `.at()` method for index access and `String#charAt()`. | | 🔧 | 💡 |
| [prefer-blob-reading-methods](docs/rules/prefer-blob-reading-methods.md) | Prefer `Blob#arrayBuffer()` over `FileReader#readAsArrayBuffer(…)` and `Blob#text()` over `FileReader#readAsText(…)`. || | |
| [prefer-code-point](docs/rules/prefer-code-point.md) | Prefer `String#codePointAt(…)` over `String#charCodeAt(…)` and `String.fromCodePoint(…)` over `String.fromCharCode(…)`. || | 💡 |
| [prefer-date-now](docs/rules/prefer-date-now.md) | Prefer `Date.now()` to get the number of milliseconds since the Unix Epoch. || 🔧 | |
| [prefer-default-parameters](docs/rules/prefer-default-parameters.md) | Prefer default parameters over reassignment. || 🔧 | 💡 |
Expand Down
37 changes: 37 additions & 0 deletions rules/prefer-blob-reading-methods.js
@@ -0,0 +1,37 @@
'use strict';
const {methodCallSelector} = require('./selectors/index.js');

const messages = {
'error/readAsArrayBuffer': 'Prefer `Blob#arrayBuffer()` over `FileReader#readAsArrayBuffer(blob)`.',
'error/readAsText': 'Prefer `Blob#text()` over `FileReader#readAsText(blob)`.',
};

const selector = methodCallSelector({
methods: ['readAsText', 'readAsArrayBuffer'],
argumentsLength: 1,
});

/** @param {import('eslint').Rule.RuleContext} context */
const create = () => ({
[selector](node) {
const method = node.callee.property;
const methodName = method.name;

return {
node: method,
messageId: `error/${methodName}`,
};
},
});

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
create,
meta: {
type: 'suggestion',
docs: {
description: 'Prefer `Blob#arrayBuffer()` over `FileReader#readAsArrayBuffer(…)` and `Blob#text()` over `FileReader#readAsText(…)`.',
},
messages,
},
};
19 changes: 19 additions & 0 deletions test/prefer-blob-reading-methods.mjs
@@ -0,0 +1,19 @@
import {getTester} from './utils/test.mjs';

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

test.snapshot({
valid: [
'blob.arrayBuffer()',
'blob.text()',
'new Response(blob).arrayBuffer()',
'new Response(blob).text()',
'fileReader.readAsDataURL(blob)',
'fileReader.readAsBinaryString(blob)',
'fileReader.readAsText(blob, "ascii")',
],
invalid: [
'fileReader.readAsArrayBuffer(blob)',
'fileReader.readAsText(blob)',
],
});
25 changes: 25 additions & 0 deletions test/snapshots/prefer-blob-reading-methods.mjs.md
@@ -0,0 +1,25 @@
# Snapshot report for `test/prefer-blob-reading-methods.mjs`

The actual snapshot is saved in `prefer-blob-reading-methods.mjs.snap`.

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

## Invalid #1
1 | fileReader.readAsArrayBuffer(blob)

> Error 1/1
`␊
> 1 | fileReader.readAsArrayBuffer(blob)␊
| ^^^^^^^^^^^^^^^^^ Prefer \`Blob#arrayBuffer()\` over \`FileReader#readAsArrayBuffer(blob)\`.␊
`

## Invalid #2
1 | fileReader.readAsText(blob)

> Error 1/1
`␊
> 1 | fileReader.readAsText(blob)␊
| ^^^^^^^^^^ Prefer \`Blob#text()\` over \`FileReader#readAsText(blob)\`.␊
`
Binary file added test/snapshots/prefer-blob-reading-methods.mjs.snap
Binary file not shown.

0 comments on commit 2bb1a04

Please sign in to comment.