From 19850ebe8748e2404b74f7355bd7b50fe32031b1 Mon Sep 17 00:00:00 2001 From: ulofiai Date: Fri, 7 Aug 2026 01:46:41 +0800 Subject: [PATCH] fix: hide incompatible download options --- .../Release/InstallationMethodDropdown.tsx | 8 +++-- .../Release/OperatingSystemDropdown.tsx | 16 +++++++--- .../Release/PackageManagerDropdown.tsx | 8 +++-- .../Downloads/Release/PlatformDropdown.tsx | 8 +++-- apps/site/pages/en/download/current.mdx | 2 +- apps/site/pages/en/download/index.mdx | 2 +- apps/site/util/__tests__/download.test.mjs | 32 +++++++++++++++++++ apps/site/util/download/index.tsx | 15 +++++++++ 8 files changed, 78 insertions(+), 13 deletions(-) diff --git a/apps/site/components/Downloads/Release/InstallationMethodDropdown.tsx b/apps/site/components/Downloads/Release/InstallationMethodDropdown.tsx index 4cc89b2149d2a..45e52a49fbf08 100644 --- a/apps/site/components/Downloads/Release/InstallationMethodDropdown.tsx +++ b/apps/site/components/Downloads/Release/InstallationMethodDropdown.tsx @@ -5,7 +5,11 @@ import { useTranslations } from 'next-intl'; import { use, useEffect, useMemo } from 'react'; import { ReleaseContext } from '#site/providers/releaseProvider'; -import { nextItem, INSTALL_METHODS, parseCompat } from '#site/util/download'; +import { + filterDropdownItems, + nextItem, + INSTALL_METHODS, +} from '#site/util/download'; import type { InstallationMethod } from '#site/types/release'; import type { FC } from 'react'; @@ -16,7 +20,7 @@ const InstallationMethodDropdown: FC = () => { // We parse the compatibility of the dropdown items const parsedInstallMethods = useMemo( - () => parseCompat(INSTALL_METHODS, release), + () => filterDropdownItems(INSTALL_METHODS, release), // We only want to react on the change of the OS and Version // eslint-disable-next-line @eslint-react/exhaustive-deps [release.os, release.version] diff --git a/apps/site/components/Downloads/Release/OperatingSystemDropdown.tsx b/apps/site/components/Downloads/Release/OperatingSystemDropdown.tsx index b559a7b046373..aebcffb736c08 100644 --- a/apps/site/components/Downloads/Release/OperatingSystemDropdown.tsx +++ b/apps/site/components/Downloads/Release/OperatingSystemDropdown.tsx @@ -6,14 +6,20 @@ import { use, useEffect, useMemo } from 'react'; import useClientContext from '#site/hooks/useClientContext'; import { ReleaseContext } from '#site/providers/releaseProvider'; -import { nextItem, OPERATING_SYSTEMS, parseCompat } from '#site/util/download'; +import { + filterDropdownItems, + nextItem, + OPERATING_SYSTEMS, +} from '#site/util/download'; import type { OperatingSystem } from '#site/types/userAgent'; import type { FC } from 'react'; type OperatingSystemDropdownProps = { exclude?: Array }; -const OperatingSystemDropdown: FC = () => { +const OperatingSystemDropdown: FC = ({ + exclude, +}) => { const { os } = useClientContext(); const release = use(ReleaseContext); const t = useTranslations(); @@ -30,10 +36,10 @@ const OperatingSystemDropdown: FC = () => { // We parse the compatibility of the dropdown items const parsedOperatingSystems = useMemo( - () => parseCompat(OPERATING_SYSTEMS, release), - // We only want to react on the change of the Install Method and Version + () => filterDropdownItems(OPERATING_SYSTEMS, release, exclude), + // We only want to react on exclusions, the Install Method, and Version // eslint-disable-next-line @eslint-react/exhaustive-deps - [release.installMethod, release.version] + [exclude, release.installMethod, release.version] ); // We set the OS to the next available OS when the current diff --git a/apps/site/components/Downloads/Release/PackageManagerDropdown.tsx b/apps/site/components/Downloads/Release/PackageManagerDropdown.tsx index 8915c29d0dbb8..e7f7cfd1e0588 100644 --- a/apps/site/components/Downloads/Release/PackageManagerDropdown.tsx +++ b/apps/site/components/Downloads/Release/PackageManagerDropdown.tsx @@ -5,7 +5,11 @@ import { useTranslations } from 'next-intl'; import { use, useEffect, useMemo } from 'react'; import { ReleaseContext } from '#site/providers/releaseProvider'; -import { nextItem, PACKAGE_MANAGERS, parseCompat } from '#site/util/download'; +import { + filterDropdownItems, + nextItem, + PACKAGE_MANAGERS, +} from '#site/util/download'; import type { PackageManager } from '#site/types/release'; import type { FC } from 'react'; @@ -16,7 +20,7 @@ const PackageManagerDropdown: FC = () => { // We parse the compatibility of the dropdown items const parsedPackageManagers = useMemo( - () => parseCompat(PACKAGE_MANAGERS, release), + () => filterDropdownItems(PACKAGE_MANAGERS, release), // We only want to react on the change of the Version // eslint-disable-next-line @eslint-react/exhaustive-deps [release.version] diff --git a/apps/site/components/Downloads/Release/PlatformDropdown.tsx b/apps/site/components/Downloads/Release/PlatformDropdown.tsx index 3285d32fdb21c..25fe5878968f7 100644 --- a/apps/site/components/Downloads/Release/PlatformDropdown.tsx +++ b/apps/site/components/Downloads/Release/PlatformDropdown.tsx @@ -6,7 +6,11 @@ import { useEffect, use, useMemo, useState } from 'react'; import useClientContext from '#site/hooks/useClientContext'; import { ReleaseContext } from '#site/providers/releaseProvider'; -import { PLATFORMS, nextItem, parseCompat } from '#site/util/download'; +import { + filterDropdownItems, + PLATFORMS, + nextItem, +} from '#site/util/download'; import { getUserPlatform } from '#site/util/userAgent'; import type { Platform } from '#site/types/userAgent'; @@ -48,7 +52,7 @@ const PlatformDropdown: FC = () => { // We only want to parse the compatibility when the OS has finished loading // Otherwise, we would be parsing the compatibility of an empty array release.os !== 'LOADING' - ? parseCompat(PLATFORMS[release.os], release) + ? filterDropdownItems(PLATFORMS[release.os], release) : [], // We only want to react on the change of the OS, Platform, and Version // eslint-disable-next-line @eslint-react/exhaustive-deps diff --git a/apps/site/pages/en/download/current.mdx b/apps/site/pages/en/download/current.mdx index cc435c8af1e41..8412be8c73a6b 100644 --- a/apps/site/pages/en/download/current.mdx +++ b/apps/site/pages/en/download/current.mdx @@ -5,7 +5,7 @@ title: Download Node.js®
-Get Node.js® for using with +Get Node.js® for using with diff --git a/apps/site/pages/en/download/index.mdx b/apps/site/pages/en/download/index.mdx index 9767b0d9bda2f..8f0f10ac78e74 100644 --- a/apps/site/pages/en/download/index.mdx +++ b/apps/site/pages/en/download/index.mdx @@ -5,7 +5,7 @@ title: Download Node.js®
-Get Node.js® for using with +Get Node.js® for using with diff --git a/apps/site/util/__tests__/download.test.mjs b/apps/site/util/__tests__/download.test.mjs index c1aa3ffd1c655..a7f2e6a4d5ec6 100644 --- a/apps/site/util/__tests__/download.test.mjs +++ b/apps/site/util/__tests__/download.test.mjs @@ -2,6 +2,7 @@ import assert from 'node:assert/strict'; import { describe, it } from 'node:test'; import { + filterDropdownItems, parseCompat, nextItem, OPERATING_SYSTEMS, @@ -134,6 +135,37 @@ describe('parseCompat', () => { }); }); +describe('filterDropdownItems', () => { + const releaseContext = { + os: 'LINUX', + installMethod: 'NVM', + platform: 'x64', + version: 'v24.0.0', + release: { status: 'LTS' }, + }; + + it('should remove incompatible items', () => { + const result = filterDropdownItems(INSTALL_METHODS, releaseContext); + + assert.ok(result.some(({ value }) => value === 'NVM')); + assert.ok(!result.some(({ value }) => value === 'CHOCO')); + }); + + it('should remove explicitly excluded items', () => { + const compatibleItems = filterDropdownItems( + OPERATING_SYSTEMS, + releaseContext + ); + const result = filterDropdownItems(OPERATING_SYSTEMS, releaseContext, [ + 'AIX', + ]); + + assert.ok(compatibleItems.some(({ value }) => value === 'AIX')); + assert.ok(result.some(({ value }) => value === 'LINUX')); + assert.ok(!result.some(({ value }) => value === 'AIX')); + }); +}); + describe('nextItem', () => { it('should find the first valid item if current is invalid', () => { const items = [ diff --git a/apps/site/util/download/index.tsx b/apps/site/util/download/index.tsx index 69713f4fb005a..91eb9a98ca9ab 100644 --- a/apps/site/util/download/index.tsx +++ b/apps/site/util/download/index.tsx @@ -73,6 +73,21 @@ export const parseCompat = < })); }; +/** + * Filters dropdown items by compatibility and explicit exclusions + */ +export const filterDropdownItems = < + K extends string, + T extends DownloadDropdownItem, +>( + items: Array, + context: Types.ReleaseContextType, + exclude: Array = [] +): Array => + parseCompat(items, context).filter( + ({ disabled, value }) => !disabled && !exclude.includes(value) + ); + /** * Creates an icon element for a component */