Skip to content

Commit 7708bf6

Browse files
committed
Try to format documentation in a standard format
1 parent ba59176 commit 7708bf6

17 files changed

+394
-139
lines changed

docs/rules/array-foreach.md

+35-22
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,17 @@
1-
# Array.forEach
1+
# Array Foreach
22

33
Prefer `for...of` statement instead of `Array.forEach`.
44

5-
```js
6-
// bad
7-
els.forEach(el => {
8-
el
9-
})
5+
## Rule Details
106

11-
// good
12-
for (const el of els) {
13-
el
14-
}
15-
```
16-
17-
## Why disallow `forEach`
7+
### Why disallow `forEach`
188

199
Here's a summary of why `forEach` is disallowed, and why we prefer `for...of` for almost any use-case of `forEach`:
2010

21-
- Allowing `forEach` encourages **layering of "bad practices"**, such as using `Array.from()` (which is less performant than using `for...of`).
22-
- When more requirements are added on, `forEach` typically gets **chained** with other methods like `filter` or `map`, causing multiple iterations over the same Array. Encouraging `for` loops discourages chaining and encourages single-iteration logic (e.g. using a `continue` instead of `filter`).
23-
- `for` loops are considered "more readable" and have **clearer intent**.
24-
- `for...of` loops offer the **most flexibility** for iteration (especially vs `Array.from`).
11+
- Allowing `forEach` encourages **layering of "bad practices"**, such as using `Array.from()` (which is less performant than using `for...of`).
12+
- When more requirements are added on, `forEach` typically gets **chained** with other methods like `filter` or `map`, causing multiple iterations over the same Array. Encouraging `for` loops discourages chaining and encourages single-iteration logic (e.g. using a `continue` instead of `filter`).
13+
- `for` loops are considered "more readable" and have **clearer intent**.
14+
- `for...of` loops offer the **most flexibility** for iteration (especially vs `Array.from`).
2515

2616
For more detail, here is a breakdown of each of those points:
2717

@@ -31,7 +21,7 @@ Typically developers will reach for a `forEach` when they want to iterate over a
3121

