···11+import { deflateSync } from 'node:zlib';
22+33+import { VERCEL_REVALIDATE } from '@/next.constants.mjs';
44+import { defaultLocale } from '@/next.locales.mjs';
55+import type { GitHubApiFile } from '@/types';
66+import { getGitHubApiDocsUrl } from '@/util/gitHubUtils';
77+import { parseRichTextIntoPlainText } from '@/util/stringUtils';
88+99+const getPathnameForApiFile = (name: string) =>
1010+ `api/${name.replace('.md', '.html')}`;
1111+1212+// This is the Route Handler for the `GET` method which handles the request
1313+// for a digest and metadata of all API pages from the Node.js Website
1414+// @see https://nextjs.org/docs/app/building-your-application/routing/router-handlers
1515+export const GET = async () => {
1616+ const gitHubApiResponse = await fetch(getGitHubApiDocsUrl('main'));
1717+1818+ return gitHubApiResponse.json().then((apiDocsFiles: Array<GitHubApiFile>) => {
1919+ // maps over each api file and get the download_url, fetch the content and deflates it
2020+ const mappedApiFiles = apiDocsFiles.map(
2121+ async ({ name, path: filename, download_url }) => {
2222+ const apiFileResponse = await fetch(download_url);
2323+2424+ // Retrieves the content as a raw text string
2525+ const source = await apiFileResponse.text();
2626+2727+ // Removes empty/blank lines or lines just with spaces and trims each line
2828+ // from leading and trailing paddings/spaces
2929+ const cleanedContent = parseRichTextIntoPlainText(source);
3030+3131+ const deflatedSource = deflateSync(cleanedContent).toString('base64');
3232+3333+ return {
3434+ filename,
3535+ pathname: getPathnameForApiFile(name),
3636+ content: deflatedSource,
3737+ };
3838+ }
3939+ );
4040+4141+ return Promise.all(mappedApiFiles).then(Response.json);
4242+ });
4343+};
4444+4545+// This function generates the static paths that come from the dynamic segments
4646+// `[locale]/next-data/api-data/` and returns an array of all available static paths
4747+// This is used for ISR static validation and generation
4848+export const generateStaticParams = async () => [
4949+ { locale: defaultLocale.code },
5050+];
5151+5252+// Enforces that only the paths from `generateStaticParams` are allowed, giving 404 on the contrary
5353+// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamicparams
5454+export const dynamicParams = false;
5555+5656+// Enforces that this route is used as static rendering
5757+// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic
5858+export const dynamic = 'force-static';
5959+6060+// Ensures that this endpoint is invalidated and re-executed every X minutes
6161+// so that when new deployments happen, the data is refreshed
6262+// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#revalidate
6363+export const revalidate = VERCEL_REVALIDATE;
+2-2
app/[locale]/next-data/page-data/route.ts
···3737 const deflatedSource = deflateSync(cleanedContent).toString('base64');
38383939 // Returns metadata of each page available on the Website
4040- return { pathname, filename, title, description, content: deflatedSource };
4040+ return { filename, pathname, title, description, content: deflatedSource };
4141 });
42424343 return Response.json(await Promise.all(availablePagesMetadata));
4444};
45454646// This function generates the static paths that come from the dynamic segments
4747-// `[locale]/next-data/release-data/` and returns an array of all available static paths
4747+// `[locale]/next-data/page-data/` and returns an array of all available static paths
4848// This is used for ISR static validation and generation
4949export const generateStaticParams = async () => [
5050 { locale: defaultLocale.code },
···55import ChangelogModal from '@/components/Downloads/ChangelogModal';
66import { MDXRenderer } from '@/components/mdxRenderer';
77import { compileMDX } from '@/next.mdx.compiler.mjs';
88-import { githubProfileAvatarUrl } from '@/util/gitHubUtils';
88+import { getGitHubAvatarUrl } from '@/util/gitHubUtils';
991010type Story = StoryObj<typeof ChangelogModal>;
1111type Meta = MetaObj<typeof ChangelogModal>;
···182182 heading: 'Node v18.17.0',
183183 subheading: "2023-07-18, Version 18.17.0 'Hydrogen' (LTS), @danielleadams",
184184 avatars: names.map(name => ({
185185- src: githubProfileAvatarUrl(name),
185185+ src: getGitHubAvatarUrl(name),
186186 alt: name,
187187 })),
188188 children,
+2-2
components/withMetaBar.tsx
···55import GitHub from '@/components/Icons/Social/GitHub';
66import Link from '@/components/Link';
77import { useClientContext } from '@/hooks/server';
88-import { getGitHubEditPageUrl } from '@/util/gitHubUtils';
88+import { getGitHubBlobUrl } from '@/util/gitHubUtils';
991010const DATE_FORMAT = {
1111 month: 'short',
···2929 'components.metabar.contribute': (
3030 <>
3131 <GitHub className="fill-neutral-700 dark:fill-neutral-100" />
3232- <Link href={getGitHubEditPageUrl(filename)}>Edit this page</Link>
3232+ <Link href={getGitHubBlobUrl(filename)}>Edit this page</Link>
3333 </>
3434 ),
3535 }}
+2-2
next.mdx.compiler.mjs
···55import { matter } from 'vfile-matter';
6677import { NEXT_REHYPE_PLUGINS, NEXT_REMARK_PLUGINS } from './next.mdx.mjs';
88-import { createGitHubSlug } from './util/gitHubUtils';
88+import { createGitHubSlugger } from './util/gitHubUtils';
991010// Defines the React Runtime Components
1111const reactRuntime = { Fragment, jsx, jsxs };
···2828 // cleaning the frontmatter to the source that is going to be parsed by the MDX Compiler
2929 matter(source, { strip: true });
30303131- const slugger = createGitHubSlug();
3131+ const slugger = createGitHubSlugger();
32323333 // This is a minimal MDX Compiler that is lightweight and only parses the MDX
3434 const { default: MDXContent } = await evaluate(source, {