diff --git a/apps/site/eslint.config.js b/apps/site/eslint.config.js index 7550dce11e375..067acb4db1582 100644 --- a/apps/site/eslint.config.js +++ b/apps/site/eslint.config.js @@ -20,6 +20,7 @@ const compatConfig = compat.config({ export default tseslint.config( ...baseConfig, + { ignores: ['pages/en/blog/**/*.{md,mdx}/**'] }, { extends: [ react.configs.flat['jsx-runtime'], @@ -40,6 +41,7 @@ export default tseslint.config( { files: ['**/*.{md,mdx}'], extends: [mdx.flat], + processor: mdx.createRemarkProcessor({ lintCodeBlocks: true }), rules: { 'no-irregular-whitespace': 'off', '@next/next/no-img-element': 'off', @@ -77,5 +79,6 @@ export default tseslint.config( }, ], }, - } + }, + mdx.flatCodeBlocks ); diff --git a/apps/site/next.mdx.plugins.mjs b/apps/site/next.mdx.plugins.mjs index 2c7d02968f380..51a76ef0f7bcf 100644 --- a/apps/site/next.mdx.plugins.mjs +++ b/apps/site/next.mdx.plugins.mjs @@ -10,8 +10,6 @@ import rehypeShikiji from './next.mdx.shiki.mjs'; /** * Provides all our Rehype Plugins that are used within MDX - * - * @type {Array} */ export const REHYPE_PLUGINS = [ // Generates `id` attributes for headings (H1, ...) @@ -25,8 +23,6 @@ export const REHYPE_PLUGINS = [ /** * Provides all our Remark Plugins that are used within MDX - * - * @type {Array} */ export const REMARK_PLUGINS = [ // Support GFM syntax to be used within Markdown diff --git a/apps/site/package.json b/apps/site/package.json index 266b9d4093df6..2519a091e0eb7 100644 --- a/apps/site/package.json +++ b/apps/site/package.json @@ -6,12 +6,11 @@ "check-types": "tsc --noEmit", "deploy": "cross-env NEXT_PUBLIC_STATIC_EXPORT=true NODE_NO_WARNINGS=1 next build", "dev": "cross-env NODE_NO_WARNINGS=1 next dev", - "lint": "turbo run lint:md lint:snippets lint:js lint:css", + "lint": "turbo run lint:md lint:js lint:css", "lint:css": "stylelint \"**/*.css\" --allow-empty-input --cache --cache-strategy=content --cache-location=.stylelintcache", "lint:fix": "turbo run lint:md lint:js lint:css --no-cache -- --fix", "lint:js": "eslint \"**/*.{js,mjs,ts,tsx}\"", "lint:md": "eslint \"**/*.md?(x)\" --cache --cache-strategy=content --cache-location=.eslintmdcache", - "lint:snippets": "node ./scripts/lint-snippets/index.mjs", "scripts:release-post": "cross-env NODE_NO_WARNINGS=1 node scripts/release-post/index.mjs", "serve": "pnpm dev", "start": "cross-env NODE_NO_WARNINGS=1 next start", @@ -97,7 +96,6 @@ "remark-lint-no-unused-definitions": "^4.0.2", "remark-lint-prohibited-strings": "^4.0.0", "remark-lint-unordered-list-marker-style": "^4.0.1", - "remark-parse": "11.0.0", "remark-preset-lint-node": "5.1.2", "stylelint": "16.19.1", "stylelint-config-standard": "38.0.0", @@ -106,7 +104,6 @@ "tsx": "^4.19.3", "typescript": "~5.8.2", "typescript-eslint": "~8.31.1", - "unified": "^11.0.5", "user-agent-data-types": "0.4.2" } } diff --git a/apps/site/pages/en/index.mdx b/apps/site/pages/en/index.mdx index 7b9f1403e3c7b..95de44c70f2a1 100644 --- a/apps/site/pages/en/index.mdx +++ b/apps/site/pages/en/index.mdx @@ -96,13 +96,12 @@ layout: home ```js displayName="Streams Pipeline" // streams.mjs - import { pipeline } from 'node:stream/promises'; import { createReadStream, createWriteStream } from 'node:fs'; + import { pipeline } from 'node:stream/promises'; import { createGzip } from 'node:zlib'; // ensure you have a `package.json` file for this test! - await pipeline - ( + await pipeline( createReadStream('package.json'), createGzip(), createWriteStream('package.json.gz') diff --git a/apps/site/pages/en/learn/asynchronous-work/asynchronous-flow-control.md b/apps/site/pages/en/learn/asynchronous-work/asynchronous-flow-control.md index 3fdaeebe8a2d7..6525d1ceab05f 100644 --- a/apps/site/pages/en/learn/asynchronous-work/asynchronous-flow-control.md +++ b/apps/site/pages/en/learn/asynchronous-work/asynchronous-flow-control.md @@ -114,7 +114,6 @@ function getSong() { let _song = ''; let i = 100; for (i; i > 0; i -= 1) { - /* eslint-disable no-loop-func */ setTimeout(function () { _song += `${i} beers on the wall, you take one down and pass it around, ${ i - 1 @@ -123,7 +122,6 @@ function getSong() { _song += "Hey let's get some more beer"; } }, 0); - /* eslint-enable no-loop-func */ } return _song; diff --git a/apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md b/apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md index 363a9fc1e935d..71a5c919b1ff0 100644 --- a/apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md +++ b/apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md @@ -31,7 +31,7 @@ The return value of the executor function is ignored: only `resolve` or `reject` ```js const myPromise = new Promise((resolve, reject) => { - let success = true; + const success = true; if (success) { resolve('Operation was successful!'); @@ -56,7 +56,7 @@ Once a Promise is created, you can handle the outcome by using the `.then()`, `. ```js const myPromise = new Promise((resolve, reject) => { - let success = true; + const success = true; if (success) { resolve('Operation was successful!'); diff --git a/apps/site/pages/en/learn/asynchronous-work/dont-block-the-event-loop.md b/apps/site/pages/en/learn/asynchronous-work/dont-block-the-event-loop.md index f3b32412d7ebb..12a93f01d5652 100644 --- a/apps/site/pages/en/learn/asynchronous-work/dont-block-the-event-loop.md +++ b/apps/site/pages/en/learn/asynchronous-work/dont-block-the-event-loop.md @@ -126,7 +126,7 @@ Example 2: An `O(n)` callback. This callback will run quickly for small `n` and ```js app.get('/countToN', (req, res) => { - let n = req.query.n; + const n = req.query.n; // n iterations before giving someone else a turn 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 ```js app.get('/countToN2', (req, res) => { - let n = req.query.n; + const n = req.query.n; // n^2 iterations before giving someone else a turn for (let i = 0; i < n; i++) { @@ -193,7 +193,7 @@ Here is an example vulnerable regexp exposing its server to REDOS: ```js app.get('/redos-me', (req, res) => { - let filePath = req.query.filePath; + const filePath = req.query.filePath; // REDOS if (filePath.match(/(\/.+)+$/)) { @@ -272,28 +272,30 @@ Example: JSON blocking. We create an object `obj` of size 2^21 and `JSON.stringi ```js let obj = { a: 1 }; -let niter = 20; +const iterations = 20; -let before, str, pos, res, took; - -for (let i = 0; i < niter; i++) { - obj = { obj1: obj, obj2: obj }; // Doubles in size each iter +// Expand the object exponentially by nesting it +for (let i = 0; i < iterations; i++) { + obj = { obj1: obj, obj2: obj }; } -before = process.hrtime(); -str = JSON.stringify(obj); -took = process.hrtime(before); -console.log('JSON.stringify took ' + took); - -before = process.hrtime(); -pos = str.indexOf('nomatch'); -took = process.hrtime(before); -console.log('Pure indexof took ' + took); - -before = process.hrtime(); -res = JSON.parse(str); -took = process.hrtime(before); -console.log('JSON.parse took ' + took); +// Measure time to stringify the object +let start = process.hrtime(); +const jsonString = JSON.stringify(obj); +let duration = process.hrtime(start); +console.log('JSON.stringify took', duration); + +// Measure time to search a string within the JSON +start = process.hrtime(); +const index = jsonString.indexOf('nomatch'); // Always -1 +duration = process.hrtime(start); +console.log('String.indexOf took', duration); + +// Measure time to parse the JSON back to an object +start = process.hrtime(); +const parsed = JSON.parse(jsonString); +duration = process.hrtime(start); +console.log('JSON.parse took', duration); ``` There are npm modules that offer asynchronous JSON APIs. See for example: @@ -317,7 +319,7 @@ Example 1: Un-partitioned average, costs `O(n)` ```js for (let i = 0; i < n; i++) sum += i; -let avg = sum / n; +const avg = sum / n; console.log('avg: ' + avg); ``` @@ -341,7 +343,7 @@ function asyncAvg(n, avgCB) { // Start the helper, with CB to call avgCB. help(1, function (sum) { - let avg = sum / n; + const avg = sum / n; avgCB(avg); }); } diff --git a/apps/site/pages/en/learn/asynchronous-work/event-loop-timers-and-nexttick.md b/apps/site/pages/en/learn/asynchronous-work/event-loop-timers-and-nexttick.md index 1f6680e9464ab..a50114c04d8fd 100644 --- a/apps/site/pages/en/learn/asynchronous-work/event-loop-timers-and-nexttick.md +++ b/apps/site/pages/en/learn/asynchronous-work/event-loop-timers-and-nexttick.md @@ -338,7 +338,7 @@ This philosophy can lead to some potentially problematic situations. Take this snippet for example: ```js -let bar; +let bar = null; // this has an asynchronous signature, but calls callback synchronously function someAsyncApiCall(callback) { @@ -370,7 +370,7 @@ useful for the user to be alerted to an error before the event loop is allowed to continue. Here is the previous example using `process.nextTick()`: ```js -let bar; +let bar = null; function someAsyncApiCall(callback) { process.nextTick(callback); diff --git a/apps/site/pages/en/learn/asynchronous-work/javascript-asynchronous-programming-and-callbacks.md b/apps/site/pages/en/learn/asynchronous-work/javascript-asynchronous-programming-and-callbacks.md index 5e64b756cf9b5..11b7bda915516 100644 --- a/apps/site/pages/en/learn/asynchronous-work/javascript-asynchronous-programming-and-callbacks.md +++ b/apps/site/pages/en/learn/asynchronous-work/javascript-asynchronous-programming-and-callbacks.md @@ -79,7 +79,11 @@ XHR requests also accept a callback, in this example by assigning a function to const xhr = new XMLHttpRequest(); xhr.onreadystatechange = () => { if (xhr.readyState === 4) { - xhr.status === 200 ? console.log(xhr.responseText) : console.error('error'); + if (xhr.status === 200) { + console.log(xhr.responseText); + } else { + console.error('error'); + } } }; xhr.open('GET', 'https://yoursite.com'); diff --git a/apps/site/pages/en/learn/command-line/how-to-read-environment-variables-from-nodejs.md b/apps/site/pages/en/learn/command-line/how-to-read-environment-variables-from-nodejs.md index d4d84c6c2e04d..e5cd78eaddcaa 100644 --- a/apps/site/pages/en/learn/command-line/how-to-read-environment-variables-from-nodejs.md +++ b/apps/site/pages/en/learn/command-line/how-to-read-environment-variables-from-nodejs.md @@ -21,8 +21,8 @@ That will pass the user `USER_ID` as **239482** and the `USER_KEY` as **foobar** Here is an example that accesses the `USER_ID` and `USER_KEY` environment variables, which we set in above code. ```js -process.env.USER_ID; // "239482" -process.env.USER_KEY; // "foobar" +console.log(process.env.USER_ID); // "239482" +console.log(process.env.USER_KEY); // "foobar" ``` In the same way you can access any custom environment variable you set. @@ -39,7 +39,7 @@ PORT=3000 In your js file ```js -process.env.PORT; // "3000" +console.log(process.env.PORT); // "3000" ``` Run `app.js` file with environment variables set in `.env` file. diff --git a/apps/site/pages/en/learn/diagnostics/memory/using-gc-traces.md b/apps/site/pages/en/learn/diagnostics/memory/using-gc-traces.md index 465562d5db03e..19b1b66f97a8d 100644 --- a/apps/site/pages/en/learn/diagnostics/memory/using-gc-traces.md +++ b/apps/site/pages/en/learn/diagnostics/memory/using-gc-traces.md @@ -248,8 +248,8 @@ Let's modify our script a bit: ```mjs // script-fix.mjs -import os from 'node:os'; import fs from 'node:fs/promises'; +import os from 'node:os'; let len = 1_000_000; const fileName = `entries-${Date.now()}`; @@ -366,13 +366,13 @@ You can get GC statistics as [PerformanceEntry][] from the callback in For example: -```ts -PerformanceEntry { - name: 'gc', - entryType: 'gc', - startTime: 2820.567669, - duration: 1.315709, - kind: 1 +```json +{ + "name": "gc", + "entryType": "gc", + "startTime": 2820.567669, + "duration": 1.315709, + "kind": 1 } ``` diff --git a/apps/site/pages/en/learn/getting-started/fetch.md b/apps/site/pages/en/learn/getting-started/fetch.md index 3664e4fd34f9f..26cd99cd51f70 100644 --- a/apps/site/pages/en/learn/getting-started/fetch.md +++ b/apps/site/pages/en/learn/getting-started/fetch.md @@ -133,9 +133,10 @@ try { [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. ```js -import { stream } from 'undici'; import { Writable } from 'stream'; +import { stream } from 'undici'; + async function fetchGitHubRepos() { const url = 'https://api.github.com/users/nodejs/repos'; diff --git a/apps/site/pages/en/learn/getting-started/security-best-practices.md b/apps/site/pages/en/learn/getting-started/security-best-practices.md index 03ce9976143fd..cd47ffdefe959 100644 --- a/apps/site/pages/en/learn/getting-started/security-best-practices.md +++ b/apps/site/pages/en/learn/getting-started/security-best-practices.md @@ -130,7 +130,7 @@ There are some mechanisms to control this behavior by defining a blocklist with `.npmignore`. Throughout these files, you can specify which files/folders should not be published. The [files property][] in `package.json` allows the inverse operation - -- allowed list. + \-- allowed list. - In case of an exposure, make sure to [unpublish the package][]. ### HTTP Request Smuggling (CWE-444) @@ -180,6 +180,7 @@ of requests. - The crypto API exposes a function `timingSafeEqual` to compare actual and expected sensitive values using a constant-time algorithm. + - For password comparison, you can use the [scrypt][] available also on the native crypto module. @@ -275,7 +276,6 @@ Monkey patching refers to the modification of properties in runtime aiming to change the existing behavior. Example: ```js -// eslint-disable-next-line no-extend-native Array.prototype.push = function (item) { // overriding the global [].push }; @@ -290,7 +290,6 @@ Therefore, the following snippet **will not** override the default behavior of `Array.prototype.push` ```js -// eslint-disable-next-line no-extend-native Array.prototype.push = function (item) { // overriding the global [].push }; diff --git a/apps/site/pages/en/learn/manipulating-files/nodejs-file-stats.md b/apps/site/pages/en/learn/manipulating-files/nodejs-file-stats.md index fb748a8a46424..2b196196d907d 100644 --- a/apps/site/pages/en/learn/manipulating-files/nodejs-file-stats.md +++ b/apps/site/pages/en/learn/manipulating-files/nodejs-file-stats.md @@ -92,7 +92,7 @@ fs.stat('/Users/joe/test.txt', (err, stats) => { stats.isFile(); // true stats.isDirectory(); // false stats.isSymbolicLink(); // false - stats.size; // 1024000 //= 1MB + console.log(stats.size); // 1024000 //= 1MB }); ``` @@ -123,7 +123,7 @@ try { stats.isFile(); // true stats.isDirectory(); // false stats.isSymbolicLink(); // false - stats.size; // 1024000 //= 1MB + console.log(stats.size); // 1024000 //= 1MB } catch (err) { console.log(err); } diff --git a/apps/site/pages/en/learn/manipulating-files/reading-files-with-nodejs.md b/apps/site/pages/en/learn/manipulating-files/reading-files-with-nodejs.md index 260515e7477d0..24735b2f375c0 100644 --- a/apps/site/pages/en/learn/manipulating-files/reading-files-with-nodejs.md +++ b/apps/site/pages/en/learn/manipulating-files/reading-files-with-nodejs.md @@ -91,8 +91,8 @@ In this case, a better option is to read the file content using streams. ```mjs import fs from 'fs'; -import path from 'path'; import { pipeline } from 'node:stream/promises'; +import path from 'path'; const fileUrl = 'https://www.gutenberg.org/files/2701/2701-0.txt'; const outputFilePath = path.join(process.cwd(), 'moby.md'); diff --git a/apps/site/pages/en/learn/modules/backpressuring-in-streams.md b/apps/site/pages/en/learn/modules/backpressuring-in-streams.md index 32346d6c67163..6d7f44869901c 100644 --- a/apps/site/pages/en/learn/modules/backpressuring-in-streams.md +++ b/apps/site/pages/en/learn/modules/backpressuring-in-streams.md @@ -94,8 +94,8 @@ inp.pipe(gzip).pipe(out); ``` ```mjs -import { createGzip } from 'node:zlib'; import { createReadStream, createWriteStream } from 'node:fs'; +import { createGzip } from 'node:zlib'; const gzip = createGzip(); @@ -147,8 +147,8 @@ pipeline( ``` ```mjs -import { pipeline } from 'node:stream'; import fs from 'node:fs'; +import { pipeline } from 'node:stream'; import zlib from 'node:zlib'; // Use the pipeline API to easily pipe a series of streams @@ -191,8 +191,8 @@ async function run() { ``` ```mjs -import { pipeline } from 'node:stream/promises'; import fs from 'node:fs'; +import { pipeline } from 'node:stream/promises'; import zlib from 'node:zlib'; async function run() { diff --git a/apps/site/pages/en/learn/modules/how-to-use-streams.md b/apps/site/pages/en/learn/modules/how-to-use-streams.md index 2eb59c87ed5ac..0e61b44c56152 100644 --- a/apps/site/pages/en/learn/modules/how-to-use-streams.md +++ b/apps/site/pages/en/learn/modules/how-to-use-streams.md @@ -80,29 +80,7 @@ A demonstration of the use of these events can be seen in the following sections Here's an example of a simple readable stream implementation that generates data dynamically: -```cjs -const { Readable } = require('node:stream'); - -class MyStream extends Readable { - #count = 0; - _read(size) { - this.push(':-)'); - if (++this.#count === 5) { - this.push(null); - } - } -} - -const stream = new MyStream(); - -stream.on('data', chunk => { - console.log(chunk.toString()); -}); -``` - -```mjs -import { Readable } from 'node:stream'; - +```js class MyStream extends Readable { #count = 0; _read(size) { @@ -126,22 +104,7 @@ In this code, the `MyStream` class extends Readable and overrides the [`_read`][ For even finer control over data flow, the readable event can be used. This event is more complex but provides better performance for certain applications by allowing explicit control over when data is read from the stream: -```cjs -const stream = new MyStream({ - highWaterMark: 1, -}); - -stream.on('readable', () => { - console.count('>> readable event'); - let chunk; - while ((chunk = stream.read()) !== null) { - console.log(chunk.toString()); // Process the chunk - } -}); -stream.on('end', () => console.log('>> end event')); -``` - -```mjs +```js const stream = new MyStream({ highWaterMark: 1, }); @@ -178,21 +141,7 @@ NOTE: You can try to run the code with `NODE_DEBUG=stream` to see that `emitRead If we want to see readable events called before each smiley, we can wrap `push` into a `setImmediate` or `process.nextTick` like this: -```cjs -class MyStream extends Readable { - #count = 0; - _read(size) { - setImmediate(() => { - this.push(':-)'); - if (++this.#count === 5) { - return this.push(null); - } - }); - } -} -``` - -```mjs +```js class MyStream extends Readable { #count = 0; _read(size) { @@ -269,8 +218,8 @@ main().catch(console.error); ``` ```mjs -import { Writable } from 'node:stream'; import { once } from 'node:events'; +import { Writable } from 'node:stream'; class MyStream extends Writable { constructor() { @@ -691,7 +640,7 @@ import { pipeline } from 'stream/promises'; await pipeline( fs.createReadStream(import.meta.filename), async function* (source) { - for await (let chunk of source) { + for await (const chunk of source) { yield chunk.toString().toUpperCase(); } }, diff --git a/apps/site/pages/en/learn/test-runner/mocking.md b/apps/site/pages/en/learn/test-runner/mocking.md index 61d58524abe84..62c08b4dcd8d6 100644 --- a/apps/site/pages/en/learn/test-runner/mocking.md +++ b/apps/site/pages/en/learn/test-runner/mocking.md @@ -150,7 +150,7 @@ import assert from 'node:assert/strict'; import { before, describe, it, mock } from 'node:test'; describe('foo', { concurrency: true }, () => { - let barMock = mock.fn(); + const barMock = mock.fn(); let foo; before(async () => { @@ -188,6 +188,7 @@ A little-known fact is that there is a builtin way to mock `fetch`. [`undici`](h ```mjs displayName="endpoints.spec.mjs" import assert from 'node:assert/strict'; import { beforeEach, describe, it } from 'node:test'; + import { MockAgent, setGlobalDispatcher } from 'undici'; import endpoints from './endpoints.mjs'; diff --git a/apps/site/pages/en/learn/test-runner/using-test-runner.md b/apps/site/pages/en/learn/test-runner/using-test-runner.md index 4d634b52b8c06..a73ab9382281b 100644 --- a/apps/site/pages/en/learn/test-runner/using-test-runner.md +++ b/apps/site/pages/en/learn/test-runner/using-test-runner.md @@ -269,7 +269,7 @@ function generateSnapshotPath(testFilePath) { The example below demonstrates snapshot testing with [testing library](https://testing-library.com/) for UI components; note the two different ways of accessing `assert.snapshot`): -```ts +```js import { describe, it } from 'node:test'; import { prettyDOM } from '@testing-library/dom'; @@ -277,16 +277,15 @@ import { render } from '@testing-library/react'; // Any framework (ex svelte) import { SomeComponent } from './SomeComponent.jsx'; - describe('', () => { // For people preferring "fat-arrow" syntax, the following is probably better for consistency - it('should render defaults when no props are provided', (t) => { + it('should render defaults when no props are provided', t => { const component = render().container.firstChild; t.assert.snapshot(prettyDOM(component)); }); - it('should consume `foo` when provided', function() { + it('should consume `foo` when provided', function () { const component = render().container.firstChild; this.assert.snapshot(prettyDOM(component)); @@ -384,7 +383,7 @@ function globalUIBeforeEach() { You can have 2 different levels of UI tests: a unit-like (wherein externals & dependencies are mocked) and a more end-to-end (where only externals like IndexedDb are mocked but the rest of the chain is real). The former is generally the purer option, and the latter is generally deferred to a fully end-to-end automated usability test via something like [Playwright](https://playwright.dev/) or [Puppeteer](https://pptr.dev/). Below is an example of the former. -```ts +```js import { before, describe, mock, it } from 'node:test'; import { screen } from '@testing-library/dom'; @@ -393,7 +392,6 @@ import { render } from '@testing-library/react'; // Any framework (ex svelte) // ⚠️ Note that SomeOtherComponent is NOT a static import; // this is necessary in order to facilitate mocking its own imports. - describe('', () => { let SomeOtherComponent; let calcSomeValue; @@ -402,7 +400,9 @@ describe('', () => { // ⚠️ Sequence matters: the mock must be set up BEFORE its consumer is imported. // Requires the `--experimental-test-module-mocks` be set. - calcSomeValue = mock.module('./calcSomeValue.js', { calcSomeValue: mock.fn() }); + calcSomeValue = mock.module('./calcSomeValue.js', { + calcSomeValue: mock.fn(), + }); ({ SomeOtherComponent } = await import('./SomeOtherComponent.jsx')); }); @@ -414,9 +414,11 @@ describe('', () => { // (and the snapshot would need to be updated for no real value). it('should fail gracefully by displaying a pretty error', () => { - calcSomeValue.mockImplementation(function mock__calcSomeValue() { return null }); + calcSomeValue.mockImplementation(function mock__calcSomeValue() { + return null; + }); - render(); + render(); const errorMessage = screen.queryByText('unable'); diff --git a/apps/site/pages/es/index.mdx b/apps/site/pages/es/index.mdx index 7597663b63680..2d590f93c6251 100644 --- a/apps/site/pages/es/index.mdx +++ b/apps/site/pages/es/index.mdx @@ -97,13 +97,12 @@ layout: home ```js displayName="Streams Pipeline" // streams.mjs - import { pipeline } from 'node:stream/promises'; import { createReadStream, createWriteStream } from 'node:fs'; + import { pipeline } from 'node:stream/promises'; import { createGzip } from 'node:zlib'; // ensure you have a `package.json` file for this test! - await pipeline - ( + await pipeline( createReadStream('package.json'), createGzip(), createWriteStream('package.json.gz') diff --git a/apps/site/pages/fa/index.mdx b/apps/site/pages/fa/index.mdx index ab1dc8d23fca3..d1fcd30f94bea 100644 --- a/apps/site/pages/fa/index.mdx +++ b/apps/site/pages/fa/index.mdx @@ -97,13 +97,12 @@ layout: home ```js displayName="Streams Pipeline" // streams.mjs - import { pipeline } from 'node:stream/promises'; import { createReadStream, createWriteStream } from 'node:fs'; + import { pipeline } from 'node:stream/promises'; import { createGzip } from 'node:zlib'; // ensure you have a `package.json` file for this test! - await pipeline - ( + await pipeline( createReadStream('package.json'), createGzip(), createWriteStream('package.json.gz') diff --git a/apps/site/pages/fr/index.mdx b/apps/site/pages/fr/index.mdx index 2cd8a9da0ec2c..2b72207fc2c0f 100644 --- a/apps/site/pages/fr/index.mdx +++ b/apps/site/pages/fr/index.mdx @@ -95,13 +95,12 @@ layout: home ```js displayName="Streams Pipeline" // streams.mjs - import { pipeline } from 'node:stream/promises'; import { createReadStream, createWriteStream } from 'node:fs'; + import { pipeline } from 'node:stream/promises'; import { createGzip } from 'node:zlib'; // ensure you have a `package.json` file for this test! - await pipeline - ( + await pipeline( createReadStream('package.json'), createGzip(), createWriteStream('package.json.gz') diff --git a/apps/site/pages/id/index.mdx b/apps/site/pages/id/index.mdx index f321063c28a4b..504b17b19c1a7 100644 --- a/apps/site/pages/id/index.mdx +++ b/apps/site/pages/id/index.mdx @@ -97,13 +97,12 @@ layout: home ```js displayName="Streams Pipeline" // streams.mjs - import { pipeline } from 'node:stream/promises'; import { createReadStream, createWriteStream } from 'node:fs'; + import { pipeline } from 'node:stream/promises'; import { createGzip } from 'node:zlib'; // ensure you have a `package.json` file for this test! - await pipeline - ( + await pipeline( createReadStream('package.json'), createGzip(), createWriteStream('package.json.gz') diff --git a/apps/site/pages/ja/index.mdx b/apps/site/pages/ja/index.mdx index f99616a253d6c..ad52b8da6fe26 100644 --- a/apps/site/pages/ja/index.mdx +++ b/apps/site/pages/ja/index.mdx @@ -95,13 +95,12 @@ layout: home ```js displayName="Streams Pipeline" // streams.mjs - import { pipeline } from 'node:stream/promises'; import { createReadStream, createWriteStream } from 'node:fs'; + import { pipeline } from 'node:stream/promises'; import { createGzip } from 'node:zlib'; // ensure you have a `package.json` file for this test! - await pipeline - ( + await pipeline( createReadStream('package.json'), createGzip(), createWriteStream('package.json.gz') diff --git a/apps/site/pages/ko/index.mdx b/apps/site/pages/ko/index.mdx index f392ffcbcb1bb..a4119867639ba 100644 --- a/apps/site/pages/ko/index.mdx +++ b/apps/site/pages/ko/index.mdx @@ -95,8 +95,8 @@ const fileHash = hasher.read(); ```js displayName="Streams Pipeline" // streams.mjs -import { pipeline } from 'node:stream/promises'; import { createReadStream, createWriteStream } from 'node:fs'; +import { pipeline } from 'node:stream/promises'; import { createGzip } from 'node:zlib'; // ensure you have a `package.json` file for this test! diff --git a/apps/site/pages/pt/index.mdx b/apps/site/pages/pt/index.mdx index af90aa6b5727e..aafd3aa3adbcf 100644 --- a/apps/site/pages/pt/index.mdx +++ b/apps/site/pages/pt/index.mdx @@ -97,13 +97,12 @@ layout: home ```js displayName="Streams Pipeline" // streams.mjs - import { pipeline } from 'node:stream/promises'; import { createReadStream, createWriteStream } from 'node:fs'; + import { pipeline } from 'node:stream/promises'; import { createGzip } from 'node:zlib'; // ensure you have a `package.json` file for this test! - await pipeline - ( + await pipeline( createReadStream('package.json'), createGzip(), createWriteStream('package.json.gz') diff --git a/apps/site/pages/tr/index.mdx b/apps/site/pages/tr/index.mdx index 19d3aa83e7ede..7d4f9f71acba1 100644 --- a/apps/site/pages/tr/index.mdx +++ b/apps/site/pages/tr/index.mdx @@ -103,13 +103,12 @@ layout: home ```js displayName="Streams Pipeline" // streams.mjs - import { pipeline } from 'node:stream/promises'; import { createReadStream, createWriteStream } from 'node:fs'; + import { pipeline } from 'node:stream/promises'; import { createGzip } from 'node:zlib'; // ensure you have a `package.json` file for this test! - await pipeline - ( + await pipeline( createReadStream('package.json'), createGzip(), createWriteStream('package.json.gz') diff --git a/apps/site/pages/uk/index.mdx b/apps/site/pages/uk/index.mdx index e7f678d14918c..3dc5d595ee0c7 100644 --- a/apps/site/pages/uk/index.mdx +++ b/apps/site/pages/uk/index.mdx @@ -96,13 +96,12 @@ layout: home ```js displayName="Streams Pipeline" // streams.mjs - import { pipeline } from 'node:stream/promises'; import { createReadStream, createWriteStream } from 'node:fs'; + import { pipeline } from 'node:stream/promises'; import { createGzip } from 'node:zlib'; // ensure you have a `package.json` file for this test! - await pipeline - ( + await pipeline( createReadStream('package.json'), createGzip(), createWriteStream('package.json.gz') diff --git a/apps/site/pages/zh-cn/index.mdx b/apps/site/pages/zh-cn/index.mdx index 120fe32b48227..1a8db0b4cefa7 100644 --- a/apps/site/pages/zh-cn/index.mdx +++ b/apps/site/pages/zh-cn/index.mdx @@ -96,13 +96,12 @@ layout: home ```js displayName="Streams Pipeline" // streams.mjs - import { pipeline } from 'node:stream/promises'; import { createReadStream, createWriteStream } from 'node:fs'; + import { pipeline } from 'node:stream/promises'; import { createGzip } from 'node:zlib'; // ensure you have a `package.json` file for this test! - await pipeline - ( + await pipeline( createReadStream('package.json'), createGzip(), createWriteStream('package.json.gz') diff --git a/apps/site/pages/zh-tw/index.mdx b/apps/site/pages/zh-tw/index.mdx index 37766774fd1e3..ab67d2e2d9670 100644 --- a/apps/site/pages/zh-tw/index.mdx +++ b/apps/site/pages/zh-tw/index.mdx @@ -95,13 +95,12 @@ layout: home ```js displayName="Streams Pipeline" // streams.mjs - import { pipeline } from 'node:stream/promises'; import { createReadStream, createWriteStream } from 'node:fs'; + import { pipeline } from 'node:stream/promises'; import { createGzip } from 'node:zlib'; // ensure you have a `package.json` file for this test! - await pipeline - ( + await pipeline( createReadStream('package.json'), createGzip(), createWriteStream('package.json.gz') diff --git a/apps/site/scripts/lint-snippets/index.mjs b/apps/site/scripts/lint-snippets/index.mjs deleted file mode 100755 index 266dba933555b..0000000000000 --- a/apps/site/scripts/lint-snippets/index.mjs +++ /dev/null @@ -1,98 +0,0 @@ -import { readFile } from 'node:fs/promises'; - -import { parse } from 'acorn'; -import { glob } from 'glob'; -import remarkParse from 'remark-parse'; -import { unified } from 'unified'; -import { visit } from 'unist-util-visit'; - -const SUPPORTED_LANGUAGES = ['js', 'mjs', 'cjs']; - -// Initialize the markdown parser -const markdownParser = unified().use(remarkParse); - -/** - * Parse JavaScript code using Acorn - * - * @param {string} code - The code to parse - * @param {string} language - The language identifier - * @returns {void} - * @throws {Error} If parsing fails - */ -function parseJavaScript(code, language) { - parse(code, { - ecmaVersion: 'latest', - sourceType: language === 'cjs' ? 'script' : 'module', - allowReturnOutsideFunction: true, - }); -} - -/** - * Validate code blocks in a markdown file - * - * @param {string} filePath - Path to the markdown file - * @returns {Array<{path: string, position: number, message: string}>} Array of errors - */ -async function validateFile(filePath) { - const errors = []; - - const content = await readFile(filePath, 'utf-8'); - const tree = markdownParser.parse(content); - - visit(tree, 'code', node => { - // TODO: Add TypeScript support - if (!SUPPORTED_LANGUAGES.includes(node.lang)) { - return; - } - - try { - parseJavaScript(node.value, node.lang); - } catch (err) { - errors.push({ - path: filePath, - position: node.position.start.line, - message: err.message, - }); - } - }); - - return errors; -} - -/** - * Print validation errors to console - * - * @param {Array<{path: string, position: number, message: string}>} errors - * @returns {void} - */ -function reportErrors(errors) { - if (errors.length === 0) { - return; - } - - console.error('Errors found in the following files:'); - errors.forEach(({ path, position, message }) => { - console.error(`- ${path}:${position}: ${message}`); - }); -} - -// Get all markdown files -const filePaths = await glob('**/*.md', { - root: process.cwd(), - cwd: 'pages/en/learn/', - absolute: true, -}); - -console.log(`Found ${filePaths.length} markdown files.`); - -// Validate all files and collect errors -const allErrors = await Promise.all(filePaths.map(validateFile)); - -// Flatten the array of errors -const flattenedErrors = allErrors.flat(); - -// Report errors if any -reportErrors(flattenedErrors); - -// Exit with appropriate code -process.exit(flattenedErrors.length > 0 ? 1 : 0); diff --git a/apps/site/turbo.json b/apps/site/turbo.json index 98a1fb32f3bcc..f9c3d06612257 100644 --- a/apps/site/turbo.json +++ b/apps/site/turbo.json @@ -108,10 +108,6 @@ "inputs": ["{app,pages}/**/*.{md,mdx}", "*.{md,mdx}"], "outputs": [".eslintmdcache"] }, - "lint:snippets": { - "inputs": ["{app,pages}/**/*.{md,mdx}", "*.{md,mdx}"], - "outputs": [] - }, "lint:css": { "inputs": ["{app,components,layouts,pages,styles}/**/*.css"], "outputs": [".stylelintcache"] diff --git a/package.json b/package.json index e52404ead05a8..236258af52ac4 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,6 @@ "test:ci": "cross-env NODE_OPTIONS=\"--test-reporter=lcov --test-reporter-destination=lcov.info --test-reporter=junit --test-reporter-destination=junit.xml --test-reporter=@reporters/github --test-reporter-destination=stdout --test-reporter=spec --test-reporter-destination=stdout\" turbo test:unit" }, "dependencies": { - "acorn": "^8.14.1", "husky": "9.1.7", "lint-staged": "15.5.1", "turbo": "2.5.2" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ffa15d561ac56..eb6a2fa7279a2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,9 +8,6 @@ importers: .: dependencies: - acorn: - specifier: ^8.14.1 - version: 8.14.1 husky: specifier: 9.1.7 version: 9.1.7 @@ -271,9 +268,6 @@ importers: remark-lint-unordered-list-marker-style: specifier: ^4.0.1 version: 4.0.1 - remark-parse: - specifier: 11.0.0 - version: 11.0.0 remark-preset-lint-node: specifier: 5.1.2 version: 5.1.2 @@ -298,9 +292,6 @@ importers: typescript-eslint: specifier: ~8.31.1 version: 8.31.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3) - unified: - specifier: ^11.0.5 - version: 11.0.5 user-agent-data-types: specifier: 0.4.2 version: 0.4.2 diff --git a/turbo.json b/turbo.json index 91a077be9babc..80bcb76f5f7ff 100644 --- a/turbo.json +++ b/turbo.json @@ -11,7 +11,6 @@ "lint": { "dependsOn": [ "@node-core/website#lint:md", - "@node-core/website#lint:snippets", "@node-core/website#lint:css", "lint:js" ] @@ -19,7 +18,6 @@ "lint:lint-staged": { "dependsOn": [ "@node-core/website#lint:md", - "@node-core/website#lint:snippets", "@node-core/website#lint:css", "@node-core/website#lint:js" ]