3222
`forEach` does not do anything special with the Array - it does not create a new array or does not aid in encapsulation (except for introducing a new lexical scope within the callback, which isn't a benefit considering we use `let`/`const`). We don't dissallow `map`/`filter`/`reduce` because they have a tangible effect - they create a new array - which would take _more_ code and be _less_ readable to do with a `for...of` loop, the exception being as more requirements are added, and we start chaining array methods together...
3323

34-
### Chaining
24+
### Chaining
3525

3626
Often when using a method like `forEach` - when coming back to add new code, let's say to filter certain elements from the Array before operating on them, a developer is implicitly encouraged to use Array's method chaining to achieve this result. For example if we wanted to filter out bad apples from an Array of Apples, if the code already uses `forEach`, then its a simple addition to add `filter()`:
3727

@@ -54,12 +44,12 @@ Chaning isn't always necessarily bad. Chaining can advertise a series of transfo
5444

5545
### Hiding Intent
5646

57-
The `forEach` method passes more than just the current item it is iterating over. The signature of the `forEach` callback method is `(cur: T, i: Number, all: []T) => void` and it can _additionally_ override the `receiver` (`this` value), meaning that often the _intent_ of what the callback does is hidden. To put this another way, there is _no way_ to know what the following code operates on without reading the implementation: `forEach(polishApple)`.
47+
The `forEach` method passes more than just the current item it is iterating over. The signature of the `forEach` callback method is `(cur: T, i: Number, all: []T) => void` and it can _additionally_ override the `receiver` (`this` value), meaning that often the _intent_ of what the callback does is hidden. To put this another way, there is _no way_ to know what the following code operates on without reading the implementation: `forEach(polishApple)`.
5848

5949
The `for` loop avoids this issue. Calls are explicit within the `for` loop, as they are not passed around. For example:
6050

6151
```js
62-
for(const apple of apples) {
52+
for (const apple of apples) {
6353
polishApple(apple)
6454
}
6555
```
@@ -98,7 +88,30 @@ Compare this to the `for` loop, which has a much simpler path to refactoring:
9888
}
9989
```
10090

101-
102-
## See Also
91+
### See Also
10392

10493
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of
94+
95+
👎 Examples of **incorrect** code for this rule:
96+
97+
```js
98+
els.forEach(el => {
99+
el
100+
})
101+
```
102+
103+
👍 Examples of **correct** code for this rule:
104+
105+
```js
106+
for (const el of els) {
107+
el
108+
}
109+
```
110+
111+
## When Not To Use It
112+
113+
TODO
114+
115+
## Version
116+
117+
4.3.2

docs/rules/async-currenttarget.md

+25-18
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
1-
# `event.currentTarget` in an async function
1+
# Async Currenttarget
22

33
Accessing `event.currentTarget` inside an `async function()` will likely be `null` as `currentTarget` is mutated as the event is propagated.
44

5+
1. A `click` event is dispatched
6+
2. The handler is invoked once with the expected `currentTarget`
7+
3. An `await` defers the execution
8+
4. The event dispatch continues, `event.currentTarget` is modified to point to the current target of another event handler and nulled out at the end of the dispatch
9+
5. The async function resumes
10+
6. `event.currentTarget` is now `null`
11+
12+
If you're using `async`, you'll need to synchronously create a reference to `currentTarget` before any async activity.
13+
14+
👎 Examples of **incorrect** code for this rule:
15+
516
```js
6-
// bad
7-
document.addEventListener('click', async function(event) {
17+
document.addEventListener('click', async function (event) {
818
// event.currentTarget will be an HTMLElement
919
const url = event.currentTarget.getAttribute('data-url')
1020
const data = await fetch(url)
@@ -15,25 +25,15 @@ document.addEventListener('click', async function(event) {
1525
})
1626
```
1727

18-
1. A `click` event is dispatched
19-
2. The handler is invoked once with the expected `currentTarget`
20-
3. An `await` defers the execution
21-
4. The event dispatch continues, `event.currentTarget` is modified to point to the current target of another event handler and nulled out at the end of the dispatch
22-
5. The async function resumes
23-
6. `event.currentTarget` is now `null`
24-
25-
## Solutions
26-
27-
If you're using `async`, you'll need to synchronously create a reference to `currentTarget` before any async activity.
28+
👍 Examples of **correct** code for this rule:
2829

2930
```js
30-
// good
31-
document.addEventListener('click', function(event) {
31+
document.addEventListener('click', function (event) {
3232
const currentTarget = event.currentTarget
3333
const url = currentTarget.getAttribute('data-url')
3434

3535
// call async IIFE
36-
;(async function() {
36+
;(async function () {
3737
const data = await fetch(url)
3838

3939
const text = currentTarget.getAttribute('data-text')
@@ -45,8 +45,7 @@ document.addEventListener('click', function(event) {
4545
Alternatively, extract a function to create an element reference.
4646

4747
```js
48-
// good
49-
document.addEventListener('click', function(event) {
48+
document.addEventListener('click', function (event) {
5049
fetchData(event.currentTarget)
5150
})
5251

@@ -57,3 +56,11 @@ async function fetchData(el) {
5756
// ...
5857
}
5958
```
59+
60+
## When Not To Use It
61+
62+
TODO
63+
64+
## Version
65+
66+
4.3.2

docs/rules/async-preventdefault.md

+26-17
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,32 @@
1-
# `event.preventDefault()` in an async function
1+
# Async Preventdefault
22

33
Using `event.preventDefault()` inside an `async function()` won't likely work as you'd expect because synchronous nature of event dispatch.
44

5-
```js
6-
// bad
7-
document.addEventListener('click', async function(event) {
8-
event.preventDefault()
9-
10-
const data = await fetch()
11-
// ...
12-
})
13-
```
5+
## Rule Details
146

157
1. A `click` event is dispatched
168
2. This handler is scheduled but not ran immediately because its marked async.
179
3. The event dispatch completes and nothing has called `preventDefault()` _yet_ and the default click behavior occurs.
1810
4. The async function is scheduled and runs.
1911
5. Calling `preventDefault()` is now a no-op as the synchronous event dispatch has already completed.
2012

21-
## Solutions
22-
2313
If you're using `async`, you likely need to wait on a promise in the event handler. In this case you can split the event handler in two parts, one synchronous and asynchronous.
2414

15+
👎 Examples of **incorrect** code for this rule:
16+
17+
```js
18+
document.addEventListener('click', async function (event) {
19+
event.preventDefault()
20+
21+
const data = await fetch()
22+
// ...
23+
})
24+
```
25+
26+
👍 Examples of **correct** code for this rule:
27+
2528
```js
26-
// good
27-
document.addEventListener('click', function(event) {
29+
document.addEventListener('click', function (event) {
2830
// preventDefault in a regular function
2931
event.preventDefault()
3032

@@ -41,15 +43,22 @@ async function loadData(el) {
4143
This could also be done with an async IIFE.
4244

4345
```js
44-
// good
45-
document.addEventListener('click', function(event) {
46+
document.addEventListener('click', function (event) {
4647
// preventDefault in a regular function
4748
event.preventDefault()
4849

4950
// call async IIFE
50-
;(async function() {
51+
;(async function () {
5152
const data = await fetch()
5253
// ...
5354
})()
5455
})
5556
```
57+
58+
## When Not To Use It
59+
60+
TODO
61+
62+
## Version
63+
64+
4.3.2

docs/rules/authenticity-token.md

+15-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
# `<input name="authenticity_token">`
1+
# Authenticity Token
2+
3+
## Rule Details
24

35
The Rails `form_tag` helper creates a `<form>` element with a `<input name="authenticity_token">` child element. The authenticity-token input tag contains a [Cross-Site Request Forgery (CSRF)](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29) token that is verified by the Rails app when the form is submitted.
46

@@ -24,13 +26,13 @@ The preferred way to make an HTTP request with JavaScript is to use the [`FormDa
2426
```
2527

2628
```js
27-
on('click', '.js-my-button', function(e) {
29+
on('click', '.js-my-button', function (e) {
2830
const form = this.closest('form')
2931

3032
fetch(form.action, {
3133
method: form.method,
3234
body: new FormData(form)
33-
}).then(function() {
35+
}).then(function () {
3436
alert('Success!')
3537
})
3638

@@ -45,14 +47,22 @@ An alternate, but less preferred approach is to include the a signed CSRF url in
4547
```
4648

4749
```js
48-
on('click', '.js-my-button', function(e) {
50+
on('click', '.js-my-button', function (e) {
4951
csrfRequest(this.getAttribute('data-url'), {
5052
method: 'PUT',
5153
body: data
52-
}).then(function() {
54+
}).then(function () {
5355
alert('Success!')
5456
})
5557

5658
e.preventDefault()
5759
})
5860
```
61+
62+
## When Not To Use It
63+
64+
TODO
65+
66+
## Version
67+
68+
4.3.2

docs/rules/get-attribute.md

+17-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,27 @@
1-
# getAttribute
1+
# Get Attribute
2+
3+
## Rule Details
24

35
As HTML attributes are case insensitive, prefer using lowercase.
46

7+
👎 Examples of **incorrect** code for this rule:
8+
59
```js
6-
// bad
710
el.getAttribute('autoComplete')
811
el.getAttribute('dataFoo')
12+
```
913

10-
// good
14+
👍 Examples of **correct** code for this rule:
15+
16+
```js
1117
el.getAttribute('autocomplete')
1218
el.getAttribute('data-foo')
1319
```
20+
21+
## When Not To Use It
22+
23+
TODO
24+
25+
## Version
26+
27+
4.3.2

docs/rules/js-class-name.md

+25-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# JS prefixed class names
1+
# Js Class Name
22

33
JavaScript should only query and handle events for `js-` prefixed class names.
44

5-
## Statically declared
5+
## Rule Details
66

77
The key benefit is that these symbols can be easily searched for.
88

@@ -17,15 +17,35 @@ In order to trust this system, all `js-` class names MUST be statically written
1717
Typically dynamically constructed `js-` classes are often mixing static symbols and user data together. Like `"js-org-#{org.login}"`. In this case, separating into a `data-` attribute would be a better solution.
1818

1919
```html
20-
<div class="js-org-update" data-org-name="<%= org.login %>">
20+
<div class="js-org-update" data-org-name="<%= org.login %>"></div>
2121
```
2222

2323
Allows you to select elements by `js-org-update` and still filter by the `data-org-name` attribute if you need to. Both `js-org-update` and `data-org-name` are clearly static symbols that are easy to search for.
2424

25-
## Formatting
25+
### Formatting
2626

2727
`js-` classes must start with `js-` (obviously) and only contain lowercase letters and numbers separated by `-`s. The ESLint [`github/js-class-name`](https://github.com/github/eslint-plugin-github/blob/master/lib/rules/js-class-name.js) rule enforces this style.
2828

29-
## See Also
29+
### See Also
3030

3131
[@defunkt's original proposal from 2010](https://web.archive.org/web/20180902223055/http://ozmm.org/posts/slightly_obtrusive_javascript.html).
32+
33+
👎 Examples of **incorrect** code for this rule:
34+
35+
```js
36+
37+
```
38+
39+
👍 Examples of **correct** code for this rule:
40+
41+
```js
42+
43+
```
44+
45+
## When Not To Use It
46+
47+
TODO
48+
49+
## Version
50+
51+
4.3.2

0 commit comments

Comments
 (0)