Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions apps/site/app/[locale]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import '#site/styles/index.css';

const fontClasses = classNames(IBM_PLEX_MONO.variable, OPEN_SANS.variable);

type RotLayoutProps = PropsWithChildren<{ params: { locale: string } }>;
type RootLayoutProps = PropsWithChildren<{
params: Promise<{ locale: string }>;
}>;

const RootLayout: FC<RotLayoutProps> = async ({ children, params }) => {
const RootLayout: FC<RootLayoutProps> = async ({ children, params }) => {
const { locale } = await params;

const { langDir, hrefLang } = availableLocalesMap[locale] || defaultLocale;
Expand Down
59 changes: 34 additions & 25 deletions apps/site/app/[locale]/next-data/api-data/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,31 +32,40 @@ export const GET = async () => {
authorizationHeaders
);

return gitHubApiResponse.json().then((apiDocsFiles: Array<GitHubApiFile>) => {
// maps over each api file and get the download_url, fetch the content and deflates it
const mappedApiFiles = apiDocsFiles.map(
async ({ name, path: filename, download_url }) => {
const apiFileResponse = await fetch(download_url);

// Retrieves the content as a raw text string
const source = await apiFileResponse.text();

// Removes empty/blank lines or lines just with spaces and trims each line
// from leading and trailing paddings/spaces
const cleanedContent = parseRichTextIntoPlainText(source);

const deflatedSource = deflateSync(cleanedContent).toString('base64');

return {
filename: filename,
pathname: getPathnameForApiFile(name, versionWithPrefix),
content: deflatedSource,
};
}
);

return Promise.all(mappedApiFiles).then(Response.json);
});
// transforms the response into an array of GitHubApiFile
const apiDocsFiles: Array<GitHubApiFile> = await gitHubApiResponse.json();

// prevent the route from crashing if the response is not an array of GitHubApiFile
// and return an empty array instead. This is a fallback for when the GitHub API is not available.
if (!Array.isArray(apiDocsFiles)) {
return Response.json([]);
}

// maps over each api file and get the download_url, fetch the content and deflates it
const mappedApiFiles = apiDocsFiles.map(
async ({ name, path: filename, download_url }) => {
const apiFileResponse = await fetch(download_url);

// Retrieves the content as a raw text string
const source = await apiFileResponse.text();

// Removes empty/blank lines or lines just with spaces and trims each line
// from leading and trailing paddings/spaces
const cleanedContent = parseRichTextIntoPlainText(source);

const deflatedSource = deflateSync(cleanedContent).toString('base64');

return {
filename: filename,
pathname: getPathnameForApiFile(name, versionWithPrefix),
content: deflatedSource,
};
}
);

const data = await Promise.all(mappedApiFiles);

return Response.json(data);
};

// This function generates the static paths that come from the dynamic segments
Expand Down
37 changes: 0 additions & 37 deletions apps/site/app/[locale]/next-data/download-snippets/route.tsx

This file was deleted.

66 changes: 37 additions & 29 deletions apps/site/app/[locale]/next-data/page-data/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,44 +10,52 @@ import { parseRichTextIntoPlainText } from '#site/util/string';
// for a digest and metadata of all existing pages on Node.js Website
// @see https://nextjs.org/docs/app/building-your-application/routing/router-handlers
export const GET = async () => {
// Retrieves all available routes for the default locale
const allAvailbleRoutes = await dynamicRouter.getRoutesByLanguage(
defaultLocale.code
);

const availablePagesMetadata = allAvailbleRoutes
.filter(route => !route.startsWith('blog'))
.map(async pathname => {
const { source, filename } = await dynamicRouter.getMarkdownFile(
defaultLocale.code,
pathname
);
// We exclude the blog routes from the available pages metadata
// as they are generated separately and are not part of the static pages
// and are not part of the static pages metadata
const routesExceptBlog = allAvailbleRoutes.filter(
route => !route.startsWith('blog')
);

const availablePagesMetadata = routesExceptBlog.map(async pathname => {
const { source, filename } = await dynamicRouter.getMarkdownFile(
defaultLocale.code,
pathname
);

// Gets the title and the Description from the Page Metadata
const { title, description } = await dynamicRouter.getPageMetadata(
defaultLocale.code,
pathname
);

// Gets the title and the Description from the Page Metadata
const { title, description } = await dynamicRouter.getPageMetadata(
defaultLocale.code,
pathname
);
// Parser the Markdown source with `gray-matter` and then only
// grabs the markdown content and cleanses it by removing HTML/JSX tags
// removing empty/blank lines or lines just with spaces and trims each line
// from leading and trailing paddings/spaces
const cleanedContent = parseRichTextIntoPlainText(matter(source).content);

// Parser the Markdown source with `gray-matter` and then only
// grabs the markdown content and cleanses it by removing HTML/JSX tags
// removing empty/blank lines or lines just with spaces and trims each line
// from leading and trailing paddings/spaces
const cleanedContent = parseRichTextIntoPlainText(matter(source).content);
// Deflates a String into a base64 string-encoded (zlib compressed)
const content = deflateSync(cleanedContent).toString('base64');

// Deflates a String into a base64 string-encoded (zlib compressed)
const content = deflateSync(cleanedContent).toString('base64');
// Returns metadata of each page available on the Website
return {
filename,
pathname,
title,
description,
content,
};
});

// Returns metadata of each page available on the Website
return {
filename,
pathname,
title,
description,
content,
};
});
const data = await Promise.all(availablePagesMetadata);

return Response.json(await Promise.all(availablePagesMetadata));
return Response.json(data);
};

// This function generates the static paths that come from the dynamic segments
Expand Down
31 changes: 0 additions & 31 deletions apps/site/app/[locale]/next-data/release-data/route.ts

This file was deleted.

2 changes: 1 addition & 1 deletion apps/site/app/[locale]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type DynamicParams = { params: Promise<DynamicStaticPaths> };

// This is the default Viewport Metadata
// @see https://nextjs.org/docs/app/api-reference/functions/generate-viewport#generateviewport-function
export const generateViewport = async () => ({ ...PAGE_VIEWPORT });
export const generateViewport = () => ({ ...PAGE_VIEWPORT });

// This generates each page's HTML Metadata
// @see https://nextjs.org/docs/app/api-reference/functions/generate-metadata
Expand Down
11 changes: 5 additions & 6 deletions apps/site/components/Downloads/DownloadReleasesTable/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import Badge from '@node-core/ui-components/Common/Badge';
import { getTranslations } from 'next-intl/server';
import { useTranslations } from 'next-intl';
import type { FC } from 'react';

import FormattedTime from '#site/components/Common/FormattedTime';
import DetailsButton from '#site/components/Downloads/DownloadReleasesTable/DetailsButton';
import getReleaseData from '#site/next-data/releaseData';
import provideReleaseData from '#site/next-data/providers/releaseData';

const BADGE_KIND_MAP = {
'End-of-life': 'warning',
Expand All @@ -14,10 +14,9 @@ const BADGE_KIND_MAP = {
Pending: 'default',
} as const;

const DownloadReleasesTable: FC = async () => {
const releaseData = await getReleaseData();

const t = await getTranslations();
const DownloadReleasesTable: FC = () => {
const releaseData = provideReleaseData();
const t = useTranslations();

return (
<table id="tbVersions" className="download-table full-width">
Expand Down
11 changes: 8 additions & 3 deletions apps/site/components/withBlogCrossLinks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ import CrossLink from '#site/components/Common/CrossLink';
import getBlogData from '#site/next-data/blogData';
import type { BlogCategory } from '#site/types';

const WithBlogCrossLinks: FC = async () => {
const WithBlogCrossLinks: FC = () => {
const { pathname } = getClientContext();

// Extracts from the static URL the components used for the Blog Post slug
const [, , category, postname] = pathname.split('/');
const [, , category, postname] = pathname.split('/') as [
unknown,
unknown,
BlogCategory,
string,
];

const { posts } = await getBlogData(category as BlogCategory);
const { posts } = getBlogData(category);

const currentItem = posts.findIndex(
({ slug }) => slug === `/blog/${category}/${postname}`
Expand Down
17 changes: 9 additions & 8 deletions apps/site/components/withDownloadSection.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { getLocale } from 'next-intl/server';
import { useLocale } from 'next-intl';
import type { FC, PropsWithChildren } from 'react';

import { getClientContext } from '#site/client-context';
import WithNodeRelease from '#site/components/withNodeRelease';
import getDownloadSnippets from '#site/next-data/downloadSnippets';
import getReleaseData from '#site/next-data/releaseData';
import provideDownloadSnippets from '#site/next-data/providers/downloadSnippets';
import provideReleaseData from '#site/next-data/providers/releaseData';
import { defaultLocale } from '#site/next.locales.mjs';
import {
ReleaseProvider,
Expand All @@ -13,12 +13,13 @@ import {

// By default the translated languages do not contain all the download snippets
// Hence we always merge any translated snippet with the fallbacks for missing snippets
const fallbackSnippets = await getDownloadSnippets(defaultLocale.code);
const fallbackSnippets = provideDownloadSnippets(defaultLocale.code);

const WithDownloadSection: FC<PropsWithChildren> = async ({ children }) => {
const locale = await getLocale();
const releases = await getReleaseData();
const snippets = await getDownloadSnippets(locale);
const WithDownloadSection: FC<PropsWithChildren> = ({ children }) => {
const locale = useLocale();
const releases = provideReleaseData();

const snippets = provideDownloadSnippets(locale);
const { pathname } = getClientContext();

// Some available translations do not have download snippets translated or have them partially translated
Expand Down
4 changes: 2 additions & 2 deletions apps/site/components/withFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const WithFooter: FC = async () => {
};

const primary = (
<>
<div className="flex flex-row gap-2">
Comment thread
ovflowd marked this conversation as resolved.
<WithNodeRelease status="Active LTS">
{({ release }) => (
<BadgeGroup
Expand All @@ -53,7 +53,7 @@ const WithFooter: FC = async () => {
</BadgeGroup>
)}
</WithNodeRelease>
</>
</div>
);

return (
Expand Down
6 changes: 3 additions & 3 deletions apps/site/components/withNodeRelease.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { FC } from 'react';

import getReleaseData from '#site/next-data/releaseData';
import provideReleaseData from '#site/next-data/providers/releaseData';
import type { NodeRelease, NodeReleaseStatus } from '#site/types';

type WithNodeReleaseProps = {
Expand All @@ -11,11 +11,11 @@ type WithNodeReleaseProps = {
// This is a React Async Server Component
// Note that Hooks cannot be used in a RSC async component
// Async Components do not get re-rendered at all.
const WithNodeRelease: FC<WithNodeReleaseProps> = async ({
const WithNodeRelease: FC<WithNodeReleaseProps> = ({
status,
children: Component,
}) => {
const releaseData = await getReleaseData();
const releaseData = provideReleaseData();

const matchingRelease = releaseData.find(release =>
[status].flat().includes(release.status)
Expand Down
Loading
Loading