Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
36 changes: 36 additions & 0 deletions apps/site/components/Releases/ReleaseSchedule/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { create } from 'lts';

import provideReleaseSchedule from '#site/next-data/providers/releaseSchedule';

import type { FC } from 'react';

const ReleaseSchedule: FC = async () => {
const schedule = await provideReleaseSchedule();

const now = new Date();

const threeMonthsAgo = new Date(now);
threeMonthsAgo.setMonth(now.getMonth() - 3);

const sixMonthsFromNow = new Date();
sixMonthsFromNow.setMonth(now.getMonth() + 6);

const svg = create({
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is showing a warning that I'm not sure how to solve:

@node-core/website:dev: Package jsdom can't be external
@node-core/website:dev: The request jsdom matches serverExternalPackages (or the default list).
@node-core/website:dev: The package resolves to a different version when requested from the project directory (27.4.0) compared to the package requested from the importing module (9.4.1).
@node-core/website:dev: Make sure to install the same version of the package in both locations.

data: schedule,
queryStart: threeMonthsAgo,
queryEnd: sixMonthsFromNow,
animate: true,
excludeMain: false,
projectName: 'Node.js',
currentDateMarker: 'red',
});

return (
<div
dangerouslySetInnerHTML={{ __html: svg.html() }}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I understand the reason for this, is there a way to avoid this potentially dangerous situation?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that I'm aware of, svg.html() returns a simple string

className="h-auto w-auto"
/>
Comment on lines +28 to +32
Copy link

Copilot AI Jan 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The generated SVG HTML is being directly injected using dangerouslySetInnerHTML without any sanitization. While the content comes from the 'lts' library, this could pose security risks if that library or the data it processes is compromised. Consider:

  1. Validating/sanitizing the SVG output before rendering
  2. Using a safer rendering method if possible
  3. Adding comments explaining why dangerouslySetInnerHTML is necessary here

Copilot uses AI. Check for mistakes.
);
};

export default ReleaseSchedule;
2 changes: 2 additions & 0 deletions apps/site/mdx/components.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import MDXImage from '#site/components/MDX/Image';
import MinorReleasesTable from '#site/components/Releases/MinorReleasesTable';
import PreviousReleasesTable from '#site/components/Releases/PreviousReleasesTable';
import ReleaseOverview from '#site/components/Releases/ReleaseOverview';
import ReleaseSchedule from '#site/components/Releases/ReleaseSchedule';
import WithBadgeGroup from '#site/components/withBadgeGroup';
import WithBanner from '#site/components/withBanner';
import WithDownloadArchive from '#site/components/withDownloadArchive';
Expand Down Expand Up @@ -96,6 +97,7 @@ export default {
BadgeGroup,
ReleaseOverview,
MinorReleasesTable,
ReleaseSchedule,
UpcomingMeetings,
EOLAlertBox,
EOLReleaseTable,
Expand Down
10 changes: 10 additions & 0 deletions apps/site/next-data/generators/releaseSchedule.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { RELEASE_SCHEDULE_URL } from '#site/next.constants.mjs';
import { fetchWithRetry } from '#site/util/fetch';

async function fetchReleaseSchedule() {
const response = await fetchWithRetry(RELEASE_SCHEDULE_URL);

return response.json();
}

export default fetchReleaseSchedule;
5 changes: 5 additions & 0 deletions apps/site/next-data/providers/releaseSchedule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { cache } from 'react';

import generateReleaseSchdule from '#site/next-data/generators/releaseSchedule.mjs';

export default cache(generateReleaseSchdule);
2 changes: 1 addition & 1 deletion apps/site/next-env.d.ts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably need to exclude this file.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we do that, all our CI steps that rely on types will need to call next types first. So, definitely something to address separately (though I agree with ignoring it).

For this PR, the change should just be reverted.

Copy link
Contributor

@malav2110 malav2110 Jan 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I meant exclude == reverting the change *

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
/// <reference types="next/navigation-types/compat/navigation" />
import './.next/types/routes.d.ts';
import './.next/dev/types/routes.d.ts';

// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
6 changes: 6 additions & 0 deletions apps/site/next.constants.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,9 @@ export const VULNERABILITIES_URL =
*/
export const OPENCOLLECTIVE_MEMBERS_URL =
'https://opencollective.com/nodejs/members/all.json';

/**
* The location of the Node.js release schedule JSON.
*/
export const RELEASE_SCHEDULE_URL =
'https://raw.githubusercontent.com/nodejs/Release/refs/heads/main/schedule.json';
1 change: 1 addition & 0 deletions apps/site/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"feed": "~5.1.0",
"github-slugger": "~2.0.0",
"gray-matter": "~4.0.3",
"lts": "github:araujogui/lts-schedule#refactor-website",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use the upstream package once this pr is merged

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding blocked until then

"mdast-util-to-string": "^4.0.0",
"next": "16.0.10",
"next-intl": "~4.5.3",
Expand Down
2 changes: 1 addition & 1 deletion apps/site/pages/en/about/previous-releases.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Production applications should only use _Active LTS_ or _Maintenance LTS_ releas

## Release Schedule

![Releases](https://raw.githubusercontent.com/nodejs/Release/main/schedule.svg?sanitize=true)
<ReleaseSchedule />

Full details regarding the Node.js release schedule are available [on GitHub](https://github.com/nodejs/release#release-schedule).

Expand Down
Loading
Loading