Skip to content

Commit 98b9e42

Browse files
Esp participation (#7086)
* added support for the OpenJS ESP program, and links to HeroDevs * feat: added support for the OpenJS ESP program and HeroDevs Links * fixed issues identified by maintainers * removed comments that didn't get cleaned * fix(nav): prevent double-highlight in nav, use constants * added unit tests --------- Co-authored-by: Brian Muenzenmeyer <[email protected]>
1 parent 851b085 commit 98b9e42

File tree

8 files changed

+103
-3
lines changed

8 files changed

+103
-3
lines changed

apps/site/components/Common/ActiveLink/__tests__/index.test.mjs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
import { render, screen } from '@testing-library/react';
22

3+
import { VERSION_SUPPORT_SHORTCUT } from '@/next.constants.mjs';
4+
35
import ActiveLink from '..';
46

7+
// mock usePathname, but retain all the other imports
8+
jest.mock('@/navigation.mjs', () => ({
9+
...jest.requireActual('@/navigation.mjs'),
10+
usePathname: jest.fn(),
11+
}));
12+
513
describe('ActiveLink', () => {
614
it('renders as localized link', () => {
715
render(
@@ -38,4 +46,61 @@ describe('ActiveLink', () => {
3846
'link active'
3947
);
4048
});
49+
50+
it('does not set active class when href base does not match', () => {
51+
const { usePathname } = require('@/navigation.mjs');
52+
usePathname.mockReturnValue('/not-link/sublink');
53+
54+
render(
55+
<ActiveLink
56+
className="link"
57+
activeClassName="active"
58+
allowSubPath={true}
59+
href={'/link/sub-link'}
60+
>
61+
Link
62+
</ActiveLink>
63+
);
64+
65+
expect(screen.findByText('Link')).resolves.toHaveAttribute('class', 'link');
66+
});
67+
68+
it('sets active class when href is other than VERSION_SUPPORT_SHORTCUT', () => {
69+
const { usePathname } = require('@/navigation.mjs');
70+
usePathname.mockReturnValue('/link/sublink');
71+
72+
render(
73+
<ActiveLink
74+
className="link"
75+
activeClassName="active"
76+
allowSubPath={true}
77+
href={'/link/sub-link'}
78+
>
79+
Link
80+
</ActiveLink>
81+
);
82+
83+
expect(screen.findByText('Link')).resolves.toHaveAttribute(
84+
'class',
85+
'link active'
86+
);
87+
});
88+
89+
it('does not set active class when href is VERSION_SUPPORT_SHORTCUT', () => {
90+
const { usePathname } = require('@/navigation.mjs');
91+
usePathname.mockReturnValue(VERSION_SUPPORT_SHORTCUT);
92+
93+
render(
94+
<ActiveLink
95+
className="link"
96+
activeClassName="active"
97+
allowSubPath={true}
98+
href={VERSION_SUPPORT_SHORTCUT}
99+
>
100+
Link
101+
</ActiveLink>
102+
);
103+
104+
expect(screen.findByText('Link')).resolves.toHaveAttribute('class', 'link');
105+
});
41106
});

apps/site/components/Common/ActiveLink/index.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type { ComponentProps, FC } from 'react';
55

66
import Link from '@/components/Link';
77
import { usePathname } from '@/navigation.mjs';
8+
import { VERSION_SUPPORT_SHORTCUT } from '@/next.constants.mjs';
89

910
type ActiveLocalizedLinkProps = ComponentProps<typeof Link> & {
1011
activeClassName?: string;
@@ -26,7 +27,9 @@ const ActiveLink: FC<ActiveLocalizedLinkProps> = ({
2627
? // When using allowSubPath we want only to check if
2728
// the current pathname starts with the utmost upper level
2829
// of an href (e.g. /docs/...)
29-
pathname.startsWith(`/${href.toString().split('/')[1]}`)
30+
pathname.startsWith(`/${href.toString().split('/')[1]}`) &&
31+
// but not when this link is for the deep link shortcut to previous releases
32+
href.toString() !== VERSION_SUPPORT_SHORTCUT
3033
: href.toString() === pathname,
3134
});
3235

apps/site/components/Downloads/Release/ReleaseCodeBox.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
import { useTranslations } from 'next-intl';
44
import { useContext, useEffect, useState } from 'react';
55
import type { FC } from 'react';
6+
import semVer from 'semver';
67

8+
import Banner from '@/components/Common/Banner';
79
import CodeBox from '@/components/Common/CodeBox';
10+
import { ESP_SUPPORT_THRESHOLD_VERSION } from '@/next.constants.mjs';
811
import { ReleaseContext } from '@/providers/releaseProvider';
912
import { shikiPromise, highlightToHtml } from '@/util/getHighlighter';
1013
import { getNodeDownloadSnippet } from '@/util/getNodeDownloadSnippet';
@@ -29,13 +32,16 @@ const ReleaseCodeBox: FC = () => {
2932
}, [release.versionWithPrefix, os, platform]);
3033

3134
const codeLanguage = os === 'WIN' ? 'PowerShell' : 'Bash';
32-
3335
return (
3436
<div className="mb-2 mt-6 flex flex-col gap-2">
37+
{semVer.lt(release.versionWithPrefix, ESP_SUPPORT_THRESHOLD_VERSION) && (
38+
<Banner type="error" link="/about/previous-releases/">
39+
{t('layouts.download.codeBox.unsupportedVersionWarning')}&nbsp;
40+
</Banner>
41+
)}
3542
<CodeBox language={codeLanguage} className="min-h-[15.5rem]">
3643
<code dangerouslySetInnerHTML={{ __html: code }} />
3744
</CodeBox>
38-
3945
<span className="text-center text-xs text-neutral-800 dark:text-neutral-200">
4046
{t('layouts.download.codeBox.communityWarning')}
4147
<br />

apps/site/jest.config.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const customJestConfig = {
1616
'next/router': '<rootDir>/components/__mocks__/next-router.mjs',
1717
'next-intl': '<rootDir>/components/__mocks__/next-intl.mjs',
1818
'github-slugger': '<rootDir>/components/__mocks__/github-slugger.mjs',
19+
'^@/(.*)$': '<rootDir>/$1',
1920
},
2021
};
2122

apps/site/navigation.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
"link": "https://nodejs.org/docs/latest/api/",
2121
"label": "components.containers.navBar.links.docs"
2222
},
23+
"support": {
24+
"link": "/about/previous-releases",
25+
"label": "components.containers.navBar.links.support"
26+
},
2327
"certification": {
2428
"link": "https://training.linuxfoundation.org/openjs/",
2529
"label": "components.containers.navBar.links.certification",

apps/site/next.constants.mjs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,18 @@ export const ORAMA_CLOUD_API_KEY = process.env.NEXT_PUBLIC_ORAMA_API_KEY || '';
168168
* Note: This has no NEXT_PUBLIC prefix as it should not be exposed to the Browser.
169169
*/
170170
export const GITHUB_API_KEY = process.env.NEXT_GITHUB_API_KEY || '';
171+
172+
/**
173+
* OpenJS Ecosystem Support Program (ESP) partners provide security updates and support for end-of-life and unsupported versions
174+
*
175+
* See https://openjsf.org/ecosystem-sustainability-program
176+
*
177+
* This is the minimum version Node.js support according to https://nodejs.org/en/about/previous-releases
178+
*/
179+
export const ESP_SUPPORT_THRESHOLD_VERSION =
180+
process.env.ESP_SUPPORT_THRESHOLD_VERSION || '18.0.0';
181+
182+
/**
183+
* This deep link into the app is repeated in the top nav, but we want to ignore it for active-link highlighting, since it will be covered by About
184+
*/
185+
export const VERSION_SUPPORT_SHORTCUT = '/about/previous-releases';

apps/site/pages/en/about/previous-releases.mdx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ Production applications should only use _Active LTS_ or _Maintenance LTS_ releas
1616

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

19+
### Commercial Support
20+
21+
Commercial support for versions past Maintenance phase is available through our OpenJS Ecosystem Sustainability Program partner [HeroDevs](https://herodevs.com/).
22+
1923
## Looking for latest release of a version branch?
2024

2125
<DownloadReleasesTable />

packages/i18n/locales/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"about": "About",
1515
"download": "Download",
1616
"docs": "Docs",
17+
"support": "Version Support",
1718
"guides": "Guides",
1819
"learn": "Learn",
1920
"security": "Security",
@@ -299,6 +300,7 @@
299300
"platform": "Platform"
300301
},
301302
"codeBox": {
303+
"unsupportedVersionWarning": "This version is out of maintenance. Find more information here:",
302304
"fnmEnvSetup": "configure fnm environment",
303305
"systemManagerWarning": "is not a Node.js package manager. Please ensure you already have {packageManager} installed.",
304306
"communityWarning": "Package managers and their installation scripts are not maintained by the Node.js project.",

0 commit comments

Comments
 (0)