The Node.js® Website

feat: introduced home layout (#6214)

* fix: fix codebox tabs and copy button

* chore: normalize export of withCurrentOS

* chore: normalized layout types and layout connector

* fix: fixed codetabs styles

* feat: download button component

* chore: mdx codetabs with external link

* feat: home page layout

* fix: base-layout without overflow hidden

* chore: tailwind changes

* feat: shiki and highlighter changes

* chore: website redesign route rewrite

* fix: markdown styles

* chore: banner and badge on home

* fix: fixed types and code

* chore: fixed rewrites

* chore: rephrase text

* chore: design fixes and removed bloat

* chore: revert site.json test changes

* chore: tailwind fixes

* chore: make default layout more organised

* chore: more design fixes

* chore: use css modules

* refactor: styling updates

* refactor: feedbacks from review

* chore: some fixes and formatting

* Update next.rewrites.mjs

Co-authored-by: Brian Muenzenmeyer <brian.muenzenmeyer@gmail.com>
Signed-off-by: Claudio W <cwunder@gnome.org>

* fix: numerous accessibility issues

* feat(styles): use `size` instead of `h` and `w`

* fix: codebox accessible comment color

* docs: color replacements on shikiji

* fix: fixed mdxcontent css priority

* fix: link component href and types

* refactor: button to be an anchor element

* fix: minor css fixes

* fix: fixed tests for button

* fix: button text always centered

---------

Signed-off-by: Claudio W <cwunder@gnome.org>
Co-authored-by: Caner Akdas <canerakdas@gmail.com>
Co-authored-by: Brian Muenzenmeyer <brian.muenzenmeyer@gmail.com>
Co-authored-by: Augustin Mauroy <augustin.mauroy@outlook.fr>

+1 -1
app/[locale]/[[...path]]/page.tsx
··· 5 5 6 6 import { setClientContext } from '@/client-context'; 7 7 import { MDXRenderer } from '@/components/mdxRenderer'; 8 - import { WithLayout } from '@/components/withLayout'; 8 + import WithLayout from '@/components/withLayout'; 9 9 import { ENABLE_STATIC_EXPORT, VERCEL_REVALIDATE } from '@/next.constants.mjs'; 10 10 import { DEFAULT_VIEWPORT } from '@/next.dynamic.constants.mjs'; 11 11 import { dynamicRouter } from '@/next.dynamic.mjs';
+6 -1
app/[locale]/layout.tsx
··· 42 42 </ThemeProvider> 43 43 </LocaleProvider> 44 44 45 - <a rel="me" href="https://social.lfx.dev/@nodejs" /> 45 + <a 46 + rel="me" 47 + aria-hidden="true" 48 + className="hidden" 49 + href="https://social.lfx.dev/@nodejs" 50 + /> 46 51 47 52 {VERCEL_ENV && ( 48 53 <>
+1 -1
components/Common/Breadcrumbs/BreadcrumbHomeLink/index.tsx
··· 21 21 const navigateToHome = t('components.common.breadcrumbs.navigateToHome'); 22 22 23 23 return ( 24 - <BreadcrumbLink href={href} {...props}> 24 + <BreadcrumbLink href={href} aria-label={navigateToHome} {...props}> 25 25 <HomeIcon 26 26 title={navigateToHome} 27 27 aria-label={navigateToHome}
+1 -1
components/Common/Breadcrumbs/BreadcrumbLink/index.tsx
··· 18 18 itemScope 19 19 itemType="http://schema.org/Thing" 20 20 itemProp="item" 21 - itemID={href.toString()} 21 + itemID={href?.toString()} 22 22 href={href} 23 23 className={classNames( 24 24 styles.link,
+1 -2
components/Common/Breadcrumbs/index.tsx
··· 1 - import { type LinkProps } from 'next/link'; 2 1 import { useMemo, type FC } from 'react'; 3 2 4 3 import BreadcrumbHomeLink from '@/components/Common/Breadcrumbs/BreadcrumbHomeLink'; ··· 10 9 11 10 type BreadcrumbLink = { 12 11 label: FormattedMessage; 13 - href: LinkProps['href']; 12 + href: string | undefined; 14 13 }; 15 14 16 15 type BreadcrumbsProps = {
+47 -47
components/Common/Button/index.module.css
··· 1 - @import '../../../styles/new/mixins'; 2 - 3 1 .button { 4 2 @apply relative 5 - px-4.5 6 - py-2.5 7 - font-semibold; 3 + px-4.5 4 + py-2.5 5 + text-center 6 + font-semibold; 8 7 9 8 &.primary { 10 9 @apply rounded 11 - border 12 - border-green-600 13 - bg-green-600 14 - text-white 15 - shadow-sm; 10 + border 11 + border-green-600 12 + bg-green-600 13 + text-white 14 + shadow-sm; 16 15 17 16 &:hover { 18 17 @apply border-green-700 19 - bg-green-700; 18 + bg-green-700 19 + text-white; 20 20 } 21 21 22 22 &:focus { 23 23 @apply border-green-700 24 - bg-green-700; 24 + bg-green-700; 25 25 } 26 26 27 - &:disabled { 27 + &[aria-disabled='true'] { 28 28 @apply bg-green-600 29 - opacity-50; 29 + opacity-50; 30 30 } 31 31 } 32 32 33 33 &.secondary { 34 34 @apply rounded-lg 35 - text-neutral-800 36 - dark:text-neutral-200/100; 35 + text-neutral-800 36 + dark:text-neutral-200; 37 37 38 38 &:hover { 39 39 @apply bg-neutral-100 40 - text-neutral-800 41 - dark:bg-neutral-900 42 - dark:text-neutral-200; 40 + text-neutral-800 41 + dark:bg-neutral-900 42 + dark:text-neutral-200; 43 43 } 44 44 45 - &:disabled { 46 - @apply bg-neutral-100/0 45 + &[aria-disabled='true'] { 46 + @apply bg-transparent 47 47 opacity-50; 48 48 } 49 49 50 50 &:focus { 51 51 @apply bg-neutral-100 52 - text-neutral-800 53 - dark:bg-neutral-900 54 - dark:text-neutral-200; 52 + text-neutral-800 53 + dark:bg-neutral-900 54 + dark:text-neutral-200; 55 55 } 56 56 } 57 57 58 58 &.special { 59 59 @apply rounded-lg 60 - border 61 - border-green-600/30 62 - bg-green-600/10 63 - text-white 64 - shadow-sm; 60 + border 61 + border-green-600/30 62 + bg-green-600/10 63 + text-white 64 + shadow-sm; 65 65 66 66 &::before { 67 67 @apply absolute 68 - right-0 69 - top-0 70 - z-[-1] 71 - h-full 72 - w-full 73 - opacity-30; 74 - 75 - @mixin glow-backdrop 8em, theme(colors.green.500); 76 - 77 - content: ''; 68 + right-0 69 + top-0 70 + -z-10 71 + h-full 72 + w-full 73 + bg-gradient-glow-backdrop 74 + opacity-30 75 + content-['']; 78 76 } 79 77 80 78 &::after { 81 79 @apply absolute 82 - right-0 83 - top-[-1px] 84 - h-px 85 - w-[40%] bg-gradient-to-r from-green-600/0 via-green-600 86 - to-green-600/0; 87 - 88 - content: ''; 80 + -top-px 81 + right-0 82 + h-px 83 + w-2/5 84 + bg-gradient-to-r 85 + from-green-600/0 86 + via-green-600 87 + to-green-600/0 88 + content-['']; 89 89 } 90 90 91 - &:disabled { 91 + &[aria-disabled='true'] { 92 92 @apply opacity-50; 93 93 } 94 94
+3 -3
components/Common/Button/index.stories.tsx
··· 7 7 8 8 export const Primary: Story = { 9 9 args: { 10 - variant: 'primary', 10 + kind: 'primary', 11 11 children: 'Download Node (LTS)', 12 12 disabled: false, 13 13 }, ··· 15 15 16 16 export const Secondary: Story = { 17 17 args: { 18 - variant: 'secondary', 18 + kind: 'secondary', 19 19 children: 'Download Node (LTS)', 20 20 disabled: false, 21 21 }, ··· 23 23 24 24 export const Special: Story = { 25 25 args: { 26 - variant: 'special', 26 + kind: 'special', 27 27 children: 'Download Node (LTS)', 28 28 disabled: false, 29 29 },
+16 -7
components/Common/Button/index.tsx
··· 1 1 import classNames from 'classnames'; 2 - import type { FC, ButtonHTMLAttributes } from 'react'; 2 + import type { FC, AnchorHTMLAttributes } from 'react'; 3 + 4 + import Link from '@/components/Link'; 3 5 4 6 import styles from './index.module.css'; 5 7 6 - type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & { 7 - variant?: 'primary' | 'secondary' | 'special'; 8 + type ButtonProps = AnchorHTMLAttributes<HTMLAnchorElement> & { 9 + kind?: 'primary' | 'secondary' | 'special'; 10 + // We have an extra `disabled` prop as we simulate a button 11 + disabled?: boolean; 8 12 }; 9 13 10 14 const Button: FC<ButtonProps> = ({ 11 - variant = 'primary', 15 + kind = 'primary', 16 + disabled = false, 17 + href = undefined, 12 18 children, 13 19 className, 14 20 ...props 15 21 }) => ( 16 - <button 17 - className={classNames(styles.button, styles[variant], className)} 22 + <Link 23 + role="button" 24 + href={disabled ? undefined : href} 25 + aria-disabled={disabled} 26 + className={classNames(styles.button, styles[kind], className)} 18 27 {...props} 19 28 > 20 29 {children} 21 - </button> 30 + </Link> 22 31 ); 23 32 24 33 export default Button;
+2 -1
components/Common/CodeBox/index.tsx
··· 63 63 language, 64 64 // For now we only want to render the Copy Button by default 65 65 // if the Website Redesign is Enabled 66 + // @todo remove this check once we migrate to website redesign 66 67 showCopyButton = ENABLE_WEBSITE_REDESIGN, 67 68 }) => { 68 69 const ref = useRef<HTMLPreElement>(null); ··· 98 99 <span className={styles.language}>{language}</span> 99 100 100 101 {showCopyButton && ( 101 - <Button type="button" className={styles.action} onClick={onCopy}> 102 + <Button className={styles.action} onClick={onCopy}> 102 103 <DocumentDuplicateIcon className={styles.icon} /> 103 104 {t('components.common.codebox.copy')} 104 105 </Button>
+21 -20
components/Common/CodeTabs/index.module.css
··· 10 10 border-neutral-900 11 11 bg-neutral-950 12 12 px-4 13 - pr-5 14 - pt-3; 13 + pt-3 14 + xs:px-2; 15 15 16 - & [role='tab'] { 16 + & [role='tablist'] > button { 17 17 @apply border-b 18 18 border-b-transparent 19 19 px-1 ··· 24 24 text-green-400; 25 25 } 26 26 } 27 - } 28 27 29 - .link { 30 - @apply flex 31 - items-center 32 - gap-2 33 - text-center 34 - text-neutral-200; 28 + .link { 29 + @apply hidden 30 + items-center 31 + gap-2 32 + text-center 33 + text-neutral-200 34 + lg:flex; 35 35 36 - & > .icon { 37 - @apply h-4 38 - w-4 39 - text-neutral-300; 40 - } 36 + & > .icon { 37 + @apply h-4 38 + w-4 39 + text-neutral-300; 40 + } 41 41 42 - &:is(:link, :visited) { 43 - &:hover { 44 - @apply text-neutral-400; 42 + &:is(:link, :visited) { 43 + &:hover { 44 + @apply text-neutral-400; 45 45 46 - & > .icon { 47 - @apply text-neutral-600; 46 + & > .icon { 47 + @apply text-neutral-600; 48 + } 48 49 } 49 50 } 50 51 }
+7 -4
components/Common/CodeTabs/index.tsx
··· 6 6 7 7 import styles from './index.module.css'; 8 8 9 + export type CodeTabsExternaLink = { 10 + linkUrl?: string; 11 + linkText?: string; 12 + }; 13 + 9 14 type CodeTabsProps = Pick< 10 15 ComponentProps<typeof Tabs>, 11 16 'tabs' | 'onValueChange' | 'defaultValue' 12 - > & { 13 - linkUrl?: string; 14 - linkText?: string; 15 - }; 17 + > & 18 + CodeTabsExternaLink; 16 19 17 20 const CodeTabs: FC<PropsWithChildren<CodeTabsProps>> = ({ 18 21 children,
+2 -2
components/Common/Pagination/__tests__/index.test.mjs
··· 162 162 screen.getByRole('button', { 163 163 name: 'components.common.pagination.prevAriaLabel', 164 164 }) 165 - ).toBeDisabled(); 165 + ).toHaveAttribute('aria-disabled'); 166 166 }); 167 167 168 168 it('Disables "Next" button when the currentPage is equal to the last page', () => { ··· 175 175 screen.getByRole('button', { 176 176 name: 'components.common.pagination.nextAriaLabel', 177 177 }) 178 - ).toBeDisabled(); 178 + ).toHaveAttribute('aria-disabled'); 179 179 }); 180 180 }); 181 181 });
+2 -4
components/Common/Pagination/index.tsx
··· 37 37 className={styles.pagination} 38 38 > 39 39 <Button 40 - type="button" 41 40 aria-label={t('components.common.pagination.prevAriaLabel')} 42 41 disabled={currentPage === 1} 43 - variant="secondary" 42 + kind="secondary" 44 43 className={styles.previousButton} 45 44 > 46 45 <ArrowLeftIcon className={styles.arrowIcon} /> ··· 48 47 </Button> 49 48 <ol className={styles.list}>{parsedPages}</ol> 50 49 <Button 51 - type="button" 52 50 aria-label={t('components.common.pagination.nextAriaLabel')} 53 51 disabled={currentPage === pages.length} 54 - variant="secondary" 52 + kind="secondary" 55 53 className={styles.nextButton} 56 54 > 57 55 <span>{t('components.common.pagination.next')}</span>
+21 -17
components/Common/Preview/index.module.css
··· 5 5 bg-neutral-950 6 6 bg-[url('/static/images/patterns/hexagon-grid.svg')] 7 7 bg-contain 8 - bg-center 9 - after:absolute 10 - after:inset-0 11 - after:m-auto 12 - after:aspect-square 13 - after:w-1/3 14 - after:rounded-full 15 - after:bg-gradient-radial 16 - after:blur-3xl; 8 + bg-center; 17 9 18 - &.announcement { 19 - @apply after:from-green-700/90; 20 - } 10 + &::after { 11 + @apply absolute 12 + inset-0 13 + m-auto 14 + aspect-square 15 + w-1/3 16 + rounded-full 17 + bg-gradient-radial 18 + blur-3xl 19 + content-['']; 21 20 22 - &.release { 23 - @apply after:from-info-600/90; 24 - } 21 + &.announcement { 22 + @apply from-green-700/90; 23 + } 24 + 25 + &.release { 26 + @apply from-info-600/90; 27 + } 25 28 26 - &.vulnerability { 27 - @apply after:from-warning-600/90; 29 + &.vulnerability { 30 + @apply from-warning-600/90; 31 + } 28 32 } 29 33 30 34 & > .container {
+1 -2
components/Common/Select/index.module.css
··· 52 52 } 53 53 54 54 .icon { 55 - @apply h-5 56 - w-5 55 + @apply size-5 57 56 text-neutral-600 58 57 dark:text-neutral-400; 59 58 }
+1 -1
components/Common/Tabs/index.module.css
··· 1 1 .tabsList { 2 2 @apply flex 3 - gap-1 3 + gap-2 4 4 font-open-sans; 5 5 6 6 .tabsTrigger {
+7 -5
components/Common/Tabs/index.tsx
··· 23 23 ...props 24 24 }) => ( 25 25 <TabsPrimitive.Root {...props}> 26 - <TabsPrimitive.List 26 + <div 27 27 className={classNames(headerClassName, { 28 28 [styles.tabsWithAddons]: addons != null, 29 29 })} 30 30 > 31 - <div className={classNames(styles.tabsList)}> 31 + <TabsPrimitive.List className={classNames(styles.tabsList)}> 32 32 {tabs.map(tab => ( 33 33 <TabsPrimitive.Trigger 34 34 key={tab.key} ··· 38 38 {tab.label} 39 39 </TabsPrimitive.Trigger> 40 40 ))} 41 - </div> 42 - {addons != null && <div className={styles.addons}>{addons}</div>} 43 - </TabsPrimitive.List> 41 + </TabsPrimitive.List> 42 + 43 + {addons && <div className={styles.addons}>{addons}</div>} 44 + </div> 45 + 44 46 {children} 45 47 </TabsPrimitive.Root> 46 48 );
+1 -1
components/Containers/Footer/index.tsx
··· 45 45 46 46 return ( 47 47 <NavItem key={link.icon} href={link.link} type="footer"> 48 - <SocialIcon width={20} height={20} /> 48 + <SocialIcon width={20} height={20} aria-label={link.link} /> 49 49 </NavItem> 50 50 ); 51 51 })}
+9 -11
components/Downloads/ChangelogModal/index.module.css
··· 82 82 } 83 83 } 84 84 85 - .wrapper { 86 - :global(.mdxContent) { 87 - @apply flex 88 - flex-col 89 - gap-4; 85 + .wrapper main { 86 + @apply flex 87 + flex-col 88 + gap-4; 90 89 91 - a { 92 - @apply underline; 93 - } 90 + a { 91 + @apply underline; 92 + } 94 93 95 - pre { 96 - @apply overflow-auto; 97 - } 94 + pre { 95 + @apply overflow-auto; 98 96 } 99 97 } 100 98 }
+2 -2
components/Downloads/ChangelogModal/index.stories.tsx
··· 198 198 return { 199 199 Content: ( 200 200 <ChangelogModal {...args}> 201 - <div className="mdxContent"> 201 + <main> 202 202 <MDXRenderer Component={MDXContent} /> 203 - </div> 203 + </main> 204 204 </ChangelogModal> 205 205 ), 206 206 };
+11
components/Downloads/DownloadButton/index.module.css
··· 1 + .downloadButton { 2 + @apply flex-row 3 + items-center 4 + justify-center 5 + gap-2; 6 + 7 + svg { 8 + @apply size-5 9 + dark:opacity-50; 10 + } 11 + }
+47
components/Downloads/DownloadButton/index.tsx
··· 1 + 'use client'; 2 + 3 + import { ArrowRightIcon } from '@heroicons/react/24/outline'; 4 + import classNames from 'classnames'; 5 + import type { FC, PropsWithChildren } from 'react'; 6 + 7 + import Button from '@/components/Common/Button'; 8 + import { useDetectOS } from '@/hooks'; 9 + import type { NodeRelease } from '@/types'; 10 + import { downloadUrlByOS } from '@/util/downloadUrlByOS'; 11 + 12 + import styles from './index.module.css'; 13 + 14 + type DownloadButtonProps = { release: NodeRelease }; 15 + 16 + const DownloadButton: FC<PropsWithChildren<DownloadButtonProps>> = ({ 17 + release: { versionWithPrefix }, 18 + children, 19 + }) => { 20 + const { os, bitness } = useDetectOS(); 21 + 22 + return ( 23 + <> 24 + <Button 25 + kind="special" 26 + href={downloadUrlByOS(versionWithPrefix, os, bitness)} 27 + className={classNames(styles.downloadButton, 'hidden dark:flex')} 28 + > 29 + {children} 30 + 31 + <ArrowRightIcon /> 32 + </Button> 33 + 34 + <Button 35 + kind="primary" 36 + href={downloadUrlByOS(versionWithPrefix, os, bitness)} 37 + className={classNames(styles.downloadButton, 'flex dark:hidden')} 38 + > 39 + {children} 40 + 41 + <ArrowRightIcon /> 42 + </Button> 43 + </> 44 + ); 45 + }; 46 + 47 + export default DownloadButton;
+4 -4
components/Downloads/PrimaryDownloadMatrix.tsx
··· 5 5 import semVer from 'semver'; 6 6 7 7 import Link from '@/components/Link'; 8 - import { WithCurrentOS } from '@/components/withCurrentOS'; 8 + import WithCurrentOS from '@/components/withCurrentOS'; 9 9 import { useClientContext } from '@/hooks'; 10 10 import { DIST_URL } from '@/next.constants.mjs'; 11 11 import type { NodeRelease } from '@/types'; ··· 60 60 <ul className="no-padding download-platform"> 61 61 <li> 62 62 <WithCurrentOS> 63 - {({ os }) => ( 63 + {({ currentOS }) => ( 64 64 <a 65 - href={`${DIST_URL}${versionWithPrefix}/node-${versionWithPrefix}-x${os.bitness}.msi`} 65 + href={`${DIST_URL}${versionWithPrefix}/node-${versionWithPrefix}-x${currentOS.bitness}.msi`} 66 66 data-version={versionWithPrefix} 67 67 > 68 68 <svg ··· 76 76 </svg> 77 77 {downloads.WindowsInstaller} 78 78 <p className="small color-lightgray"> 79 - node-{versionWithPrefix}-x{os.bitness}.msi 79 + node-{versionWithPrefix}-x{currentOS.bitness}.msi 80 80 </p> 81 81 </a> 82 82 )}
-34
components/Home/Banner.tsx
··· 1 - import { siteConfig } from '@/next.json.mjs'; 2 - import { dateIsBetween } from '@/util/dateIsBetween'; 3 - 4 - const Banner = () => { 5 - if (siteConfig.websiteBanners && siteConfig.websiteBanners['index']) { 6 - const indexBanner = siteConfig.websiteBanners['index']; 7 - 8 - const showBanner = dateIsBetween( 9 - indexBanner.startDate, 10 - indexBanner.endDate 11 - ); 12 - 13 - if (showBanner && indexBanner.text) { 14 - return ( 15 - <p className="home-version home-version-banner"> 16 - <a href={indexBanner.link}>{indexBanner.text}</a> 17 - </p> 18 - ); 19 - } 20 - 21 - if (showBanner && indexBanner.html) { 22 - return ( 23 - <a 24 - href={indexBanner.link} 25 - dangerouslySetInnerHTML={{ __html: indexBanner.html }} 26 - /> 27 - ); 28 - } 29 - } 30 - 31 - return null; 32 - }; 33 - 34 - export default Banner;
+16 -22
components/Link.tsx
··· 1 - import { useMemo } from 'react'; 2 - import type { FC, ComponentProps, HTMLAttributes as Attributes } from 'react'; 1 + import type { FC, ComponentProps } from 'react'; 3 2 4 3 import { Link as LocalizedLink } from '@/navigation.mjs'; 5 4 6 - // This is a wrapper on HTML's `a` tag 7 - const Html: FC<Attributes<HTMLAnchorElement>> = ({ children, ...p }) => ( 8 - <a {...p}>{children}</a> 9 - ); 5 + type LinkProps = Omit<ComponentProps<typeof LocalizedLink>, 'href'> & { 6 + href: string | undefined; 7 + }; 10 8 11 - // This is Next.js's Link Component but with pre-fetch disabled 12 - const Next: FC<ComponentProps<typeof Link>> = ({ children, ...p }) => ( 13 - <LocalizedLink {...p}>{children}</LocalizedLink> 14 - ); 9 + const Link: FC<LinkProps> = ({ children, href, ...props }) => { 10 + if (!href || href.toString().startsWith('http')) { 11 + return ( 12 + <a href={href} {...props}> 13 + {children} 14 + </a> 15 + ); 16 + } 15 17 16 - const Link: FC<ComponentProps<typeof LocalizedLink>> = ({ 17 - children, 18 - ...props 19 - }) => { 20 - const Component = useMemo( 21 - // Uses a different Link element/tag based on the nature of the Link 22 - // as we don't want prefetch/rsc or etc for external links 23 - () => 24 - !props.href || props.href.toString().startsWith('http') ? Html : Next, 25 - [props.href] 18 + return ( 19 + <LocalizedLink href={href?.toString()} {...props}> 20 + {children} 21 + </LocalizedLink> 26 22 ); 27 - 28 - return <Component {...props}>{children}</Component>; 29 23 }; 30 24 31 25 export default Link;
+2 -2
components/MDX/CodeBox/index.tsx
··· 3 3 import CodeBox from '@/components/Common/CodeBox'; 4 4 import { getLanguageDisplayName } from '@/util/getLanguageDisplayName'; 5 5 6 - type CodeBoxProps = { className?: string; showCopyButton?: boolean }; 6 + type CodeBoxProps = { className?: string; showCopyButton?: string }; 7 7 8 8 const MDXCodeBox: FC<PropsWithChildren<CodeBoxProps>> = ({ 9 9 children: code, ··· 16 16 return ( 17 17 <CodeBox 18 18 language={getLanguageDisplayName(language)} 19 - showCopyButton={showCopyButton} 19 + showCopyButton={showCopyButton ? showCopyButton === 'true' : undefined} 20 20 > 21 21 {code} 22 22 </CodeBox>
+13 -5
components/MDX/CodeTabs/index.tsx
··· 3 3 import * as TabsPrimitive from '@radix-ui/react-tabs'; 4 4 import type { FC, ReactElement } from 'react'; 5 5 6 + import type { CodeTabsExternaLink } from '@/components/Common/CodeTabs'; 6 7 import CodeTabs from '@/components/Common/CodeTabs'; 7 8 8 9 type MDXCodeTabsProps = { 9 10 children: Array<ReactElement>; 10 11 languages: string; 11 12 displayNames?: string; 12 - }; 13 + defaultTab?: string; 14 + } & CodeTabsExternaLink; 13 15 14 16 const MDXCodeTabs: FC<MDXCodeTabsProps> = ({ 15 17 languages: rawLanguages, 16 18 displayNames: rawDisplayNames, 17 19 children: codes, 20 + defaultTab = '0', 21 + ...props 18 22 }) => { 19 23 const languages = rawLanguages.split('|'); 20 24 const displayNames = rawDisplayNames?.split('|') ?? []; ··· 23 27 const displayName = displayNames[index]; 24 28 25 29 return { 26 - key: language, 30 + key: `${language}-${index}`, 27 31 label: displayName?.length ? displayName : language.toUpperCase(), 28 32 }; 29 33 }); 30 34 31 35 return ( 32 - <CodeTabs tabs={tabs} defaultValue={languages[0]}> 33 - {languages.map((language, index) => ( 34 - <TabsPrimitive.Content key={language} value={language}> 36 + <CodeTabs 37 + tabs={tabs} 38 + defaultValue={tabs[Number(defaultTab)].key} 39 + {...props} 40 + > 41 + {languages.map((_, index) => ( 42 + <TabsPrimitive.Content key={tabs[index].key} value={tabs[index].key}> 35 43 {codes[index]} 36 44 </TabsPrimitive.Content> 37 45 ))}
+4 -4
components/__design__/list.stories.tsx
··· 2 2 3 3 export const OrderedLists: StoryObj = { 4 4 render: () => ( 5 - <div className="mdxContent"> 5 + <main> 6 6 <ol> 7 7 <li>Ordered lists</li> 8 8 <li>Like this</li> 9 9 <li>with numbers</li> 10 10 </ol> 11 - </div> 11 + </main> 12 12 ), 13 13 }; 14 14 15 15 export const UnorderedLists: StoryObj = { 16 16 render: () => ( 17 - <div className="mdxContent"> 17 + <main> 18 18 <ul> 19 19 <li>Unordered lists</li> 20 20 <li>those without</li> 21 21 <li>numbers</li> 22 22 </ul> 23 - </div> 23 + </main> 24 24 ), 25 25 }; 26 26
+4 -4
components/__design__/table.stories.tsx
··· 2 2 3 3 export const Table: StoryObj = { 4 4 render: () => ( 5 - <div className="mdxContent"> 5 + <main> 6 6 <table> 7 7 <thead> 8 8 <tr> ··· 29 29 </tr> 30 30 </tbody> 31 31 </table> 32 - </div> 32 + </main> 33 33 ), 34 34 }; 35 35 36 36 export const HeadlessTable: StoryObj = { 37 37 render: () => ( 38 - <div className="mdxContent"> 38 + <main> 39 39 <table> 40 40 <tbody> 41 41 <tr> ··· 55 55 </tr> 56 56 </tbody> 57 57 </table> 58 - </div> 58 + </main> 59 59 ), 60 60 }; 61 61
+6 -6
components/__design__/text.stories.tsx
··· 2 2 3 3 export const Anchor: StoryObj = { 4 4 render: () => ( 5 - <div className="mdxContent"> 5 + <main> 6 6 <p> 7 7 The current Node.js security policy can be found at{' '} 8 8 <a href="https://github.com/nodejs/node/security/policy#security"> ··· 17 17 releases of Node.js and the projects maintained in the nodejs GitHub 18 18 organization. 19 19 </p> 20 - </div> 20 + </main> 21 21 ), 22 22 }; 23 23 24 24 export const InlineCode: StoryObj = { 25 25 render: () => ( 26 - <div className="mdxContent"> 26 + <main> 27 27 This is an example of <code>inline code block</code> 28 - </div> 28 + </main> 29 29 ), 30 30 }; 31 31 32 32 export const Headings: StoryObj = { 33 33 render: () => ( 34 - <div className="mdxContent"> 34 + <main> 35 35 <h1>HTML Section Heading 1</h1> 36 36 <h2>HTML Section Heading 2</h2> 37 37 <h3>HTML Section Heading 3</h3> 38 38 <h4>HTML Section Heading 4</h4> 39 39 <h5>HTML Section Heading 5</h5> 40 40 <h6>HTML Section Heading 6</h6> 41 - </div> 41 + </main> 42 42 ), 43 43 }; 44 44
+5 -3
components/withCurrentOS.tsx
··· 5 5 import { useDetectOS } from '@/hooks'; 6 6 7 7 type WithCurrentOS = { 8 - children: FC<{ os: ReturnType<typeof useDetectOS> }>; 8 + children: FC<{ currentOS: ReturnType<typeof useDetectOS> }>; 9 9 }; 10 10 11 - export const WithCurrentOS: FC<WithCurrentOS> = ({ children: Component }) => { 11 + const WithCurrentOS: FC<WithCurrentOS> = ({ children: Component }) => { 12 12 const osData = useDetectOS(); 13 13 14 - return <Component os={osData} />; 14 + return <Component currentOS={osData} />; 15 15 }; 16 + 17 + export default WithCurrentOS;
+19 -17
components/withLayout.tsx
··· 11 11 import AboutLayout from '@/layouts/New/About'; 12 12 import DefaultLayout from '@/layouts/New/Default'; 13 13 import DocsLayout from '@/layouts/New/Docs'; 14 + import HomeLayout from '@/layouts/New/Home'; 14 15 import LearnLayout from '@/layouts/New/Learn'; 15 16 import { ENABLE_WEBSITE_REDESIGN } from '@/next.constants.mjs'; 16 - import type { LegacyLayouts } from '@/types'; 17 + import type { Layouts, LegacyLayouts } from '@/types'; 17 18 18 19 /** @deprecated these should be removed with the website redesin */ 19 20 const legacyLayouts = { ··· 21 22 'about.hbs': LegacyAboutLayout, 22 23 'blog-category.hbs': LegacyBlogCategoryLayout, 23 24 'blog-post.hbs': LegacyBlogPostLayout, 24 - 'contribute.hbs': LegacyAboutLayout, 25 25 'download.hbs': LegacyDownloadLayout, 26 26 'index.hbs': LegacyIndexLayout, 27 27 'learn.hbs': LegacyLearnLayout, 28 28 'page.hbs': LegacyDefaultLayout, 29 - } satisfies Record<string, FC>; 29 + } satisfies Record<LegacyLayouts, FC>; 30 30 31 31 /** all the currently available layouts from website redesign */ 32 32 const redesignLayouts = { 33 - 'docs.hbs': DocsLayout, 34 33 'about.hbs': AboutLayout, 35 - 'blog-category.hbs': DefaultLayout, 36 - 'blog-post.hbs': DefaultLayout, 37 - 'contribute.hbs': AboutLayout, 38 - 'download.hbs': DefaultLayout, 39 - 'index.hbs': DefaultLayout, 34 + 'docs.hbs': DocsLayout, 35 + 'home.hbs': HomeLayout, 40 36 'learn.hbs': LearnLayout, 41 37 'page.hbs': DefaultLayout, 42 - } satisfies Record<string, FC>; 38 + } satisfies Record<Layouts, FC>; 43 39 44 - /** @deprecated this should be removed once we sunset the legacy layouts */ 45 - const availableLayouts = ENABLE_WEBSITE_REDESIGN 46 - ? redesignLayouts 47 - : legacyLayouts; 40 + type WithLayout<L = Layouts | LegacyLayouts> = PropsWithChildren<{ layout: L }>; 48 41 49 - type WithLayoutProps = PropsWithChildren<{ layout: LegacyLayouts }>; 42 + const WithRedesign: FC<WithLayout<Layouts>> = ({ layout, children }) => { 43 + const LayoutComponent = redesignLayouts[layout] ?? DefaultLayout; 50 44 51 - export const WithLayout: FC<WithLayoutProps> = ({ layout, children }) => { 52 - const LayoutComponent = availableLayouts[layout]; 45 + return <LayoutComponent>{children}</LayoutComponent>; 46 + }; 47 + 48 + /** @deprecated method to be removed once website redesign is finished */ 49 + const WithLegacy: FC<WithLayout<LegacyLayouts>> = ({ layout, children }) => { 50 + const LayoutComponent = legacyLayouts[layout] ?? LegacyDefaultLayout; 53 51 54 52 return <LayoutComponent>{children}</LayoutComponent>; 55 53 }; 54 + 55 + // Decides which Layout Connector to use based on the Environment 56 + // @todo: This should be removed once we switch to Redesign 57 + export default ENABLE_WEBSITE_REDESIGN ? WithRedesign : WithLegacy;
+1 -1
layouts/New/About.tsx
··· 13 13 <ArticleLayout> 14 14 <WithSidebar navKeys={['about', 'getInvolved']} /> 15 15 16 - <div className="mdxContent">{children}</div> 16 + <main>{children}</main> 17 17 18 18 <WithMetaBar /> 19 19
+1 -1
layouts/New/Article.tsx
··· 3 3 import styles from './layouts.module.css'; 4 4 5 5 const ArticleLayout: FC<PropsWithChildren> = ({ children }) => ( 6 - <article className={styles.articleLayout}>{children}</article> 6 + <div className={styles.articleLayout}>{children}</div> 7 7 ); 8 8 9 9 export default ArticleLayout;
+7 -1
layouts/New/Default.tsx
··· 2 2 3 3 import WithFooter from '@/components/withFooter'; 4 4 import WithNavBar from '@/components/withNavBar'; 5 + import WithSidebar from '@/components/withSidebar'; 6 + import ArticleLayout from '@/layouts/New/Article'; 5 7 6 8 const DefaultLayout: FC<PropsWithChildren> = ({ children }) => ( 7 9 <> 8 10 <WithNavBar /> 9 11 10 - <div className="mdxContent">{children}</div> 12 + <ArticleLayout> 13 + <WithSidebar navKeys={[]} /> 14 + 15 + <main>{children}</main> 16 + </ArticleLayout> 11 17 12 18 <WithFooter /> 13 19 </>
+1 -1
layouts/New/Docs.tsx
··· 16 16 <ArticleLayout> 17 17 <WithSideBar navKeys={[]} /> 18 18 19 - <div className="mdxContent">{children}</div> 19 + <main>{children}</main> 20 20 21 21 <WithMetaBar /> 22 22 </ArticleLayout>
+22
layouts/New/Home.tsx
··· 1 + import type { FC, PropsWithChildren } from 'react'; 2 + 3 + import WithFooter from '@/components/withFooter'; 4 + import WithNavBar from '@/components/withNavBar'; 5 + 6 + import styles from './layouts.module.css'; 7 + 8 + const HomeLayout: FC<PropsWithChildren> = ({ children }) => ( 9 + <> 10 + <WithNavBar /> 11 + 12 + <main className={styles.homeLayout}> 13 + <div className={styles.hexagonBackdrop} /> 14 + 15 + {children} 16 + </main> 17 + 18 + <WithFooter /> 19 + </> 20 + ); 21 + 22 + export default HomeLayout;
+2 -2
layouts/New/Learn.tsx
··· 14 14 <ArticleLayout> 15 15 <WithProgressionSidebar navKey="learn" /> 16 16 17 - <div className="mdxContent"> 17 + <main> 18 18 {children} 19 19 20 20 <WithCrossLinks navKey="learn" /> 21 - </div> 21 + </main> 22 22 23 23 <WithMetaBar /> 24 24
+107
layouts/New/layouts.module.css
··· 64 64 dark:bg-neutral-950; 65 65 } 66 66 } 67 + 68 + .homeLayout { 69 + @apply mx-auto 70 + flex 71 + w-full 72 + flex-col 73 + items-center 74 + gap-8 75 + self-stretch 76 + px-4 77 + py-14 78 + md:w-auto 79 + md:flex-row 80 + md:gap-14 81 + md:px-14 82 + md:py-0 83 + lg:gap-28 84 + lg:px-28; 85 + 86 + .hexagonBackdrop { 87 + @apply absolute 88 + left-0 89 + -z-10 90 + h-full 91 + w-full 92 + bg-[url('/static/images/patterns/hexagon-grid.svg')] 93 + bg-center 94 + bg-no-repeat 95 + opacity-50 96 + md:opacity-100; 97 + 98 + &::after { 99 + @apply absolute 100 + inset-0 101 + m-auto 102 + aspect-square 103 + w-[300px] 104 + rounded-full 105 + bg-green-300 106 + blur-[120px] 107 + content-[''] 108 + dark:bg-green-700; 109 + } 110 + } 111 + 112 + section { 113 + &:nth-of-type(1) { 114 + @apply flex 115 + max-w-md 116 + flex-[1_0_0] 117 + flex-col 118 + items-start 119 + gap-8; 120 + 121 + h1 { 122 + @apply bg-gradient-subtle-gray 123 + bg-clip-text 124 + text-4xl 125 + -tracking-[0.045rem] 126 + [-webkit-text-fill-color:transparent] 127 + md:text-5xl 128 + md:-tracking-[0.06rem] 129 + dark:bg-gradient-subtle-white; 130 + } 131 + 132 + p { 133 + @apply text-base 134 + text-neutral-900 135 + md:text-lg 136 + dark:text-white; 137 + } 138 + 139 + > div { 140 + &:nth-of-type(1) { 141 + @apply flex 142 + flex-col 143 + gap-4; 144 + } 145 + 146 + &:nth-of-type(2) { 147 + @apply flex 148 + w-full 149 + flex-col 150 + gap-2 151 + lg:flex-row; 152 + } 153 + } 154 + } 155 + 156 + &:nth-of-type(2) { 157 + @apply flex 158 + max-w-md 159 + flex-col 160 + content-center 161 + items-center 162 + gap-4 163 + md:max-w-2xl; 164 + 165 + p { 166 + @apply text-center 167 + text-sm 168 + text-neutral-800 169 + dark:text-neutral-200; 170 + } 171 + } 172 + } 173 + }
+7 -3
next.mdx.compiler.mjs
··· 1 1 'use strict'; 2 2 3 3 import { evaluate } from '@mdx-js/mdx'; 4 - import * as jsxRuntime from 'react/jsx-runtime'; 4 + import { Fragment, jsx, jsxs } from 'react/jsx-runtime'; 5 5 import { matter } from 'vfile-matter'; 6 6 7 7 import { NEXT_REHYPE_PLUGINS, NEXT_REMARK_PLUGINS } from './next.mdx.mjs'; 8 8 import { createGitHubSlug } from './util/gitHubUtils'; 9 + 10 + // Defines the React Runtime Components 11 + const reactRuntime = { Fragment, jsx, jsxs }; 9 12 10 13 /** 11 14 * This is our custom simple MDX Compiler that is used to compile Markdown and MDX ··· 31 34 rehypePlugins: NEXT_REHYPE_PLUGINS, 32 35 remarkPlugins: NEXT_REMARK_PLUGINS, 33 36 format: fileExtension, 34 - // Provide the JSX Runtime to the MDX Compiler 35 - ...jsxRuntime, 37 + baseUrl: import.meta.url, 38 + jsxRuntime: 'automatic', 39 + ...reactRuntime, 36 40 }); 37 41 38 42 // Retrieve some parsed data from the VFile metadata
+4 -1
next.mdx.mjs
··· 17 17 // Generates `id` attributes for headings (H1, ...) 18 18 rehypeSlug, 19 19 // Automatically add anchor links to headings (H1, ...) 20 - [rehypeAutolinkHeadings, { properties: { tabIndex: -1, class: 'anchor' } }], 20 + [ 21 + rehypeAutolinkHeadings, 22 + { properties: { ariaHidden: true, tabIndex: -1, class: 'anchor' } }, 23 + ], 21 24 // Transforms sequential code elements into code tabs and 22 25 // adds our syntax highlighter (Shikiji) to Codeboxes 23 26 rehypeShikiji,
+20 -15
next.mdx.shiki.mjs
··· 2 2 3 3 import classNames from 'classnames'; 4 4 import { toString } from 'hast-util-to-string'; 5 - import { getHighlighterCore } from 'shikiji/core'; 6 - import { getWasmInlined } from 'shikiji/wasm'; 7 5 import { SKIP, visit } from 'unist-util-visit'; 8 6 9 - import { LANGUAGES, DEFAULT_THEME } from './shiki.config.mjs'; 10 - 11 - // This creates a memoized minimal Shikiji Syntax Highlighter 12 - const memoizedShikiji = await getHighlighterCore({ 13 - themes: [DEFAULT_THEME], 14 - langs: LANGUAGES, 15 - loadWasm: getWasmInlined, 16 - }); 7 + import { highlightToHast } from './util/getHighlighter'; 17 8 18 9 // This is what Remark will use as prefix within a <pre> className 19 10 // to attribute the current language of the <pre> element ··· 115 106 const displayNames = []; 116 107 const codeTabsChildren = []; 117 108 109 + let defaultTab = '0'; 110 + 118 111 visit(slicedTree, 'element', node => { 119 112 const codeElement = node.children[0]; 120 113 ··· 135 128 displayNames.push(displayName?.replaceAll('|', '') ?? ''); 136 129 codeTabsChildren.push(node); 137 130 131 + // If `active="true"` is provided in a CodeBox 132 + // then the default selected entry of the CodeTabs will be the desired entry 133 + const specificActive = getMetaParameter( 134 + codeElement.data?.meta, 135 + 'active' 136 + ); 137 + 138 + if (specificActive === 'true') { 139 + defaultTab = String(codeTabsChildren.length - 1); 140 + } 141 + 138 142 // Prevent visiting the code block children 139 143 return SKIP; 140 144 }); ··· 157 161 properties: { 158 162 languages: languages.join('|'), 159 163 displayNames: displayNames.join('|'), 164 + defaultTab, 160 165 }, 161 166 }); 162 167 } ··· 210 215 const languageId = codeLanguage.slice(languagePrefix.length); 211 216 212 217 // Parses the <pre> contents and returns a HAST tree with the highlighted code 213 - const { children } = memoizedShikiji.codeToHast(preElementContents, { 214 - theme: DEFAULT_THEME, 215 - lang: languageId, 216 - }); 218 + const { children } = highlightToHast(preElementContents, languageId); 217 219 218 220 // Adds the original language back to the <pre> element 219 221 children[0].properties.class = classNames( ··· 227 229 ); 228 230 229 231 // Adds a Copy Button to the CodeBox if requested as an additional parameter 230 - children[0].properties.showCopyButton = showCopyButton === 'true'; 232 + // And avoids setting the property (overriding) if undefined or invalid value 233 + if (showCopyButton && ['true', 'false'].includes(showCopyButton)) { 234 + children[0].properties.showCopyButton = showCopyButton; 235 + } 231 236 232 237 // Replaces the <pre> element with the updated one 233 238 parent.children.splice(index, 1, ...children);
+21 -5
next.mdx.use.mjs
··· 1 1 'use strict'; 2 2 3 3 import Blockquote from './components/Common/Blockquote'; 4 + import Button from './components/Common/Button'; 5 + import DownloadButton from './components/Downloads/DownloadButton'; 4 6 import DownloadReleasesTable from './components/Downloads/DownloadReleasesTable'; 5 - import Banner from './components/Home/Banner'; 6 7 import HomeDownloadButton from './components/Home/HomeDownloadButton'; 7 8 import Link from './components/Link'; 8 9 import MDXCodeBox from './components/MDX/CodeBox'; 9 10 import MDXCodeTabs from './components/MDX/CodeTabs'; 11 + import WithBadge from './components/withBadge'; 12 + import WithBanner from './components/withBanner'; 10 13 import WithNodeRelease from './components/withNodeRelease'; 11 14 import { ENABLE_WEBSITE_REDESIGN } from './next.constants.mjs'; 12 15 ··· 16 19 * @type {import('mdx/types').MDXComponents} 17 20 */ 18 21 export const mdxComponents = { 19 - WithNodeRelease, 20 - HomeDownloadButton, 21 - DownloadReleasesTable, 22 + // Legacy Component 23 + HomeDownloadButton: HomeDownloadButton, 24 + // Legacy Component 25 + DownloadReleasesTable: DownloadReleasesTable, 26 + // HOC for getting Node.js Release Metadata 27 + WithNodeRelease: WithNodeRelease, 28 + // HOC for providing Banner Data 29 + WithBanner: WithBanner, 30 + // HOC for providing Badge Data 31 + WithBadge: WithBadge, 32 + // Renders MDX CodeTabs 22 33 CodeTabs: MDXCodeTabs, 23 - Banner, 34 + // Renders a Download Button 35 + DownloadButton: DownloadButton, 36 + // Renders a Button Component for `button` tags 37 + Button: Button, 24 38 }; 25 39 26 40 /** ··· 29 43 * @type {import('mdx/types').MDXComponents} 30 44 */ 31 45 export const htmlComponents = { 46 + // Renders a Link Component for `a` tags 32 47 a: Link, 33 48 // @deprecated once the website redesign happens 34 49 // switch to only use the Blockquote Component 35 50 blockquote: ENABLE_WEBSITE_REDESIGN 36 51 ? Blockquote 37 52 : ({ children }) => <div className="highlight-box">{children}</div>, 53 + // Renders a CodeBox Component for `pre` tags 38 54 pre: ({ children, ...props }) => ( 39 55 <MDXCodeBox {...props}>{children}</MDXCodeBox> 40 56 ),
+19 -7
next.rewrites.mjs
··· 1 1 'use strict'; 2 2 3 + import { ENABLE_WEBSITE_REDESIGN } from './next.constants.mjs'; 3 4 import { siteRedirects } from './next.json.mjs'; 4 5 import { availableLocaleCodes } from './next.locales.mjs'; 5 6 ··· 9 10 // Example: /:locale(ar/|ca/|de/|en/|es/|fa/|fr/|)about/security 10 11 // Would match /ar/about/security, /ar/about/security/ for every language code (replace "ar") and 11 12 // it would also match /about/security (without any language prefix) 12 - const localesMatch = `/:locale(${availableLocaleCodes.join('|')}|)?/`; 13 + const localesMatch = `/:locale(${availableLocaleCodes.join('|')}|)?`; 13 14 14 15 /** 15 16 * These are external redirects that happen before we check dynamic routes and rewrites ··· 20 21 */ 21 22 const redirects = async () => { 22 23 return siteRedirects.external.map(({ source, destination }) => ({ 23 - source: source.replace('/:locale/', localesMatch), 24 + source: source.replace('/:locale', localesMatch), 24 25 // We prevent permanent redirects as in general the redirects are safeguards 25 26 // of legacy or old pages or pages that moved, and in general we don't want permanent redirects 26 27 permanent: false, ··· 37 38 * @return {Promise<import('next').NextConfig['rewrites']>} 38 39 */ 39 40 const rewrites = async () => { 40 - return { 41 - afterFiles: siteRedirects.internal.map(({ source, destination }) => ({ 42 - source: source.replace('/:locale/', localesMatch), 41 + const mappedRewrites = siteRedirects.internal.map( 42 + ({ source, destination }) => ({ 43 + source: source.replace('/:locale', localesMatch), 43 44 destination, 44 - })), 45 - }; 45 + }) 46 + ); 47 + 48 + // This allows us to remap legacy website URLs to the temporary redesign ones 49 + // @todo: remove this once website redesign is done 50 + if (ENABLE_WEBSITE_REDESIGN) { 51 + mappedRewrites.push({ 52 + source: localesMatch, 53 + destination: '/:locale/new-design', 54 + }); 55 + } 56 + 57 + return { afterFiles: mappedRewrites }; 46 58 }; 47 59 48 60 export { rewrites, redirects };
+1 -1
pages/en/about/get-involved/collab-summit.md
··· 1 1 --- 2 2 title: Collab Summit 3 - layout: contribute.hbs 3 + layout: about.hbs 4 4 --- 5 5 6 6 # Collab Summit
+1 -1
pages/en/about/get-involved/contribute.md
··· 1 1 --- 2 2 title: Contributing 3 - layout: contribute.hbs 3 + layout: about.hbs 4 4 --- 5 5 6 6 # Contributing
+1 -1
pages/en/about/get-involved/index.md
··· 1 1 --- 2 2 title: Get involved 3 - layout: contribute.hbs 3 + layout: about.hbs 4 4 --- 5 5 6 6 # Get Involved
+2 -2
pages/en/about/security-reporting.mdx
··· 64 64 65 65 Security notifications will be distributed via the following methods. 66 66 67 - - [https://groups.google.com/group/nodejs-sec](https://groups.google.com/group/nodejs-sec) 68 - - [/blog/](/blog/) 67 + - [Google Group](https://groups.google.com/group/nodejs-sec) 68 + - [Node.js Blog](/blog) 69 69 70 70 ## Comments on this policy 71 71
+1 -1
pages/en/index.mdx
··· 4 4 5 5 Node.js® is an open-source, cross-platform JavaScript runtime environment. 6 6 7 - <Banner /> 7 + <WithBanner section="index" /> 8 8 9 9 <h2>Download Node.js®</h2> 10 10
+65
pages/en/new-design/index.mdx
··· 1 + --- 2 + layout: home.hbs 3 + --- 4 + 5 + <section> 6 + <WithBadge section="index" /> 7 + 8 + <div> 9 + # Run JavaScript Everywhere 10 + 11 + Node.js is a free, open-sourced, cross-platform JavaScript run-time 12 + environment that lets developers write command line tools and server-side 13 + scripts outside of a browser. 14 + 15 + </div> 16 + <div> 17 + <WithNodeRelease status={['Active LTS', 'Maintenance LTS']}> 18 + {({ release }) => ( 19 + <DownloadButton release={release}>Download Node.js (LTS)</DownloadButton> 20 + )} 21 + </WithNodeRelease> 22 + 23 + <Button kind="secondary" href="/learn">Get Started</Button> 24 + 25 + </div> 26 + </section> 27 + 28 + <section> 29 + <CodeTabs 30 + languages="bash|bash" 31 + displayNames="macOS / Linux (nvm)|Windows (Chocolatey)" 32 + linkUrl="/download/package-manager" 33 + linkText="More Options" 34 + > 35 + ```bash 36 + # Install Node Version Manager (NVM) 37 + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash 38 + 39 + # Install Node.js 40 + nvm install --lts 41 + 42 + # Check that Node is installed 43 + node -v 44 + 45 + # Check your NPM version 46 + npm -v 47 + ``` 48 + 49 + ```bash 50 + # Install Chocolatey 51 + iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) 52 + 53 + # Install Node.js 54 + choco install nodejs-lts 55 + 56 + # Check that Node is installed 57 + node -v 58 + 59 + # Check your NPM version 60 + npm -v 61 + ``` 62 + 63 + </CodeTabs> 64 + Copy and paste this snippet to install Node.js LTS via a Package Manager 65 + </section>
+551 -138
public/static/images/patterns/hexagon-grid.svg
··· 6 6 <g mask="url(#mask0_91_8)"> 7 7 <path 8 8 d="M717.133 231.367L759.799 206.733L802.465 231.367V280.633L759.799 305.267L717.133 280.633V231.367Z" 9 - stroke="white" stroke-width="1.27" /> 9 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 10 + <path 11 + d="M760.432 306.367L803.099 281.733L845.765 306.367V355.633L803.099 380.267L760.432 355.633V306.367Z" 12 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 13 + <path 14 + d="M803.732 231.367L846.398 206.733L889.065 231.367V280.633L846.398 305.267L803.732 280.633V231.367Z" 15 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 16 + <path 17 + d="M847.032 306.367L889.698 281.733L932.365 306.367V355.633L889.698 380.267L847.032 355.633V306.367Z" 18 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 19 + <path 20 + d="M890.332 381.367L932.998 356.733L975.664 381.367V430.633L932.998 455.267L890.332 430.633V381.367Z" 21 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 22 + <path 23 + d="M933.632 306.367L976.298 281.733L1018.96 306.367V355.633L976.298 380.267L933.632 355.633V306.367Z" 24 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 25 + <path 26 + d="M587.233 306.367L629.899 281.733L672.566 306.367V355.633L629.899 380.267L587.233 355.633V306.367Z" 27 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 28 + <path 29 + d="M630.533 381.367L673.199 356.733L715.865 381.367V430.633L673.199 455.267L630.533 430.633V381.367Z" 30 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 31 + <path 32 + d="M673.833 306.367L716.499 281.733L759.165 306.367V355.633L716.499 380.267L673.833 355.633V306.367Z" 33 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 34 + <path 35 + d="M717.133 381.367L759.799 356.733L802.465 381.367V430.633L759.799 455.267L717.133 430.633V381.367Z" 36 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 37 + <path 38 + d="M760.432 456.367L803.099 431.733L845.765 456.367V505.633L803.099 530.267L760.432 505.633V456.367Z" 39 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 40 + <path 41 + d="M803.732 381.367L846.398 356.733L889.065 381.367V430.633L846.398 455.267L803.732 430.633V381.367Z" 42 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 43 + <path 44 + d="M976.931 381.367L1019.6 356.733L1062.26 381.367V430.633L1019.6 455.267L976.931 430.633V381.367Z" 45 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 46 + <path 47 + d="M1020.23 456.367L1062.9 431.733L1105.56 456.367V505.633L1062.9 530.267L1020.23 505.633V456.367Z" 48 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 49 + <path 50 + d="M1063.53 381.367L1106.2 356.733L1148.86 381.367V430.633L1106.2 455.267L1063.53 430.633V381.367Z" 51 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 52 + <path 53 + d="M1106.83 456.367L1149.5 431.733L1192.16 456.367V505.633L1149.5 530.267L1106.83 505.633V456.367Z" 54 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 55 + <path 56 + d="M1150.13 531.367L1192.8 506.733L1235.46 531.367V580.633L1192.8 605.267L1150.13 580.633V531.367Z" 57 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 58 + <path 59 + d="M1193.43 456.367L1236.1 431.733L1278.76 456.367V505.633L1236.1 530.267L1193.43 505.633V456.367Z" 60 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 61 + <path 62 + d="M847.032 456.367L889.698 431.733L932.365 456.367V505.633L889.698 530.267L847.032 505.633V456.367Z" 63 + fill="white" fill-opacity="0.25" stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 64 + <path 65 + d="M890.332 531.367L932.998 506.733L975.664 531.367V580.633L932.998 605.267L890.332 580.633V531.367Z" 66 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 67 + <path 68 + d="M933.632 456.367L976.298 431.733L1018.96 456.367V505.633L976.298 530.267L933.632 505.633V456.367Z" 69 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 70 + <path 71 + d="M976.931 531.367L1019.6 506.733L1062.26 531.367V580.633L1019.6 605.267L976.931 580.633V531.367Z" 72 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 73 + <path 74 + d="M1020.23 606.367L1062.9 581.733L1105.56 606.367V655.633L1062.9 680.267L1020.23 655.633V606.367Z" 75 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 76 + <path 77 + d="M1063.53 531.367L1106.2 506.733L1148.86 531.367V580.633L1106.2 605.267L1063.53 580.633V531.367Z" 78 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 79 + <path 80 + d="M976.931 81.3666L1019.6 56.7332L1062.26 81.3666V130.633L1019.6 155.267L976.931 130.633V81.3666Z" 81 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 82 + <path 83 + d="M1020.23 156.367L1062.9 131.733L1105.56 156.367V205.633L1062.9 230.267L1020.23 205.633V156.367Z" 84 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 85 + <path 86 + d="M1063.53 81.3666L1106.2 56.7332L1148.86 81.3666V130.633L1106.2 155.267L1063.53 130.633V81.3666Z" 87 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 88 + <path 89 + d="M1106.83 156.367L1149.5 131.733L1192.16 156.367V205.633L1149.5 230.267L1106.83 205.633V156.367Z" 90 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 91 + <path 92 + d="M1150.13 231.367L1192.8 206.733L1235.46 231.367V280.633L1192.8 305.267L1150.13 280.633V231.367Z" 93 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 94 + <path 95 + d="M1193.43 156.367L1236.1 131.733L1278.76 156.367V205.633L1236.1 230.267L1193.43 205.633V156.367Z" 96 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 97 + <path 98 + d="M847.032 156.367L889.698 131.733L932.365 156.367V205.633L889.698 230.267L847.032 205.633V156.367Z" 99 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 100 + <path 101 + d="M890.332 231.367L932.998 206.733L975.664 231.367V280.633L932.998 305.267L890.332 280.633V231.367Z" 102 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 103 + <path 104 + d="M933.632 156.367L976.298 131.733L1018.96 156.367V205.633L976.298 230.267L933.632 205.633V156.367Z" 105 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 106 + <path 107 + d="M976.931 231.367L1019.6 206.733L1062.26 231.367V280.633L1019.6 305.267L976.931 280.633V231.367Z" 108 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 109 + <path 110 + d="M1020.23 306.367L1062.9 281.733L1105.56 306.367V355.633L1062.9 380.267L1020.23 355.633V306.367Z" 111 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 112 + <path 113 + d="M1063.53 231.367L1106.2 206.733L1148.86 231.367V280.633L1106.2 305.267L1063.53 280.633V231.367Z" 114 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 115 + <path 116 + d="M1106.83 306.367L1149.5 281.733L1192.16 306.367V355.633L1149.5 380.267L1106.83 355.633V306.367Z" 117 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 118 + <path 119 + d="M1150.13 381.367L1192.8 356.733L1235.46 381.367V430.633L1192.8 455.267L1150.13 430.633V381.367Z" 120 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 121 + <path 122 + d="M1193.43 306.367L1236.1 281.733L1278.76 306.367V355.633L1236.1 380.267L1193.43 355.633V306.367Z" 123 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 124 + <path 125 + d="M240.523 6.36671L283.211 -18.2669L325.899 6.36671V55.6333L283.211 80.2669L240.523 55.6333V6.36671Z" 126 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 127 + <path 128 + d="M327.167 6.36671L369.855 -18.2669L412.543 6.36671V55.6333L369.855 80.2669L327.167 55.6333V6.36671Z" 129 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 130 + <path 131 + d="M370.486 81.3667L413.174 56.7331L455.862 81.3667V130.633L413.174 155.267L370.486 130.633V81.3667Z" 132 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 133 + <path 134 + d="M413.81 6.36671L456.498 -18.2669L499.186 6.36671V55.6333L456.498 80.2669L413.81 55.6333V6.36671Z" 135 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 136 + <path 137 + d="M67.2365 6.36671L109.925 -18.2669L152.613 6.36671V55.6333L109.925 80.2669L67.2365 55.6333V6.36671Z" 138 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 139 + <path 140 + d="M110.558 81.3667L153.246 56.7331L195.934 81.3667V130.633L153.246 155.267L110.558 130.633V81.3667Z" 141 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 142 + <path 143 + d="M153.88 6.36671L196.568 -18.2669L239.256 6.36671V55.6333L196.568 80.2669L153.88 55.6333V6.36671Z" 144 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 145 + <path 146 + d="M197.201 81.3667L239.889 56.7331L282.577 81.3667V130.633L239.889 155.267L197.201 130.633V81.3667Z" 147 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 148 + <path 149 + d="M240.523 156.367L283.211 131.733L325.899 156.367V205.633L283.211 230.267L240.523 205.633V156.367Z" 150 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 151 + <path 152 + d="M283.845 81.3667L326.533 56.7331L369.221 81.3667V130.633L326.533 155.267L283.845 130.633V81.3667Z" 153 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 154 + <path 155 + d="M457.13 81.3667L499.818 56.7331L542.506 81.3667V130.633L499.818 155.267L457.13 130.633V81.3667Z" 156 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 157 + <path 158 + d="M500.452 156.367L543.14 131.733L585.828 156.367V205.633L543.14 230.267L500.452 205.633V156.367Z" 159 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 160 + <path 161 + d="M543.775 81.3667L586.463 56.7331L629.151 81.3667V130.633L586.463 155.267L543.775 130.633V81.3667Z" 162 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 163 + <path 164 + d="M587.095 156.367L629.783 131.733L672.471 156.367V205.633L629.783 230.267L587.095 205.633V156.367Z" 165 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 166 + <path 167 + d="M630.416 231.367L673.104 206.733L715.792 231.367V280.633L673.104 305.267L630.416 280.633V231.367Z" 168 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 169 + <path 170 + d="M673.738 156.367L716.426 131.733L759.114 156.367V205.633L716.426 230.267L673.738 205.633V156.367Z" 171 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 172 + <path 173 + d="M327.167 156.367L369.855 131.733L412.543 156.367V205.633L369.855 230.267L327.167 205.633V156.367Z" 174 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 175 + <path 176 + d="M370.486 231.367L413.174 206.733L455.862 231.367V280.633L413.174 305.267L370.486 280.633V231.367Z" 177 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 178 + <path 179 + d="M413.81 156.367L456.498 131.733L499.186 156.367V205.633L456.498 230.267L413.81 205.633V156.367Z" 180 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 181 + <path 182 + d="M457.13 231.367L499.818 206.733L542.506 231.367V280.633L499.818 305.267L457.13 280.633V231.367Z" 183 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 184 + <path 185 + d="M500.452 306.367L543.14 281.733L585.828 306.367V355.633L543.14 380.267L500.452 355.633V306.367Z" 186 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 187 + <path 188 + d="M543.775 231.367L586.463 206.733L629.151 231.367V280.633L586.463 305.267L543.775 280.633V231.367Z" 189 + fill="white" fill-opacity="0.25" stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 190 + <path 191 + d="M500.452 6.36671L543.14 -18.2669L585.828 6.36671V55.6333L543.14 80.2669L500.452 55.6333V6.36671Z" 192 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 193 + <path 194 + d="M760.383 6.36671L803.071 -18.2669L845.759 6.36671V55.6333L803.071 80.2669L760.383 55.6333V6.36671Z" 195 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 196 + <path 197 + d="M847.026 6.36671L889.714 -18.2669L932.402 6.36671V55.6333L889.714 80.2669L847.026 55.6333V6.36671Z" 198 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 199 + <path 200 + d="M890.348 81.3667L933.036 56.7331L975.724 81.3667V130.633L933.036 155.267L890.348 130.633V81.3667Z" 201 + fill="white" fill-opacity="0.25" stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 202 + <path 203 + d="M933.667 6.36671L976.355 -18.2669L1019.04 6.36671V55.6333L976.355 80.2669L933.667 55.6333V6.36671Z" 204 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 205 + <path 206 + d="M587.095 6.36671L629.783 -18.2669L672.471 6.36671V55.6333L629.783 80.2669L587.095 55.6333V6.36671Z" 207 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 208 + <path 209 + d="M630.416 81.3667L673.104 56.7331L715.792 81.3667V130.633L673.104 155.267L630.416 130.633V81.3667Z" 210 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 211 + <path 212 + d="M673.738 6.36671L716.426 -18.2669L759.114 6.36671V55.6333L716.426 80.2669L673.738 55.6333V6.36671Z" 213 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 214 + <path 215 + d="M717.061 81.3667L759.749 56.7331L802.437 81.3667V130.633L759.749 155.267L717.061 130.633V81.3667Z" 216 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 217 + <path 218 + d="M760.383 156.367L803.071 131.733L845.759 156.367V205.633L803.071 230.267L760.383 205.633V156.367Z" 219 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 220 + <path 221 + d="M803.702 81.3667L846.39 56.7331L889.078 81.3667V130.633L846.39 155.267L803.702 130.633V81.3667Z" 222 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 223 + <path 224 + d="M327.233 606.367L369.899 581.733L412.566 606.367V655.633L369.899 680.267L327.233 655.633V606.367Z" 225 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 226 + <path 227 + d="M370.533 681.367L413.199 656.733L455.865 681.367V730.633L413.199 755.267L370.533 730.633V681.367Z" 228 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 229 + <path 230 + d="M413.833 606.367L456.499 581.733L499.165 606.367V655.633L456.499 680.267L413.833 655.633V606.367Z" 231 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 232 + <path 233 + d="M457.133 681.367L499.799 656.733L542.465 681.367V730.633L499.799 755.267L457.133 730.633V681.367Z" 234 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 235 + <path 236 + d="M543.732 681.367L586.398 656.733L629.065 681.367V730.633L586.398 755.267L543.732 730.633V681.367Z" 237 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 238 + <path 239 + d="M197.334 681.367L240 656.733L282.666 681.367V730.633L240 755.267L197.334 730.633V681.367Z" 240 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 241 + <path 242 + d="M283.933 681.367L326.6 656.733L369.266 681.367V730.633L326.6 755.267L283.933 730.633V681.367Z" 243 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 244 + <path 245 + d="M587.032 456.367L629.698 431.733L672.365 456.367V505.633L629.698 530.267L587.032 505.633V456.367Z" 246 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 247 + <path 248 + d="M630.332 531.367L672.998 506.733L715.664 531.367V580.633L672.998 605.267L630.332 580.633V531.367Z" 249 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 250 + <path 251 + d="M673.632 456.367L716.298 431.733L758.964 456.367V505.633L716.298 530.267L673.632 505.633V456.367Z" 252 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 253 + <path 254 + d="M716.931 531.367L759.598 506.733L802.264 531.367V580.633L759.598 605.267L716.931 580.633V531.367Z" 255 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 256 + <path 257 + d="M760.231 606.367L802.897 581.733L845.564 606.367V655.633L802.897 680.267L760.231 655.633V606.367Z" 258 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 259 + <path 260 + d="M803.531 531.367L846.197 506.733L888.864 531.367V580.633L846.197 605.267L803.531 580.633V531.367Z" 261 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 262 + <path 263 + d="M457.133 531.367L499.799 506.733L542.465 531.367V580.633L499.799 605.267L457.133 580.633V531.367Z" 264 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 265 + <path 266 + d="M500.432 606.367L543.099 581.733L585.765 606.367V655.633L543.099 680.267L500.432 655.633V606.367Z" 267 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 268 + <path 269 + d="M543.732 531.367L586.398 506.733L629.065 531.367V580.633L586.398 605.267L543.732 580.633V531.367Z" 270 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 271 + <path 272 + d="M587.032 606.367L629.698 581.733L672.365 606.367V655.633L629.698 680.267L587.032 655.633V606.367Z" 273 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 274 + <path 275 + d="M630.332 681.367L672.998 656.733L715.664 681.367V730.633L672.998 755.267L630.332 730.633V681.367Z" 276 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 277 + <path 278 + d="M673.632 606.367L716.298 581.733L758.964 606.367V655.633L716.298 680.267L673.632 655.633V606.367Z" 279 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 280 + <path 281 + d="M846.831 606.367L889.497 581.733L932.163 606.367V655.633L889.497 680.267L846.831 655.633V606.367Z" 282 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 283 + <path 284 + d="M890.131 681.367L932.797 656.733L975.463 681.367V730.633L932.797 755.267L890.131 730.633V681.367Z" 285 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 286 + <path 287 + d="M933.43 606.367L976.097 581.733L1018.76 606.367V655.633L976.097 680.267L933.43 655.633V606.367Z" 288 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 289 + <path 290 + d="M976.73 681.367L1019.4 656.733L1062.06 681.367V730.633L1019.4 755.267L976.73 730.633V681.367Z" 291 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 292 + <path 293 + d="M1063.33 681.367L1106 656.733L1148.66 681.367V730.633L1106 755.267L1063.33 730.633V681.367Z" 294 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 295 + <path 296 + d="M716.931 681.367L759.598 656.733L802.264 681.367V730.633L759.598 755.267L716.931 730.633V681.367Z" 297 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 298 + <path 299 + d="M803.531 681.367L846.197 656.733L888.864 681.367V730.633L846.197 755.267L803.531 730.633V681.367Z" 300 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 301 + <path 302 + d="M-62.7322 381.367L-20.0442 356.733L22.6438 381.367V430.633L-20.0442 455.267L-62.7322 430.633V381.367Z" 303 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 304 + <path 305 + d="M-19.4139 456.367L23.2741 431.733L65.9621 456.367V505.633L23.2741 530.267L-19.4139 505.633V456.367Z" 306 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 307 + <path 308 + d="M23.9103 381.367L66.5983 356.733L109.286 381.367V430.633L66.5983 455.267L23.9103 430.633V381.367Z" 309 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 310 + <path 311 + d="M67.2306 456.367L109.919 431.733L152.607 456.367V505.633L109.919 530.267L67.2306 505.633V456.367Z" 312 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 313 + <path 314 + d="M110.553 531.367L153.241 506.733L195.929 531.367V580.633L153.241 605.267L110.553 580.633V531.367Z" 315 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 316 + <path 317 + d="M153.875 456.367L196.563 431.733L239.251 456.367V505.633L196.563 530.267L153.875 505.633V456.367Z" 318 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 319 + <path 320 + d="M197.195 531.367L239.884 506.733L282.572 531.367V580.633L239.884 605.267L197.195 580.633V531.367Z" 321 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 322 + <path 323 + d="M240.517 606.367L283.205 581.733L325.893 606.367V655.633L283.205 680.267L240.517 655.633V606.367Z" 324 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 325 + <path 326 + d="M283.839 531.367L326.527 506.733L369.215 531.367V580.633L326.527 605.267L283.839 580.633V531.367Z" 327 + fill="white" fill-opacity="0.25" stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 328 + <path 329 + d="M-62.7322 531.367L-20.0442 506.733L22.6438 531.367V580.633L-20.0442 605.267L-62.7322 580.633V531.367Z" 330 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 331 + <path 332 + d="M-19.4139 606.367L23.2741 581.733L65.9621 606.367V655.633L23.2741 680.267L-19.4139 655.633V606.367Z" 333 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 334 + <path 335 + d="M23.9103 531.367L66.5983 506.733L109.286 531.367V580.633L66.5983 605.267L23.9103 580.633V531.367Z" 336 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 337 + <path 338 + d="M67.2306 606.367L109.919 581.733L152.607 606.367V655.633L109.919 680.267L67.2306 655.633V606.367Z" 339 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 340 + <path 341 + d="M110.553 681.367L153.241 656.733L195.929 681.367V730.633L153.241 755.267L110.553 730.633V681.367Z" 342 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 343 + <path 344 + d="M153.875 606.367L196.563 581.733L239.251 606.367V655.633L196.563 680.267L153.875 655.633V606.367Z" 345 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 346 + <path 347 + d="M67.2306 156.367L109.919 131.733L152.607 156.367V205.633L109.919 230.267L67.2306 205.633V156.367Z" 348 + fill="white" fill-opacity="0.25" stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 349 + <path 350 + d="M110.553 231.367L153.241 206.733L195.929 231.367V280.633L153.241 305.267L110.553 280.633V231.367Z" 351 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 352 + <path 353 + d="M153.875 156.367L196.563 131.733L239.251 156.367V205.633L196.563 230.267L153.875 205.633V156.367Z" 354 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 355 + <path 356 + d="M197.195 231.367L239.884 206.733L282.572 231.367V280.633L239.884 305.267L197.195 280.633V231.367Z" 357 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 358 + <path 359 + d="M240.517 306.367L283.205 281.733L325.893 306.367V355.633L283.205 380.267L240.517 355.633V306.367Z" 360 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 361 + <path 362 + d="M283.839 231.367L326.527 206.733L369.215 231.367V280.633L326.527 305.267L283.839 280.633V231.367Z" 363 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 364 + <path 365 + d="M-62.7322 231.367L-20.0442 206.733L22.6438 231.367V280.633L-20.0442 305.267L-62.7322 280.633V231.367Z" 366 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 367 + <path 368 + d="M-19.4139 306.367L23.2741 281.733L65.9621 306.367V355.633L23.2741 380.267L-19.4139 355.633V306.367Z" 369 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 370 + <path 371 + d="M23.9103 231.367L66.5983 206.733L109.286 231.367V280.633L66.5983 305.267L23.9103 280.633V231.367Z" 372 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 373 + <path 374 + d="M67.2306 306.367L109.919 281.733L152.607 306.367V355.633L109.919 380.267L67.2306 355.633V306.367Z" 375 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 376 + <path 377 + d="M110.553 381.367L153.241 356.733L195.929 381.367V430.633L153.241 455.267L110.553 430.633V381.367Z" 378 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 379 + <path 380 + d="M153.875 306.367L196.563 281.733L239.251 306.367V355.633L196.563 380.267L153.875 355.633V306.367Z" 381 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 382 + <path 383 + d="M327.161 306.367L369.849 281.733L412.537 306.367V355.633L369.849 380.267L327.161 355.633V306.367Z" 384 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 385 + <path 386 + d="M370.484 381.367L413.172 356.733L455.86 381.367V430.633L413.172 455.267L370.484 430.633V381.367Z" 387 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 388 + <path 389 + d="M413.803 306.367L456.491 281.733L499.179 306.367V355.633L456.491 380.267L413.803 355.633V306.367Z" 390 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 391 + <path 392 + d="M457.126 381.367L499.814 356.733L542.502 381.367V430.633L499.814 455.267L457.126 430.633V381.367Z" 393 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 394 + <path 395 + d="M500.448 456.367L543.136 431.733L585.824 456.367V505.633L543.136 530.267L500.448 505.633V456.367Z" 396 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 397 + <path 398 + d="M543.768 381.367L586.456 356.733L629.144 381.367V430.633L586.456 455.267L543.768 430.633V381.367Z" 399 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 400 + <path 401 + d="M197.195 381.367L239.884 356.733L282.572 381.367V430.633L239.884 455.267L197.195 430.633V381.367Z" 402 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 403 + <path 404 + d="M240.517 456.367L283.205 431.733L325.893 456.367V505.633L283.205 530.267L240.517 505.633V456.367Z" 405 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 406 + <path 407 + d="M283.839 381.367L326.527 356.733L369.215 381.367V430.633L326.527 455.267L283.839 430.633V381.367Z" 408 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 409 + <path 410 + d="M327.161 456.367L369.849 431.733L412.537 456.367V505.633L369.849 530.267L327.161 505.633V456.367Z" 411 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 412 + <path 413 + d="M370.484 531.367L413.172 506.733L455.86 531.367V580.633L413.172 605.267L370.484 580.633V531.367Z" 414 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 415 + <path 416 + d="M413.803 456.367L456.491 431.733L499.179 456.367V505.633L456.491 530.267L413.803 505.633V456.367Z" 417 + stroke="rgba(255, 255, 255, 0.50)" stroke-width="1.27" /> 418 + </g> 419 + <g mask="url(#mask0_91_8)"> 420 + <path 421 + d="M717.133 231.367L759.799 206.733L802.465 231.367V280.633L759.799 305.267L717.133 280.633V231.367Z" 422 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 10 423 <path 11 424 d="M760.432 306.367L803.099 281.733L845.765 306.367V355.633L803.099 380.267L760.432 355.633V306.367Z" 12 - stroke="white" stroke-width="1.27" /> 425 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 13 426 <path 14 427 d="M803.732 231.367L846.398 206.733L889.065 231.367V280.633L846.398 305.267L803.732 280.633V231.367Z" 15 - stroke="white" stroke-width="1.27" /> 428 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 16 429 <path 17 430 d="M847.032 306.367L889.698 281.733L932.365 306.367V355.633L889.698 380.267L847.032 355.633V306.367Z" 18 - stroke="white" stroke-width="1.27" /> 431 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 19 432 <path 20 433 d="M890.332 381.367L932.998 356.733L975.664 381.367V430.633L932.998 455.267L890.332 430.633V381.367Z" 21 - stroke="white" stroke-width="1.27" /> 434 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 22 435 <path 23 436 d="M933.632 306.367L976.298 281.733L1018.96 306.367V355.633L976.298 380.267L933.632 355.633V306.367Z" 24 - stroke="white" stroke-width="1.27" /> 437 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 25 438 <path 26 439 d="M587.233 306.367L629.899 281.733L672.566 306.367V355.633L629.899 380.267L587.233 355.633V306.367Z" 27 - stroke="white" stroke-width="1.27" /> 440 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 28 441 <path 29 442 d="M630.533 381.367L673.199 356.733L715.865 381.367V430.633L673.199 455.267L630.533 430.633V381.367Z" 30 - stroke="white" stroke-width="1.27" /> 443 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 31 444 <path 32 445 d="M673.833 306.367L716.499 281.733L759.165 306.367V355.633L716.499 380.267L673.833 355.633V306.367Z" 33 - stroke="white" stroke-width="1.27" /> 446 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 34 447 <path 35 448 d="M717.133 381.367L759.799 356.733L802.465 381.367V430.633L759.799 455.267L717.133 430.633V381.367Z" 36 - stroke="white" stroke-width="1.27" /> 449 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 37 450 <path 38 451 d="M760.432 456.367L803.099 431.733L845.765 456.367V505.633L803.099 530.267L760.432 505.633V456.367Z" 39 - stroke="white" stroke-width="1.27" /> 452 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 40 453 <path 41 454 d="M803.732 381.367L846.398 356.733L889.065 381.367V430.633L846.398 455.267L803.732 430.633V381.367Z" 42 - stroke="white" stroke-width="1.27" /> 455 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 43 456 <path 44 457 d="M976.931 381.367L1019.6 356.733L1062.26 381.367V430.633L1019.6 455.267L976.931 430.633V381.367Z" 45 - stroke="white" stroke-width="1.27" /> 458 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 46 459 <path 47 460 d="M1020.23 456.367L1062.9 431.733L1105.56 456.367V505.633L1062.9 530.267L1020.23 505.633V456.367Z" 48 - stroke="white" stroke-width="1.27" /> 461 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 49 462 <path 50 463 d="M1063.53 381.367L1106.2 356.733L1148.86 381.367V430.633L1106.2 455.267L1063.53 430.633V381.367Z" 51 - stroke="white" stroke-width="1.27" /> 464 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 52 465 <path 53 466 d="M1106.83 456.367L1149.5 431.733L1192.16 456.367V505.633L1149.5 530.267L1106.83 505.633V456.367Z" 54 - stroke="white" stroke-width="1.27" /> 467 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 55 468 <path 56 469 d="M1150.13 531.367L1192.8 506.733L1235.46 531.367V580.633L1192.8 605.267L1150.13 580.633V531.367Z" 57 - stroke="white" stroke-width="1.27" /> 470 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 58 471 <path 59 472 d="M1193.43 456.367L1236.1 431.733L1278.76 456.367V505.633L1236.1 530.267L1193.43 505.633V456.367Z" 60 - stroke="white" stroke-width="1.27" /> 473 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 61 474 <path 62 475 d="M847.032 456.367L889.698 431.733L932.365 456.367V505.633L889.698 530.267L847.032 505.633V456.367Z" 63 - fill="white" fill-opacity="0.25" stroke="white" stroke-width="1.27" /> 476 + fill="white" fill-opacity="0.25" stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 64 477 <path 65 478 d="M890.332 531.367L932.998 506.733L975.664 531.367V580.633L932.998 605.267L890.332 580.633V531.367Z" 66 - stroke="white" stroke-width="1.27" /> 479 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 67 480 <path 68 481 d="M933.632 456.367L976.298 431.733L1018.96 456.367V505.633L976.298 530.267L933.632 505.633V456.367Z" 69 - stroke="white" stroke-width="1.27" /> 482 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 70 483 <path 71 484 d="M976.931 531.367L1019.6 506.733L1062.26 531.367V580.633L1019.6 605.267L976.931 580.633V531.367Z" 72 - stroke="white" stroke-width="1.27" /> 485 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 73 486 <path 74 487 d="M1020.23 606.367L1062.9 581.733L1105.56 606.367V655.633L1062.9 680.267L1020.23 655.633V606.367Z" 75 - stroke="white" stroke-width="1.27" /> 488 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 76 489 <path 77 490 d="M1063.53 531.367L1106.2 506.733L1148.86 531.367V580.633L1106.2 605.267L1063.53 580.633V531.367Z" 78 - stroke="white" stroke-width="1.27" /> 491 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 79 492 <path 80 493 d="M976.931 81.3666L1019.6 56.7332L1062.26 81.3666V130.633L1019.6 155.267L976.931 130.633V81.3666Z" 81 - stroke="white" stroke-width="1.27" /> 494 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 82 495 <path 83 496 d="M1020.23 156.367L1062.9 131.733L1105.56 156.367V205.633L1062.9 230.267L1020.23 205.633V156.367Z" 84 - stroke="white" stroke-width="1.27" /> 497 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 85 498 <path 86 499 d="M1063.53 81.3666L1106.2 56.7332L1148.86 81.3666V130.633L1106.2 155.267L1063.53 130.633V81.3666Z" 87 - stroke="white" stroke-width="1.27" /> 500 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 88 501 <path 89 502 d="M1106.83 156.367L1149.5 131.733L1192.16 156.367V205.633L1149.5 230.267L1106.83 205.633V156.367Z" 90 - stroke="white" stroke-width="1.27" /> 503 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 91 504 <path 92 505 d="M1150.13 231.367L1192.8 206.733L1235.46 231.367V280.633L1192.8 305.267L1150.13 280.633V231.367Z" 93 - stroke="white" stroke-width="1.27" /> 506 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 94 507 <path 95 508 d="M1193.43 156.367L1236.1 131.733L1278.76 156.367V205.633L1236.1 230.267L1193.43 205.633V156.367Z" 96 - stroke="white" stroke-width="1.27" /> 509 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 97 510 <path 98 511 d="M847.032 156.367L889.698 131.733L932.365 156.367V205.633L889.698 230.267L847.032 205.633V156.367Z" 99 - stroke="white" stroke-width="1.27" /> 512 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 100 513 <path 101 514 d="M890.332 231.367L932.998 206.733L975.664 231.367V280.633L932.998 305.267L890.332 280.633V231.367Z" 102 - stroke="white" stroke-width="1.27" /> 515 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 103 516 <path 104 517 d="M933.632 156.367L976.298 131.733L1018.96 156.367V205.633L976.298 230.267L933.632 205.633V156.367Z" 105 - stroke="white" stroke-width="1.27" /> 518 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 106 519 <path 107 520 d="M976.931 231.367L1019.6 206.733L1062.26 231.367V280.633L1019.6 305.267L976.931 280.633V231.367Z" 108 - stroke="white" stroke-width="1.27" /> 521 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 109 522 <path 110 523 d="M1020.23 306.367L1062.9 281.733L1105.56 306.367V355.633L1062.9 380.267L1020.23 355.633V306.367Z" 111 - stroke="white" stroke-width="1.27" /> 524 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 112 525 <path 113 526 d="M1063.53 231.367L1106.2 206.733L1148.86 231.367V280.633L1106.2 305.267L1063.53 280.633V231.367Z" 114 - stroke="white" stroke-width="1.27" /> 527 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 115 528 <path 116 529 d="M1106.83 306.367L1149.5 281.733L1192.16 306.367V355.633L1149.5 380.267L1106.83 355.633V306.367Z" 117 - stroke="white" stroke-width="1.27" /> 530 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 118 531 <path 119 532 d="M1150.13 381.367L1192.8 356.733L1235.46 381.367V430.633L1192.8 455.267L1150.13 430.633V381.367Z" 120 - stroke="white" stroke-width="1.27" /> 533 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 121 534 <path 122 535 d="M1193.43 306.367L1236.1 281.733L1278.76 306.367V355.633L1236.1 380.267L1193.43 355.633V306.367Z" 123 - stroke="white" stroke-width="1.27" /> 536 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 124 537 <path 125 538 d="M240.523 6.36671L283.211 -18.2669L325.899 6.36671V55.6333L283.211 80.2669L240.523 55.6333V6.36671Z" 126 - stroke="white" stroke-width="1.27" /> 539 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 127 540 <path 128 541 d="M327.167 6.36671L369.855 -18.2669L412.543 6.36671V55.6333L369.855 80.2669L327.167 55.6333V6.36671Z" 129 - stroke="white" stroke-width="1.27" /> 542 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 130 543 <path 131 544 d="M370.486 81.3667L413.174 56.7331L455.862 81.3667V130.633L413.174 155.267L370.486 130.633V81.3667Z" 132 - stroke="white" stroke-width="1.27" /> 545 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 133 546 <path 134 547 d="M413.81 6.36671L456.498 -18.2669L499.186 6.36671V55.6333L456.498 80.2669L413.81 55.6333V6.36671Z" 135 - stroke="white" stroke-width="1.27" /> 548 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 136 549 <path 137 550 d="M67.2365 6.36671L109.925 -18.2669L152.613 6.36671V55.6333L109.925 80.2669L67.2365 55.6333V6.36671Z" 138 - stroke="white" stroke-width="1.27" /> 551 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 139 552 <path 140 553 d="M110.558 81.3667L153.246 56.7331L195.934 81.3667V130.633L153.246 155.267L110.558 130.633V81.3667Z" 141 - stroke="white" stroke-width="1.27" /> 554 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 142 555 <path 143 556 d="M153.88 6.36671L196.568 -18.2669L239.256 6.36671V55.6333L196.568 80.2669L153.88 55.6333V6.36671Z" 144 - stroke="white" stroke-width="1.27" /> 557 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 145 558 <path 146 559 d="M197.201 81.3667L239.889 56.7331L282.577 81.3667V130.633L239.889 155.267L197.201 130.633V81.3667Z" 147 - stroke="white" stroke-width="1.27" /> 560 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 148 561 <path 149 562 d="M240.523 156.367L283.211 131.733L325.899 156.367V205.633L283.211 230.267L240.523 205.633V156.367Z" 150 - stroke="white" stroke-width="1.27" /> 563 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 151 564 <path 152 565 d="M283.845 81.3667L326.533 56.7331L369.221 81.3667V130.633L326.533 155.267L283.845 130.633V81.3667Z" 153 - stroke="white" stroke-width="1.27" /> 566 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 154 567 <path 155 568 d="M457.13 81.3667L499.818 56.7331L542.506 81.3667V130.633L499.818 155.267L457.13 130.633V81.3667Z" 156 - stroke="white" stroke-width="1.27" /> 569 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 157 570 <path 158 571 d="M500.452 156.367L543.14 131.733L585.828 156.367V205.633L543.14 230.267L500.452 205.633V156.367Z" 159 - stroke="white" stroke-width="1.27" /> 572 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 160 573 <path 161 574 d="M543.775 81.3667L586.463 56.7331L629.151 81.3667V130.633L586.463 155.267L543.775 130.633V81.3667Z" 162 - stroke="white" stroke-width="1.27" /> 575 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 163 576 <path 164 577 d="M587.095 156.367L629.783 131.733L672.471 156.367V205.633L629.783 230.267L587.095 205.633V156.367Z" 165 - stroke="white" stroke-width="1.27" /> 578 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 166 579 <path 167 580 d="M630.416 231.367L673.104 206.733L715.792 231.367V280.633L673.104 305.267L630.416 280.633V231.367Z" 168 - stroke="white" stroke-width="1.27" /> 581 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 169 582 <path 170 583 d="M673.738 156.367L716.426 131.733L759.114 156.367V205.633L716.426 230.267L673.738 205.633V156.367Z" 171 - stroke="white" stroke-width="1.27" /> 584 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 172 585 <path 173 586 d="M327.167 156.367L369.855 131.733L412.543 156.367V205.633L369.855 230.267L327.167 205.633V156.367Z" 174 - stroke="white" stroke-width="1.27" /> 587 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 175 588 <path 176 589 d="M370.486 231.367L413.174 206.733L455.862 231.367V280.633L413.174 305.267L370.486 280.633V231.367Z" 177 - stroke="white" stroke-width="1.27" /> 590 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 178 591 <path 179 592 d="M413.81 156.367L456.498 131.733L499.186 156.367V205.633L456.498 230.267L413.81 205.633V156.367Z" 180 - stroke="white" stroke-width="1.27" /> 593 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 181 594 <path 182 595 d="M457.13 231.367L499.818 206.733L542.506 231.367V280.633L499.818 305.267L457.13 280.633V231.367Z" 183 - stroke="white" stroke-width="1.27" /> 596 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 184 597 <path 185 598 d="M500.452 306.367L543.14 281.733L585.828 306.367V355.633L543.14 380.267L500.452 355.633V306.367Z" 186 - stroke="white" stroke-width="1.27" /> 599 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 187 600 <path 188 601 d="M543.775 231.367L586.463 206.733L629.151 231.367V280.633L586.463 305.267L543.775 280.633V231.367Z" 189 - fill="white" fill-opacity="0.25" stroke="white" stroke-width="1.27" /> 602 + fill="white" fill-opacity="0.25" stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 190 603 <path 191 604 d="M500.452 6.36671L543.14 -18.2669L585.828 6.36671V55.6333L543.14 80.2669L500.452 55.6333V6.36671Z" 192 - stroke="white" stroke-width="1.27" /> 605 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 193 606 <path 194 607 d="M760.383 6.36671L803.071 -18.2669L845.759 6.36671V55.6333L803.071 80.2669L760.383 55.6333V6.36671Z" 195 - stroke="white" stroke-width="1.27" /> 608 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 196 609 <path 197 610 d="M847.026 6.36671L889.714 -18.2669L932.402 6.36671V55.6333L889.714 80.2669L847.026 55.6333V6.36671Z" 198 - stroke="white" stroke-width="1.27" /> 611 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 199 612 <path 200 613 d="M890.348 81.3667L933.036 56.7331L975.724 81.3667V130.633L933.036 155.267L890.348 130.633V81.3667Z" 201 - fill="white" fill-opacity="0.25" stroke="white" stroke-width="1.27" /> 614 + fill="white" fill-opacity="0.25" stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 202 615 <path 203 616 d="M933.667 6.36671L976.355 -18.2669L1019.04 6.36671V55.6333L976.355 80.2669L933.667 55.6333V6.36671Z" 204 - stroke="white" stroke-width="1.27" /> 617 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 205 618 <path 206 619 d="M587.095 6.36671L629.783 -18.2669L672.471 6.36671V55.6333L629.783 80.2669L587.095 55.6333V6.36671Z" 207 - stroke="white" stroke-width="1.27" /> 620 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 208 621 <path 209 622 d="M630.416 81.3667L673.104 56.7331L715.792 81.3667V130.633L673.104 155.267L630.416 130.633V81.3667Z" 210 - stroke="white" stroke-width="1.27" /> 623 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 211 624 <path 212 625 d="M673.738 6.36671L716.426 -18.2669L759.114 6.36671V55.6333L716.426 80.2669L673.738 55.6333V6.36671Z" 213 - stroke="white" stroke-width="1.27" /> 626 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 214 627 <path 215 628 d="M717.061 81.3667L759.749 56.7331L802.437 81.3667V130.633L759.749 155.267L717.061 130.633V81.3667Z" 216 - stroke="white" stroke-width="1.27" /> 629 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 217 630 <path 218 631 d="M760.383 156.367L803.071 131.733L845.759 156.367V205.633L803.071 230.267L760.383 205.633V156.367Z" 219 - stroke="white" stroke-width="1.27" /> 632 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 220 633 <path 221 634 d="M803.702 81.3667L846.39 56.7331L889.078 81.3667V130.633L846.39 155.267L803.702 130.633V81.3667Z" 222 - stroke="white" stroke-width="1.27" /> 635 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 223 636 <path 224 637 d="M327.233 606.367L369.899 581.733L412.566 606.367V655.633L369.899 680.267L327.233 655.633V606.367Z" 225 - stroke="white" stroke-width="1.27" /> 638 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 226 639 <path 227 640 d="M370.533 681.367L413.199 656.733L455.865 681.367V730.633L413.199 755.267L370.533 730.633V681.367Z" 228 - stroke="white" stroke-width="1.27" /> 641 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 229 642 <path 230 643 d="M413.833 606.367L456.499 581.733L499.165 606.367V655.633L456.499 680.267L413.833 655.633V606.367Z" 231 - stroke="white" stroke-width="1.27" /> 644 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 232 645 <path 233 646 d="M457.133 681.367L499.799 656.733L542.465 681.367V730.633L499.799 755.267L457.133 730.633V681.367Z" 234 - stroke="white" stroke-width="1.27" /> 647 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 235 648 <path 236 649 d="M543.732 681.367L586.398 656.733L629.065 681.367V730.633L586.398 755.267L543.732 730.633V681.367Z" 237 - stroke="white" stroke-width="1.27" /> 650 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 238 651 <path 239 652 d="M197.334 681.367L240 656.733L282.666 681.367V730.633L240 755.267L197.334 730.633V681.367Z" 240 - stroke="white" stroke-width="1.27" /> 653 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 241 654 <path 242 655 d="M283.933 681.367L326.6 656.733L369.266 681.367V730.633L326.6 755.267L283.933 730.633V681.367Z" 243 - stroke="white" stroke-width="1.27" /> 656 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 244 657 <path 245 658 d="M587.032 456.367L629.698 431.733L672.365 456.367V505.633L629.698 530.267L587.032 505.633V456.367Z" 246 - stroke="white" stroke-width="1.27" /> 659 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 247 660 <path 248 661 d="M630.332 531.367L672.998 506.733L715.664 531.367V580.633L672.998 605.267L630.332 580.633V531.367Z" 249 - stroke="white" stroke-width="1.27" /> 662 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 250 663 <path 251 664 d="M673.632 456.367L716.298 431.733L758.964 456.367V505.633L716.298 530.267L673.632 505.633V456.367Z" 252 - stroke="white" stroke-width="1.27" /> 665 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 253 666 <path 254 667 d="M716.931 531.367L759.598 506.733L802.264 531.367V580.633L759.598 605.267L716.931 580.633V531.367Z" 255 - stroke="white" stroke-width="1.27" /> 668 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 256 669 <path 257 670 d="M760.231 606.367L802.897 581.733L845.564 606.367V655.633L802.897 680.267L760.231 655.633V606.367Z" 258 - stroke="white" stroke-width="1.27" /> 671 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 259 672 <path 260 673 d="M803.531 531.367L846.197 506.733L888.864 531.367V580.633L846.197 605.267L803.531 580.633V531.367Z" 261 - stroke="white" stroke-width="1.27" /> 674 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 262 675 <path 263 676 d="M457.133 531.367L499.799 506.733L542.465 531.367V580.633L499.799 605.267L457.133 580.633V531.367Z" 264 - stroke="white" stroke-width="1.27" /> 677 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 265 678 <path 266 679 d="M500.432 606.367L543.099 581.733L585.765 606.367V655.633L543.099 680.267L500.432 655.633V606.367Z" 267 - stroke="white" stroke-width="1.27" /> 680 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 268 681 <path 269 682 d="M543.732 531.367L586.398 506.733L629.065 531.367V580.633L586.398 605.267L543.732 580.633V531.367Z" 270 - stroke="white" stroke-width="1.27" /> 683 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 271 684 <path 272 685 d="M587.032 606.367L629.698 581.733L672.365 606.367V655.633L629.698 680.267L587.032 655.633V606.367Z" 273 - stroke="white" stroke-width="1.27" /> 686 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 274 687 <path 275 688 d="M630.332 681.367L672.998 656.733L715.664 681.367V730.633L672.998 755.267L630.332 730.633V681.367Z" 276 - stroke="white" stroke-width="1.27" /> 689 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 277 690 <path 278 691 d="M673.632 606.367L716.298 581.733L758.964 606.367V655.633L716.298 680.267L673.632 655.633V606.367Z" 279 - stroke="white" stroke-width="1.27" /> 692 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 280 693 <path 281 694 d="M846.831 606.367L889.497 581.733L932.163 606.367V655.633L889.497 680.267L846.831 655.633V606.367Z" 282 - stroke="white" stroke-width="1.27" /> 695 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 283 696 <path 284 697 d="M890.131 681.367L932.797 656.733L975.463 681.367V730.633L932.797 755.267L890.131 730.633V681.367Z" 285 - stroke="white" stroke-width="1.27" /> 698 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 286 699 <path 287 700 d="M933.43 606.367L976.097 581.733L1018.76 606.367V655.633L976.097 680.267L933.43 655.633V606.367Z" 288 - stroke="white" stroke-width="1.27" /> 701 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 289 702 <path 290 703 d="M976.73 681.367L1019.4 656.733L1062.06 681.367V730.633L1019.4 755.267L976.73 730.633V681.367Z" 291 - stroke="white" stroke-width="1.27" /> 704 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 292 705 <path 293 706 d="M1063.33 681.367L1106 656.733L1148.66 681.367V730.633L1106 755.267L1063.33 730.633V681.367Z" 294 - stroke="white" stroke-width="1.27" /> 707 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 295 708 <path 296 709 d="M716.931 681.367L759.598 656.733L802.264 681.367V730.633L759.598 755.267L716.931 730.633V681.367Z" 297 - stroke="white" stroke-width="1.27" /> 710 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 298 711 <path 299 712 d="M803.531 681.367L846.197 656.733L888.864 681.367V730.633L846.197 755.267L803.531 730.633V681.367Z" 300 - stroke="white" stroke-width="1.27" /> 713 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 301 714 <path 302 715 d="M-62.7322 381.367L-20.0442 356.733L22.6438 381.367V430.633L-20.0442 455.267L-62.7322 430.633V381.367Z" 303 - stroke="white" stroke-width="1.27" /> 716 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 304 717 <path 305 718 d="M-19.4139 456.367L23.2741 431.733L65.9621 456.367V505.633L23.2741 530.267L-19.4139 505.633V456.367Z" 306 - stroke="white" stroke-width="1.27" /> 719 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 307 720 <path 308 721 d="M23.9103 381.367L66.5983 356.733L109.286 381.367V430.633L66.5983 455.267L23.9103 430.633V381.367Z" 309 - stroke="white" stroke-width="1.27" /> 722 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 310 723 <path 311 724 d="M67.2306 456.367L109.919 431.733L152.607 456.367V505.633L109.919 530.267L67.2306 505.633V456.367Z" 312 - stroke="white" stroke-width="1.27" /> 725 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 313 726 <path 314 727 d="M110.553 531.367L153.241 506.733L195.929 531.367V580.633L153.241 605.267L110.553 580.633V531.367Z" 315 - stroke="white" stroke-width="1.27" /> 728 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 316 729 <path 317 730 d="M153.875 456.367L196.563 431.733L239.251 456.367V505.633L196.563 530.267L153.875 505.633V456.367Z" 318 - stroke="white" stroke-width="1.27" /> 731 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 319 732 <path 320 733 d="M197.195 531.367L239.884 506.733L282.572 531.367V580.633L239.884 605.267L197.195 580.633V531.367Z" 321 - stroke="white" stroke-width="1.27" /> 734 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 322 735 <path 323 736 d="M240.517 606.367L283.205 581.733L325.893 606.367V655.633L283.205 680.267L240.517 655.633V606.367Z" 324 - stroke="white" stroke-width="1.27" /> 737 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 325 738 <path 326 739 d="M283.839 531.367L326.527 506.733L369.215 531.367V580.633L326.527 605.267L283.839 580.633V531.367Z" 327 - fill="white" fill-opacity="0.25" stroke="white" stroke-width="1.27" /> 740 + fill="white" fill-opacity="0.25" stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 328 741 <path 329 742 d="M-62.7322 531.367L-20.0442 506.733L22.6438 531.367V580.633L-20.0442 605.267L-62.7322 580.633V531.367Z" 330 - stroke="white" stroke-width="1.27" /> 743 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 331 744 <path 332 745 d="M-19.4139 606.367L23.2741 581.733L65.9621 606.367V655.633L23.2741 680.267L-19.4139 655.633V606.367Z" 333 - stroke="white" stroke-width="1.27" /> 746 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 334 747 <path 335 748 d="M23.9103 531.367L66.5983 506.733L109.286 531.367V580.633L66.5983 605.267L23.9103 580.633V531.367Z" 336 - stroke="white" stroke-width="1.27" /> 749 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 337 750 <path 338 751 d="M67.2306 606.367L109.919 581.733L152.607 606.367V655.633L109.919 680.267L67.2306 655.633V606.367Z" 339 - stroke="white" stroke-width="1.27" /> 752 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 340 753 <path 341 754 d="M110.553 681.367L153.241 656.733L195.929 681.367V730.633L153.241 755.267L110.553 730.633V681.367Z" 342 - stroke="white" stroke-width="1.27" /> 755 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 343 756 <path 344 757 d="M153.875 606.367L196.563 581.733L239.251 606.367V655.633L196.563 680.267L153.875 655.633V606.367Z" 345 - stroke="white" stroke-width="1.27" /> 758 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 346 759 <path 347 760 d="M67.2306 156.367L109.919 131.733L152.607 156.367V205.633L109.919 230.267L67.2306 205.633V156.367Z" 348 - fill="white" fill-opacity="0.25" stroke="white" stroke-width="1.27" /> 761 + fill="white" fill-opacity="0.25" stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 349 762 <path 350 763 d="M110.553 231.367L153.241 206.733L195.929 231.367V280.633L153.241 305.267L110.553 280.633V231.367Z" 351 - stroke="white" stroke-width="1.27" /> 764 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 352 765 <path 353 766 d="M153.875 156.367L196.563 131.733L239.251 156.367V205.633L196.563 230.267L153.875 205.633V156.367Z" 354 - stroke="white" stroke-width="1.27" /> 767 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 355 768 <path 356 769 d="M197.195 231.367L239.884 206.733L282.572 231.367V280.633L239.884 305.267L197.195 280.633V231.367Z" 357 - stroke="white" stroke-width="1.27" /> 770 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 358 771 <path 359 772 d="M240.517 306.367L283.205 281.733L325.893 306.367V355.633L283.205 380.267L240.517 355.633V306.367Z" 360 - stroke="white" stroke-width="1.27" /> 773 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 361 774 <path 362 775 d="M283.839 231.367L326.527 206.733L369.215 231.367V280.633L326.527 305.267L283.839 280.633V231.367Z" 363 - stroke="white" stroke-width="1.27" /> 776 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 364 777 <path 365 778 d="M-62.7322 231.367L-20.0442 206.733L22.6438 231.367V280.633L-20.0442 305.267L-62.7322 280.633V231.367Z" 366 - stroke="white" stroke-width="1.27" /> 779 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 367 780 <path 368 781 d="M-19.4139 306.367L23.2741 281.733L65.9621 306.367V355.633L23.2741 380.267L-19.4139 355.633V306.367Z" 369 - stroke="white" stroke-width="1.27" /> 782 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 370 783 <path 371 784 d="M23.9103 231.367L66.5983 206.733L109.286 231.367V280.633L66.5983 305.267L23.9103 280.633V231.367Z" 372 - stroke="white" stroke-width="1.27" /> 785 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 373 786 <path 374 787 d="M67.2306 306.367L109.919 281.733L152.607 306.367V355.633L109.919 380.267L67.2306 355.633V306.367Z" 375 - stroke="white" stroke-width="1.27" /> 788 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 376 789 <path 377 790 d="M110.553 381.367L153.241 356.733L195.929 381.367V430.633L153.241 455.267L110.553 430.633V381.367Z" 378 - stroke="white" stroke-width="1.27" /> 791 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 379 792 <path 380 793 d="M153.875 306.367L196.563 281.733L239.251 306.367V355.633L196.563 380.267L153.875 355.633V306.367Z" 381 - stroke="white" stroke-width="1.27" /> 794 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 382 795 <path 383 796 d="M327.161 306.367L369.849 281.733L412.537 306.367V355.633L369.849 380.267L327.161 355.633V306.367Z" 384 - stroke="white" stroke-width="1.27" /> 797 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 385 798 <path 386 799 d="M370.484 381.367L413.172 356.733L455.86 381.367V430.633L413.172 455.267L370.484 430.633V381.367Z" 387 - stroke="white" stroke-width="1.27" /> 800 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 388 801 <path 389 802 d="M413.803 306.367L456.491 281.733L499.179 306.367V355.633L456.491 380.267L413.803 355.633V306.367Z" 390 - stroke="white" stroke-width="1.27" /> 803 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 391 804 <path 392 805 d="M457.126 381.367L499.814 356.733L542.502 381.367V430.633L499.814 455.267L457.126 430.633V381.367Z" 393 - stroke="white" stroke-width="1.27" /> 806 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 394 807 <path 395 808 d="M500.448 456.367L543.136 431.733L585.824 456.367V505.633L543.136 530.267L500.448 505.633V456.367Z" 396 - stroke="white" stroke-width="1.27" /> 809 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 397 810 <path 398 811 d="M543.768 381.367L586.456 356.733L629.144 381.367V430.633L586.456 455.267L543.768 430.633V381.367Z" 399 - stroke="white" stroke-width="1.27" /> 812 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 400 813 <path 401 814 d="M197.195 381.367L239.884 356.733L282.572 381.367V430.633L239.884 455.267L197.195 430.633V381.367Z" 402 - stroke="white" stroke-width="1.27" /> 815 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 403 816 <path 404 817 d="M240.517 456.367L283.205 431.733L325.893 456.367V505.633L283.205 530.267L240.517 505.633V456.367Z" 405 - stroke="white" stroke-width="1.27" /> 818 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 406 819 <path 407 820 d="M283.839 381.367L326.527 356.733L369.215 381.367V430.633L326.527 455.267L283.839 430.633V381.367Z" 408 - stroke="white" stroke-width="1.27" /> 821 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 409 822 <path 410 823 d="M327.161 456.367L369.849 431.733L412.537 456.367V505.633L369.849 530.267L327.161 505.633V456.367Z" 411 - stroke="white" stroke-width="1.27" /> 824 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 412 825 <path 413 826 d="M370.484 531.367L413.172 506.733L455.86 531.367V580.633L413.172 605.267L370.484 580.633V531.367Z" 414 - stroke="white" stroke-width="1.27" /> 827 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 415 828 <path 416 829 d="M413.803 456.367L456.491 431.733L499.179 456.367V505.633L456.491 530.267L413.803 505.633V456.367Z" 417 - stroke="white" stroke-width="1.27" /> 830 + stroke="rgba(0, 0, 0, 0.50)" stroke-width="1.27" /> 418 831 </g> 419 832 <defs> 420 833 <radialGradient id="paint0_radial_91_8" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" ··· 423 836 <stop offset="0.802083" stop-color="#D9D9D9" stop-opacity="0" /> 424 837 </radialGradient> 425 838 </defs> 426 - </svg> 839 + </svg>
+7 -1
shiki.config.mjs
··· 59 59 ]; 60 60 61 61 // This is the default theme we use for our Shiki Syntax Highlighter 62 - export const DEFAULT_THEME = shikiNordTheme; 62 + export const DEFAULT_THEME = { 63 + // We updating this color because the background color and comment text color 64 + // in the Codebox component do not comply with accessibility standards 65 + // @see https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html 66 + colorReplacements: { '#616e88': '#707e99' }, 67 + ...shikiNordTheme, 68 + };
+1 -3
styles/new/base.css
··· 4 4 5 5 html, 6 6 body { 7 - @apply h-full 8 - w-full 9 - overflow-hidden; 7 + @apply size-full; 10 8 } 11 9 12 10 body {
-1
styles/new/index.css
··· 9 9 @import 'tailwindcss/base'; 10 10 @import 'tailwindcss/components'; 11 11 @import 'tailwindcss/utilities'; 12 - @import './mixins'; 13 12 @import './base.css'; 14 13 @import './markdown.css';
+3 -6
styles/new/markdown.css
··· 1 - .mdxContent { 1 + main { 2 2 hr { 3 3 @apply w-full 4 4 border-t ··· 53 53 dark:text-white; 54 54 } 55 55 56 - a, 57 - a:link, 58 - a:visited { 59 - @apply inline-block 60 - text-green-600 56 + a { 57 + @apply text-green-600 61 58 dark:text-green-400; 62 59 63 60 &:hover {
-7
styles/new/mixins.css
··· 1 - @define-mixin glow-backdrop $radius, $color { 2 - background: radial-gradient( 3 - $radius circle at calc(100% - 40px) 10px, 4 - $color, 5 - transparent 30% 6 - ); 7 - }
+7 -2
tailwind.config.ts
··· 14 14 green: { 15 15 100: '#EDF2EB', 16 16 200: '#C5E5B4', 17 - 300: '#C5E5B4', 17 + 300: '#99CC7D', 18 18 400: '#84BA64', 19 19 500: '#5FA04E', 20 20 600: '#417E38', ··· 90 90 900: '#411526', 91 91 }, 92 92 white: '#FFFFFF', 93 - 'white-opaque': 'rgba(255, 255, 255, 0.5)', 94 93 transparent: 'transparent', 95 94 shadow: '#101828', 96 95 }, ··· 125 124 'linear-gradient(180deg, theme(colors.neutral.100 / 50%) 0%, theme(colors.neutral.100 / 0%) 48.32%)', 126 125 'gradient-subtle-dark': 127 126 'linear-gradient(180deg, theme(colors.neutral.900 / 50%) 0%, theme(colors.neutral.900 / 0%) 48.32%)', 127 + 'gradient-subtle-gray': 128 + 'linear-gradient(180deg, theme(colors.neutral.900) 0%, theme(colors.neutral.900 / 80%) 100%)', 129 + 'gradient-subtle-white': 130 + 'linear-gradient(180deg, theme(colors.white) 0%, theme(colors.white / 80%) 100%)', 131 + 'gradient-glow-backdrop': 132 + 'radial-gradient(8em circle at calc(100% - 40px) 10px, theme(colors.green.500), transparent 30%)', 128 133 }, 129 134 boxShadow: { 130 135 xs: '0px 1px 2px 0px theme(colors.shadow / 5%)',
+8 -1
types/layouts.ts
··· 1 + // @TODO: These are the Website Redesign Layouts 2 + export type Layouts = 3 + | 'about.hbs' 4 + | 'docs.hbs' 5 + | 'home.hbs' 6 + | 'learn.hbs' 7 + | 'page.hbs'; 8 + 1 9 // @TODO: These are legacy layouts that are going to be replaced with the `nodejs/nodejs.dev` Layouts in the future 2 10 export type LegacyLayouts = 3 11 | 'about.hbs' 4 12 | 'learn.hbs' 5 13 | 'blog-category.hbs' 6 14 | 'blog-post.hbs' 7 - | 'contribute.hbs' 8 15 | 'index.hbs' 9 16 | 'docs.hbs' 10 17 | 'download.hbs'
+17
util/getHighlighter.ts
··· 1 + import { getHighlighterCore } from 'shikiji/core'; 2 + import { getWasmInlined } from 'shikiji/wasm'; 3 + 4 + import { LANGUAGES, DEFAULT_THEME } from '@/shiki.config.mjs'; 5 + 6 + // This creates a memoized minimal Shikiji Syntax Highlighter 7 + const memoizedShikiji = await getHighlighterCore({ 8 + themes: [DEFAULT_THEME], 9 + langs: LANGUAGES, 10 + loadWasm: getWasmInlined, 11 + }); 12 + 13 + export const highlightToHtml = (code: string, language: string) => 14 + memoizedShikiji.codeToHtml(code, { lang: language, theme: DEFAULT_THEME }); 15 + 16 + export const highlightToHast = (code: string, language: string) => 17 + memoizedShikiji.codeToHast(code, { lang: language, theme: DEFAULT_THEME });