diff --git a/apps/site/components/Downloads/DownloadButton/index.module.css b/apps/site/components/Downloads/DownloadButton/index.module.css deleted file mode 100644 index 7cc12d7f700e3..0000000000000 --- a/apps/site/components/Downloads/DownloadButton/index.module.css +++ /dev/null @@ -1,19 +0,0 @@ -@reference "../../../styles/index.css"; - -.downloadButton { - @apply justify-center; - - &.primary { - @apply inline-flex - dark:hidden; - } - - &.special { - @apply hidden - dark:inline-flex; - } - - svg { - @apply dark:opacity-50; - } -} diff --git a/apps/site/components/Downloads/DownloadButton/index.tsx b/apps/site/components/Downloads/DownloadButton/index.tsx deleted file mode 100644 index f238ce4546505..0000000000000 --- a/apps/site/components/Downloads/DownloadButton/index.tsx +++ /dev/null @@ -1,51 +0,0 @@ -'use client'; - -import { CloudArrowDownIcon } from '@heroicons/react/24/outline'; -import classNames from 'classnames'; -import type { FC, PropsWithChildren } from 'react'; - -import Button from '#site/components/Common/Button'; -import { useClientContext } from '#site/hooks'; -import type { NodeRelease } from '#site/types'; -import { getNodeDownloadUrl } from '#site/util/getNodeDownloadUrl'; -import { getUserPlatform } from '#site/util/getUserPlatform'; - -import styles from './index.module.css'; - -type DownloadButtonProps = { release: NodeRelease }; - -const DownloadButton: FC> = ({ - release: { versionWithPrefix }, - children, -}) => { - const { os, bitness, architecture } = useClientContext(); - - const platform = getUserPlatform(architecture, bitness); - const downloadLink = getNodeDownloadUrl(versionWithPrefix, os, platform); - - return ( - <> - - - - - ); -}; - -export default DownloadButton; diff --git a/apps/site/components/Downloads/DownloadLink.tsx b/apps/site/components/Downloads/DownloadLink.tsx index e639a83d2ac7c..6bb0dea587fe0 100644 --- a/apps/site/components/Downloads/DownloadLink.tsx +++ b/apps/site/components/Downloads/DownloadLink.tsx @@ -20,12 +20,12 @@ const DownloadLink: FC> = ({ const platform = getUserPlatform(architecture, bitness); - const downloadLink = getNodeDownloadUrl( - versionWithPrefix, - os, - platform, - kind - ); + const downloadLink = getNodeDownloadUrl({ + version: versionWithPrefix, + os: os, + platform: platform, + kind: kind, + }); return {children}; }; diff --git a/apps/site/components/Downloads/DownloadReleasesTable/index.tsx b/apps/site/components/Downloads/DownloadReleasesTable/index.tsx index fa2180f5f7fbe..68900ad7ae013 100644 --- a/apps/site/components/Downloads/DownloadReleasesTable/index.tsx +++ b/apps/site/components/Downloads/DownloadReleasesTable/index.tsx @@ -4,6 +4,7 @@ import type { FC } from 'react'; import FormattedTime from '#site/components/Common/FormattedTime'; import DetailsButton from '#site/components/Downloads/DownloadReleasesTable/DetailsButton'; +import Link from '#site/components/Link'; import getReleaseData from '#site/next-data/releaseData'; const DownloadReleasesTable: FC = async () => { @@ -26,7 +27,11 @@ const DownloadReleasesTable: FC = async () => { {releaseData.map(release => ( - v{release.major} + + + v{release.major} + + {release.codename || '-'} diff --git a/apps/site/components/Downloads/DownloadsTable/index.tsx b/apps/site/components/Downloads/DownloadsTable/index.tsx new file mode 100644 index 0000000000000..bcdea982dc9e5 --- /dev/null +++ b/apps/site/components/Downloads/DownloadsTable/index.tsx @@ -0,0 +1,49 @@ +'use client'; + +import { useTranslations } from 'next-intl'; +import type { FC } from 'react'; + +import Link from '#site/components/Link'; +import { OperatingSystemLabel } from '#site/util/downloadUtils'; +import type { NodeDownloadArtifact } from '#site/util/downloadUtils/archive'; + +type DownloadsTableProps = { + source: Array; +}; + +const DownloadsTable: FC = ({ source }) => { + const t = useTranslations(); + + return ( + + + + + + + + + + {source.map(release => ( + + + + + + ))} + +
{t('components.downloadsTable.fileName')} + {t('components.downloadsTable.operatingSystem')} + + {t('components.downloadsTable.architecture')} +
+ {release.file} + + {OperatingSystemLabel[release.os]} + + {release.architecture} +
+ ); +}; + +export default DownloadsTable; diff --git a/apps/site/components/Downloads/MinorReleasesTable/index.module.css b/apps/site/components/Downloads/MinorReleasesTable/index.module.css index 5740edadd7de7..645f033173934 100644 --- a/apps/site/components/Downloads/MinorReleasesTable/index.module.css +++ b/apps/site/components/Downloads/MinorReleasesTable/index.module.css @@ -1,8 +1,29 @@ @reference "../../../styles/index.css"; -.links { +.additionalLinks { @apply flex h-4 items-center gap-2; } + +.items { + @apply flex + h-9 + gap-2; +} + +.scrollable { + @apply scrollbar-thin + flex + max-h-[29rem] + overflow-y-auto; +} + +.information { + @apply md:w-96; +} + +.links { + @apply md:w-44; +} diff --git a/apps/site/components/Downloads/MinorReleasesTable/index.tsx b/apps/site/components/Downloads/MinorReleasesTable/index.tsx index c2cf17ec975a5..97fa5b59886ea 100644 --- a/apps/site/components/Downloads/MinorReleasesTable/index.tsx +++ b/apps/site/components/Downloads/MinorReleasesTable/index.tsx @@ -1,15 +1,19 @@ 'use client'; +import { CodeBracketSquareIcon } from '@heroicons/react/24/outline'; import Separator from '@node-core/ui-components/Common/Separator'; +import NpmIcon from '@node-core/ui-components/Icons/PackageManager/Npm'; import { useTranslations } from 'next-intl'; import type { FC } from 'react'; import Link from '#site/components/Link'; +import LinkWithArrow from '#site/components/LinkWithArrow'; import { BASE_CHANGELOG_URL } from '#site/next.constants.mjs'; import type { MinorVersion } from '#site/types'; import { getNodeApiLink } from '#site/util/getNodeApiLink'; import styles from './index.module.css'; +import { ReleaseOverviewItem } from '../ReleaseOverview'; type MinorReleasesTableProps = { releases: Array; @@ -18,47 +22,78 @@ type MinorReleasesTableProps = { export const MinorReleasesTable: FC = ({ releases, }) => { - const t = useTranslations('components.minorReleasesTable'); + const t = useTranslations('components'); return ( - - - - - - - - - {releases.map(release => ( - - - +
+
{t('version')}{t('links')}
v{release.version} -
- - {t('actions.release')} - - - - {t('actions.changelog')} - - - - {t('actions.docs')} - -
-
+ + + + + - ))} - -
{t('minorReleasesTable.version')} + {t('minorReleasesTable.information')} + {t('minorReleasesTable.links')}
+ + + {releases.map(release => ( + + + + v{release.version} + + + +
+ {release.modules && ( + <> + + + + )} + {release.npm && ( + <> + + + + )} + +
+ + +
+ + {t('minorReleasesTable.actions.docs')} + + + + {t('minorReleasesTable.actions.changelog')} + +
+ + + ))} + + + ); }; diff --git a/apps/site/components/Downloads/Release/PrebuiltDownloadButtons.tsx b/apps/site/components/Downloads/Release/PrebuiltDownloadButtons.tsx index ca037f6a443c2..d015294397775 100644 --- a/apps/site/components/Downloads/Release/PrebuiltDownloadButtons.tsx +++ b/apps/site/components/Downloads/Release/PrebuiltDownloadButtons.tsx @@ -22,11 +22,21 @@ const PrebuiltDownloadButtons: FC = () => { const { release, os, platform } = useContext(ReleaseContext); const installerUrl = platform - ? getNodeDownloadUrl(release.versionWithPrefix, os, platform, 'installer') + ? getNodeDownloadUrl({ + version: release.versionWithPrefix, + os: os, + platform: platform, + kind: 'installer', + }) : ''; const binaryUrl = platform - ? getNodeDownloadUrl(release.versionWithPrefix, os, platform, 'binary') + ? getNodeDownloadUrl({ + version: release.versionWithPrefix, + os: os, + platform: platform, + kind: 'binary', + }) : ''; return ( diff --git a/apps/site/components/Downloads/Release/ReleaseCodeBox.tsx b/apps/site/components/Downloads/Release/ReleaseCodeBox.tsx index 7e18a7bea4b9b..656f198a8cb18 100644 --- a/apps/site/components/Downloads/Release/ReleaseCodeBox.tsx +++ b/apps/site/components/Downloads/Release/ReleaseCodeBox.tsx @@ -10,6 +10,7 @@ import { useContext, useMemo } from 'react'; import CodeBox from '#site/components/Common/CodeBox'; import Link from '#site/components/Link'; import LinkWithArrow from '#site/components/LinkWithArrow'; +import WithReleaseAlertBox from '#site/components/withReleaseAlertBox'; import { createSval } from '#site/next.jsx.compiler.mjs'; import { ReleaseContext, @@ -106,7 +107,7 @@ const ReleaseCodeBox: FC = () => { > {t.rich('layouts.download.codeBox.noScriptDetected', { link: text => ( - + {text} ), @@ -114,17 +115,10 @@ const ReleaseCodeBox: FC = () => { - {release.status === 'End-of-life' && ( - - {t.rich('layouts.download.codeBox.unsupportedVersionWarning', { - link: text => {text}, - })} - - )} + {!currentPlatform || currentPlatform.recommended || ( = ({ : 'components.releaseModal.titleWithoutCodename'; const modalHeading = t(modalHeadingKey, { - version: release.major, + version: `v${release.major}`, codename: release.codename ?? '', }); return ( - {release.status === 'End-of-life' && ( - - {t('components.releaseModal.unsupportedVersionWarning')} - - )} + {release.releaseAnnounceLink && ( diff --git a/apps/site/components/Downloads/ReleaseOverview/index.module.css b/apps/site/components/Downloads/ReleaseOverview/index.module.css index 5043967ac27f1..da1541398edbc 100644 --- a/apps/site/components/Downloads/ReleaseOverview/index.module.css +++ b/apps/site/components/Downloads/ReleaseOverview/index.module.css @@ -15,24 +15,24 @@ gap-4 lg:grid-cols-3; } +} - .item { - @apply flex - items-center - gap-2; +.item { + @apply flex + items-center + gap-2; - h1 { - @apply text-sm - font-semibold; - } + dt { + @apply text-sm + font-semibold; + } - h2 { - @apply text-xs - font-normal; - } + dd { + @apply text-xs + font-normal; + } - svg { - @apply size-4; - } + svg { + @apply size-4; } } diff --git a/apps/site/components/Downloads/ReleaseOverview/index.tsx b/apps/site/components/Downloads/ReleaseOverview/index.tsx index a29118a8e400f..af38c606d5cfc 100644 --- a/apps/site/components/Downloads/ReleaseOverview/index.tsx +++ b/apps/site/components/Downloads/ReleaseOverview/index.tsx @@ -13,23 +13,25 @@ import type { NodeRelease } from '#site/types'; import styles from './index.module.css'; -type ItemProps = { +type ReleaseOverviewItemProps = { Icon: FC>; title: ReactNode; subtitle: ReactNode; }; -const Item: FC = ({ Icon, title, subtitle }) => { - return ( -
- -
-

{subtitle}

-

{title}

-
-
- ); -}; +export const ReleaseOverviewItem: FC = ({ + Icon, + title, + subtitle, +}) => ( +
+ +
+
{subtitle}
+
{title}
+
+
+); type ReleaseOverviewProps = { release: NodeRelease; @@ -41,36 +43,36 @@ export const ReleaseOverview: FC = ({ release }) => { return (
- } subtitle={t('components.releaseOverview.firstReleased')} /> - } subtitle={t('components.releaseOverview.lastUpdated')} /> - {release.modules && ( - )} {release.npm && ( - )} - ; + +type Navigation = { + label: string; + href: string; +}; + +type WithDownloadArchiveProps = { + children: FC }>; +}; + +/** + * Higher-order component that extracts version from pathname, + * fetches release data, and provides download artifacts to child component + */ +const WithDownloadArchive: FC = async ({ + children: Component, +}) => { + const { pathname } = getClientContext(); + + // Extract version from pathname + const version = extractVersionFromPath(pathname); + + if (version == null) { + return null; + } + + // Find the release data for the given version + const releaseData = await getReleaseData(); + const release = findReleaseByVersion(releaseData, version); + + if (!release) { + return null; + } + + const navigation = getDownloadArchiveNavigation(releaseData); + const releaseArtifacts = buildReleaseArtifacts( + release, + version === 'archive' ? release.versionWithPrefix : version + ); + + return ; +}; + +export default WithDownloadArchive; diff --git a/apps/site/components/withLayout.tsx b/apps/site/components/withLayout.tsx index ec553190e621d..c7f948a5946dc 100644 --- a/apps/site/components/withLayout.tsx +++ b/apps/site/components/withLayout.tsx @@ -5,6 +5,7 @@ import ArticlePageLayout from '#site/layouts/ArticlePage'; import BlogLayout from '#site/layouts/Blog'; import DefaultLayout from '#site/layouts/Default'; import DownloadLayout from '#site/layouts/Download'; +import DownloadArchiveLayout from '#site/layouts/DownloadArchive'; import GlowingBackdropLayout from '#site/layouts/GlowingBackdrop'; import LearnLayout from '#site/layouts/Learn'; import PostLayout from '#site/layouts/Post'; @@ -18,6 +19,7 @@ const layouts = { 'blog-post': PostLayout, 'blog-category': BlogLayout, download: DownloadLayout, + 'download-archive': DownloadArchiveLayout, article: ArticlePageLayout, } satisfies Record; diff --git a/apps/site/components/withMarkdownContent.tsx b/apps/site/components/withMarkdownContent.tsx new file mode 100644 index 0000000000000..9747729c3e3c3 --- /dev/null +++ b/apps/site/components/withMarkdownContent.tsx @@ -0,0 +1,35 @@ +import { getLocale } from 'next-intl/server'; +import type { FC } from 'react'; + +import { dynamicRouter } from '#site/next.dynamic'; + +const getMarkdownContent = async (locale: string, file: Array) => { + const filePathname = dynamicRouter.getPathname(file); + + // Retrieves the Markdown file source content based on the file path and locale + // Uses dynamic routing to locate and load the appropriate markdown file + // for the given locale and file path segments + const { source, filename } = await dynamicRouter.getMarkdownFile( + locale, + filePathname + ); + + // Parses the Markdown/MDX source content and transforms it into a React component + // Handles both standard Markdown and MDX files + const { content } = await dynamicRouter.getMDXContent(source, filename); + + return content; +}; + +type WithMarkdownContentProps = { + file: Array; +}; + +const WithMarkdownContent: FC = async ({ file }) => { + const locale = await getLocale(); + const content = await getMarkdownContent(locale, file); + + return content; +}; + +export default WithMarkdownContent; diff --git a/apps/site/components/withReleaseAlertBox.tsx b/apps/site/components/withReleaseAlertBox.tsx new file mode 100644 index 0000000000000..e2c421c4a01a7 --- /dev/null +++ b/apps/site/components/withReleaseAlertBox.tsx @@ -0,0 +1,44 @@ +import AlertBox from '@node-core/ui-components/Common/AlertBox'; +import { useTranslations } from 'next-intl'; +import type { FC } from 'react'; + +import Link from '#site/components/Link'; +import type { NodeReleaseStatus } from '#site/types'; + +type WithReleaseAlertBoxProps = { + status: NodeReleaseStatus; + link?: string; +}; + +const WithReleaseAlertBox: FC = ({ + status, + link, +}) => { + const t = useTranslations(); + + const getAlertContent = () => { + if (link) { + return t.rich('layouts.download.codeBox.unsupportedVersionWarning', { + link: text => {text}, + }); + } + + return t('components.releaseModal.unsupportedVersionWarning'); + }; + + switch (status) { + case 'End-of-life': + return ( + + {getAlertContent()} + + ); + default: + return null; + } +}; + +export default WithReleaseAlertBox; diff --git a/apps/site/layouts/DownloadArchive.tsx b/apps/site/layouts/DownloadArchive.tsx new file mode 100644 index 0000000000000..7050c2ce4af36 --- /dev/null +++ b/apps/site/layouts/DownloadArchive.tsx @@ -0,0 +1,23 @@ +import type { FC } from 'react'; + +import WithFooter from '#site/components/withFooter'; +import WithMarkdownContent from '#site/components/withMarkdownContent'; +import WithNavBar from '#site/components/withNavBar'; + +import styles from './layouts.module.css'; + +const DownloadArchiveLayout: FC = () => ( + <> + + +
+
+ +
+
+ + + +); + +export default DownloadArchiveLayout; diff --git a/apps/site/next-data/generators/releaseData.mjs b/apps/site/next-data/generators/releaseData.mjs index 319f5608815f9..09349b4afe5f8 100644 --- a/apps/site/next-data/generators/releaseData.mjs +++ b/apps/site/next-data/generators/releaseData.mjs @@ -77,8 +77,12 @@ const generateReleaseData = async () => { const status = getNodeReleaseStatus(new Date(), support); const minorVersions = Object.entries(major.releases).map(([, release]) => ({ - version: release.semver.raw, + modules: release.modules.version || '', + npm: release.dependencies.npm || '', releaseDate: release.releaseDate, + v8: release.dependencies.v8, + version: release.semver.raw, + versionWithPrefix: `v${release.semver.raw}`, })); const majorVersion = latestVersion.semver.major; diff --git a/apps/site/next.dynamic.constants.mjs b/apps/site/next.dynamic.constants.mjs index 294344b09ea15..8c84f1b566081 100644 --- a/apps/site/next.dynamic.constants.mjs +++ b/apps/site/next.dynamic.constants.mjs @@ -1,5 +1,6 @@ 'use strict'; +import provideReleaseData from '#site/next-data/providers/releaseData'; import { blogData } from '#site/next.json.mjs'; import { provideBlogPosts } from './next-data/providers/blogData'; @@ -19,6 +20,8 @@ export const IGNORED_ROUTES = [ locale !== defaultLocale.code && /^blog/.test(pathname), // This is used to ignore all pathnames that are empty ({ locale, pathname }) => locale.length && !pathname.length, + // This is used to ignore download routes for Node.js versions and downloads archive page + ({ pathname }) => /^download\/(v\d+(\.\d+)*|archive)$/.test(pathname), ]; /** @@ -29,6 +32,14 @@ export const IGNORED_ROUTES = [ * @type {Map} A Map of pathname and Layout Name */ export const DYNAMIC_ROUTES = new Map([ + // Creates dynamic routes for downloads archive pages for each version + // (e.g., /download/v18.20.8, /download/v20.19.2) + ...provideReleaseData() + .flatMap(({ minorVersions, versionWithPrefix }) => [ + `download/${versionWithPrefix}`, + ...minorVersions.map(minor => `download/${minor.versionWithPrefix}`), + ]) + .map(version => [version, 'download-archive']), // Provides Routes for all Blog Categories ...blogData.categories.map(c => [`blog/${c}`, 'blog-category']), // Provides Routes for all Blog Categories w/ Pagination diff --git a/apps/site/next.mdx.use.client.mjs b/apps/site/next.mdx.use.client.mjs index b9e0f64d0daa1..e466a1d1a9a3b 100644 --- a/apps/site/next.mdx.use.client.mjs +++ b/apps/site/next.mdx.use.client.mjs @@ -4,7 +4,6 @@ import Blockquote from '@node-core/ui-components/Common/Blockquote'; import MDXCodeTabs from '@node-core/ui-components/MDX/CodeTabs'; import Button from './components/Common/Button'; -import DownloadButton from './components/Downloads/DownloadButton'; import DownloadLink from './components/Downloads/DownloadLink'; import BlogPostLink from './components/Downloads/Release/BlogPostLink'; import ChangelogLink from './components/Downloads/Release/ChangelogLink'; @@ -36,8 +35,6 @@ export const clientMdxComponents = { LinkWithArrow: LinkWithArrow, // Regular links (without arrow) Link: Link, - // Renders a Download Button - DownloadButton: DownloadButton, // Renders a Download Link DownloadLink: DownloadLink, // Group of components that enable you to select versions for Node.js diff --git a/apps/site/next.mdx.use.mjs b/apps/site/next.mdx.use.mjs index 537872c020e64..bd5b54e48f1be 100644 --- a/apps/site/next.mdx.use.mjs +++ b/apps/site/next.mdx.use.mjs @@ -1,10 +1,15 @@ 'use strict'; import DownloadReleasesTable from './components/Downloads/DownloadReleasesTable'; +import DownloadsTable from './components/Downloads/DownloadsTable'; +import { MinorReleasesTable } from './components/Downloads/MinorReleasesTable'; +import { ReleaseOverview } from './components/Downloads/ReleaseOverview'; import UpcomingMeetings from './components/MDX/Calendar/UpcomingMeetings'; import WithBadgeGroup from './components/withBadgeGroup'; import WithBanner from './components/withBanner'; +import WithDownloadArchive from './components/withDownloadArchive'; import WithNodeRelease from './components/withNodeRelease'; +import WithReleaseAlertBox from './components/withReleaseAlertBox'; /** * A full list of React Components that we want to pass through to MDX @@ -13,12 +18,22 @@ import WithNodeRelease from './components/withNodeRelease'; */ export const mdxComponents = { DownloadReleasesTable: DownloadReleasesTable, + // HOC for providing the Download Archive Page properties + WithDownloadArchive: WithDownloadArchive, + // Renders a table with Node.js Releases with different platforms and architectures + DownloadsTable: DownloadsTable, // HOC for getting Node.js Release Metadata WithNodeRelease: WithNodeRelease, + // Renders an alert box with the given release status + WithReleaseAlertBox: WithReleaseAlertBox, // HOC for providing Banner Data WithBanner: WithBanner, // HOC for providing Badge Data WithBadgeGroup: WithBadgeGroup, // Renders an container for Upcoming Node.js Meetings UpcomingMeetings: UpcomingMeetings, + // Renders the Release Overview for a specified version + ReleaseOverview: ReleaseOverview, + // Renders a table with all the Minor Releases for a Major Version + MinorReleasesTable: MinorReleasesTable, }; diff --git a/apps/site/pages/en/download/archive.mdx b/apps/site/pages/en/download/archive.mdx new file mode 100644 index 0000000000000..3ad29f3a1289f --- /dev/null +++ b/apps/site/pages/en/download/archive.mdx @@ -0,0 +1,69 @@ +--- +title: Download Node.js® +layout: download-archive +--- + + + {({ binaries, installers, version, release, sources, navigation }) => ( + <> +

Node.js® Download Archive

+ +

+ Node.js Logo + {version} + {release.codename && ` (${release.codename})`} +

+ + + + + +
    + +
  • + Learn more about Node.js releases, including the release schedule and LTS status. +
  • + +
  • + Signed SHASUMS for release files. How to verify signed SHASUMS. +
  • + +
  • + Download a signed Node.js {version} source tarball. +
  • + +
+ +
+ +

Other releases

+
+
    + {navigation.map(({ href, label }) => ( +
  • + +

    {label}

    + +
  • + ))} +
+
+ +

Binary Downloads

+ + +

Installer Packages

+ + +

Minor versions

+ + + +)} + +
diff --git a/apps/site/pages/en/download/current.mdx b/apps/site/pages/en/download/current.mdx index 16e78d6a8e1d7..a3c838e5f70e3 100644 --- a/apps/site/pages/en/download/current.mdx +++ b/apps/site/pages/en/download/current.mdx @@ -30,7 +30,7 @@ Learn how to Node.js source tarball. Check out our nightly binaries or -all previous releases +all previous releases or the unofficial binaries for other platforms. diff --git a/apps/site/pages/en/download/index.mdx b/apps/site/pages/en/download/index.mdx index 16e78d6a8e1d7..a3c838e5f70e3 100644 --- a/apps/site/pages/en/download/index.mdx +++ b/apps/site/pages/en/download/index.mdx @@ -30,7 +30,7 @@ Learn how to Node.js source tarball. Check out our nightly binaries or -all previous releases +all previous releases or the unofficial binaries for other platforms. diff --git a/apps/site/pages/en/index.mdx b/apps/site/pages/en/index.mdx index 95de44c70f2a1..96f029e6aabc6 100644 --- a/apps/site/pages/en/index.mdx +++ b/apps/site/pages/en/index.mdx @@ -14,25 +14,22 @@ layout: home
-
- - {({ release }) => ( - <> - Download Node.js (LTS) - - Downloads Node.js {release.versionWithPrefix} - 1 with long-term support. - Node.js can also be installed via version managers. - - - )} - +
+ +
+ + + + + + +
{({ release }) => ( Want new features sooner? - Get Node.js {release.versionWithPrefix} + Get Node.js {release.versionWithPrefix} 1 instead. )} diff --git a/apps/site/pages/es/index.mdx b/apps/site/pages/es/index.mdx deleted file mode 100644 index 2d590f93c6251..0000000000000 --- a/apps/site/pages/es/index.mdx +++ /dev/null @@ -1,135 +0,0 @@ ---- -title: Ejecuta JavaScript en cualquier parte -layout: home ---- - -
- - -
-

Ejecuta JavaScript en cualquier parte

- - Node.js® es un entorno de ejecución de JavaScript multiplataforma, - de código abierto y gratuito que permite a los desarrolladores crear servidores, - aplicaciones web, herramientas de línea de comando y scripts. - -
- -
- - {({ release }) => ( - <> - Descargar Node.js (LTS) - - Descarga Node.js {release.versionWithPrefix} - 1 con soporte a largo plazo. - Node.js también puede ser instalado a través de gestores de versiones. - - - )} - - - - {({ release }) => ( - - ¿Quieres nuevas funciones más pronto? - ConsigueNode.js {release.versionWithPrefix} - 1 en vez. - - )} - - -
-
- -
-
- ```js displayName="Create an HTTP Server" - // server.mjs - import { createServer } from 'node:http'; - - const server = createServer((req, res) => { - res.writeHead(200, { 'Content-Type': 'text/plain' }); - res.end('Hello World!\n'); - }); - - // starts a simple http server locally on port 3000 - server.listen(3000, '127.0.0.1', () => { - console.log('Listening on 127.0.0.1:3000'); - }); - - // run with `node server.mjs` - ``` - - ```js displayName="Write Tests" - // tests.mjs - import assert from 'node:assert'; - import test from 'node:test'; - - test('that 1 is equal 1', () => { - assert.strictEqual(1, 1); - }); - - test('that throws as 1 is not equal 2', () => { - // throws an exception because 1 != 2 - assert.strictEqual(1, 2); - }); - - // run with `node tests.mjs` - ``` - - ```js displayName="Read and Hash a File" - // crypto.mjs - import { createHash } from 'node:crypto'; - import { readFile } from 'node:fs/promises'; - - const hasher = createHash('sha1'); - - hasher.setEncoding('hex'); - // ensure you have a `package.json` file for this test! - hasher.write(await readFile('package.json')); - hasher.end(); - - const fileHash = hasher.read(); - - // run with `node crypto.mjs` - ``` - - ```js displayName="Streams Pipeline" - // streams.mjs - import { createReadStream, createWriteStream } from 'node:fs'; - import { pipeline } from 'node:stream/promises'; - import { createGzip } from 'node:zlib'; - - // ensure you have a `package.json` file for this test! - await pipeline( - createReadStream('package.json'), - createGzip(), - createWriteStream('package.json.gz') - ); - - // run with `node streams.mjs` - ``` - - ```js displayName="Work with Threads" - // threads.mjs - import { Worker, isMainThread, - workerData, parentPort } from 'node:worker_threads'; - - if (isMainThread) { - const data = 'some data'; - const worker = new Worker(import.meta.filename, { workerData: data }); - worker.on('message', msg => console.log('Reply from Thread:', msg)); - } else { - const source = workerData; - parentPort.postMessage(btoa(source.toUpperCase())); - } - - // run with `node threads.mjs` - ``` - -
- -Aprenda más sobre lo que Node.js puede ofrecer con nuestros [Materiales de aprendizaje](/learn). - -
diff --git a/apps/site/pages/fa/index.mdx b/apps/site/pages/fa/index.mdx deleted file mode 100644 index d1fcd30f94bea..0000000000000 --- a/apps/site/pages/fa/index.mdx +++ /dev/null @@ -1,133 +0,0 @@ ---- -title: اجرا جاوااسکریپت در همه جا -layout: home ---- - -
- - -
-

اجرا جاوااسکریپت در همه جا

- - Node.js یک محیط اجرای جاوااسکریپت متن‌باز، رایگان و چندسکویی است - که به توسعه دهندگان اجازه می‌دهد تا سرورها، وب اپلیکیشن‌ها - ابزارهای خط فرمان و اسکریپت‌ها را ایجاد کنند. - -
- -
- - {({ release }) => ( - <> - دانلود Node.js (نسخه پایدار) - - دانلود Node.js {release.versionWithPrefix} - 1 با پشتیبانی بلندمدت. - Node.js همچنین از طریق package managers نیز قابل نصب است. - - - )} - - - - {({ release }) => ( - - می‌خواهید زودتر از ویژگی‌های جدید برخوردار شوید؟ - به‌جای آن Node.js {release.versionWithPrefix} - 1 را دریافت کنید. - - )} - - -
-
- -
-
- ```js displayName="Create an HTTP Server" - // server.mjs - import { createServer } from 'node:http'; - - const server = createServer((req, res) => { - res.writeHead(200, { 'Content-Type': 'text/plain' }); - res.end('Hello World!\n'); - }); - - // starts a simple http server locally on port 3000 - server.listen(3000, '127.0.0.1', () => { - console.log('Listening on 127.0.0.1:3000'); - }); - - // run with `node server.mjs` - ``` - - ```js displayName="Write Tests" - // tests.mjs - import assert from 'node:assert'; - import test from 'node:test'; - - test('that 1 is equal 1', () => { - assert.strictEqual(1, 1); - }); - - test('that throws as 1 is not equal 2', () => { - // throws an exception because 1 != 2 - assert.strictEqual(1, 2); - }); - - // run with `node tests.mjs` - ``` - - ```js displayName="Read and Hash a File" - // crypto.mjs - import { createHash } from 'node:crypto'; - import { readFile } from 'node:fs/promises'; - - const hasher = createHash('sha1'); - - hasher.setEncoding('hex'); - // ensure you have a `package.json` file for this test! - hasher.write(await readFile('package.json')); - hasher.end(); - - const fileHash = hasher.read(); - - // run with `node crypto.mjs` - ``` - - ```js displayName="Streams Pipeline" - // streams.mjs - import { createReadStream, createWriteStream } from 'node:fs'; - import { pipeline } from 'node:stream/promises'; - import { createGzip } from 'node:zlib'; - - // ensure you have a `package.json` file for this test! - await pipeline( - createReadStream('package.json'), - createGzip(), - createWriteStream('package.json.gz') - ); - - // run with `node streams.mjs` - ``` - - ```js displayName="Work with Threads" - // threads.mjs - import { Worker, isMainThread, - workerData, parentPort } from 'node:worker_threads'; - - if (isMainThread) { - const data = 'some data'; - const worker = new Worker(import.meta.filename, { workerData: data }); - worker.on('message', msg => console.log('Reply from Thread:', msg)); - } else { - const source = workerData; - parentPort.postMessage(btoa(source.toUpperCase())); - } - - // run with `node threads.mjs` - ``` - -
- با [مطالب آموزشی](/learn) ما، بیشتر در مورد اینکه Node.js چه امکاناتی را ارائه می دهد بیاموزید. -
diff --git a/apps/site/pages/fr/index.mdx b/apps/site/pages/fr/index.mdx deleted file mode 100644 index 2b72207fc2c0f..0000000000000 --- a/apps/site/pages/fr/index.mdx +++ /dev/null @@ -1,133 +0,0 @@ ---- -title: Exécuter du JavaScript partout -layout: home ---- - -
- - -
-

Exécuter du JavaScript partout

- - Node.js® est un environnement d'exécution JavaScript gratuit, open-source et multiplateforme qui permet aux développeurs de créer des serveurs, des applications web, des outils en ligne de commande et des scripts. - -
- -
- - {({ release }) => ( - <> - Télécharger Node.js (LTS) - - Téléchargements Node.js {release.versionWithPrefix} - 1 avec un support à long terme. - Node.js peut également être installé via le gestionnaire de versions. - - - )} - - - - {({ release }) => ( - - Vous voulez de nouvelles fonctionnalités plus tôt ? - Obtenez Node.js {release.versionWithPrefix} - 1 à la place. - - )} - - -
-
- -
-
- ```js displayName="Create an HTTP Server" - // server.mjs - import { createServer } from 'node:http'; - - const server = createServer((req, res) => { - res.writeHead(200, { 'Content-Type': 'text/plain' }); - res.end('Hello World!\n'); - }); - - // starts a simple http server locally on port 3000 - server.listen(3000, '127.0.0.1', () => { - console.log('Listening on 127.0.0.1:3000'); - }); - - // run with `node server.mjs` - ``` - - ```js displayName="Write Tests" - // tests.mjs - import assert from 'node:assert'; - import test from 'node:test'; - - test('that 1 is equal 1', () => { - assert.strictEqual(1, 1); - }); - - test('that throws as 1 is not equal 2', () => { - // throws an exception because 1 != 2 - assert.strictEqual(1, 2); - }); - - // run with `node tests.mjs` - ``` - - ```js displayName="Read and Hash a File" - // crypto.mjs - import { createHash } from 'node:crypto'; - import { readFile } from 'node:fs/promises'; - - const hasher = createHash('sha1'); - - hasher.setEncoding('hex'); - // ensure you have a `package.json` file for this test! - hasher.write(await readFile('package.json')); - hasher.end(); - - const fileHash = hasher.read(); - - // run with `node crypto.mjs` - ``` - - ```js displayName="Streams Pipeline" - // streams.mjs - import { createReadStream, createWriteStream } from 'node:fs'; - import { pipeline } from 'node:stream/promises'; - import { createGzip } from 'node:zlib'; - - // ensure you have a `package.json` file for this test! - await pipeline( - createReadStream('package.json'), - createGzip(), - createWriteStream('package.json.gz') - ); - - // run with `node streams.mjs` - ``` - - ```js displayName="Work with Threads" - // threads.mjs - import { Worker, isMainThread, - workerData, parentPort } from 'node:worker_threads'; - - if (isMainThread) { - const data = 'some data'; - const worker = new Worker(import.meta.filename, { workerData: data }); - worker.on('message', msg => console.log('Reply from Thread:', msg)); - } else { - const source = workerData; - parentPort.postMessage(btoa(source.toUpperCase())); - } - - // run with `node threads.mjs` - ``` - -
- -Apprenez-en plus sur ce que Node.js est capable d'offrir avec notre [Matériel d'apprentissage](/learn). - -
diff --git a/apps/site/pages/id/index.mdx b/apps/site/pages/id/index.mdx deleted file mode 100644 index 504b17b19c1a7..0000000000000 --- a/apps/site/pages/id/index.mdx +++ /dev/null @@ -1,135 +0,0 @@ ---- -title: Jalankan JavaScript Di Mana Saja -layout: home ---- - -
- - -
-

Jalankan JavaScript Di Mana Saja

- - Node.js® adalah lingkungan runtime JavaScript gratis dan sumber terbuka yang - lintas platform, yang memungkinkan pengembang membuat server, aplikasi web, - alat baris perintah, dan skrip. - -
- -
- - {({ release }) => ( - <> - Unduh Node.js (LTS) - - Unduhan Node.js {release.versionWithPrefix} - 1 dengan dukungan jangka panjang (LTS). - Node.js juga dapat diinstal melalui manajer paket. - - - )} - - - - {({ release }) => ( - - Ingin fitur baru lebih cepat? - Dapatkan Node.js {release.versionWithPrefix} - 1 sebagai gantinya. - - )} - - -
-
- -
-
- ```js displayName="Create an HTTP Server" - // server.mjs - import { createServer } from 'node:http'; - - const server = createServer((req, res) => { - res.writeHead(200, { 'Content-Type': 'text/plain' }); - res.end('Hello World!\n'); - }); - - // starts a simple http server locally on port 3000 - server.listen(3000, '127.0.0.1', () => { - console.log('Listening on 127.0.0.1:3000'); - }); - - // run with `node server.mjs` - ``` - - ```js displayName="Write Tests" - // tests.mjs - import assert from 'node:assert'; - import test from 'node:test'; - - test('that 1 is equal 1', () => { - assert.strictEqual(1, 1); - }); - - test('that throws as 1 is not equal 2', () => { - // throws an exception because 1 != 2 - assert.strictEqual(1, 2); - }); - - // run with `node tests.mjs` - ``` - - ```js displayName="Read and Hash a File" - // crypto.mjs - import { createHash } from 'node:crypto'; - import { readFile } from 'node:fs/promises'; - - const hasher = createHash('sha1'); - - hasher.setEncoding('hex'); - // ensure you have a `package.json` file for this test! - hasher.write(await readFile('package.json')); - hasher.end(); - - const fileHash = hasher.read(); - - // run with `node crypto.mjs` - ``` - - ```js displayName="Streams Pipeline" - // streams.mjs - import { createReadStream, createWriteStream } from 'node:fs'; - import { pipeline } from 'node:stream/promises'; - import { createGzip } from 'node:zlib'; - - // ensure you have a `package.json` file for this test! - await pipeline( - createReadStream('package.json'), - createGzip(), - createWriteStream('package.json.gz') - ); - - // run with `node streams.mjs` - ``` - - ```js displayName="Work with Threads" - // threads.mjs - import { Worker, isMainThread, - workerData, parentPort } from 'node:worker_threads'; - - if (isMainThread) { - const data = 'some data'; - const worker = new Worker(import.meta.filename, { workerData: data }); - worker.on('message', msg => console.log('Reply from Thread:', msg)); - } else { - const source = workerData; - parentPort.postMessage(btoa(source.toUpperCase())); - } - - // run with `node threads.mjs` - ``` - -
- -Pelajari lebih lanjut tentang apa yang bisa ditawarkan Node.js melalui [Bahan Pembelajaran](/learn) kami. - -
diff --git a/apps/site/pages/ja/index.mdx b/apps/site/pages/ja/index.mdx deleted file mode 100644 index ad52b8da6fe26..0000000000000 --- a/apps/site/pages/ja/index.mdx +++ /dev/null @@ -1,133 +0,0 @@ ---- -title: どこでもJavaScriptを使おう -layout: home ---- - -
- - -
-

どこでもJavaScriptを使おう

- - Node.js®はクロスプラットフォームに対応したフリーでオープンソースのJavaScript実行環境です。開発者にサーバー、ウェブアプリ、コマンドラインツール、スクリプトなどを開発する環境を提供します。 - -
- -
- - {({ release }) => ( - <> - Node.js(LTS)をダウンロードする - - 長期サポート版Node.js {release.versionWithPrefix} - 1をダウンロードする。 - バージョンマネージャーを利用したインストール方法もあります。 - - - )} - - - - {({ release }) => ( - - 最新の機能をすぐに試したい場合は - Node.js {release.versionWithPrefix} - 1をインストールできます。 - - )} - - -
-
- -
-
- ```js displayName="Create an HTTP Server" - // server.mjs - import { createServer } from 'node:http'; - - const server = createServer((req, res) => { - res.writeHead(200, { 'Content-Type': 'text/plain' }); - res.end('Hello World!\n'); - }); - - // starts a simple http server locally on port 3000 - server.listen(3000, '127.0.0.1', () => { - console.log('Listening on 127.0.0.1:3000'); - }); - - // run with `node server.mjs` - ``` - - ```js displayName="Write Tests" - // tests.mjs - import assert from 'node:assert'; - import test from 'node:test'; - - test('that 1 is equal 1', () => { - assert.strictEqual(1, 1); - }); - - test('that throws as 1 is not equal 2', () => { - // throws an exception because 1 != 2 - assert.strictEqual(1, 2); - }); - - // run with `node tests.mjs` - ``` - - ```js displayName="Read and Hash a File" - // crypto.mjs - import { createHash } from 'node:crypto'; - import { readFile } from 'node:fs/promises'; - - const hasher = createHash('sha1'); - - hasher.setEncoding('hex'); - // ensure you have a `package.json` file for this test! - hasher.write(await readFile('package.json')); - hasher.end(); - - const fileHash = hasher.read(); - - // run with `node crypto.mjs` - ``` - - ```js displayName="Streams Pipeline" - // streams.mjs - import { createReadStream, createWriteStream } from 'node:fs'; - import { pipeline } from 'node:stream/promises'; - import { createGzip } from 'node:zlib'; - - // ensure you have a `package.json` file for this test! - await pipeline( - createReadStream('package.json'), - createGzip(), - createWriteStream('package.json.gz') - ); - - // run with `node streams.mjs` - ``` - - ```js displayName="Work with Threads" - // threads.mjs - import { Worker, isMainThread, - workerData, parentPort } from 'node:worker_threads'; - - if (isMainThread) { - const data = 'some data'; - const worker = new Worker(import.meta.filename, { workerData: data }); - worker.on('message', msg => console.log('Reply from Thread:', msg)); - } else { - const source = workerData; - parentPort.postMessage(btoa(source.toUpperCase())); - } - - // run with `node threads.mjs` - ``` - -
- -私たちの[学習教材](/learn)でNode.jsでできることをさらに学んでみましょう。 - -
diff --git a/apps/site/pages/ko/index.mdx b/apps/site/pages/ko/index.mdx deleted file mode 100644 index a4119867639ba..0000000000000 --- a/apps/site/pages/ko/index.mdx +++ /dev/null @@ -1,137 +0,0 @@ ---- -title: 어디서든 JavaScript를 실행하세요 -layout: home ---- - -
- - -
-

어디서든 JavaScript를 실행하세요

- -Node.js®는 무료, 오픈소스, 다중 플랫폼 JavaScript 런타임 환경으로 개발자 여러분이 서버, 웹 애플리케이션, 명령어 작성 도구와 스크립트를 만들도록 해줍니다. - -
- -
- - {({ release }) => ( - <> - Node.js 다운로드 (LTS) - - Node.js 다운로드 {release.versionWithPrefix} - 1 LTS. - Node.js는 패키지 관리자를 통해서도 다운로드 할 수 있습니다. - - - )} - - - - {({ release }) => ( - - 새로운 기능을 먼저 경험하고 싶다면 - Node.js {release.versionWithPrefix} - 1 를 다운 받으세요. - - )} - -
-
- -
-
- ```js displayName="Create an HTTP Server" - // server.mjs - import { createServer } from 'node:http'; - -const server = createServer((req, res) => { -res.writeHead(200, { 'Content-Type': 'text/plain' }); -res.end('Hello World!\n'); -}); - -// starts a simple http server locally on port 3000 -server.listen(3000, '127.0.0.1', () => { -console.log('Listening on 127.0.0.1:3000'); -}); - -// run with `node server.mjs` - -```` - -```js displayName="Write Tests" -// tests.mjs -import assert from 'node:assert'; -import test from 'node:test'; - -test('that 1 is equal 1', () => { - assert.strictEqual(1, 1); -}); - -test('that throws as 1 is not equal 2', () => { - // throws an exception because 1 != 2 - assert.strictEqual(1, 2); -}); - -// run with `node tests.mjs` -```` - -```js displayName="Read and Hash a File" -// crypto.mjs -import { createHash } from 'node:crypto'; -import { readFile } from 'node:fs/promises'; - -const hasher = createHash('sha1'); - -hasher.setEncoding('hex'); -// ensure you have a `package.json` file for this test! -hasher.write(await readFile('package.json')); -hasher.end(); - -const fileHash = hasher.read(); - -// run with `node crypto.mjs` -``` - -```js displayName="Streams Pipeline" -// streams.mjs -import { createReadStream, createWriteStream } from 'node:fs'; -import { pipeline } from 'node:stream/promises'; -import { createGzip } from 'node:zlib'; - -// ensure you have a `package.json` file for this test! -await pipeline( - createReadStream('package.json'), - createGzip(), - createWriteStream('package.json.gz') -); - -// run with `node streams.mjs` -``` - -```js displayName="Work with Threads" -// threads.mjs -import { - Worker, - isMainThread, - workerData, - parentPort, -} from 'node:worker_threads'; - -if (isMainThread) { - const data = 'some data'; - const worker = new Worker(import.meta.filename, { workerData: data }); - worker.on('message', msg => console.log('Reply from Thread:', msg)); -} else { - const source = workerData; - parentPort.postMessage(btoa(source.toUpperCase())); -} - -// run with `node threads.mjs` -``` - -
- -Node.js가 제공하는 [학습 자료](/learn)를 통해 더 많은 정보를 알아보세요. - -
diff --git a/apps/site/pages/pt/index.mdx b/apps/site/pages/pt/index.mdx deleted file mode 100644 index aafd3aa3adbcf..0000000000000 --- a/apps/site/pages/pt/index.mdx +++ /dev/null @@ -1,135 +0,0 @@ ---- -title: Executar a JavaScript em Toda Parte -layout: home ---- - -
- - -
-

Executar a JavaScript em Toda Parte

- - Node.js® é um ambiente de execução de JavaScript multiplataforma, - de código-aberto e gratuita, que permite aos programadores criar servidores, aplicações - da Web, ferramentas de linha de comando e programas de automação de tarefas. - -
- -
- - {({ release }) => ( - <> - Descarregar a Node.js (LTS) - - Descarrega a Node.js {release.versionWithPrefix} - 1 com suporte de longo prazo. - A Node.js também pode ser instalada por meio de gestores de versão. - - - )} - - - - {({ release }) => ( - - Queremos novas funcionalidades mais cedo? - Podemos então obter a Node.js {release.versionWithPrefix} - 1. - - )} - - -
-
- -
-
- ```js displayName="Create an HTTP Server" - // server.mjs - import { createServer } from 'node:http'; - - const server = createServer((req, res) => { - res.writeHead(200, { 'Content-Type': 'text/plain' }); - res.end('Hello World!\n'); - }); - - // starts a simple http server locally on port 3000 - server.listen(3000, '127.0.0.1', () => { - console.log('Listening on 127.0.0.1:3000'); - }); - - // run with `node server.mjs` - ``` - - ```js displayName="Write Tests" - // tests.mjs - import assert from 'node:assert'; - import test from 'node:test'; - - test('that 1 is equal 1', () => { - assert.strictEqual(1, 1); - }); - - test('that throws as 1 is not equal 2', () => { - // throws an exception because 1 != 2 - assert.strictEqual(1, 2); - }); - - // run with `node tests.mjs` - ``` - - ```js displayName="Read and Hash a File" - // crypto.mjs - import { createHash } from 'node:crypto'; - import { readFile } from 'node:fs/promises'; - - const hasher = createHash('sha1'); - - hasher.setEncoding('hex'); - // ensure you have a `package.json` file for this test! - hasher.write(await readFile('package.json')); - hasher.end(); - - const fileHash = hasher.read(); - - // run with `node crypto.mjs` - ``` - - ```js displayName="Streams Pipeline" - // streams.mjs - import { createReadStream, createWriteStream } from 'node:fs'; - import { pipeline } from 'node:stream/promises'; - import { createGzip } from 'node:zlib'; - - // ensure you have a `package.json` file for this test! - await pipeline( - createReadStream('package.json'), - createGzip(), - createWriteStream('package.json.gz') - ); - - // run with `node streams.mjs` - ``` - - ```js displayName="Work with Threads" - // threads.mjs - import { Worker, isMainThread, - workerData, parentPort } from 'node:worker_threads'; - - if (isMainThread) { - const data = 'some data'; - const worker = new Worker(import.meta.filename, { workerData: data }); - worker.on('message', msg => console.log('Reply from Thread:', msg)); - } else { - const source = workerData; - parentPort.postMessage(btoa(source.toUpperCase())); - } - - // run with `node threads.mjs` - ``` - -
- -É possível saber que mais a Node.js consegue oferecer com os nossos [materiais de estudo](/learn). - -
diff --git a/apps/site/pages/tr/index.mdx b/apps/site/pages/tr/index.mdx deleted file mode 100644 index 7d4f9f71acba1..0000000000000 --- a/apps/site/pages/tr/index.mdx +++ /dev/null @@ -1,139 +0,0 @@ ---- -title: JavaScript'i Her Yerde Çalıştırın -layout: home ---- - -
- - -
-

Her Yerde JavaScript Çalıştırın

- - Node.js®, ücretsiz, açık kaynaklı, çapraz platform JavaScript çalıştırma ortamıdır. - Geliştiricilere sunucular, web uygulamaları, komut satırı araçları ve betikler oluşturma - imkanı sağlar. - -
- -
- - {({ release }) => ( - <> - Node.js'i İndir (LTS) - - Node.js'i indir {release.versionWithPrefix} - 1 uzun vadeli destek ile indirin. - Node.js ayrıca paket yöneticileri aracılığıyla da kurulabilir. - - - )} - - - - {({ release }) => ( - - Yeni özellikleri daha erken mi istiyorsunuz?{" "} - - Node.js{" "} - - {release.versionWithPrefix} - - {" "} - 1{" "} - alabilirsiniz. - - )} - - -
-
- -
-
- ```js displayName="Create an HTTP Server" - // server.mjs - import { createServer } from 'node:http'; - - const server = createServer((req, res) => { - res.writeHead(200, { 'Content-Type': 'text/plain' }); - res.end('Hello World!\n'); - }); - - // starts a simple http server locally on port 3000 - server.listen(3000, '127.0.0.1', () => { - console.log('Listening on 127.0.0.1:3000'); - }); - - // run with `node server.mjs` - ``` - - ```js displayName="Write Tests" - // tests.mjs - import assert from 'node:assert'; - import test from 'node:test'; - - test('that 1 is equal 1', () => { - assert.strictEqual(1, 1); - }); - - test('that throws as 1 is not equal 2', () => { - // throws an exception because 1 != 2 - assert.strictEqual(1, 2); - }); - - // run with `node tests.mjs` - ``` - - ```js displayName="Read and Hash a File" - // crypto.mjs - import { createHash } from 'node:crypto'; - import { readFile } from 'node:fs/promises'; - - const hasher = createHash('sha1'); - - hasher.setEncoding('hex'); - // ensure you have a `package.json` file for this test! - hasher.write(await readFile('package.json')); - hasher.end(); - - const fileHash = hasher.read(); - - // run with `node crypto.mjs` - ``` - - ```js displayName="Streams Pipeline" - // streams.mjs - import { createReadStream, createWriteStream } from 'node:fs'; - import { pipeline } from 'node:stream/promises'; - import { createGzip } from 'node:zlib'; - - // ensure you have a `package.json` file for this test! - await pipeline( - createReadStream('package.json'), - createGzip(), - createWriteStream('package.json.gz') - ); - - // run with `node streams.mjs` - ``` - - ```js displayName="Work with Threads" - // threads.mjs - import { Worker, isMainThread, - workerData, parentPort } from 'node:worker_threads'; - - if (isMainThread) { - const data = 'some data'; - const worker = new Worker(import.meta.filename, { workerData: data }); - worker.on('message', msg => console.log('Reply from Thread:', msg)); - } else { - const source = workerData; - parentPort.postMessage(btoa(source.toUpperCase())); - } - - // run with `node threads.mjs` - ``` - -
- Node.js'in sunabileceklerini daha yakından keşfetmek için [Öğrenme materyallerimize](/learn) göz atın. -
diff --git a/apps/site/pages/uk/index.mdx b/apps/site/pages/uk/index.mdx deleted file mode 100644 index 3dc5d595ee0c7..0000000000000 --- a/apps/site/pages/uk/index.mdx +++ /dev/null @@ -1,134 +0,0 @@ ---- -title: Запускайте JavaScript будь‑де -layout: home ---- - -
- - -
-

Запускайте JavaScript будь‑де

- - Node.js® — це безплатне, кросплатформне середовище виконання JavaScript із відкритим кодом, - яке дозволяє розробникам створювати сервери, вебзастосунки, інструменти командного рядка та скрипти. - -
- -
- - {({ release }) => ( - <> - Завантажити Node.js (LTS) - - Завантажує Node.js {release.versionWithPrefix} - 1 із довгостроковою підтримкою. - Node.js також можна встановити через менеджери версій. - - - )} - - - - {({ release }) => ( - - Хочете отримати нові функції швидше? - Завантажте Node.js {release.versionWithPrefix} - 1. - - )} - - -
-
- -
-
- ```js displayName="Create an HTTP Server" - // server.mjs - import { createServer } from 'node:http'; - - const server = createServer((req, res) => { - res.writeHead(200, { 'Content-Type': 'text/plain' }); - res.end('Hello World!\n'); - }); - - // starts a simple http server locally on port 3000 - server.listen(3000, '127.0.0.1', () => { - console.log('Listening on 127.0.0.1:3000'); - }); - - // run with `node server.mjs` - ``` - - ```js displayName="Write Tests" - // tests.mjs - import assert from 'node:assert'; - import test from 'node:test'; - - test('that 1 is equal 1', () => { - assert.strictEqual(1, 1); - }); - - test('that throws as 1 is not equal 2', () => { - // throws an exception because 1 != 2 - assert.strictEqual(1, 2); - }); - - // run with `node tests.mjs` - ``` - - ```js displayName="Read and Hash a File" - // crypto.mjs - import { createHash } from 'node:crypto'; - import { readFile } from 'node:fs/promises'; - - const hasher = createHash('sha1'); - - hasher.setEncoding('hex'); - // ensure you have a `package.json` file for this test! - hasher.write(await readFile('package.json')); - hasher.end(); - - const fileHash = hasher.read(); - - // run with `node crypto.mjs` - ``` - - ```js displayName="Streams Pipeline" - // streams.mjs - import { createReadStream, createWriteStream } from 'node:fs'; - import { pipeline } from 'node:stream/promises'; - import { createGzip } from 'node:zlib'; - - // ensure you have a `package.json` file for this test! - await pipeline( - createReadStream('package.json'), - createGzip(), - createWriteStream('package.json.gz') - ); - - // run with `node streams.mjs` - ``` - - ```js displayName="Work with Threads" - // threads.mjs - import { Worker, isMainThread, - workerData, parentPort } from 'node:worker_threads'; - - if (isMainThread) { - const data = 'some data'; - const worker = new Worker(import.meta.filename, { workerData: data }); - worker.on('message', msg => console.log('Reply from Thread:', msg)); - } else { - const source = workerData; - parentPort.postMessage(btoa(source.toUpperCase())); - } - - // run with `node threads.mjs` - ``` - -
- -Дізнайтеся більше про можливості Node.js із [нашими навчальними матеріалами](/learn). - -
diff --git a/apps/site/pages/zh-cn/index.mdx b/apps/site/pages/zh-cn/index.mdx deleted file mode 100644 index 1a8db0b4cefa7..0000000000000 --- a/apps/site/pages/zh-cn/index.mdx +++ /dev/null @@ -1,132 +0,0 @@ ---- -title: 在任何地方运行 JavaScript -layout: home ---- - -
- - -
-

在任何地方运行 JavaScript

- - Node.js® 是一个免费、开源、跨平台的 JavaScript 运行时环境, 它让开发人员能够创建服务器 - Web 应用、命令行工具和脚本。 - -
- -
- - {({ release }) => ( - <> - 下载 Node.js (LTS) - - 下载 Node.js {release.versionWithPrefix} - 1 长期支持版本。 - Node.js 也可以通过 软件包管理器 进行安装。 - - - )} - - - - {({ release }) => ( - - 想要更快获得新功能吗? - 获取 Node.js {release.versionWithPrefix} - 1 版本吧。 - - )} - - -
-
- -
-
- ```js displayName="Create an HTTP Server" - // server.mjs - import { createServer } from 'node:http'; - - const server = createServer((req, res) => { - res.writeHead(200, { 'Content-Type': 'text/plain' }); - res.end('Hello World!\n'); - }); - - // starts a simple http server locally on port 3000 - server.listen(3000, '127.0.0.1', () => { - console.log('Listening on 127.0.0.1:3000'); - }); - - // run with `node server.mjs` - ``` - - ```js displayName="Write Tests" - // tests.mjs - import assert from 'node:assert'; - import test from 'node:test'; - - test('that 1 is equal 1', () => { - assert.strictEqual(1, 1); - }); - - test('that throws as 1 is not equal 2', () => { - // throws an exception because 1 != 2 - assert.strictEqual(1, 2); - }); - - // run with `node tests.mjs` - ``` - - ```js displayName="Read and Hash a File" - // crypto.mjs - import { createHash } from 'node:crypto'; - import { readFile } from 'node:fs/promises'; - - const hasher = createHash('sha1'); - - hasher.setEncoding('hex'); - // ensure you have a `package.json` file for this test! - hasher.write(await readFile('package.json')); - hasher.end(); - - const fileHash = hasher.read(); - - // run with `node crypto.mjs` - ``` - - ```js displayName="Streams Pipeline" - // streams.mjs - import { createReadStream, createWriteStream } from 'node:fs'; - import { pipeline } from 'node:stream/promises'; - import { createGzip } from 'node:zlib'; - - // ensure you have a `package.json` file for this test! - await pipeline( - createReadStream('package.json'), - createGzip(), - createWriteStream('package.json.gz') - ); - - // run with `node streams.mjs` - ``` - - ```js displayName="Work with Threads" - // threads.mjs - import { Worker, isMainThread, - workerData, parentPort } from 'node:worker_threads'; - - if (isMainThread) { - const data = 'some data'; - const worker = new Worker(import.meta.filename, { workerData: data }); - worker.on('message', msg => console.log('Reply from Thread:', msg)); - } else { - const source = workerData; - parentPort.postMessage(btoa(source.toUpperCase())); - } - - // run with `node threads.mjs` - ``` - -
- 通过我们的[学习资料](/learn)了解 Node.js 。 -
diff --git a/apps/site/pages/zh-tw/index.mdx b/apps/site/pages/zh-tw/index.mdx deleted file mode 100644 index ab67d2e2d9670..0000000000000 --- a/apps/site/pages/zh-tw/index.mdx +++ /dev/null @@ -1,133 +0,0 @@ ---- -title: 隨時隨地執行 JavaScript -layout: home ---- - -
- - -
-

隨時隨地執行 JavaScript

- - Node.js® 是一款免費的跨平台開源 JavaScript 執行環境,供開發者建立伺服器、網頁應用程式、命令列工具與指令稿。 - -
- -
- - {({ release }) => ( - <> - 下載 Node.js (LTS) - - 下載享有長期支援的 Node.js {release.versionWithPrefix} - 1。 - 您也可以透過版本管理程式來安裝 Node.js。 - - - )} - - - - {({ release }) => ( - - 想要更快體驗新功能嗎? - 那就下載 Node.js {release.versionWithPrefix} - 1 吧。 - - )} - - -
-
- -
-
- ```js displayName="Create an HTTP Server" - // server.mjs - import { createServer } from 'node:http'; - - const server = createServer((req, res) => { - res.writeHead(200, { 'Content-Type': 'text/plain' }); - res.end('Hello World!\n'); - }); - - // starts a simple http server locally on port 3000 - server.listen(3000, '127.0.0.1', () => { - console.log('Listening on 127.0.0.1:3000'); - }); - - // run with `node server.mjs` - ``` - - ```js displayName="Write Tests" - // tests.mjs - import assert from 'node:assert'; - import test from 'node:test'; - - test('that 1 is equal 1', () => { - assert.strictEqual(1, 1); - }); - - test('that throws as 1 is not equal 2', () => { - // throws an exception because 1 != 2 - assert.strictEqual(1, 2); - }); - - // run with `node tests.mjs` - ``` - - ```js displayName="Read and Hash a File" - // crypto.mjs - import { createHash } from 'node:crypto'; - import { readFile } from 'node:fs/promises'; - - const hasher = createHash('sha1'); - - hasher.setEncoding('hex'); - // ensure you have a `package.json` file for this test! - hasher.write(await readFile('package.json')); - hasher.end(); - - const fileHash = hasher.read(); - - // run with `node crypto.mjs` - ``` - - ```js displayName="Streams Pipeline" - // streams.mjs - import { createReadStream, createWriteStream } from 'node:fs'; - import { pipeline } from 'node:stream/promises'; - import { createGzip } from 'node:zlib'; - - // ensure you have a `package.json` file for this test! - await pipeline( - createReadStream('package.json'), - createGzip(), - createWriteStream('package.json.gz') - ); - - // run with `node streams.mjs` - ``` - - ```js displayName="Work with Threads" - // threads.mjs - import { Worker, isMainThread, - workerData, parentPort } from 'node:worker_threads'; - - if (isMainThread) { - const data = 'some data'; - const worker = new Worker(import.meta.filename, { workerData: data }); - worker.on('message', msg => console.log('Reply from Thread:', msg)); - } else { - const source = workerData; - parentPort.postMessage(btoa(source.toUpperCase())); - } - - // run with `node threads.mjs` - ``` - -
- -我們提供大量[學習資源](/learn),探索 Node.js 的無限潛能。 - -
diff --git a/apps/site/types/layouts.ts b/apps/site/types/layouts.ts index a3e81f69132f7..ff6ad599eca79 100644 --- a/apps/site/types/layouts.ts +++ b/apps/site/types/layouts.ts @@ -6,4 +6,5 @@ export type Layouts = | 'blog-category' | 'blog-post' | 'download' + | 'download-archive' | 'article'; diff --git a/apps/site/types/releases.ts b/apps/site/types/releases.ts index cf71f7bea406d..ac9732d86d803 100644 --- a/apps/site/types/releases.ts +++ b/apps/site/types/releases.ts @@ -20,8 +20,12 @@ export interface NodeReleaseSource { } export interface MinorVersion { - version: string; + npm?: string; + modules?: string; releaseDate: string; + v8: string; + version: string; + versionWithPrefix: string; } export interface NodeRelease extends NodeReleaseSource { diff --git a/apps/site/util/__tests__/getNodeDownloadUrl.test.mjs b/apps/site/util/__tests__/getNodeDownloadUrl.test.mjs index 8ec40abda7fb2..d2504459fe3de 100644 --- a/apps/site/util/__tests__/getNodeDownloadUrl.test.mjs +++ b/apps/site/util/__tests__/getNodeDownloadUrl.test.mjs @@ -8,48 +8,58 @@ const version = 'v18.16.0'; describe('getNodeDownloadUrl', () => { it('should return the correct download URL for Mac', () => { const os = 'MAC'; - const bitness = 86; + const platform = 86; const expectedUrl = 'https://nodejs.org/dist/v18.16.0/node-v18.16.0.pkg'; - assert.equal(getNodeDownloadUrl(version, os, bitness), expectedUrl); + assert.equal(getNodeDownloadUrl({ version, os, platform }), expectedUrl); }); it('should return the correct download URL for Windows (32-bit)', () => { const os = 'WIN'; - const bitness = 86; + const platform = 86; const expectedUrl = 'https://nodejs.org/dist/v18.16.0/node-v18.16.0-x86.msi'; - assert.equal(getNodeDownloadUrl(version, os, bitness), expectedUrl); + assert.equal(getNodeDownloadUrl({ version, os, platform }), expectedUrl); }); it('should return the correct download URL for Windows (64-bit)', () => { const os = 'WIN'; - const bitness = 64; + const platform = 64; const expectedUrl = 'https://nodejs.org/dist/v18.16.0/node-v18.16.0-x64.msi'; - assert.equal(getNodeDownloadUrl(version, os, bitness), expectedUrl); + assert.equal(getNodeDownloadUrl({ version, os, platform }), expectedUrl); }); it('should return the default download URL for other operating systems', () => { const os = 'OTHER'; - const bitness = 86; + const platform = 86; const expectedUrl = 'https://nodejs.org/dist/v18.16.0/node-v18.16.0.tar.gz'; - assert.equal(getNodeDownloadUrl(version, os, bitness), expectedUrl); + assert.equal(getNodeDownloadUrl({ version, os, platform }), expectedUrl); }); describe('MAC', () => { it('should return .pkg link for installer', () => { - const url = getNodeDownloadUrl('v18.0.0', 'MAC', 'x64', 'installer'); + const url = getNodeDownloadUrl({ + version: 'v18.0.0', + os: 'MAC', + platform: 'x64', + kind: 'installer', + }); assert.ok(url.includes('.pkg')); }); }); describe('WIN', () => { it('should return an MSI link for installer', () => { - const url = getNodeDownloadUrl('v18.0.0', 'WIN', 'x64', 'installer'); + const url = getNodeDownloadUrl({ + version: 'v18.0.0', + os: 'WIN', + platform: 'x64', + kind: 'installer', + }); assert.ok(url.includes('.msi')); }); }); diff --git a/apps/site/util/downloadUtils/archive.tsx b/apps/site/util/downloadUtils/archive.tsx new file mode 100644 index 0000000000000..eb7ecdfb4d2fc --- /dev/null +++ b/apps/site/util/downloadUtils/archive.tsx @@ -0,0 +1,177 @@ +import semVer from 'semver'; + +import type { NodeRelease } from '#site/types/releases'; +import type { UserOS, UserPlatform } from '#site/types/userOS'; +import type { DownloadDropdownItem } from '#site/util/downloadUtils'; +import { + PLATFORMS, + OS_NOT_SUPPORTING_INSTALLERS, +} from '#site/util/downloadUtils'; +import type { DownloadKind } from '#site/util/getNodeDownloadUrl'; +import { getNodeDownloadUrl } from '#site/util/getNodeDownloadUrl'; + +import { DIST_URL } from '#site/next.constants'; + +export type NodeDownloadArtifact = { + file: string; + kind: DownloadKind; + os: UserOS; + architecture: string; + url: string; + version: string; +}; + +/** + * Checks if a download item is compatible with the given OS, platform, and version. + */ +function isCompatible( + compatibility: DownloadDropdownItem['compatibility'], + os: UserOS, + platform: UserPlatform, + version: string +): boolean { + const { + os: osList, + platform: platformList, + semver: versions, + } = compatibility; + + return ( + (osList?.includes(os) ?? true) && + (platformList?.includes(platform) ?? true) && + (versions?.every(r => semVer.satisfies(version, r)) ?? true) + ); +} + +type CompatibleArtifactOptions = { + platforms?: Record>>; + exclude?: Array; + version: string; + kind?: DownloadKind; +}; + +/** + * Returns a list of compatible artifacts for the given options. + */ +const getCompatibleArtifacts = ({ + platforms = PLATFORMS, + exclude = [], + version, + kind = 'binary', +}: CompatibleArtifactOptions): Array => { + return Object.entries(platforms).flatMap(([os, items]) => { + if (exclude.includes(os)) return []; + + const operatingSystem = os as UserOS; + + return items + .filter(({ compatibility, value }) => + isCompatible(compatibility, operatingSystem, value, version) + ) + .map(({ value, label }) => { + const url = getNodeDownloadUrl({ + version: version, + os: operatingSystem, + platform: value, + kind: kind, + }); + + return { + file: url.replace(`${DIST_URL}${version}/`, ''), + kind: kind, + os: operatingSystem, + architecture: label, + url: url, + version: version, + }; + }); + }); +}; + +/** + * Generates the navigation links for the Node.js download archive + * It creates a list of links for each major release, formatted with the major + * version and codename if available. + */ +export const getDownloadArchiveNavigation = (releases: Array) => + releases.map(({ major, codename, versionWithPrefix }) => ({ + label: `Node.js v${major} ${codename ? `(${codename})` : ''}`, + href: `/download/${versionWithPrefix}`, + })); + +/** + * Builds the release artifacts for a given Node.js release and version. + * It retrieves binaries, installers, and source files based on the version. + */ +export const buildReleaseArtifacts = ( + release: NodeRelease, + version: string +) => { + const minorVersion = release.minorVersions.find( + ({ versionWithPrefix }) => versionWithPrefix === version + ); + + const enrichedRelease = { + ...release, + ...minorVersion, + }; + + return { + binaries: getCompatibleArtifacts({ + version: version, + kind: 'binary', + }), + installers: getCompatibleArtifacts({ + exclude: OS_NOT_SUPPORTING_INSTALLERS, + version: version, + kind: 'installer', + }), + sources: { + shasum: getNodeDownloadUrl({ + version: version, + kind: 'shasum', + }), + tarball: getNodeDownloadUrl({ + version: version, + kind: 'source', + }), + }, + version: version, + release: enrichedRelease, + }; +}; + +/** + * Extracts the version from the pathname. + * It expects the version to be in the format 'v22.0.4' or 'archive'. + */ +export const extractVersionFromPath = (pathname: string | undefined) => { + if (!pathname) { + return null; + } + + const segments = pathname.split('/').filter(Boolean); + const version = segments.pop(); + + // Check version format like (v22.0.4 or 'archive') + if (!version || !version.match(/^v\d+(\.\d+)*|archive$/)) { + return null; + } + + return version; +}; + +/** + * Finds the appropriate release based on version, if 'archive' is passed, + * it returns the latest LTS release. + */ +export const findReleaseByVersion = ( + releaseData: Array, + version: string | 'archive' +) => { + if (version === 'archive') { + return releaseData.find(release => release.status === 'LTS'); + } + + return releaseData.find(release => semVer.major(version) === release.major); +}; diff --git a/apps/site/util/downloadUtils/constants.json b/apps/site/util/downloadUtils/constants.json index a04695ee3dd40..fc6d5d45b80b3 100644 --- a/apps/site/util/downloadUtils/constants.json +++ b/apps/site/util/downloadUtils/constants.json @@ -8,7 +8,10 @@ "platforms": [ { "label": "x64", - "value": "x64" + "value": "x64", + "compatibility": { + "semver": [">= 4.0.0"] + } }, { "label": "x86", @@ -40,7 +43,7 @@ "label": "ARM64", "value": "arm64", "compatibility": { - "semver": [">= 19.9.0"] + "semver": [">= 16.0.0"] } } ] diff --git a/apps/site/util/downloadUtils/index.tsx b/apps/site/util/downloadUtils/index.tsx index b7fa11d3dca8b..0280358859880 100644 --- a/apps/site/util/downloadUtils/index.tsx +++ b/apps/site/util/downloadUtils/index.tsx @@ -32,7 +32,7 @@ type DownloadCompatibility = { releases?: Array; }; -type DownloadDropdownItem = { +export type DownloadDropdownItem = { label: IntlMessageKeys; recommended?: boolean; url?: string; diff --git a/apps/site/util/getNodeDownloadUrl.ts b/apps/site/util/getNodeDownloadUrl.ts index d5f2a8ef0c44d..f1ff8c2b0e1a4 100644 --- a/apps/site/util/getNodeDownloadUrl.ts +++ b/apps/site/util/getNodeDownloadUrl.ts @@ -1,75 +1,100 @@ import { DIST_URL } from '#site/next.constants.mjs'; import type { UserOS, UserPlatform } from '#site/types/userOS'; -export type DownloadKind = 'installer' | 'binary' | 'source'; +export type DownloadKind = 'installer' | 'binary' | 'source' | 'shasum'; -export const getNodeDownloadUrl = ( - versionWithPrefix: string, - os: UserOS | 'LOADING', - platform: UserPlatform = 'x64', - kind: DownloadKind = 'installer' -) => { - const baseURL = `${DIST_URL}${versionWithPrefix}`; +type DownloadOptions = { + version: string; + os?: UserOS | 'LOADING'; + platform?: UserPlatform; + kind?: DownloadKind; +}; + +/** + * Generates a Node.js download URL for the given options. + * + * @param options - The download options. + * @param options.version - The Node.js version string, must include the 'v' prefix (e.g., 'v20.12.2'). + * @param options.os - The target operating system. Defaults to 'LOADING'. + * @param options.platform - The target platform/architecture (e.g., 'x64', 'arm64'). Defaults to 'x64'. + * @param options.kind - The type of download artifact. Can be 'installer', 'binary', 'source', or 'shasum'. Defaults to 'installer'. + * @returns The fully qualified URL to the requested Node.js artifact. + * + * @example + * getNodeDownloadUrl({ version: 'v20.12.2', os: 'MAC', platform: 'arm64', kind: 'binary' }); + * // => 'https://nodejs.org/dist/v20.12.2/node-v20.12.2-darwin-arm64.tar.gz' + */ +export const getNodeDownloadUrl = ({ + version, + os = 'LOADING', + platform = 'x64', + kind = 'installer', +}: DownloadOptions) => { + const baseURL = `${DIST_URL}${version}`; if (kind === 'source') { - return `${baseURL}/node-${versionWithPrefix}.tar.gz`; + return `${baseURL}/node-${version}.tar.gz`; + } + + if (kind === 'shasum') { + return `${baseURL}/SHASUMS256.txt.asc`; } switch (os) { case 'MAC': // Prepares a downloadable Node.js installer link for the x64, ARM64 platforms if (kind === 'installer') { - return `${baseURL}/node-${versionWithPrefix}.pkg`; + return `${baseURL}/node-${version}.pkg`; } // Prepares a downloadable Node.js link for the ARM64 platform if (typeof platform === 'string') { - return `${baseURL}/node-${versionWithPrefix}-darwin-${platform}.tar.gz`; + return `${baseURL}/node-${version}-darwin-${platform}.tar.gz`; } // Prepares a downloadable Node.js link for the x64 platform. // Since the x86 platform is not officially supported, returns the x64 // link as the default value. - return `${baseURL}/node-${versionWithPrefix}-darwin-x64.tar.gz`; + return `${baseURL}/node-${version}-darwin-x64.tar.gz`; case 'WIN': { if (kind === 'installer') { // Prepares a downloadable Node.js installer link for the ARM platforms if (typeof platform === 'string') { - return `${baseURL}/node-${versionWithPrefix}-${platform}.msi`; + return `${baseURL}/node-${version}-${platform}.msi`; } // Prepares a downloadable Node.js installer link for the x64 and x86 platforms - return `${baseURL}/node-${versionWithPrefix}-x${platform}.msi`; + return `${baseURL}/node-${version}-x${platform}.msi`; } // Prepares a downloadable Node.js link for the ARM64 platform if (typeof platform === 'string') { - return `${baseURL}/node-${versionWithPrefix}-win-${platform}.zip`; + return `${baseURL}/node-${version}-win-${platform}.zip`; } // Prepares a downloadable Node.js link for the x64 and x86 platforms - return `${baseURL}/node-${versionWithPrefix}-win-x${platform}.zip`; + return `${baseURL}/node-${version}-win-x${platform}.zip`; } case 'LINUX': // Prepares a downloadable Node.js link for the ARM platforms such as // ARMv7 and ARMv8 if (typeof platform === 'string') { - return `${baseURL}/node-${versionWithPrefix}-linux-${platform}.tar.xz`; + return `${baseURL}/node-${version}-linux-${platform}.tar.xz`; } // Prepares a downloadable Node.js link for the x64 platform. // Since the x86 platform is not officially supported, returns the x64 // link as the default value. - return `${baseURL}/node-${versionWithPrefix}-linux-x64.tar.xz`; + return `${baseURL}/node-${version}-linux-x64.tar.xz`; case 'AIX': // Prepares a downloadable Node.js link for AIX if (typeof platform === 'string') { - return `${baseURL}/node-${versionWithPrefix}-aix-${platform}.tar.gz`; + return `${baseURL}/node-${version}-aix-${platform}.tar.gz`; } - return `${baseURL}/node-${versionWithPrefix}-aix-ppc64.tar.gz`; + return `${baseURL}/node-${version}-aix-ppc64.tar.gz`; default: // Prepares a downloadable Node.js source code link - return `${baseURL}/node-${versionWithPrefix}.tar.gz`; + return `${baseURL}/node-${version}.tar.gz`; } }; diff --git a/packages/i18n/locales/en.json b/packages/i18n/locales/en.json index 446608b40ef35..9614d782e3ec4 100644 --- a/packages/i18n/locales/en.json +++ b/packages/i18n/locales/en.json @@ -162,6 +162,11 @@ "status": "Status", "details": "Details" }, + "downloadsTable": { + "fileName": "File Name", + "operatingSystem": "OS", + "architecture": "Architecture" + }, "releaseModal": { "title": "Node.js {version} ({codename})", "titleWithoutCodename": "Node.js {version}", @@ -173,6 +178,8 @@ "minorReleasesTable": { "version": "Version", "links": "Links", + "showMore": "Show more", + "information": "Version Informations", "actions": { "release": "Release", "changelog": "Changelog", @@ -321,7 +328,7 @@ "unsupportedVersionWarning": "This version is out of maintenance. Please use a currently supported version. Understand EOL support.", "communityPlatformInfo": "Installation methods that involve community software are supported by the teams maintaining that software.", "externalSupportInfo": "If you encounter any issues please visit {platform}'s website", - "noScriptDetected": "This page requires JavaScript. You can download Node.js without JavaScript by visiting the releases page directly.", + "noScriptDetected": "This page requires JavaScript. You can download Node.js without JavaScript by visiting the downloads archive page directly.", "platformInfo": { "default": "{platform} and their installation scripts are not maintained by the Node.js project.", "nvm": "\"nvm\" is a cross-platform Node.js version manager.", diff --git a/packages/ui-components/Common/Modal/index.module.css b/packages/ui-components/Common/Modal/index.module.css index 5b399767fdf7e..42e8b79c10e0c 100644 --- a/packages/ui-components/Common/Modal/index.module.css +++ b/packages/ui-components/Common/Modal/index.module.css @@ -26,6 +26,7 @@ focus:outline-none sm:my-20 xl:p-12 + dark:border-neutral-800 dark:bg-neutral-950; } diff --git a/packages/ui-components/Common/Separator/index.module.css b/packages/ui-components/Common/Separator/index.module.css index 61d7dc140faa0..49ef6d6896fec 100644 --- a/packages/ui-components/Common/Separator/index.module.css +++ b/packages/ui-components/Common/Separator/index.module.css @@ -2,7 +2,8 @@ .root { @apply shrink-0 - bg-neutral-800; + bg-neutral-200 + dark:bg-neutral-800; &.horizontal { @apply h-px diff --git a/packages/ui-components/styles/markdown.css b/packages/ui-components/styles/markdown.css index 862cd6450f05e..6451c1a8875c1 100644 --- a/packages/ui-components/styles/markdown.css +++ b/packages/ui-components/styles/markdown.css @@ -170,4 +170,24 @@ main { @apply sm:border-l-0; } } + + details { + summary * { + @apply inline + pl-2; + } + + a { + h1, + h2, + h3, + h4, + h5, + h6 { + @apply inline + text-green-600 + dark:text-green-400; + } + } + } }