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
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<OperatingSystem> };

const OperatingSystemDropdown: FC<OperatingSystemDropdownProps> = () => {
const OperatingSystemDropdown: FC<OperatingSystemDropdownProps> = ({
exclude,
}) => {
const { os } = useClientContext();
const release = use(ReleaseContext);
const t = useTranslations();
Expand All @@ -30,10 +36,10 @@ const OperatingSystemDropdown: FC<OperatingSystemDropdownProps> = () => {

// 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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]
Expand Down
8 changes: 6 additions & 2 deletions apps/site/components/Downloads/Release/PlatformDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion apps/site/pages/en/download/current.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: Download Node.js®

<section>

Get Node.js® <Release.VersionDropdown /> for <Release.OperatingSystemDropdown /> using <Release.InstallationMethodDropdown /> with <Release.PackageManagerDropdown />
Get Node.js® <Release.VersionDropdown /> for <Release.OperatingSystemDropdown exclude={['AIX']} /> using <Release.InstallationMethodDropdown /> with <Release.PackageManagerDropdown />

<Release.ReleaseCodeBox />

Expand Down
2 changes: 1 addition & 1 deletion apps/site/pages/en/download/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: Download Node.js®

<section>

Get Node.js® <Release.VersionDropdown /> for <Release.OperatingSystemDropdown /> using <Release.InstallationMethodDropdown /> with <Release.PackageManagerDropdown />
Get Node.js® <Release.VersionDropdown /> for <Release.OperatingSystemDropdown exclude={['AIX']} /> using <Release.InstallationMethodDropdown /> with <Release.PackageManagerDropdown />

<Release.ReleaseCodeBox />

Expand Down
32 changes: 32 additions & 0 deletions apps/site/util/__tests__/download.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import assert from 'node:assert/strict';
import { describe, it } from 'node:test';

import {
filterDropdownItems,
parseCompat,
nextItem,
OPERATING_SYSTEMS,
Expand Down Expand Up @@ -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 = [
Expand Down
15 changes: 15 additions & 0 deletions apps/site/util/download/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,21 @@ export const parseCompat = <
}));
};

/**
* Filters dropdown items by compatibility and explicit exclusions
*/
export const filterDropdownItems = <
K extends string,
T extends DownloadDropdownItem<K>,
>(
items: Array<T>,
context: Types.ReleaseContextType,
exclude: Array<K> = []
): Array<T> =>
parseCompat(items, context).filter(
({ disabled, value }) => !disabled && !exclude.includes(value)
);

/**
* Creates an icon element for a component
*/
Expand Down