diff --git a/apps/site/.cloudflare/node/fs.mjs b/apps/site/.cloudflare/node/fs.mjs index a110392827702..5a94da8c318dc 100644 --- a/apps/site/.cloudflare/node/fs.mjs +++ b/apps/site/.cloudflare/node/fs.mjs @@ -1,12 +1,20 @@ -// import { AsyncLocalStorage } from 'node:async_hooks'; -// import { Buffer } from 'node:buffer'; +import { files } from '../../next.helpers.mjs'; -// export const als = new AsyncLocalStorage(); - -export function readFileSync(path) { - return globalThis.PAGES.fetch(path); +export function readdir(params, cb) { + console.log('fs#readdir', params); + cb(null, []); } -export function readdir(params) { - console.log('claudio', params); +export function exists(path, cb) { + console.log('fs#exists', path, files.includes(path)); + cb(files.includes(path)); } + +// export function createReadStream(path) { +// return env.ASSETS.fetch(path).then(response => response.body); +// } + +export default { + readdir, + exists, +}; diff --git a/apps/site/.cloudflare/node/fs/promises.mjs b/apps/site/.cloudflare/node/fs/promises.mjs index 74fd650e6ebe2..c2e5539097f38 100644 --- a/apps/site/.cloudflare/node/fs/promises.mjs +++ b/apps/site/.cloudflare/node/fs/promises.mjs @@ -1,3 +1,28 @@ +import { getCloudflareContext } from '@opennextjs/cloudflare'; + export async function readFile(path) { - return env.PAGES.fetch(path); + console.log('fs/promies#readFile', path); + + const { env } = await getCloudflareContext(); + + const text = await env.ASSETS.fetch( + new URL(path, 'https://jamesrocks/') + ).then(response => response.text()); + return text; } + +export async function readdir(params) { + console.log('fs/promises#readdir', params); + return Promise.resolve([]); +} + +export async function exists(...args) { + console.log('fs/promises#exists', args); + return Promise.resolve(false); +} + +export default { + readdir, + exists, + readFile, +}; diff --git a/apps/site/CLOUDFLARE.md b/apps/site/CLOUDFLARE.md new file mode 100644 index 0000000000000..0fa86716878ad --- /dev/null +++ b/apps/site/CLOUDFLARE.md @@ -0,0 +1,87 @@ +# nodejs.org on OpenNext for Cloudflare + +## Getting started + +To develop, build, preview, and deploy nodejs.org, execute the following commands to get started: + +``` +nvm use +npm install +cd apps/site +``` + +As some of the commands use [turborepo](https://turbo.build/repo/docs), we recommend you install it globally: + +``` +npm install turbo --global +``` + +## Developing locally + +To develop locally, run the usual: + +``` +npm run dev +``` + +or with turbo: + +``` +turbo dev +``` + +## Build nodejs.org production distribution using OpenNext + +To build you need connection to the Internet because the build system will try to fetch the following files: + +- https://nodejs.org/dist/index.json +- https://raw.githubusercontent.com/nodejs/Release/master/schedule.json + +``` +npm run build:cloudflare +``` + +or you can build with turborepo: + +``` +turbo build:cloudflare +``` + +## Preview a production build locally + +You can preview production build locally using [wrangler](https://developers.cloudflare.com/workers/wrangler/): + +``` +turbo preview:cloudflare +``` + +## Deploying a build to production + +To build and deploy the application run: + +``` +turbo deploy:cloudflare +``` + +The build is currently deployed to a dedicated "nodejs.org" (Cloudflare account id: fb4a2d0f103c6ff38854ac69eb709272). + +You can monitor and configure the project at https://dash.cloudflare.com/fb4a2d0f103c6ff38854ac69eb709272/workers/services/view/nodejs-website/production + +## TODOs + +The following is an incomplete list of tasks and problems that still need to be resolved: + +- [ ] update `@opennextjs/cloudflare` to the latest in `/apps/site/package.json` +- [ ] sort out issues with `eval` and MDX and undo edits in `./app/[locale]/[[...path]]/page.tsx` +- [ ] reimplement `getMarkdownFiles` in `next.helpers.mjs` to be generated at build time + - this can be accomplished either via a npm/turbo prebuild task, or possibly as part of next.js SSG/staticProps (but we need to ensure that we don't end up accidentaly downloading this big file to the client as part of hydration) + - [ ] once we have easy access to the list of files, we should roll back changes to `next-data/providers/blogData.ts` +- [ ] back out most changes from `next.dynamic.mjs` + - [ ] instead of using runtime detection via `globalThis.navigator?.userAgent`, we should instead use `alias` feature in `wrangler.toml` to override the implementation of `node:fs` calls but only when running in workerd as we need the build to keep on running in node.js for SSG to work + - [ ] could we reimplement the `existsAsync` call as sync `exists` which consults `getMarkdownFiles` from the task above? alternatively + - [ ] properly implement the rest of `.cloudflare/node/*` polyfills +- [ ] remove symlink hack in `package.json#build:cloudflare` + - would it be possible to make the pages directory part of assets in a less hacky way? + - [ ] move these files under `.worker-next/assets/cdn-cgi/pages` so that these raw md files are not publicly accessible as that could become a maintenance burden down the road. +- [ ] review and improve `/apps/site/turbo.json` changes +- [ ] reenable minification in `next.config.mjs` diff --git a/apps/site/next-data/providers/blogData.ts b/apps/site/next-data/providers/blogData.ts index 4f26637eac2a6..b065b0cb93ad9 100644 --- a/apps/site/next-data/providers/blogData.ts +++ b/apps/site/next-data/providers/blogData.ts @@ -1,10 +1,10 @@ import { cache } from 'react'; -import generateBlogData from '@/next-data/generators/blogData.mjs'; +// import generateBlogData from '@/next-data/generators/blogData.mjs'; import { BLOG_POSTS_PER_PAGE } from '@/next.constants.mjs'; import type { BlogPostsRSC } from '@/types'; -const { categories, posts } = await generateBlogData(); +const { categories, posts } = { categories: [], posts: [] }; export const provideBlogCategories = cache(() => categories); diff --git a/apps/site/next.config.mjs b/apps/site/next.config.mjs index 2fc5c7ef02749..7dc8529633f6c 100644 --- a/apps/site/next.config.mjs +++ b/apps/site/next.config.mjs @@ -76,6 +76,11 @@ const nextConfig = { resolve: { fullySpecified: false }, }); + // CF hacking: temporarily disable minification to make debugging easier + config.optimization = { + minimize: false, + }; + return config; }, experimental: { diff --git a/apps/site/next.dynamic.mjs b/apps/site/next.dynamic.mjs index c7879e2783a70..4ae5937024a8d 100644 --- a/apps/site/next.dynamic.mjs +++ b/apps/site/next.dynamic.mjs @@ -1,13 +1,15 @@ 'use strict'; -import { existsSync } from 'node:fs'; -import { readFile } from 'node:fs/promises'; +import { exists as nodeExists } from 'node:fs'; +import { readFile as nodeReadFile } from 'node:fs/promises'; import { join, normalize, sep } from 'node:path'; import matter from 'gray-matter'; import { cache } from 'react'; import { VFile } from 'vfile'; +import { readFile as runtimeReadFile } from './.cloudflare/node/fs/promises.mjs'; +import { exists as runtimeExists } from './.cloudflare/node/fs.mjs'; import { BASE_URL, BASE_PATH, IS_DEVELOPMENT } from './next.constants.mjs'; import { IGNORED_ROUTES, @@ -19,6 +21,15 @@ import { siteConfig } from './next.json.mjs'; import { availableLocaleCodes, defaultLocale } from './next.locales.mjs'; import { compileMDX } from './next.mdx.compiler.mjs'; +const readFile = + globalThis.navigator?.userAgent === 'Cloudflare-Workers' + ? runtimeReadFile + : nodeReadFile; +const exists = + globalThis.navigator?.userAgent === 'Cloudflare-Workers' + ? runtimeExists + : nodeExists; + // This is the combination of the Application Base URL and Base PATH const baseUrlAndPath = `${BASE_URL}${BASE_PATH}`; @@ -56,7 +67,7 @@ const getDynamicRouter = async () => { const websitePages = await getMarkdownFiles( process.cwd(), - `pages/${defaultLocale.code}` + `/pages/${defaultLocale.code}` ); websitePages.forEach(filename => { @@ -120,11 +131,14 @@ const getDynamicRouter = async () => { return { source: fileContent, filename }; } + const existsPromise = path => + new Promise(resolve => exists(path, resolve)); + // No cache hit exists, so we check if the localized file actually // exists within our file system and if it does we set it on the cache // and return the current fetched result; If the file does not exist // we fallback to the English source - if (existsSync(join(filePath, locale, filename))) { + if (await existsPromise(join(filePath, locale, filename))) { filePath = join(filePath, locale, filename); const fileContent = await readFile(filePath, 'utf8'); diff --git a/apps/site/next.helpers.mjs b/apps/site/next.helpers.mjs index e4cb68533d1e9..b96fe9a08e91a 100644 --- a/apps/site/next.helpers.mjs +++ b/apps/site/next.helpers.mjs @@ -2,7 +2,7 @@ import { fileURLToPath } from 'node:url'; -import { glob } from 'glob'; +//import { glob } from 'glob'; /** * We create a locale cache of Glob Promises @@ -16,19 +16,6 @@ const globCacheByPath = new Map(); export const getMatchingRoutes = (route = '', matches = []) => matches.some(match => route === match); -/** - * This method is responsible for reading all immediate subdirectories of a directory - * - * @param {string} root the root directory to search from - * @param {string} cwd the current working directory - * @returns {Promise>} a promise containing an array of directories - */ -export const getDirectories = async (root, cwd) => { - return glob('*', { root, cwd, withFileTypes: true }) - .then(d => d.filter(e => e.isDirectory())) - .then(d => d.map(e => e.name)); -}; - /** * This gets the relative path from `import.meta.url` * @@ -53,8 +40,1190 @@ export const getMarkdownFiles = async (root, cwd, ignore = []) => { const cacheKey = `${root}${cwd}${ignore.join('')}`; if (!globCacheByPath.has(cacheKey)) { - globCacheByPath.set(cacheKey, glob('**/*.{md,mdx}', { root, cwd, ignore })); + //globCacheByPath.set(cacheKey, glob('**/*.{md,mdx}', { root, cwd, ignore })); + globCacheByPath.set( + cacheKey, + Promise.resolve( + files + .filter(file => file.startsWith(cwd)) + .map(file => file.replace(`${cwd}/`, '/')) + ) + ); } return globCacheByPath.get(cacheKey); }; + +export const files = [ + '/pages/ja/search.mdx', + '/pages/ja/index.mdx', + '/pages/ja/about/get-involved/events.mdx', + '/pages/ja/about/get-involved/index.md', + '/pages/ja/about/index.mdx', + '/pages/ja/about/branding.mdx', + '/pages/ja/about/previous-releases.mdx', + '/pages/ja/download/prebuilt-installer/index.mdx', + '/pages/ja/download/prebuilt-installer/current.mdx', + '/pages/ja/download/package-manager/index.mdx', + '/pages/ja/download/package-manager/current.mdx', + '/pages/ja/download/prebuilt-binaries/index.mdx', + '/pages/ja/download/prebuilt-binaries/current.mdx', + '/pages/ja/download/source-code/index.mdx', + '/pages/ja/download/source-code/current.mdx', + '/pages/zh-cn/search.mdx', + '/pages/zh-cn/index.mdx', + '/pages/zh-cn/about/security-reporting.mdx', + '/pages/zh-cn/about/get-involved/events.mdx', + '/pages/zh-cn/about/get-involved/contribute.md', + '/pages/zh-cn/about/get-involved/index.md', + '/pages/zh-cn/about/get-involved/collab-summit.md', + '/pages/zh-cn/about/index.mdx', + '/pages/zh-cn/about/governance.md', + '/pages/zh-cn/about/branding.mdx', + '/pages/zh-cn/about/previous-releases.mdx', + '/pages/zh-cn/download/prebuilt-installer/index.mdx', + '/pages/zh-cn/download/prebuilt-installer/current.mdx', + '/pages/zh-cn/download/package-manager/index.mdx', + '/pages/zh-cn/download/package-manager/current.mdx', + '/pages/zh-cn/download/package-manager/all.md', + '/pages/zh-cn/download/prebuilt-binaries/index.mdx', + '/pages/zh-cn/download/prebuilt-binaries/current.mdx', + '/pages/zh-cn/download/source-code/index.mdx', + '/pages/zh-cn/download/source-code/current.mdx', + '/pages/pt/search.mdx', + '/pages/pt/index.mdx', + '/pages/pt/about/security-reporting.mdx', + '/pages/pt/about/get-involved/events.mdx', + '/pages/pt/about/get-involved/contribute.md', + '/pages/pt/about/get-involved/index.md', + '/pages/pt/about/get-involved/collab-summit.md', + '/pages/pt/about/index.mdx', + '/pages/pt/about/governance.md', + '/pages/pt/about/branding.mdx', + '/pages/pt/about/previous-releases.mdx', + '/pages/pt/download/prebuilt-installer/index.mdx', + '/pages/pt/download/prebuilt-installer/current.mdx', + '/pages/pt/download/package-manager/index.mdx', + '/pages/pt/download/package-manager/current.mdx', + '/pages/pt/download/package-manager/all.md', + '/pages/pt/download/prebuilt-binaries/index.mdx', + '/pages/pt/download/prebuilt-binaries/current.mdx', + '/pages/pt/download/source-code/index.mdx', + '/pages/pt/download/source-code/current.mdx', + '/pages/uk/search.mdx', + '/pages/uk/index.mdx', + '/pages/uk/about/security-reporting.mdx', + '/pages/uk/about/get-involved/events.mdx', + '/pages/uk/about/get-involved/contribute.md', + '/pages/uk/about/get-involved/index.md', + '/pages/uk/about/get-involved/collab-summit.md', + '/pages/uk/about/index.mdx', + '/pages/uk/about/governance.md', + '/pages/uk/about/branding.mdx', + '/pages/uk/about/previous-releases.mdx', + '/pages/uk/download/prebuilt-installer/index.mdx', + '/pages/uk/download/prebuilt-installer/current.mdx', + '/pages/uk/download/package-manager/index.mdx', + '/pages/uk/download/package-manager/current.mdx', + '/pages/uk/download/package-manager/all.md', + '/pages/uk/download/prebuilt-binaries/index.mdx', + '/pages/uk/download/prebuilt-binaries/current.mdx', + '/pages/uk/download/source-code/index.mdx', + '/pages/uk/download/source-code/current.mdx', + '/pages/zh-tw/search.mdx', + '/pages/zh-tw/index.mdx', + '/pages/zh-tw/about/security-reporting.mdx', + '/pages/zh-tw/about/get-involved/events.mdx', + '/pages/zh-tw/about/get-involved/contribute.md', + '/pages/zh-tw/about/get-involved/index.md', + '/pages/zh-tw/about/get-involved/collab-summit.md', + '/pages/zh-tw/about/index.mdx', + '/pages/zh-tw/about/governance.md', + '/pages/zh-tw/about/branding.mdx', + '/pages/zh-tw/about/previous-releases.mdx', + '/pages/zh-tw/download/prebuilt-installer/index.mdx', + '/pages/zh-tw/download/prebuilt-installer/current.mdx', + '/pages/zh-tw/download/package-manager/index.mdx', + '/pages/zh-tw/download/package-manager/current.mdx', + '/pages/zh-tw/download/package-manager/all.md', + '/pages/zh-tw/download/prebuilt-binaries/index.mdx', + '/pages/zh-tw/download/prebuilt-binaries/current.mdx', + '/pages/zh-tw/download/source-code/index.mdx', + '/pages/zh-tw/download/source-code/current.mdx', + '/pages/ko/search.mdx', + '/pages/ko/index.mdx', + '/pages/ko/download/source-code/index.mdx', + '/pages/id/search.mdx', + '/pages/id/index.mdx', + '/pages/id/about/security-reporting.mdx', + '/pages/id/about/get-involved/events.mdx', + '/pages/id/about/get-involved/contribute.md', + '/pages/id/about/get-involved/index.md', + '/pages/id/about/get-involved/collab-summit.md', + '/pages/id/about/index.mdx', + '/pages/id/about/governance.md', + '/pages/id/about/branding.mdx', + '/pages/id/about/previous-releases.mdx', + '/pages/id/download/prebuilt-installer/index.mdx', + '/pages/id/download/prebuilt-installer/current.mdx', + '/pages/id/download/package-manager/index.mdx', + '/pages/id/download/package-manager/current.mdx', + '/pages/id/download/package-manager/all.md', + '/pages/id/download/prebuilt-binaries/index.mdx', + '/pages/id/download/prebuilt-binaries/current.mdx', + '/pages/id/download/source-code/index.mdx', + '/pages/id/download/source-code/current.mdx', + '/pages/fr/search.mdx', + '/pages/fr/index.mdx', + '/pages/fr/about/security-reporting.mdx', + '/pages/fr/about/get-involved/events.mdx', + '/pages/fr/about/get-involved/contribute.md', + '/pages/fr/about/get-involved/index.md', + '/pages/fr/about/get-involved/collab-summit.md', + '/pages/fr/about/index.mdx', + '/pages/fr/about/governance.md', + '/pages/fr/about/branding.mdx', + '/pages/fr/about/previous-releases.mdx', + '/pages/fr/download/prebuilt-installer/index.mdx', + '/pages/fr/download/prebuilt-installer/current.mdx', + '/pages/fr/download/package-manager/index.mdx', + '/pages/fr/download/package-manager/current.mdx', + '/pages/fr/download/package-manager/all.md', + '/pages/fr/download/prebuilt-binaries/index.mdx', + '/pages/fr/download/prebuilt-binaries/current.mdx', + '/pages/fr/download/source-code/index.mdx', + '/pages/fr/download/source-code/current.mdx', + '/pages/es/search.mdx', + '/pages/es/index.mdx', + '/pages/en/search.mdx', + '/pages/en/learn/typescript/introduction.md', + '/pages/en/learn/typescript/transpile.md', + '/pages/en/learn/typescript/run.md', + '/pages/en/learn/typescript/run-natively.md', + '/pages/en/learn/command-line/accept-input-from-the-command-line-in-nodejs.md', + '/pages/en/learn/command-line/output-to-the-command-line-using-nodejs.md', + '/pages/en/learn/command-line/how-to-read-environment-variables-from-nodejs.md', + '/pages/en/learn/command-line/run-nodejs-scripts-from-the-command-line.md', + '/pages/en/learn/command-line/how-to-use-the-nodejs-repl.md', + '/pages/en/learn/getting-started/nodejs-the-difference-between-development-and-production.md', + '/pages/en/learn/getting-started/how-much-javascript-do-you-need-to-know-to-use-nodejs.md', + '/pages/en/learn/getting-started/an-introduction-to-the-npm-package-manager.md', + '/pages/en/learn/getting-started/differences-between-nodejs-and-the-browser.md', + '/pages/en/learn/getting-started/security-best-practices.md', + '/pages/en/learn/getting-started/profiling.md', + '/pages/en/learn/getting-started/introduction-to-nodejs.md', + '/pages/en/learn/getting-started/ecmascript-2015-es6-and-beyond.md', + '/pages/en/learn/getting-started/nodejs-with-webassembly.md', + '/pages/en/learn/getting-started/the-v8-javascript-engine.md', + '/pages/en/learn/getting-started/how-to-install-nodejs.md', + '/pages/en/learn/getting-started/debugging.md', + '/pages/en/learn/diagnostics/memory/using-gc-traces.md', + '/pages/en/learn/diagnostics/memory/index.md', + '/pages/en/learn/diagnostics/memory/using-heap-snapshot.md', + '/pages/en/learn/diagnostics/memory/using-heap-profiler.md', + '/pages/en/learn/diagnostics/live-debugging/using-inspector.md', + '/pages/en/learn/diagnostics/live-debugging/index.md', + '/pages/en/learn/diagnostics/user-journey.md', + '/pages/en/learn/diagnostics/flame-graphs.md', + '/pages/en/learn/diagnostics/poor-performance/index.md', + '/pages/en/learn/diagnostics/poor-performance/using-linux-perf.md', + '/pages/en/learn/test-runner/mocking.md', + '/pages/en/learn/test-runner/introduction.md', + '/pages/en/learn/test-runner/using-test-runner.md', + '/pages/en/learn/manipulating-files/writing-files-with-nodejs.md', + '/pages/en/learn/manipulating-files/nodejs-file-stats.md', + '/pages/en/learn/manipulating-files/working-with-different-filesystems.md', + '/pages/en/learn/manipulating-files/working-with-folders-in-nodejs.md', + '/pages/en/learn/manipulating-files/nodejs-file-paths.md', + '/pages/en/learn/manipulating-files/reading-files-with-nodejs.md', + '/pages/en/learn/manipulating-files/working-with-file-descriptors-in-nodejs.md', + '/pages/en/learn/modules/publishing-node-api-modules.md', + '/pages/en/learn/modules/anatomy-of-an-http-transaction.md', + '/pages/en/learn/modules/backpressuring-in-streams.md', + '/pages/en/learn/modules/abi-stability.md', + '/pages/en/learn/asynchronous-work/understanding-setimmediate.md', + '/pages/en/learn/asynchronous-work/discover-javascript-timers.md', + '/pages/en/learn/asynchronous-work/javascript-asynchronous-programming-and-callbacks.md', + '/pages/en/learn/asynchronous-work/event-loop-timers-and-nexttick.md', + '/pages/en/learn/asynchronous-work/overview-of-blocking-vs-non-blocking.md', + '/pages/en/learn/asynchronous-work/asynchronous-flow-control.md', + '/pages/en/learn/asynchronous-work/understanding-processnexttick.md', + '/pages/en/learn/asynchronous-work/dont-block-the-event-loop.md', + '/pages/en/learn/asynchronous-work/the-nodejs-event-emitter.md', + '/pages/en/index.mdx', + '/pages/en/about/security-reporting.mdx', + '/pages/en/about/get-involved/events.mdx', + '/pages/en/about/get-involved/contribute.md', + '/pages/en/about/get-involved/index.md', + '/pages/en/about/get-involved/collab-summit.md', + '/pages/en/about/index.mdx', + '/pages/en/about/governance.md', + '/pages/en/about/branding.mdx', + '/pages/en/about/previous-releases.mdx', + '/pages/en/blog/video/bert-belder-libuv-lxjs-2012.md', + '/pages/en/blog/video/welcome-to-the-node-blog.md', + '/pages/en/blog/video/bryan-cantrill-instrumenting-the-real-time-web.md', + '/pages/en/blog/module/multi-server-continuous-deployment-with-fleet.md', + '/pages/en/blog/module/service-logging-in-json-with-bunyan.md', + '/pages/en/blog/announcements/interactive-2016-ams.md', + '/pages/en/blog/announcements/interactive-2016-north-america-schedule.md', + '/pages/en/blog/announcements/nodejs-security-project.md', + '/pages/en/blog/announcements/v22-release-announce.md', + '/pages/en/blog/announcements/interactive-2015.md', + '/pages/en/blog/announcements/v21-release-announce.md', + '/pages/en/blog/announcements/foundation-advances-growth.md', + '/pages/en/blog/announcements/v20-release-announce.md', + '/pages/en/blog/announcements/appdynamics-newrelic-opbeat-sphinx.md', + '/pages/en/blog/announcements/nodejs-foundation-survey.md', + '/pages/en/blog/announcements/update-v8-5.4.md', + '/pages/en/blog/announcements/diving-into-the-nodejs-website-redesign.md', + '/pages/en/blog/announcements/foundation-elects-board.md', + '/pages/en/blog/announcements/apigee-rising-stack-yahoo.md', + '/pages/en/blog/announcements/foundation-express-news.md', + '/pages/en/blog/announcements/v5-to-v7.md', + '/pages/en/blog/announcements/v6-release.md', + '/pages/en/blog/announcements/welcome-google.md', + '/pages/en/blog/announcements/nodejs-trademarks-transferred-to-openjs-foundation.md', + '/pages/en/blog/announcements/cars-dynatrace.md', + '/pages/en/blog/announcements/v19-release-announce.md', + '/pages/en/blog/announcements/retiring-the-node-js-community-committee.md', + '/pages/en/blog/announcements/nodejs-certified-developer-program.md', + '/pages/en/blog/announcements/v18-release-announce.md', + '/pages/en/blog/announcements/interactive-2015-keynotes.md', + '/pages/en/blog/announcements/interactive-2015-programming.md', + '/pages/en/blog/announcements/foundation-v4-announce.md', + '/pages/en/blog/announcements/node-js-march-17-incident.md', + '/pages/en/blog/announcements/adjusted-release-schedule-covid.md', + '/pages/en/blog/announcements/nodejs16-eol.md', + '/pages/en/blog/announcements/nodejs-foundation-momentum-release.md', + '/pages/en/blog/announcements/welcome-redhat.md', + '/pages/en/blog/release/v9.11.1.md', + '/pages/en/blog/release/v18.10.0.md', + '/pages/en/blog/release/v4.6.0.md', + '/pages/en/blog/release/v0.11.15.md', + '/pages/en/blog/release/v15.9.0.md', + '/pages/en/blog/release/v7.2.1.md', + '/pages/en/blog/release/v9.2.0.md', + '/pages/en/blog/release/v8.11.0.md', + '/pages/en/blog/release/v5.2.0.md', + '/pages/en/blog/release/v12.22.6.md', + '/pages/en/blog/release/v0.12.2.md', + '/pages/en/blog/release/v0.8.25.md', + '/pages/en/blog/release/v21.7.3.md', + '/pages/en/blog/release/v8.6.0.md', + '/pages/en/blog/release/v8.9.3.md', + '/pages/en/blog/release/v19.9.0.md', + '/pages/en/blog/release/v17.9.1.md', + '/pages/en/blog/release/v6.9.2.md', + '/pages/en/blog/release/v0.4.9.md', + '/pages/en/blog/release/v16.18.0.md', + '/pages/en/blog/release/v0.11.5.md', + '/pages/en/blog/release/v0.6.12.md', + '/pages/en/blog/release/v0.8.11.md', + '/pages/en/blog/release/v20.15.1.md', + '/pages/en/blog/release/v12.20.0.md', + '/pages/en/blog/release/v20.14.0.md', + '/pages/en/blog/release/v19.8.1.md', + '/pages/en/blog/release/v6.7.0.md', + '/pages/en/blog/release/v17.8.0.md', + '/pages/en/blog/release/v16.19.1.md', + '/pages/en/blog/release/v0.5.8.md', + '/pages/en/blog/release/v0.10.4.md', + '/pages/en/blog/release/v21.6.2.md', + '/pages/en/blog/release/v4.4.6.md', + '/pages/en/blog/release/v7.3.0.md', + '/pages/en/blog/release/v9.10.0.md', + '/pages/en/blog/release/v4.8.2.md', + '/pages/en/blog/release/v4.7.1.md', + '/pages/en/blog/release/v20.0.0.md', + '/pages/en/blog/release/v8.11.4.md', + '/pages/en/blog/release/v15.12.0.md', + '/pages/en/blog/release/v15.5.0.md', + '/pages/en/blog/release/v16.20.2.md', + '/pages/en/blog/release/v0.11.11.md', + '/pages/en/blog/release/v18.1.0.md', + '/pages/en/blog/release/v12.16.0.md', + '/pages/en/blog/release/v11.2.0.md', + '/pages/en/blog/release/v0.11.1.md', + '/pages/en/blog/release/v21.4.0.md', + '/pages/en/blog/release/v11.10.0.md', + '/pages/en/blog/release/v0.8.15.md', + '/pages/en/blog/release/v14.1.0.md', + '/pages/en/blog/release/v6.15.0.md', + '/pages/en/blog/release/v0.6.16.md', + '/pages/en/blog/release/v12.22.2.md', + '/pages/en/blog/release/v10.6.0.md', + '/pages/en/blog/release/v19.5.0.md', + '/pages/en/blog/release/v0.12.6.md', + '/pages/en/blog/release/v16.14.0.md', + '/pages/en/blog/release/v0.8.21.md', + '/pages/en/blog/release/v0.8.9.md', + '/pages/en/blog/release/v17.4.0.md', + '/pages/en/blog/release/v0.9.8.md', + '/pages/en/blog/release/v16.15.1.md', + '/pages/en/blog/release/v10.11.0.md', + '/pages/en/blog/release/v22.1.0.md', + '/pages/en/blog/release/v20.18.0.md', + '/pages/en/blog/release/v13.3.0.md', + '/pages/en/blog/release/v6.14.1.md', + '/pages/en/blog/release/v0.4.12.md', + '/pages/en/blog/release/v0.10.0.md', + '/pages/en/blog/release/v12.18.2.md', + '/pages/en/blog/release/v16.0.0.md', + '/pages/en/blog/release/v14.13.0.md', + '/pages/en/blog/release/v4.8.6.md', + '/pages/en/blog/release/v12.7.0.md', + '/pages/en/blog/release/v4.4.2.md', + '/pages/en/blog/release/v12.6.0.md', + '/pages/en/blog/release/v15.5.1.md', + '/pages/en/blog/release/v14.12.0.md', + '/pages/en/blog/release/v0.11.10.md', + '/pages/en/blog/release/v12.16.1.md', + '/pages/en/blog/release/v16.1.0.md', + '/pages/en/blog/release/v0.11.0.md', + '/pages/en/blog/release/v11.10.1.md', + '/pages/en/blog/release/v0.8.14.md', + '/pages/en/blog/release/v13.2.0.md', + '/pages/en/blog/release/v6.15.1.md', + '/pages/en/blog/release/v0.6.17.md', + '/pages/en/blog/release/v12.22.3.md', + '/pages/en/blog/release/v10.10.0.md', + '/pages/en/blog/release/v22.0.0.md', + '/pages/en/blog/release/v17.5.0.md', + '/pages/en/blog/release/v0.12.7.md', + '/pages/en/blog/release/v0.8.8.md', + '/pages/en/blog/release/v0.8.20.md', + '/pages/en/blog/release/v16.14.1.md', + '/pages/en/blog/release/v10.7.0.md', + '/pages/en/blog/release/v19.4.0.md', + '/pages/en/blog/release/v16.15.0.md', + '/pages/en/blog/release/v14.0.0.md', + '/pages/en/blog/release/v6.14.0.md', + '/pages/en/blog/release/v0.10.1.md', + '/pages/en/blog/release/v21.5.0.md', + '/pages/en/blog/release/v11.11.0.md', + '/pages/en/blog/release/v12.18.3.md', + '/pages/en/blog/release/v18.0.0.md', + '/pages/en/blog/release/v12.17.0.md', + '/pages/en/blog/release/v11.3.0.md', + '/pages/en/blog/release/v4.8.7.md', + '/pages/en/blog/release/v14.13.1.md', + '/pages/en/blog/release/v5.12.0.md', + '/pages/en/blog/release/v15.4.0.md', + '/pages/en/blog/release/v4.4.3.md', + '/pages/en/blog/release/v20.1.0.md', + '/pages/en/blog/release/v15.13.0.md', + '/pages/en/blog/release/v9.11.0.md', + '/pages/en/blog/release/v0.11.14.md', + '/pages/en/blog/release/v4.6.1.md', + '/pages/en/blog/release/v7.2.0.md', + '/pages/en/blog/release/v8.11.1.md', + '/pages/en/blog/release/v9.2.1.md', + '/pages/en/blog/release/v12.22.7.md', + '/pages/en/blog/release/v0.12.3.md', + '/pages/en/blog/release/v0.8.24.md', + '/pages/en/blog/release/v21.7.2.md', + '/pages/en/blog/release/v8.9.2.md', + '/pages/en/blog/release/v6.6.0.md', + '/pages/en/blog/release/v6.9.3.md', + '/pages/en/blog/release/v17.9.0.md', + '/pages/en/blog/release/v16.18.1.md', + '/pages/en/blog/release/v0.4.8.md', + '/pages/en/blog/release/v0.11.4.md', + '/pages/en/blog/release/v12.21.0.md', + '/pages/en/blog/release/v0.6.13.md', + '/pages/en/blog/release/v20.15.0.md', + '/pages/en/blog/release/v0.8.10.md', + '/pages/en/blog/release/v6.14.4.md', + '/pages/en/blog/release/v12.20.1.md', + '/pages/en/blog/release/v8.7.0.md', + '/pages/en/blog/release/v19.8.0.md', + '/pages/en/blog/release/v17.7.2.md', + '/pages/en/blog/release/v0.5.9.md', + '/pages/en/blog/release/v16.19.0.md', + '/pages/en/blog/release/v0.10.5.md', + '/pages/en/blog/release/v5.3.0.md', + '/pages/en/blog/release/v4.4.7.md', + '/pages/en/blog/release/v9.3.0.md', + '/pages/en/blog/release/v8.10.0.md', + '/pages/en/blog/release/v9.10.1.md', + '/pages/en/blog/release/v18.11.0.md', + '/pages/en/blog/release/v4.7.0.md', + '/pages/en/blog/release/v4.8.3.md', + '/pages/en/blog/release/v15.8.0.md', + '/pages/en/blog/release/v0.12.8.md', + '/pages/en/blog/release/v20.6.0.md', + '/pages/en/blog/release/v0.8.7.md', + '/pages/en/blog/release/v0.7.4.md', + '/pages/en/blog/release/v15.14.0.md', + '/pages/en/blog/release/v13.10.1.md', + '/pages/en/blog/release/v14.17.6.md', + '/pages/en/blog/release/v15.3.0.md', + '/pages/en/blog/release/v0.6.18.md', + '/pages/en/blog/release/v11.4.0.md', + '/pages/en/blog/release/v0.4.3.md', + '/pages/en/blog/release/v7.7.2.md', + '/pages/en/blog/release/v18.7.0.md', + '/pages/en/blog/release/v9.8.0.md', + '/pages/en/blog/release/v12.10.0.md', + '/pages/en/blog/release/v0.10.11.md', + '/pages/en/blog/release/v0.10.40.md', + '/pages/en/blog/release/v21.2.0.md', + '/pages/en/blog/release/v14.7.0.md', + '/pages/en/blog/release/v5.8.0.md', + '/pages/en/blog/release/v6.13.0.md', + '/pages/en/blog/release/v10.16.1.md', + '/pages/en/blog/release/v0.10.25.md', + '/pages/en/blog/release/v19.3.0.md', + '/pages/en/blog/release/v10.0.0.md', + '/pages/en/blog/release/v17.3.1.md', + '/pages/en/blog/release/v16.12.0.md', + '/pages/en/blog/release/v17.2.0.md', + '/pages/en/blog/release/v14.21.2.md', + '/pages/en/blog/release/v16.13.1.md', + '/pages/en/blog/release/v10.17.0.md', + '/pages/en/blog/release/v0.10.35.md', + '/pages/en/blog/release/v22.7.0.md', + '/pages/en/blog/release/v13.5.0.md', + '/pages/en/blog/release/v5.9.1.md', + '/pages/en/blog/release/v6.12.1.md', + '/pages/en/blog/release/v18.20.0.md', + '/pages/en/blog/release/v0.12.15.md', + '/pages/en/blog/release/v12.22.10.md', + '/pages/en/blog/release/v16.6.0.md', + '/pages/en/blog/release/v7.9.0.md', + '/pages/en/blog/release/v0.5.2.md', + '/pages/en/blog/release/v12.11.1.md', + '/pages/en/blog/release/v10.23.2.md', + '/pages/en/blog/release/v14.15.0.md', + '/pages/en/blog/release/v13.11.0.md', + '/pages/en/blog/release/v18.14.2.md', + '/pages/en/blog/release/v12.1.0.md', + '/pages/en/blog/release/v15.2.1.md', + '/pages/en/blog/release/v4.2.2.md', + '/pages/en/blog/release/v0.6.5.md', + '/pages/en/blog/release/v0.9.6.md', + '/pages/en/blog/release/v4.0.0.md', + '/pages/en/blog/release/v18.16.0.md', + '/pages/en/blog/release/v0.4.7.md', + '/pages/en/blog/release/v0.7.12.md', + '/pages/en/blog/release/v0.9.11.md', + '/pages/en/blog/release/v8.17.0.md', + '/pages/en/blog/release/v9.4.0.md', + '/pages/en/blog/release/v10.21.0.md', + '/pages/en/blog/release/v0.7.0.md', + '/pages/en/blog/release/v0.8.3.md', + '/pages/en/blog/release/v11.8.0.md', + '/pages/en/blog/release/v16.4.2.md', + '/pages/en/blog/release/v12.22.8.md', + '/pages/en/blog/release/v14.18.1.md', + '/pages/en/blog/release/v14.17.2.md', + '/pages/en/blog/release/v0.10.21.md', + '/pages/en/blog/release/v5.4.0.md', + '/pages/en/blog/release/v6.10.3.md', + '/pages/en/blog/release/v8.0.0.md', + '/pages/en/blog/release/v0.10.44.md', + '/pages/en/blog/release/v0.10.15.md', + '/pages/en/blog/release/v10.15.2.md', + '/pages/en/blog/release/v20.13.1.md', + '/pages/en/blog/release/v20.12.0.md', + '/pages/en/blog/release/v6.1.0.md', + '/pages/en/blog/release/v8.1.1.md', + '/pages/en/blog/release/v18.20.4.md', + '/pages/en/blog/release/v0.12.11.md', + '/pages/en/blog/release/v13.9.0.md', + '/pages/en/blog/release/v6.11.2.md', + '/pages/en/blog/release/v0.10.31.md', + '/pages/en/blog/release/v4.2.6.md', + '/pages/en/blog/release/v14.19.0.md', + '/pages/en/blog/release/v10.20.1.md', + '/pages/en/blog/release/v8.16.1.md', + '/pages/en/blog/release/v7.5.0.md', + '/pages/en/blog/release/v0.9.2.md', + '/pages/en/blog/release/v0.6.1.md', + '/pages/en/blog/release/v0.5.6.md', + '/pages/en/blog/release/v14.15.4.md', + '/pages/en/blog/release/v4.1.1.md', + '/pages/en/blog/release/v18.18.2.md', + '/pages/en/blog/release/v18.17.1.md', + '/pages/en/blog/release/v18.16.1.md', + '/pages/en/blog/release/v0.4.6.md', + '/pages/en/blog/release/v0.9.10.md', + '/pages/en/blog/release/v7.4.0.md', + '/pages/en/blog/release/v0.8.2.md', + '/pages/en/blog/release/v0.7.1.md', + '/pages/en/blog/release/v12.22.9.md', + '/pages/en/blog/release/v14.17.3.md', + '/pages/en/blog/release/v14.18.0.md', + '/pages/en/blog/release/v0.10.20.md', + '/pages/en/blog/release/v5.4.1.md', + '/pages/en/blog/release/v13.8.0.md', + '/pages/en/blog/release/v6.10.2.md', + '/pages/en/blog/release/v6.0.0.md', + '/pages/en/blog/release/v0.10.45.md', + '/pages/en/blog/release/v0.10.14.md', + '/pages/en/blog/release/v10.15.3.md', + '/pages/en/blog/release/v20.13.0.md', + '/pages/en/blog/release/v10.14.2.md', + '/pages/en/blog/release/v20.12.1.md', + '/pages/en/blog/release/v8.1.0.md', + '/pages/en/blog/release/v0.12.10.md', + '/pages/en/blog/release/v5.5.0.md', + '/pages/en/blog/release/v6.11.3.md', + '/pages/en/blog/release/v0.10.30.md', + '/pages/en/blog/release/v14.19.1.md', + '/pages/en/blog/release/v8.16.0.md', + '/pages/en/blog/release/v9.5.0.md', + '/pages/en/blog/release/v10.20.0.md', + '/pages/en/blog/release/v0.6.0.md', + '/pages/en/blog/release/v0.9.3.md', + '/pages/en/blog/release/v11.9.0.md', + '/pages/en/blog/release/v0.5.7.md', + '/pages/en/blog/release/v4.1.0.md', + '/pages/en/blog/release/v14.15.5.md', + '/pages/en/blog/release/v18.17.0.md', + '/pages/en/blog/release/v20.6.1.md', + '/pages/en/blog/release/v0.12.9.md', + '/pages/en/blog/release/v0.7.5.md', + '/pages/en/blog/release/v0.8.6.md', + '/pages/en/blog/release/v13.10.0.md', + '/pages/en/blog/release/v12.0.0.md', + '/pages/en/blog/release/v4.3.2.md', + '/pages/en/blog/release/v14.14.0.md', + '/pages/en/blog/release/v0.6.19.md', + '/pages/en/blog/release/v16.7.0.md', + '/pages/en/blog/release/v7.7.3.md', + '/pages/en/blog/release/v7.8.0.md', + '/pages/en/blog/release/v0.10.10.md', + '/pages/en/blog/release/v0.10.41.md', + '/pages/en/blog/release/v13.4.0.md', + '/pages/en/blog/release/v6.13.1.md', + '/pages/en/blog/release/v10.16.0.md', + '/pages/en/blog/release/v0.10.24.md', + '/pages/en/blog/release/v22.6.0.md', + '/pages/en/blog/release/v17.3.0.md', + '/pages/en/blog/release/v19.2.0.md', + '/pages/en/blog/release/v10.1.0.md', + '/pages/en/blog/release/v6.2.2.md', + '/pages/en/blog/release/v16.13.0.md', + '/pages/en/blog/release/v14.21.3.md', + '/pages/en/blog/release/v0.10.34.md', + '/pages/en/blog/release/v14.6.0.md', + '/pages/en/blog/release/v5.9.0.md', + '/pages/en/blog/release/v6.12.0.md', + '/pages/en/blog/release/v18.20.1.md', + '/pages/en/blog/release/v12.22.11.md', + '/pages/en/blog/release/v0.12.14.md', + '/pages/en/blog/release/v21.3.0.md', + '/pages/en/blog/release/v8.1.4.md', + '/pages/en/blog/release/v11.5.0.md', + '/pages/en/blog/release/v0.5.3.md', + '/pages/en/blog/release/v16.6.1.md', + '/pages/en/blog/release/v18.6.0.md', + '/pages/en/blog/release/v10.23.3.md', + '/pages/en/blog/release/v9.9.0.md', + '/pages/en/blog/release/v12.11.0.md', + '/pages/en/blog/release/v14.15.1.md', + '/pages/en/blog/release/v4.2.3.md', + '/pages/en/blog/release/v15.2.0.md', + '/pages/en/blog/release/v20.7.0.md', + '/pages/en/blog/release/v0.9.7.md', + '/pages/en/blog/release/v0.6.4.md', + '/pages/en/blog/release/v0.4.5.md', + '/pages/en/blog/release/v7.7.4.md', + '/pages/en/blog/release/v20.5.1.md', + '/pages/en/blog/release/v0.7.10.md', + '/pages/en/blog/release/v0.11.9.md', + '/pages/en/blog/release/v12.3.0.md', + '/pages/en/blog/release/v15.0.1.md', + '/pages/en/blog/release/v18.19.1.md', + '/pages/en/blog/release/v13.13.0.md', + '/pages/en/blog/release/v23.1.0.md', + '/pages/en/blog/release/v14.17.0.md', + '/pages/en/blog/release/v14.18.3.md', + '/pages/en/blog/release/v12.13.1.md', + '/pages/en/blog/release/v16.4.0.md', + '/pages/en/blog/release/v0.8.1.md', + '/pages/en/blog/release/v0.7.2.md', + '/pages/en/blog/release/v6.10.1.md', + '/pages/en/blog/release/v0.10.23.md', + '/pages/en/blog/release/v13.7.0.md', + '/pages/en/blog/release/v22.5.0.md', + '/pages/en/blog/release/v10.15.0.md', + '/pages/en/blog/release/v16.11.1.md', + '/pages/en/blog/release/v0.10.17.md', + '/pages/en/blog/release/v17.0.0.md', + '/pages/en/blog/release/v19.0.1.md', + '/pages/en/blog/release/v0.10.46.md', + '/pages/en/blog/release/v7.10.0.md', + '/pages/en/blog/release/v0.12.13.md', + '/pages/en/blog/release/v16.10.0.md', + '/pages/en/blog/release/v10.2.0.md', + '/pages/en/blog/release/v8.1.3.md', + '/pages/en/blog/release/v19.1.0.md', + '/pages/en/blog/release/v22.4.1.md', + '/pages/en/blog/release/v20.12.2.md', + '/pages/en/blog/release/v10.14.1.md', + '/pages/en/blog/release/v6.11.0.md', + '/pages/en/blog/release/v0.10.33.md', + '/pages/en/blog/release/v14.5.0.md', + '/pages/en/blog/release/v21.0.0.md', + '/pages/en/blog/release/v11.14.0.md', + '/pages/en/blog/release/v18.5.0.md', + '/pages/en/blog/release/v12.12.0.md', + '/pages/en/blog/release/v11.6.0.md', + '/pages/en/blog/release/v0.6.3.md', + '/pages/en/blog/release/v0.9.0.md', + '/pages/en/blog/release/v14.19.2.md', + '/pages/en/blog/release/v14.16.1.md', + '/pages/en/blog/release/v4.2.4.md', + '/pages/en/blog/release/v15.1.0.md', + '/pages/en/blog/release/v18.18.0.md', + '/pages/en/blog/release/v0.5.4.md', + '/pages/en/blog/release/v0.10.8.md', + '/pages/en/blog/release/v20.4.0.md', + '/pages/en/blog/release/v14.17.4.md', + '/pages/en/blog/release/v4.3.1.md', + '/pages/en/blog/release/v0.7.6.md', + '/pages/en/blog/release/v0.8.5.md', + '/pages/en/blog/release/v7.7.0.md', + '/pages/en/blog/release/v16.8.0.md', + '/pages/en/blog/release/v9.7.1.md', + '/pages/en/blog/release/v10.22.1.md', + '/pages/en/blog/release/v8.14.1.md', + '/pages/en/blog/release/v0.8.19.md', + '/pages/en/blog/release/v5.7.1.md', + '/pages/en/blog/release/v0.10.42.md', + '/pages/en/blog/release/v0.10.13.md', + '/pages/en/blog/release/v14.20.1.md', + '/pages/en/blog/release/v6.3.0.md', + '/pages/en/blog/release/v22.9.0.md', + '/pages/en/blog/release/v0.10.27.md', + '/pages/en/blog/release/v20.10.0.md', + '/pages/en/blog/release/v10.19.0.md', + '/pages/en/blog/release/v10.16.3.md', + '/pages/en/blog/release/v20.11.1.md', + '/pages/en/blog/release/v6.11.4.md', + '/pages/en/blog/release/v0.10.37.md', + '/pages/en/blog/release/v10.18.1.md', + '/pages/en/blog/release/v14.21.0.md', + '/pages/en/blog/release/v8.2.0.md', + '/pages/en/blog/release/v6.2.1.md', + '/pages/en/blog/release/v18.20.2.md', + '/pages/en/blog/release/v12.22.12.md', + '/pages/en/blog/release/v0.12.17.md', + '/pages/en/blog/release/v6.12.3.md', + '/pages/en/blog/release/v5.6.0.md', + '/pages/en/blog/release/v14.9.0.md', + '/pages/en/blog/release/v14.15.2.md', + '/pages/en/blog/release/v16.9.1.md', + '/pages/en/blog/release/v0.5.0.md', + '/pages/en/blog/release/v16.6.2.md', + '/pages/en/blog/release/v8.15.0.md', + '/pages/en/blog/release/v10.23.0.md', + '/pages/en/blog/release/v9.6.0.md', + '/pages/en/blog/release/v0.5.10.md', + '/pages/en/blog/release/v18.9.0.md', + '/pages/en/blog/release/v20.8.0.md', + '/pages/en/blog/release/v0.9.4.md', + '/pages/en/blog/release/v0.6.7.md', + '/pages/en/blog/release/v18.14.0.md', + '/pages/en/blog/release/v4.2.0.md', + '/pages/en/blog/release/v18.15.0.md', + '/pages/en/blog/release/v4.3.0.md', + '/pages/en/blog/release/v14.17.5.md', + '/pages/en/blog/release/v20.9.0.md', + '/pages/en/blog/release/v0.8.4.md', + '/pages/en/blog/release/v0.7.7.md', + '/pages/en/blog/release/v7.7.1.md', + '/pages/en/blog/release/v8.14.0.md', + '/pages/en/blog/release/v10.22.0.md', + '/pages/en/blog/release/v9.7.0.md', + '/pages/en/blog/release/v18.8.0.md', + '/pages/en/blog/release/v0.8.18.md', + '/pages/en/blog/release/v5.7.0.md', + '/pages/en/blog/release/v14.8.0.md', + '/pages/en/blog/release/v0.10.43.md', + '/pages/en/blog/release/v0.10.12.md', + '/pages/en/blog/release/v14.20.0.md', + '/pages/en/blog/release/v8.3.0.md', + '/pages/en/blog/release/v6.3.1.md', + '/pages/en/blog/release/v0.10.26.md', + '/pages/en/blog/release/v10.16.2.md', + '/pages/en/blog/release/v22.8.0.md', + '/pages/en/blog/release/v20.11.0.md', + '/pages/en/blog/release/v6.11.5.md', + '/pages/en/blog/release/v10.18.0.md', + '/pages/en/blog/release/v0.10.36.md', + '/pages/en/blog/release/v14.21.1.md', + '/pages/en/blog/release/v16.13.2.md', + '/pages/en/blog/release/v8.2.1.md', + '/pages/en/blog/release/v6.2.0.md', + '/pages/en/blog/release/v18.20.3.md', + '/pages/en/blog/release/v0.12.16.md', + '/pages/en/blog/release/v6.12.2.md', + '/pages/en/blog/release/v14.15.3.md', + '/pages/en/blog/release/v7.6.0.md', + '/pages/en/blog/release/v0.5.1.md', + '/pages/en/blog/release/v16.9.0.md', + '/pages/en/blog/release/v18.9.1.md', + '/pages/en/blog/release/v9.6.1.md', + '/pages/en/blog/release/v10.23.1.md', + '/pages/en/blog/release/v8.15.1.md', + '/pages/en/blog/release/v20.8.1.md', + '/pages/en/blog/release/v0.6.6.md', + '/pages/en/blog/release/v0.9.5.md', + '/pages/en/blog/release/v18.14.1.md', + '/pages/en/blog/release/v4.2.1.md', + '/pages/en/blog/release/v0.9.12.md', + '/pages/en/blog/release/v0.4.4.md', + '/pages/en/blog/release/v0.11.8.md', + '/pages/en/blog/release/v0.7.11.md', + '/pages/en/blog/release/v20.5.0.md', + '/pages/en/blog/release/v15.0.0.md', + '/pages/en/blog/release/v12.3.1.md', + '/pages/en/blog/release/v18.19.0.md', + '/pages/en/blog/release/v14.18.2.md', + '/pages/en/blog/release/v14.17.1.md', + '/pages/en/blog/release/v18.4.0.md', + '/pages/en/blog/release/v12.13.0.md', + '/pages/en/blog/release/v0.8.28.md', + '/pages/en/blog/release/v11.7.0.md', + '/pages/en/blog/release/v0.7.3.md', + '/pages/en/blog/release/v0.8.0.md', + '/pages/en/blog/release/v16.4.1.md', + '/pages/en/blog/release/v21.1.0.md', + '/pages/en/blog/release/v11.15.0.md', + '/pages/en/blog/release/v6.10.0.md', + '/pages/en/blog/release/v0.10.22.md', + '/pages/en/blog/release/v14.4.0.md', + '/pages/en/blog/release/v22.5.1.md', + '/pages/en/blog/release/v10.15.1.md', + '/pages/en/blog/release/v0.10.16.md', + '/pages/en/blog/release/v16.11.0.md', + '/pages/en/blog/release/v10.3.0.md', + '/pages/en/blog/release/v17.0.1.md', + '/pages/en/blog/release/v7.10.1.md', + '/pages/en/blog/release/v0.10.47.md', + '/pages/en/blog/release/v19.0.0.md', + '/pages/en/blog/release/v0.12.12.md', + '/pages/en/blog/release/v17.1.0.md', + '/pages/en/blog/release/v10.2.1.md', + '/pages/en/blog/release/v8.1.2.md', + '/pages/en/blog/release/v22.4.0.md', + '/pages/en/blog/release/v10.14.0.md', + '/pages/en/blog/release/v6.11.1.md', + '/pages/en/blog/release/v0.10.32.md', + '/pages/en/blog/release/v13.6.0.md', + '/pages/en/blog/release/v8.16.2.md', + '/pages/en/blog/release/v16.5.0.md', + '/pages/en/blog/release/v0.9.1.md', + '/pages/en/blog/release/v0.6.2.md', + '/pages/en/blog/release/v23.0.0.md', + '/pages/en/blog/release/v4.2.5.md', + '/pages/en/blog/release/v14.16.0.md', + '/pages/en/blog/release/v14.19.3.md', + '/pages/en/blog/release/v12.2.0.md', + '/pages/en/blog/release/v4.1.2.md', + '/pages/en/blog/release/v18.18.1.md', + '/pages/en/blog/release/v13.12.0.md', + '/pages/en/blog/release/v0.5.5.md', + '/pages/en/blog/release/v0.10.9.md', + '/pages/en/blog/release/v12.9.0.md', + '/pages/en/blog/release/v0.10.29.md', + '/pages/en/blog/release/v12.16.2.md', + '/pages/en/blog/release/v12.19.1.md', + '/pages/en/blog/release/v10.24.1.md', + '/pages/en/blog/release/v7.1.0.md', + '/pages/en/blog/release/v16.20.0.md', + '/pages/en/blog/release/v0.6.14.md', + '/pages/en/blog/release/v0.8.17.md', + '/pages/en/blog/release/v5.1.1.md', + '/pages/en/blog/release/v6.9.4.md', + '/pages/en/blog/release/v0.11.3.md', + '/pages/en/blog/release/v0.12.4.md', + '/pages/en/blog/release/v0.7.8.md', + '/pages/en/blog/release/v16.14.2.md', + '/pages/en/blog/release/v0.8.23.md', + '/pages/en/blog/release/v6.5.0.md', + '/pages/en/blog/release/v0.6.20.md', + '/pages/en/blog/release/v20.16.0.md', + '/pages/en/blog/release/v12.22.0.md', + '/pages/en/blog/release/v0.6.9.md', + '/pages/en/blog/release/v10.8.0.md', + '/pages/en/blog/release/v8.4.0.md', + '/pages/en/blog/release/v0.10.2.md', + '/pages/en/blog/release/v6.14.3.md', + '/pages/en/blog/release/v0.4.10.md', + '/pages/en/blog/release/v5.0.0.md', + '/pages/en/blog/release/v4.8.4.md', + '/pages/en/blog/release/v12.18.0.md', + '/pages/en/blog/release/v9.0.0.md', + '/pages/en/blog/release/v8.13.0.md', + '/pages/en/blog/release/v22.11.0.md', + '/pages/en/blog/release/v12.8.1.md', + '/pages/en/blog/release/v4.4.0.md', + '/pages/en/blog/release/v18.12.0.md', + '/pages/en/blog/release/v0.10.39.md', + '/pages/en/blog/release/v0.10.48.md', + '/pages/en/blog/release/v20.3.1.md', + '/pages/en/blog/release/v0.10.19.md', + '/pages/en/blog/release/v12.5.0.md', + '/pages/en/blog/release/v4.9.1.md', + '/pages/en/blog/release/v4.6.2.md', + '/pages/en/blog/release/v5.10.1.md', + '/pages/en/blog/release/v14.11.0.md', + '/pages/en/blog/release/v16.2.0.md', + '/pages/en/blog/release/v8.11.2.md', + '/pages/en/blog/release/v21.7.1.md', + '/pages/en/blog/release/v0.12.0.md', + '/pages/en/blog/release/v0.8.27.md', + '/pages/en/blog/release/v12.22.4.md', + '/pages/en/blog/release/v13.1.0.md', + '/pages/en/blog/release/v0.8.13.md', + '/pages/en/blog/release/v22.3.0.md', + '/pages/en/blog/release/v0.6.10.md', + '/pages/en/blog/release/v10.13.0.md', + '/pages/en/blog/release/v16.17.1.md', + '/pages/en/blog/release/v0.11.7.md', + '/pages/en/blog/release/v8.9.1.md', + '/pages/en/blog/release/v19.6.1.md', + '/pages/en/blog/release/v17.6.0.md', + '/pages/en/blog/release/v6.9.0.md', + '/pages/en/blog/release/v16.16.0.md', + '/pages/en/blog/release/v0.10.6.md', + '/pages/en/blog/release/v19.7.0.md', + '/pages/en/blog/release/v8.8.0.md', + '/pages/en/blog/release/v10.4.0.md', + '/pages/en/blog/release/v6.8.1.md', + '/pages/en/blog/release/v17.7.1.md', + '/pages/en/blog/release/v12.20.2.md', + '/pages/en/blog/release/v6.17.0.md', + '/pages/en/blog/release/v14.3.0.md', + '/pages/en/blog/release/v13.0.1.md', + '/pages/en/blog/release/v11.12.0.md', + '/pages/en/blog/release/v21.6.0.md', + '/pages/en/blog/release/v11.0.0.md', + '/pages/en/blog/release/v18.3.0.md', + '/pages/en/blog/release/v12.14.0.md', + '/pages/en/blog/release/v5.11.0.md', + '/pages/en/blog/release/v4.4.4.md', + '/pages/en/blog/release/v14.10.1.md', + '/pages/en/blog/release/v15.7.0.md', + '/pages/en/blog/release/v4.7.3.md', + '/pages/en/blog/release/v4.8.0.md', + '/pages/en/blog/release/v15.10.0.md', + '/pages/en/blog/release/v20.2.0.md', + '/pages/en/blog/release/v12.18.4.md', + '/pages/en/blog/release/v15.11.0.md', + '/pages/en/blog/release/v20.3.0.md', + '/pages/en/blog/release/v0.10.18.md', + '/pages/en/blog/release/v15.6.0.md', + '/pages/en/blog/release/v0.11.16.md', + '/pages/en/blog/release/v4.9.0.md', + '/pages/en/blog/release/v9.11.2.md', + '/pages/en/blog/release/v5.10.0.md', + '/pages/en/blog/release/v11.1.0.md', + '/pages/en/blog/release/v8.11.3.md', + '/pages/en/blog/release/v18.2.0.md', + '/pages/en/blog/release/v12.15.0.md', + '/pages/en/blog/release/v11.13.0.md', + '/pages/en/blog/release/v21.7.0.md', + '/pages/en/blog/release/v0.12.1.md', + '/pages/en/blog/release/v0.8.26.md', + '/pages/en/blog/release/v12.22.5.md', + '/pages/en/blog/release/v6.16.0.md', + '/pages/en/blog/release/v14.2.0.md', + '/pages/en/blog/release/v0.8.12.md', + '/pages/en/blog/release/v0.6.11.md', + '/pages/en/blog/release/v16.17.0.md', + '/pages/en/blog/release/v0.11.6.md', + '/pages/en/blog/release/v19.6.0.md', + '/pages/en/blog/release/v8.9.0.md', + '/pages/en/blog/release/v10.5.0.md', + '/pages/en/blog/release/v6.9.1.md', + '/pages/en/blog/release/v0.10.7.md', + '/pages/en/blog/release/v8.8.1.md', + '/pages/en/blog/release/v17.7.0.md', + '/pages/en/blog/release/v6.8.0.md', + '/pages/en/blog/release/v10.4.1.md', + '/pages/en/blog/release/v22.2.0.md', + '/pages/en/blog/release/v10.12.0.md', + '/pages/en/blog/release/v6.17.1.md', + '/pages/en/blog/release/v13.0.0.md', + '/pages/en/blog/release/v21.6.1.md', + '/pages/en/blog/release/v16.3.0.md', + '/pages/en/blog/release/v12.14.1.md', + '/pages/en/blog/release/v5.11.1.md', + '/pages/en/blog/release/v14.10.0.md', + '/pages/en/blog/release/v4.4.5.md', + '/pages/en/blog/release/v12.4.0.md', + '/pages/en/blog/release/v4.8.1.md', + '/pages/en/blog/release/v4.7.2.md', + '/pages/en/blog/release/v13.14.0.md', + '/pages/en/blog/release/v12.9.1.md', + '/pages/en/blog/release/v4.5.0.md', + '/pages/en/blog/release/v18.13.0.md', + '/pages/en/blog/release/v0.10.28.md', + '/pages/en/blog/release/v10.24.0.md', + '/pages/en/blog/release/v12.19.0.md', + '/pages/en/blog/release/v9.1.0.md', + '/pages/en/blog/release/v8.12.0.md', + '/pages/en/blog/release/v12.16.3.md', + '/pages/en/blog/release/v22.10.0.md', + '/pages/en/blog/release/v16.20.1.md', + '/pages/en/blog/release/v0.11.12.md', + '/pages/en/blog/release/v0.6.15.md', + '/pages/en/blog/release/v0.8.16.md', + '/pages/en/blog/release/v5.1.0.md', + '/pages/en/blog/release/v8.9.4.md', + '/pages/en/blog/release/v6.9.5.md', + '/pages/en/blog/release/v0.11.2.md', + '/pages/en/blog/release/v0.12.5.md', + '/pages/en/blog/release/v0.8.22.md', + '/pages/en/blog/release/v0.7.9.md', + '/pages/en/blog/release/v0.6.21.md', + '/pages/en/blog/release/v10.9.0.md', + '/pages/en/blog/release/v8.5.0.md', + '/pages/en/blog/release/v12.22.1.md', + '/pages/en/blog/release/v20.17.0.md', + '/pages/en/blog/release/v0.6.8.md', + '/pages/en/blog/release/v6.4.0.md', + '/pages/en/blog/release/v0.10.3.md', + '/pages/en/blog/release/v6.14.2.md', + '/pages/en/blog/release/v0.4.11.md', + '/pages/en/blog/release/v4.8.5.md', + '/pages/en/blog/release/v12.18.1.md', + '/pages/en/blog/release/v7.0.0.md', + '/pages/en/blog/release/v0.12.18.md', + '/pages/en/blog/release/v4.4.1.md', + '/pages/en/blog/release/v12.8.0.md', + '/pages/en/blog/release/v0.10.38.md', + '/pages/en/blog/release/v18.12.1.md', + '/pages/en/blog/index.md', + '/pages/en/blog/uncategorized/profiling-node-js.md', + '/pages/en/blog/uncategorized/notes-from-the-road.md', + '/pages/en/blog/uncategorized/node-office-hours-cut-short.md', + '/pages/en/blog/uncategorized/version-0-6.md', + '/pages/en/blog/uncategorized/the-videos-from-node-meetup.md', + '/pages/en/blog/uncategorized/bnoordhuis-departure.md', + '/pages/en/blog/uncategorized/tj-fontaine-new-node-lead.md', + '/pages/en/blog/uncategorized/an-easy-way-to-build-scalable-network-programs.md', + '/pages/en/blog/uncategorized/node-interactive-convince-boss.md', + '/pages/en/blog/uncategorized/office-hours.md', + '/pages/en/blog/uncategorized/node-meetup-this-thursday.md', + '/pages/en/blog/uncategorized/growing-up.md', + '/pages/en/blog/uncategorized/porting-node-to-windows-with-microsofts-help.md', + '/pages/en/blog/uncategorized/some-new-node-projects.md', + '/pages/en/blog/uncategorized/evolving-the-node-js-brand.md', + '/pages/en/blog/uncategorized/10-lts-to-12-lts.md', + '/pages/en/blog/uncategorized/ldapjs-a-reprise-of-ldap.md', + '/pages/en/blog/uncategorized/trademark.md', + '/pages/en/blog/uncategorized/libuv-status-report.md', + '/pages/en/blog/uncategorized/jobs-nodejs-org.md', + '/pages/en/blog/uncategorized/development-environment.md', + '/pages/en/blog/feature/streams2.md', + '/pages/en/blog/vulnerability/openssl-fixes-in-regular-releases-oct2023.md', + '/pages/en/blog/vulnerability/openssl-march-2016.md', + '/pages/en/blog/vulnerability/december-2015-security-releases.md', + '/pages/en/blog/vulnerability/november-2020-security-releases.md', + '/pages/en/blog/vulnerability/november-2018-security-releases.md', + '/pages/en/blog/vulnerability/september-2019-openssl-updates.md', + '/pages/en/blog/vulnerability/february-2020-security-releases.md', + '/pages/en/blog/vulnerability/september-2017-path-validation.md', + '/pages/en/blog/vulnerability/september-2020-security-releases.md', + '/pages/en/blog/vulnerability/http-server-security-vulnerability-please-upgrade-to-0-6-17.md', + '/pages/en/blog/vulnerability/openssl-january-2017.md', + '/pages/en/blog/vulnerability/jan-2022-security-releases.md', + '/pages/en/blog/vulnerability/openssl-fixes-in-regular-releases-dec2022.md', + '/pages/en/blog/vulnerability/april-2024-security-releases.md', + '/pages/en/blog/vulnerability/july-2022-security-releases.md', + '/pages/en/blog/vulnerability/june-2016-security-releases.md', + '/pages/en/blog/vulnerability/october-2023-security-releases.md', + '/pages/en/blog/vulnerability/april-2021-security-releases.md', + '/pages/en/blog/vulnerability/npm-tokens-leak-march-2016.md', + '/pages/en/blog/vulnerability/openssl-november-2022.md', + '/pages/en/blog/vulnerability/august-2018-security-releases.md', + '/pages/en/blog/vulnerability/cve-2015-8027_cve-2015-6764.md', + '/pages/en/blog/vulnerability/openssl-and-utf8.md', + '/pages/en/blog/vulnerability/openssl-november-2017.md', + '/pages/en/blog/vulnerability/september-2016-security-releases.md', + '/pages/en/blog/vulnerability/february-2016-security-releases.md', + '/pages/en/blog/vulnerability/june-2018-security-releases.md', + '/pages/en/blog/vulnerability/february-2019-security-releases.md', + '/pages/en/blog/vulnerability/jan-2018-spectre-meltdown.md', + '/pages/en/blog/vulnerability/june-2020-security-releases.md', + '/pages/en/blog/vulnerability/september-2019-openssl-no-updates.md', + '/pages/en/blog/vulnerability/february-2021-security-releases.md', + '/pages/en/blog/vulnerability/march-2018-security-releases.md', + '/pages/en/blog/vulnerability/openssl-fixes-in-regular-releases-may2022.md', + '/pages/en/blog/vulnerability/oct-2017-dos.md', + '/pages/en/blog/vulnerability/february-2024-security-releases.md', + '/pages/en/blog/vulnerability/january-2021-security-releases.md', + '/pages/en/blog/vulnerability/october-2016-security-releases.md', + '/pages/en/blog/vulnerability/september-2022-security-releases.md', + '/pages/en/blog/vulnerability/openssl-fixes-in-regular-releases-jun2022.md', + '/pages/en/blog/vulnerability/june-2023-security-releases.md', + '/pages/en/blog/vulnerability/openssl-may-2016.md', + '/pages/en/blog/vulnerability/july-2017-security-releases.md', + '/pages/en/blog/vulnerability/http-server-pipeline-flood-dos.md', + '/pages/en/blog/vulnerability/april-2020-openssl-updates.md', + '/pages/en/blog/vulnerability/august-2023-security-releases.md', + '/pages/en/blog/vulnerability/july-2021-security-releases-2.md', + '/pages/en/blog/vulnerability/openssl-and-low-severity-fixes-jan-2016.md', + '/pages/en/blog/vulnerability/mar-2022-security-releases.md', + '/pages/en/blog/vulnerability/november-2022-security-releases.md', + '/pages/en/blog/vulnerability/december-2017-security-releases.md', + '/pages/en/blog/vulnerability/december-2015-security-release-update.md', + '/pages/en/blog/vulnerability/july-2021-security-releases.md', + '/pages/en/blog/vulnerability/july-2024-security-releases.md', + '/pages/en/blog/vulnerability/aug-2021-security-releases2.md', + '/pages/en/blog/vulnerability/february-2023-security-releases.md', + '/pages/en/blog/vulnerability/oct-2021-security-releases.md', + '/pages/en/blog/vulnerability/aug-2019-security-releases.md', + '/pages/en/blog/vulnerability/aug-2021-security-releases.md', + '/pages/en/blog/vulnerability/december-2019-security-releases.md', + '/pages/en/blog/vulnerability/v8-memory-corruption-stack-overflow.md', + '/pages/en/blog/vulnerability/april-2024-security-releases-2.md', + '/pages/en/blog/vulnerability/openssl-and-zlib-vulnerability-assessment.md', + '/pages/en/blog/events/collab-summit-2024-london.md', + '/pages/en/blog/community/node-v5.md', + '/pages/en/blog/community/transitions.md', + '/pages/en/blog/community/domain-postmortem.md', + '/pages/en/blog/community/node-leaders-building-open-neutral-foundation.md', + '/pages/en/blog/community/quality-with-speed.md', + '/pages/en/blog/community/individual-membership.md', + '/pages/en/blog/community/next-chapter.md', + '/pages/en/blog/community/foundation-benefits-all.md', + '/pages/en/blog/community/building-nodejs-together.md', + '/pages/en/blog/community/2017-election.md', + '/pages/en/blog/weekly/weekly-update.2015-12-04.md', + '/pages/en/blog/weekly/weekly-update.2015-07-03.md', + '/pages/en/blog/weekly/weekly-update.2016-02-15.md', + '/pages/en/blog/weekly/weekly-update.2015-09-04.md', + '/pages/en/blog/weekly/weekly-update.2015-07-17.md', + '/pages/en/blog/weekly/weekly-update.2015-06-19.md', + '/pages/en/blog/weekly/weekly-update.2015-03-06.md', + '/pages/en/blog/weekly/weekly-update.2015-10-30.md', + '/pages/en/blog/weekly/weekly-update.2015-12-11.md', + '/pages/en/blog/weekly/weekly-update.2015-03-13.md', + '/pages/en/blog/weekly/weekly-update.2015-03-27.md', + '/pages/en/blog/weekly/weekly-update.2016-10-28.md', + '/pages/en/blog/weekly/weekly-update.2017-02-10.md', + '/pages/en/blog/weekly/weekly-update.2015-05-22.md', + '/pages/en/blog/weekly/weekly-update.2015-09-11.md', + '/pages/en/blog/weekly/weekly-update.2015-05-29.md', + '/pages/en/blog/weekly/weekly-update.2016-01-01.md', + '/pages/en/blog/weekly/weekly-update.2015-11-20.md', + '/pages/en/blog/weekly/weekly-update.2015-02-06.md', + '/pages/en/blog/weekly/weekly-update.2016-01-11.md', + '/pages/en/blog/weekly/weekly-update.2015-04-03.md', + '/pages/en/blog/weekly/weekly-update.2015-08-14.md', + '/pages/en/blog/weekly/weekly-update.2015-04-17.md', + '/pages/en/blog/weekly/weekly-update.2016-05-30.md', + '/pages/en/blog/weekly/weekly-update.2016-03-01.md', + '/pages/en/blog/weekly/weekly-update.2015-02-27.md', + '/pages/en/blog/weekly/weekly-update.2015-02-13.md', + '/pages/en/blog/weekly/weekly-update.2015-06-12.md', + '/pages/en/blog/weekly/weekly-update.2015-05-08.md', + '/pages/en/blog/weekly/weekly-update.2015-06-26.md', + '/pages/en/blog/weekly/weekly-update.2016-12-02.md', + '/pages/en/blog/weekly/weekly-update.2016-03-14.md', + '/pages/en/blog/weekly/weekly-update.2015-08-21.md', + '/pages/en/blog/weekly/weekly-update.2015-06-05.md', + '/pages/en/blog/weekly/weekly-update.2015-02-20.md', + '/pages/en/blog/weekly/weekly-update.2016-07-16.md', + '/pages/en/blog/weekly/weekly-update.2015-11-06.md', + '/pages/en/blog/weekly/weekly-update.2016-07-22.md', + '/pages/en/blog/weekly/weekly-update.2016-03-07.md', + '/pages/en/blog/weekly/weekly-update.2016-12-25.md', + '/pages/en/blog/weekly/weekly-update.2015-09-18.md', + '/pages/en/blog/weekly/weekly-update.2015-04-10.md', + '/pages/en/blog/weekly/weekly-update.2015-08-07.md', + '/pages/en/blog/weekly/weekly-update.2015-04-24.md', + '/pages/en/blog/weekly/weekly-update.2016-04-29.md', + '/pages/en/blog/weekly/weekly-update.2015-10-09.md', + '/pages/en/blog/weekly/weekly-update.2016-02-08.md', + '/pages/en/blog/weekly/weekly-update.2015-11-27.md', + '/pages/en/blog/weekly/weekly-update.2015-11-13.md', + '/pages/en/blog/weekly/weekly-update.2016-01-22.md', + '/pages/en/blog/weekly/weekly-update.2015-03-20.md', + '/pages/en/blog/weekly/weekly-update.2016-07-08.md', + '/pages/en/blog/weekly/weekly-update.2015-10-16.md', + '/pages/en/blog/weekly/weekly-update.2015-07-31.md', + '/pages/en/blog/weekly/weekly-update.2016-01-29.md', + '/pages/en/blog/weekly/weekly-update.2015-05-01.md', + '/pages/en/blog/weekly/weekly-update.2016-08-15.md', + '/pages/en/blog/weekly/weekly-update.2016-06-16.md', + '/pages/en/blog/weekly/weekly-update.2015-05-15.md', + '/pages/en/blog/weekly/weekly-update.2016-11-11.md', + '/pages/en/blog/weekly/weekly-update.2015-08-28.md', + '/pages/en/blog/weekly/weekly-update.2015-10-02.md', + '/pages/en/blog/weekly/weekly-update.2016-06-26.md', + '/pages/en/blog/weekly/weekly-update.2016-04-23.md', + '/pages/en/blog/weekly/weekly-update.2016-04-17.md', + '/pages/en/blog/weekly/weekly-update.2016-11-24.md', + '/pages/en/blog/weekly/weekly-update.2016-01-18.md', + '/pages/en/blog/weekly/weekly-update.2015-07-24.md', + '/pages/en/blog/weekly/weekly-update.2015-07-10.md', + '/pages/en/blog/weekly/weekly-update.2015-10-23.md', + '/pages/en/blog/weekly/weekly-update.2016-02-22.md', + '/pages/en/blog/weekly/weekly-update.2016-11-04.md', + '/pages/en/blog/wg/diag-wg-update-2017-02.md', + '/pages/en/blog/npm/npm-1-0-global-vs-local-installation.md', + '/pages/en/blog/npm/2013-outage-postmortem.md', + '/pages/en/blog/npm/npm-1-0-released.md', + '/pages/en/blog/npm/peer-dependencies.mdx', + '/pages/en/blog/npm/managing-node-js-dependencies-with-shrinkwrap.md', + '/pages/en/blog/npm/npm-1-0-the-new-ls.md', + '/pages/en/blog/npm/npm-1-0-link.md', + '/pages/en/download/prebuilt-installer/index.mdx', + '/pages/en/download/prebuilt-installer/current.mdx', + '/pages/en/download/package-manager/index.mdx', + '/pages/en/download/package-manager/current.mdx', + '/pages/en/download/package-manager/all.md', + '/pages/en/download/prebuilt-binaries/index.mdx', + '/pages/en/download/prebuilt-binaries/current.mdx', + '/pages/en/download/source-code/index.mdx', + '/pages/en/download/source-code/current.mdx', + '/pages/fa/search.mdx', + '/pages/fa/index.mdx', + '/pages/fa/about/security-reporting.mdx', + '/pages/fa/about/get-involved/events.mdx', + '/pages/fa/about/get-involved/contribute.md', + '/pages/fa/about/get-involved/index.md', + '/pages/fa/about/get-involved/collab-summit.md', + '/pages/fa/about/index.mdx', + '/pages/fa/about/governance.md', + '/pages/fa/about/branding.mdx', + '/pages/fa/about/previous-releases.mdx', + '/pages/fa/download/prebuilt-installer/index.mdx', + '/pages/fa/download/prebuilt-installer/current.mdx', + '/pages/fa/download/package-manager/index.mdx', + '/pages/fa/download/package-manager/current.mdx', + '/pages/fa/download/package-manager/all.md', + '/pages/fa/download/prebuilt-binaries/index.mdx', + '/pages/fa/download/prebuilt-binaries/current.mdx', + '/pages/fa/download/source-code/index.mdx', + '/pages/fa/download/source-code/current.mdx', + '/pages/tr/search.mdx', + '/pages/tr/index.mdx', + '/pages/tr/about/security-reporting.mdx', + '/pages/tr/about/get-involved/events.mdx', + '/pages/tr/about/get-involved/contribute.md', + '/pages/tr/about/get-involved/index.md', + '/pages/tr/about/get-involved/collab-summit.md', + '/pages/tr/about/index.mdx', + '/pages/tr/about/governance.md', + '/pages/tr/about/branding.mdx', + '/pages/tr/about/previous-releases.mdx', + '/pages/tr/download/prebuilt-installer/index.mdx', + '/pages/tr/download/prebuilt-installer/current.mdx', + '/pages/tr/download/package-manager/index.mdx', + '/pages/tr/download/package-manager/current.mdx', + '/pages/tr/download/package-manager/all.md', + '/pages/tr/download/prebuilt-binaries/index.mdx', + '/pages/tr/download/prebuilt-binaries/current.mdx', + '/pages/tr/download/source-code/index.mdx', + '/pages/tr/download/source-code/current.mdx', +]; diff --git a/apps/site/next.mdx.compiler.mjs b/apps/site/next.mdx.compiler.mjs index 6fcdf963cdd39..e6e33bf48e73d 100644 --- a/apps/site/next.mdx.compiler.mjs +++ b/apps/site/next.mdx.compiler.mjs @@ -1,5 +1,6 @@ 'use strict'; +import React from 'react'; import { evaluate } from '@mdx-js/mdx'; import { Fragment, jsx, jsxs } from 'react/jsx-runtime'; import { matter } from 'vfile-matter'; @@ -31,12 +32,22 @@ export async function compileMDX(source, fileExtension) { const slugger = createGitHubSlugger(); // This is a minimal MDX Compiler that is lightweight and only parses the MDX - const { default: MDXContent } = await evaluate(source, { - rehypePlugins: NEXT_REHYPE_PLUGINS, - remarkPlugins: NEXT_REMARK_PLUGINS, - format: fileExtension, - ...reactRuntime, - }); + const { default: MDXContent } = { + default: () => { + return React.createElement('span', {}, source.value); + }, + }; + + // TODO: disable this because it's calling `eval` under the hood + // await evaluate(source, { + // rehypePlugins: NEXT_REHYPE_PLUGINS, + // remarkPlugins: NEXT_REMARK_PLUGINS, + // format: fileExtension, + // ...reactRuntime, + // }); + + // the evaluate above is side-effecty, and modifies `source`, so we need to change it as well. + source.data.headings = []; // Retrieve some parsed data from the VFile metadata // such as frontmatter and Markdown headings diff --git a/apps/site/package.json b/apps/site/package.json index cd2a910bcfb82..30d57770d703c 100644 --- a/apps/site/package.json +++ b/apps/site/package.json @@ -34,10 +34,9 @@ "test:unit": "cross-env NODE_NO_WARNINGS=1 jest", "test:unit:watch": "npm run test:unit -- --watch", "test": "turbo test:unit", - "build:worker": "cross-env cloudflare", - "dev:worker": "wrangler dev --port 8771", - "preview:worker": "npm run build:worker && npm run dev:worker", - "deploy:worker": "npm run build:worker && wrangler deploy" + "build:cloudflare": "cross-env cloudflare && ln -s ../../pages ./.worker-next/assets/", + "preview:cloudflare": "wrangler dev --port 8771", + "deploy:cloudflare": "wrangler deploy" }, "dependencies": { "@heroicons/react": "~2.1.5", diff --git a/apps/site/turbo.json b/apps/site/turbo.json index 926a21dc5a378..1b33f739d430a 100644 --- a/apps/site/turbo.json +++ b/apps/site/turbo.json @@ -130,6 +130,15 @@ "*.{md,mdx,json,ts,tsx,mjs,yml}" ], "outputs": ["coverage/**", "junit.xml"] + }, + "build:cloudflare": { + "outputs": [".worker-next/**"] + }, + "preview:cloudflare": { + "dependsOn": ["build:cloudflare"] + }, + "deploy:cloudflare": { + "dependsOn": ["build:cloudflare"] } } } diff --git a/apps/site/wrangler.toml b/apps/site/wrangler.toml index 59aa8f6a0a7d2..05368c99d8bb7 100644 --- a/apps/site/wrangler.toml +++ b/apps/site/wrangler.toml @@ -9,8 +9,12 @@ enabled = true head_sampling_rate = 1 [alias] -"node:fs" = "./.cloudflare/node/fs.mjs" -"node:fs/promises" = "./.cloudflare/node/fs/promises.mjs" +# "node:fs" = "./.cloudflare/node/fs.mjs" +# "node:fs/promises" = "./.cloudflare/node/fs/promises.mjs" +# "node:fs" = "./.cloudflare/node/fs.mjs" +# "node:fs/promises" = "./.cloudflare/node/fs/promises.mjs" -[vars] -PAGES = 'pages' + +[assets] +directory = ".worker-next/assets" +binding = "ASSETS"