Skip to content

Commit 91544e7

Browse files
authored
feat(lint): use ESLint for linting snippets (#7720)
1 parent bf334d9 commit 91544e7

35 files changed

+102
-275
lines changed

apps/site/eslint.config.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const compatConfig = compat.config({
2020

2121
export default tseslint.config(
2222
...baseConfig,
23+
{ ignores: ['pages/en/blog/**/*.{md,mdx}/**'] },
2324
{
2425
extends: [
2526
react.configs.flat['jsx-runtime'],
@@ -40,6 +41,7 @@ export default tseslint.config(
4041
{
4142
files: ['**/*.{md,mdx}'],
4243
extends: [mdx.flat],
44+
processor: mdx.createRemarkProcessor({ lintCodeBlocks: true }),
4345
rules: {
4446
'no-irregular-whitespace': 'off',
4547
'@next/next/no-img-element': 'off',
@@ -77,5 +79,6 @@ export default tseslint.config(
7779
},
7880
],
7981
},
80-
}
82+
},
83+
mdx.flatCodeBlocks
8184
);

apps/site/next.mdx.plugins.mjs

-4
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ import rehypeShikiji from './next.mdx.shiki.mjs';
1010

1111
/**
1212
* Provides all our Rehype Plugins that are used within MDX
13-
*
14-
* @type {Array<import('unified').Plugin>}
1513
*/
1614
export const REHYPE_PLUGINS = [
1715
// Generates `id` attributes for headings (H1, ...)
@@ -25,8 +23,6 @@ export const REHYPE_PLUGINS = [
2523

2624
/**
2725
* Provides all our Remark Plugins that are used within MDX
28-
*
29-
* @type {Array<import('unified').Plugin>}
3026
*/
3127
export const REMARK_PLUGINS = [
3228
// Support GFM syntax to be used within Markdown

apps/site/package.json

+1-4
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@
66
"check-types": "tsc --noEmit",
77
"deploy": "cross-env NEXT_PUBLIC_STATIC_EXPORT=true NODE_NO_WARNINGS=1 next build",
88
"dev": "cross-env NODE_NO_WARNINGS=1 next dev",
9-
"lint": "turbo run lint:md lint:snippets lint:js lint:css",
9+
"lint": "turbo run lint:md lint:js lint:css",
1010
"lint:css": "stylelint \"**/*.css\" --allow-empty-input --cache --cache-strategy=content --cache-location=.stylelintcache",
1111
"lint:fix": "turbo run lint:md lint:js lint:css --no-cache -- --fix",
1212
"lint:js": "eslint \"**/*.{js,mjs,ts,tsx}\"",
1313
"lint:md": "eslint \"**/*.md?(x)\" --cache --cache-strategy=content --cache-location=.eslintmdcache",
14-
"lint:snippets": "node ./scripts/lint-snippets/index.mjs",
1514
"scripts:release-post": "cross-env NODE_NO_WARNINGS=1 node scripts/release-post/index.mjs",
1615
"serve": "pnpm dev",
1716
"start": "cross-env NODE_NO_WARNINGS=1 next start",
@@ -97,7 +96,6 @@
9796
"remark-lint-no-unused-definitions": "^4.0.2",
9897
"remark-lint-prohibited-strings": "^4.0.0",
9998
"remark-lint-unordered-list-marker-style": "^4.0.1",
100-
"remark-parse": "11.0.0",
10199
"remark-preset-lint-node": "5.1.2",
102100
"stylelint": "16.19.1",
103101
"stylelint-config-standard": "38.0.0",
@@ -106,7 +104,6 @@
106104
"tsx": "^4.19.3",
107105
"typescript": "~5.8.2",
108106
"typescript-eslint": "~8.31.1",
109-
"unified": "^11.0.5",
110107
"user-agent-data-types": "0.4.2"
111108
},
112109
"imports": {

apps/site/pages/en/index.mdx

+2-3
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,12 @@ layout: home
9696

9797
```js displayName="Streams Pipeline"
9898
// streams.mjs
99-
import { pipeline } from 'node:stream/promises';
10099
import { createReadStream, createWriteStream } from 'node:fs';
100+
import { pipeline } from 'node:stream/promises';
101101
import { createGzip } from 'node:zlib';
102102

103103
// ensure you have a `package.json` file for this test!
104-
await pipeline
105-
(
104+
await pipeline(
106105
createReadStream('package.json'),
107106
createGzip(),
108107
createWriteStream('package.json.gz')

apps/site/pages/en/learn/asynchronous-work/asynchronous-flow-control.md

-2
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ function getSong() {
114114
let _song = '';
115115
let i = 100;
116116
for (i; i > 0; i -= 1) {
117-
/* eslint-disable no-loop-func */
118117
setTimeout(function () {
119118
_song += `${i} beers on the wall, you take one down and pass it around, ${
120119
i - 1
@@ -123,7 +122,6 @@ function getSong() {
123122
_song += "Hey let's get some more beer";
124123
}
125124
}, 0);
126-
/* eslint-enable no-loop-func */
127125
}
128126

129127
return _song;

apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ The return value of the executor function is ignored: only `resolve` or `reject`
3131

3232
```js
3333
const myPromise = new Promise((resolve, reject) => {
34-
let success = true;
34+
const success = true;
3535

3636
if (success) {
3737
resolve('Operation was successful!');
@@ -56,7 +56,7 @@ Once a Promise is created, you can handle the outcome by using the `.then()`, `.
5656

5757
```js
5858
const myPromise = new Promise((resolve, reject) => {
59-
let success = true;
59+
const success = true;
6060

6161
if (success) {
6262
resolve('Operation was successful!');

apps/site/pages/en/learn/asynchronous-work/dont-block-the-event-loop.md

+26-24
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ Example 2: An `O(n)` callback. This callback will run quickly for small `n` and
126126

127127
```js
128128
app.get('/countToN', (req, res) => {
129-
let n = req.query.n;
129+
const n = req.query.n;
130130

131131
// n iterations before giving someone else a turn
132132
for (let i = 0; i < n; i++) {
@@ -141,7 +141,7 @@ Example 3: An `O(n^2)` callback. This callback will still run quickly for small
141141

142142
```js
143143
app.get('/countToN2', (req, res) => {
144-
let n = req.query.n;
144+
const n = req.query.n;
145145

146146
// n^2 iterations before giving someone else a turn
147147
for (let i = 0; i < n; i++) {
@@ -193,7 +193,7 @@ Here is an example vulnerable regexp exposing its server to REDOS:
193193

194194
```js
195195
app.get('/redos-me', (req, res) => {
196-
let filePath = req.query.filePath;
196+
const filePath = req.query.filePath;
197197

198198
// REDOS
199199
if (filePath.match(/(\/.+)+$/)) {
@@ -272,28 +272,30 @@ Example: JSON blocking. We create an object `obj` of size 2^21 and `JSON.stringi
272272

273273
```js
274274
let obj = { a: 1 };
275-
let niter = 20;
275+
const iterations = 20;
276276

277-
let before, str, pos, res, took;
278-
279-
for (let i = 0; i < niter; i++) {
280-
obj = { obj1: obj, obj2: obj }; // Doubles in size each iter
277+
// Expand the object exponentially by nesting it
278+
for (let i = 0; i < iterations; i++) {
279+
obj = { obj1: obj, obj2: obj };
281280
}
282281

283-
before = process.hrtime();
284-
str = JSON.stringify(obj);
285-
took = process.hrtime(before);
286-
console.log('JSON.stringify took ' + took);
287-
288-
before = process.hrtime();
289-
pos = str.indexOf('nomatch');
290-
took = process.hrtime(before);
291-
console.log('Pure indexof took ' + took);
292-
293-
before = process.hrtime();
294-
res = JSON.parse(str);
295-
took = process.hrtime(before);
296-
console.log('JSON.parse took ' + took);
282+
// Measure time to stringify the object
283+
let start = process.hrtime();
284+
const jsonString = JSON.stringify(obj);
285+
let duration = process.hrtime(start);
286+
console.log('JSON.stringify took', duration);
287+
288+
// Measure time to search a string within the JSON
289+
start = process.hrtime();
290+
const index = jsonString.indexOf('nomatch'); // Always -1
291+
duration = process.hrtime(start);
292+
console.log('String.indexOf took', duration);
293+
294+
// Measure time to parse the JSON back to an object
295+
start = process.hrtime();
296+
const parsed = JSON.parse(jsonString);
297+
duration = process.hrtime(start);
298+
console.log('JSON.parse took', duration);
297299
```
298300

299301
There are npm modules that offer asynchronous JSON APIs. See for example:
@@ -317,7 +319,7 @@ Example 1: Un-partitioned average, costs `O(n)`
317319

318320
```js
319321
for (let i = 0; i < n; i++) sum += i;
320-
let avg = sum / n;
322+
const avg = sum / n;
321323
console.log('avg: ' + avg);
322324
```
323325

@@ -341,7 +343,7 @@ function asyncAvg(n, avgCB) {
341343

342344
// Start the helper, with CB to call avgCB.
343345
help(1, function (sum) {
344-
let avg = sum / n;
346+
const avg = sum / n;
345347
avgCB(avg);
346348
});
347349
}

apps/site/pages/en/learn/asynchronous-work/event-loop-timers-and-nexttick.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ This philosophy can lead to some potentially problematic situations.
338338
Take this snippet for example:
339339

340340
```js
341-
let bar;
341+
let bar = null;
342342

343343
// this has an asynchronous signature, but calls callback synchronously
344344
function someAsyncApiCall(callback) {
@@ -370,7 +370,7 @@ useful for the user to be alerted to an error before the event loop is
370370
allowed to continue. Here is the previous example using `process.nextTick()`:
371371

372372
```js
373-
let bar;
373+
let bar = null;
374374

375375
function someAsyncApiCall(callback) {
376376
process.nextTick(callback);

apps/site/pages/en/learn/asynchronous-work/javascript-asynchronous-programming-and-callbacks.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,11 @@ XHR requests also accept a callback, in this example by assigning a function to
7979
const xhr = new XMLHttpRequest();
8080
xhr.onreadystatechange = () => {
8181
if (xhr.readyState === 4) {
82-
xhr.status === 200 ? console.log(xhr.responseText) : console.error('error');
82+
if (xhr.status === 200) {
83+
console.log(xhr.responseText);
84+
} else {
85+
console.error('error');
86+
}
8387
}
8488
};
8589
xhr.open('GET', 'https://yoursite.com');

apps/site/pages/en/learn/command-line/how-to-read-environment-variables-from-nodejs.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ That will pass the user `USER_ID` as **239482** and the `USER_KEY` as **foobar**
2121
Here is an example that accesses the `USER_ID` and `USER_KEY` environment variables, which we set in above code.
2222

2323
```js
24-
process.env.USER_ID; // "239482"
25-
process.env.USER_KEY; // "foobar"
24+
console.log(process.env.USER_ID); // "239482"
25+
console.log(process.env.USER_KEY); // "foobar"
2626
```
2727

2828
In the same way you can access any custom environment variable you set.
@@ -39,7 +39,7 @@ PORT=3000
3939
In your js file
4040

4141
```js
42-
process.env.PORT; // "3000"
42+
console.log(process.env.PORT); // "3000"
4343
```
4444

4545
Run `app.js` file with environment variables set in `.env` file.

apps/site/pages/en/learn/diagnostics/memory/using-gc-traces.md

+8-8
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,8 @@ Let's modify our script a bit:
248248

249249
```mjs
250250
// script-fix.mjs
251-
import os from 'node:os';
252251
import fs from 'node:fs/promises';
252+
import os from 'node:os';
253253

254254
let len = 1_000_000;
255255
const fileName = `entries-${Date.now()}`;
@@ -366,13 +366,13 @@ You can get GC statistics as [PerformanceEntry][] from the callback in
366366

367367
For example:
368368

369-
```ts
370-
PerformanceEntry {
371-
name: 'gc',
372-
entryType: 'gc',
373-
startTime: 2820.567669,
374-
duration: 1.315709,
375-
kind: 1
369+
```json
370+
{
371+
"name": "gc",
372+
"entryType": "gc",
373+
"startTime": 2820.567669,
374+
"duration": 1.315709,
375+
"kind": 1
376376
}
377377
```
378378

apps/site/pages/en/learn/getting-started/fetch.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,10 @@ try {
133133
[Streams](https://nodejs.org/docs/v22.14.0/api/stream.html#stream) is a feature in Node.js that allows you to read and write chunks of data.
134134

135135
```js
136-
import { stream } from 'undici';
137136
import { Writable } from 'stream';
138137

138+
import { stream } from 'undici';
139+
139140
async function fetchGitHubRepos() {
140141
const url = 'https://api.github.com/users/nodejs/repos';
141142

apps/site/pages/en/learn/getting-started/security-best-practices.md

+2-3
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ There are some mechanisms to control this behavior by defining a blocklist with
130130
`.npmignore`.
131131
Throughout these files, you can specify which files/folders should not be published.
132132
The [files property][] in `package.json` allows the inverse operation
133-
-- allowed list.
133+
\-- allowed list.
134134
- In case of an exposure, make sure to [unpublish the package][].
135135

136136
### HTTP Request Smuggling (CWE-444)
@@ -180,6 +180,7 @@ of requests.
180180

181181
- The crypto API exposes a function `timingSafeEqual` to compare actual and
182182
expected sensitive values using a constant-time algorithm.
183+
183184
- For password comparison, you can use the [scrypt][] available also on the
184185
native crypto module.
185186

@@ -275,7 +276,6 @@ Monkey patching refers to the modification of properties in runtime aiming to
275276
change the existing behavior. Example:
276277

277278
```js
278-
// eslint-disable-next-line no-extend-native
279279
Array.prototype.push = function (item) {
280280
// overriding the global [].push
281281
};
@@ -290,7 +290,6 @@ Therefore, the following snippet **will not** override the default behavior of
290290
`Array.prototype.push`
291291

292292
```js
293-
// eslint-disable-next-line no-extend-native
294293
Array.prototype.push = function (item) {
295294
// overriding the global [].push
296295
};

apps/site/pages/en/learn/manipulating-files/nodejs-file-stats.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ fs.stat('/Users/joe/test.txt', (err, stats) => {
9292
stats.isFile(); // true
9393
stats.isDirectory(); // false
9494
stats.isSymbolicLink(); // false
95-
stats.size; // 1024000 //= 1MB
95+
console.log(stats.size); // 1024000 //= 1MB
9696
});
9797
```
9898

@@ -123,7 +123,7 @@ try {
123123
stats.isFile(); // true
124124
stats.isDirectory(); // false
125125
stats.isSymbolicLink(); // false
126-
stats.size; // 1024000 //= 1MB
126+
console.log(stats.size); // 1024000 //= 1MB
127127
} catch (err) {
128128
console.log(err);
129129
}

apps/site/pages/en/learn/manipulating-files/reading-files-with-nodejs.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ In this case, a better option is to read the file content using streams.
9191

9292
```mjs
9393
import fs from 'fs';
94-
import path from 'path';
9594
import { pipeline } from 'node:stream/promises';
95+
import path from 'path';
9696

9797
const fileUrl = 'https://www.gutenberg.org/files/2701/2701-0.txt';
9898
const outputFilePath = path.join(process.cwd(), 'moby.md');

0 commit comments

Comments
 (0)