/
githubmirror
/
docusaurus
Обзор
Документация
Войти
/
githubmirror
/
docusaurus
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
website/src/pages/index.tsx
279 строк
8 KB
Sébastien Lorber
chore(monorepo): upgrade monorepo to ESLint 9 (#12024)
15 май 2026, 21:08
Не верифицирован
15 май 2026, 21:08
7518645
Код
Авторство
О чём код?
/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import type {ReactNode} from 'react'; import clsx from 'clsx'; import LiteYouTubeEmbed from 'react-lite-youtube-embed'; import Link from '@docusaurus/Link'; import Translate, {translate} from '@docusaurus/Translate'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import useBaseUrl, {useBaseUrlUtils} from '@docusaurus/useBaseUrl'; import Image from '@theme/IdealImage'; import Layout from '@theme/Layout'; import Tweet from '@site/src/components/Tweet'; import Tweets, {type TweetItem} from '@site/src/data/tweets'; import Quotes from '@site/src/data/quotes'; import Features, {type FeatureItem} from '@site/src/data/features'; import Heading from '@theme/Heading'; import styles from './styles.module.css'; import 'react-lite-youtube-embed/dist/LiteYouTubeEmbed.css'; function HeroBanner() { return ( <div className={styles.hero} data-theme="dark"> <div className={styles.heroInner}> <Heading as="h1" className={styles.heroProjectTagline}> <img alt={translate({message: 'Docusaurus with Keytar'})} className={styles.heroLogo} src={useBaseUrl('/img/docusaurus_keytar.svg')} width="200" height="200" /> <span className={styles.heroTitleTextHtml} dangerouslySetInnerHTML={{ __html: translate({ id: 'homepage.hero.title', message: 'Build <b>optimized</b> websites <b>quickly</b>, focus on your <b>content</b>', description: 'Home page hero title, can contain simple html tags', }), }} /> </Heading> <div className={styles.indexCtas}> <Link className="button button--primary" to="/docs"> <Translate>Get Started</Translate> </Link> <Link className="button button--info" to="https://docusaurus.new"> <Translate>Try a Demo</Translate> </Link> <span className={styles.indexCtasGitHubButtonWrapper}> <iframe className={styles.indexCtasGitHubButton} src="https://ghbtns.com/github-btn.html?user=facebook&repo=docusaurus&type=star&count=true&size=large" width={160} height={30} title="GitHub Stars" /> </span> </div> </div> </div> ); } function TweetsSection() { const tweetColumns: TweetItem[][] = [[], [], []]; Tweets.filter((tweet) => tweet.showOnHomepage).forEach((tweet, i) => tweetColumns[i % 3]!.push(tweet), ); return ( <div className={clsx(styles.section, styles.sectionAlt)}> <div className="container"> <Heading as="h2" className={clsx('margin-bottom--lg', 'text--center')}> <Translate>Loved by many engineers</Translate> </Heading> <div className={clsx('row', styles.tweetsSection)}> {tweetColumns.map((tweetItems, i) => ( <div className="col col--4" key={i}> {tweetItems.map((tweet) => ( <Tweet {...tweet} key={tweet.url} /> ))} </div> ))} </div> </div> </div> ); } function QuotesSection() { return ( <div className={clsx(styles.section)}> <div className="container"> <div className="row"> {Quotes.map((quote) => ( <div className="col" key={quote.name}> <div className="avatar avatar--vertical margin-bottom--sm"> <Image alt={quote.name} className="avatar__photo avatar__photo--xl" img={quote.thumbnail} style={{overflow: 'hidden'}} /> <div className="avatar__intro padding-top--sm"> <div className="avatar__name">{quote.name}</div> <small className="avatar__subtitle">{quote.title}</small> </div> </div> <p className="text--center text--italic padding-horiz--md"> {quote.text} </p> </div> ))} </div> </div> </div> ); } function VideoContainer() { return ( <div className="container text--center margin-top--xl"> <div className="row"> <div className="col"> <Heading as="h2"> <Translate>Check it out in the intro video</Translate> </Heading> <div className="video-container"> <LiteYouTubeEmbed id="_An9EsKPhp0" params="autoplay=1&autohide=1&showinfo=0&rel=0" title="Explain Like I'm 5: Docusaurus" poster="maxresdefault" webp /> </div> </div> </div> </div> ); } function Feature({ feature, className, }: { feature: FeatureItem; className?: string; }) { const {withBaseUrl} = useBaseUrlUtils(); return ( <div className={clsx('col', className)}> <img className={styles.featureImage} alt={feature.title} width={Math.floor(feature.image.width)} height={Math.floor(feature.image.height)} src={withBaseUrl(feature.image.src)} loading="lazy" /> <Heading as="h3" className={clsx(styles.featureHeading)}> {feature.title} </Heading> <p className="padding-horiz--md">{feature.text}</p> </div> ); } function FeaturesContainer() { const firstRow = Features.slice(0, 3); const secondRow = Features.slice(3); return ( <div className="container text--center"> <div className="row margin-top--lg margin-bottom--lg"> {firstRow.map((feature, idx) => ( <Feature feature={feature} key={idx} /> ))} </div> <div className="row"> {secondRow.map((feature, idx) => ( <Feature feature={feature} key={idx} className={clsx('col--4', idx === 0 && 'col--offset-2')} /> ))} </div> </div> ); } function TopBanner() { // TODO We should be able to strongly type customFields // Refactor to use a CustomFields interface + TS declaration merging const announcedVersion = useDocusaurusContext().siteConfig.customFields ?.announcedVersion as string; return ( <div className={styles.topBanner}> <div className={styles.topBannerTitle}> {'🎉\xa0'} <Link to={`/blog/releases/${announcedVersion}`} className={styles.topBannerTitleText}> <Translate id="homepage.banner.launch.newVersion" values={{newVersion: announcedVersion}}> {'Docusaurus\xa0{newVersion} is\xa0out!️'} </Translate> </Link> {'\xa0🥳'} </div> {/* <div style={{display: 'flex', alignItems: 'center', flexWrap: 'wrap'}}> <div style={{flex: 1, whiteSpace: 'nowrap'}}> <div className={styles.topBannerDescription}> We are on{' '} <b> <Link to="https://www.producthunt.com/posts/docusaurus-2-0"> ProductHunt </Link>{' '} and{' '} <Link to="https://news.ycombinator.com/item?id=32303052"> Hacker News </Link>{' '} today! </b> </div> </div> <div style={{ flexGrow: 1, flexShrink: 0, padding: '0.5rem', display: 'flex', justifyContent: 'center', }}> <ProductHuntCard /> <HackerNewsIcon /> </div> </div> */} </div> ); } export default function Home(): ReactNode { const { siteConfig: {customFields, tagline}, } = useDocusaurusContext(); const {description} = customFields as {description: string}; return ( <Layout title={tagline} description={description}> <main> <TopBanner /> <HeroBanner /> <div className={styles.section}> <FeaturesContainer /> <VideoContainer /> </div> <TweetsSection /> <QuotesSection /> </main> </Layout> ); }