Skip to content

Commit b417a64

Browse files
ovflowdmikeestoljharbbmuenzenmeyercanerakdas
authored
feat: official vs community and instructions for downloads page (#7365)
* feat: official vs community and instructions for downloads page * chore: semantical fixes * chore: removed unused code * chore: transform into a requirements table * chore: update requirements * chore: review changes * Apply suggestions from code review Co-authored-by: Michael Esteban <[email protected]> Signed-off-by: Claudio W <[email protected]> * Update apps/site/pages/en/about/previous-releases.mdx Co-authored-by: Jordan Harband <[email protected]> Signed-off-by: Claudio W <[email protected]> * Update apps/site/pages/en/about/previous-releases.mdx Co-authored-by: Jordan Harband <[email protected]> Signed-off-by: Claudio W <[email protected]> * Update previous-releases.mdx Signed-off-by: Claudio W <[email protected]> * Update COLLABORATOR_GUIDE.md Co-authored-by: Caner Akdas <[email protected]> Signed-off-by: Brian Muenzenmeyer <[email protected]> * Update COLLABORATOR_GUIDE.md Co-authored-by: Caner Akdas <[email protected]> Signed-off-by: Brian Muenzenmeyer <[email protected]> * Update COLLABORATOR_GUIDE.md Co-authored-by: Caner Akdas <[email protected]> Signed-off-by: Brian Muenzenmeyer <[email protected]> * Update COLLABORATOR_GUIDE.md Co-authored-by: Caner Akdas <[email protected]> Signed-off-by: Brian Muenzenmeyer <[email protected]> * Apply suggestions from code review Co-authored-by: Caner Akdas <[email protected]> Signed-off-by: Claudio W <[email protected]> --------- Signed-off-by: Claudio W <[email protected]> Signed-off-by: Brian Muenzenmeyer <[email protected]> Co-authored-by: Michael Esteban <[email protected]> Co-authored-by: Jordan Harband <[email protected]> Co-authored-by: Brian Muenzenmeyer <[email protected]> Co-authored-by: Caner Akdas <[email protected]>
1 parent 5a69946 commit b417a64

File tree

20 files changed

+184
-152
lines changed

20 files changed

+184
-152
lines changed

COLLABORATOR_GUIDE.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
- [Best practices when creating a Component](#best-practices-when-creating-a-component)
1414
- [How a new Component should look like when freshly created](#how-a-new-component-should-look-like-when-freshly-created)
1515
- [Best practices for Component development in general](#best-practices-for-component-development-in-general)
16+
- [The new Downloads page](#the-new-downloads-page)
17+
- [Adding a Download Installation Method](#adding-a-download-installation-method)
18+
- [Adding a Download Package Manager](#adding-a-download-package-manager)
1619
- [Unit Tests and Storybooks](#unit-tests-and-storybooks)
1720
- [General Guidelines for Unit Tests](#general-guidelines-for-unit-tests)
1821
- [General Guidelines for Storybooks](#general-guidelines-for-storybooks)
@@ -259,6 +262,117 @@ export default MyComponent;
259262
Use utilities or Hooks when you need a Reactive state
260263
- Avoid making your Component too big. Deconstruct it into smaller Components/Hooks whenever possible
261264

265+
## The new Downloads page
266+
267+
### Adding a Download Installation Method
268+
269+
To add a new download installation method, follow these steps:
270+
271+
1. **Update `INSTALL_METHODS` in `apps/site/util/downloadUtils.tsx`:**
272+
273+
- Add a new entry to the `INSTALL_METHODS` array.
274+
- Each entry should have the following properties:
275+
- `iconImage`: The React component of the icon image for the installation method. This should be an SVG component stored within `apps/site/components/Icons/InstallationMethod` and must follow the other icon component references (being a `FC` supporting `SVGSVGElement` props).
276+
- Don't forget to add it on the `index.tsx` file from the `InstallationMethod` folder.
277+
- `recommended`: A boolean indicating if this method is recommended. This property is available only for official installation methods.
278+
- `url`: The URL for the installation method.
279+
- `value`: The key of the installation method, which must be unique.
280+
281+
Example:
282+
283+
```javascript
284+
// filepath: /nodejs.org/apps/site/util/downloadUtils.tsx
285+
// See full reference of INSTALL_METHODS within `downloadUtils.tsx`
286+
export const INSTALL_METHODS = [
287+
// ...existing methods...
288+
{
289+
iconImage: <InstallMethodIcons.YourIconImage width={16} height={16} />,
290+
url: 'https://example.com/install',
291+
value: 'exampleMethod',
292+
},
293+
];
294+
```
295+
296+
2. **Add translation key in `packages/i18n/locales/en.json`:**
297+
298+
- Add an entry under `layouts.download.codeBox.platformInfo` for the `info` property of the new installation method.
299+
300+
Example:
301+
302+
```json
303+
// filepath: /nodejs.org/packages/i18n/locales/en.json
304+
{
305+
"layouts": {
306+
"download": {
307+
"codeBox": {
308+
"platformInfo": {
309+
"exampleMethod": "Example installation method description."
310+
}
311+
}
312+
}
313+
}
314+
}
315+
```
316+
317+
3. **Update `InstallationMethodLabel` and `InstallationMethod` in `@/types/release.ts`:**
318+
319+
- Add the new method to the `InstallationMethodLabel` and `InstallationMethod` types.
320+
321+
Example:
322+
323+
```typescript
324+
// filepath: /nodejs.org/apps/site/types/release.ts
325+
export type InstallationMethod = 'exampleMethod' | 'anotherMethod' | ...;
326+
327+
export const InstallationMethodLabel: Record<InstallationMethod, string> = {
328+
exampleMethod: 'Example Method',
329+
anotherMethod: 'Another Method',
330+
// ...existing methods...
331+
};
332+
```
333+
334+
4. **Add a snippet in `apps/site/snippets/en/download`:**
335+
336+
- Create a new file with the same key as the `value` property (e.g., `exampleMethod.bash`).
337+
- Add the installation instructions in this file.
338+
- The snippet file can use JavaScript template syntax and has access to a `props` variable of type `ReleaseContextType`.
339+
340+
Example:
341+
342+
```bash
343+
// filepath: /nodejs.org/apps/site/snippets/en/download/exampleMethod.bash
344+
echo "Installing Node.js version ${props.version} using Example Method"
345+
```
346+
347+
5. **Configure `compatibility` within the `INSTALL_METHODS` object in `downloadUtils.ts`:**
348+
349+
- Use the `compatibility` property to enable/list the installation method for specific OSs, Node.js version ranges, or architectures/platforms.
350+
351+
Example:
352+
353+
```javascript
354+
// filepath: /nodejs.org/apps/site/util/downloadUtils.tsx
355+
// See full reference of compatibility property within `downloadUtils.tsx`
356+
export const INSTALL_METHODS = [
357+
{
358+
iconImage: 'path/to/icon.svg',
359+
url: 'https://example.com/install',
360+
value: 'exampleMethod',
361+
compatibility: {
362+
os: ['LINUX', 'MAC'],
363+
semver: ['>=14.0.0'],
364+
platform: ['x64', 'arm64'],
365+
},
366+
},
367+
];
368+
```
369+
370+
By following these steps, you can successfully add a new download installation method to the Node.js website.
371+
372+
### Adding a Download Package Manager
373+
374+
You can add a PACKAGE_MANAGER the same way as adding an INSTALLATION_METHOD (from the section above, "Adding a Download Installation Method") but it should be added to the PACKAGE_MANAGERS object in `apps/site/util/downloadUtils.tsx`.
375+
262376
## Unit Tests and Storybooks
263377

264378
Each new feature or bug fix should be accompanied by a unit test (when deemed valuable).

apps/site/components/Downloads/DownloadReleasesTable.tsx

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { getTranslations } from 'next-intl/server';
22
import type { FC } from 'react';
33

4+
import LinkWithArrow from '@/components/LinkWithArrow';
45
import getReleaseData from '@/next-data/releaseData';
6+
import { BASE_CHANGELOG_URL } from '@/next.constants.mjs';
57
import { getNodeApiLink } from '@/util/getNodeApiLink';
6-
import { getNodeJsChangelog } from '@/util/getNodeJsChangelog';
78

89
// This is a React Async Server Component
910
// Note that Hooks cannot be used in a RSC async component
@@ -17,11 +18,12 @@ const DownloadReleasesTable: FC = async () => {
1718
<table id="tbVersions" className="download-table full-width">
1819
<thead>
1920
<tr>
20-
<th>Node.js Version</th>
21-
<th>Module Version</th>
22-
<th>Codename</th>
23-
<th>Release Date</th>
24-
<th colSpan={2}>npm</th>
21+
<th>{t('components.downloadReleasesTable.version')}</th>
22+
<th>{t('components.downloadReleasesTable.nApiVersion')}</th>
23+
<th>{t('components.downloadReleasesTable.codename')}</th>
24+
<th>{t('components.downloadReleasesTable.releaseDate')}</th>
25+
<th>{t('components.downloadReleasesTable.npmVersion')}</th>
26+
<th></th>
2527
</tr>
2628
</thead>
2729
<tbody>
@@ -35,17 +37,19 @@ const DownloadReleasesTable: FC = async () => {
3537
</td>
3638
<td data-label="npm">v{release.npm}</td>
3739
<td className="download-table-last">
38-
<a
40+
<LinkWithArrow
3941
href={`https://nodejs.org/download/release/${release.versionWithPrefix}/`}
4042
>
41-
{t('components.downloadReleasesTable.releases')}
42-
</a>
43-
<a href={getNodeJsChangelog(release.versionWithPrefix)}>
44-
{t('components.downloadReleasesTable.changelog')}
45-
</a>
46-
<a href={getNodeApiLink(release.versionWithPrefix)}>
47-
{t('components.downloadReleasesTable.docs')}
48-
</a>
43+
{t('components.downloadReleasesTable.actions.releases')}
44+
</LinkWithArrow>
45+
46+
<LinkWithArrow href={`${BASE_CHANGELOG_URL}${release.version}`}>
47+
{t('components.downloadReleasesTable.actions.changelog')}
48+
</LinkWithArrow>
49+
50+
<LinkWithArrow href={getNodeApiLink(release.versionWithPrefix)}>
51+
{t('components.downloadReleasesTable.actions.docs')}
52+
</LinkWithArrow>
4953
</td>
5054
</tr>
5155
))}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
import type { FC, PropsWithChildren } from 'react';
44
import { useContext } from 'react';
55

6-
import LinkWithArrow from '@/components/Downloads/Release/LinkWithArrow';
76
import Link from '@/components/Link';
7+
import LinkWithArrow from '@/components/LinkWithArrow';
88
import { BASE_CHANGELOG_URL } from '@/next.constants.mjs';
99
import { ReleaseContext } from '@/providers/releaseProvider';
1010

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,13 @@ import AlertBox from '@/components/Common/AlertBox';
88
import CodeBox from '@/components/Common/CodeBox';
99
import Skeleton from '@/components/Common/Skeleton';
1010
import Link from '@/components/Link';
11+
import LinkWithArrow from '@/components/LinkWithArrow';
1112
import { createSval } from '@/next.jsx.compiler.mjs';
1213
import { ReleaseContext, ReleasesContext } from '@/providers/releaseProvider';
1314
import type { ReleaseContextType } from '@/types/release';
1415
import { INSTALL_METHODS } from '@/util/downloadUtils';
1516
import { highlightToHtml } from '@/util/getHighlighter';
1617

17-
import LinkWithArrow from './LinkWithArrow';
18-
1918
// Creates a minimal JavaScript interpreter for parsing the JavaScript code from the snippets
2019
// Note: that the code runs inside a sandboxed environment and cannot interact with any code outside of the sandbox
2120
// It also does not have access to any Global or Window objects, nor it can execute code on the end-user's browser
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import Choco from '@/components/Icons/InstallationMethod/Choco';
2+
import Docker from '@/components/Icons/InstallationMethod/Docker';
3+
import FNM from '@/components/Icons/InstallationMethod/FNM';
4+
import Homebrew from '@/components/Icons/InstallationMethod/Homebrew';
5+
import NVM from '@/components/Icons/InstallationMethod/NVM';
6+
7+
export default { Choco, Docker, FNM, Homebrew, NVM };

0 commit comments

Comments
 (0)