From e7c3b860ba486e186b8cf23d4a3de8ede7bb865e Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Wed, 25 Jun 2025 13:47:14 -0400 Subject: [PATCH 1/6] docs: overhaul homepage --- .gitignore | 1 + README.md | 2 +- docs/maintenance/Branding.mdx | 2 +- packages/website/docusaurus.config.mts | 4 +- packages/website/package.json | 5 +- .../plugins/recent-blog-posts/index.ts | 48 +++++ .../FinancialContributors/index.tsx | 65 ------ .../home/ExplainerSpotlight/index.tsx | 26 +++ .../home/ExplainerSpotlight/styles.module.css | 24 +++ .../src/components/home/Explainers/index.tsx | 83 ++++++++ .../home/Explainers/styles.module.css | 52 +++++ .../src/components/home/Feature.module.css | 6 + .../home/FinancialContributors/index.tsx | 77 +++++++ .../FinancialContributors/styles.module.css | 21 +- .../{ => home}/FinancialContributors/types.ts | 0 .../components/home/RecentBlogPosts/index.tsx | 48 +++++ .../home/RecentBlogPosts/styles.module.css | 84 ++++++++ .../Sponsor.tsx => home/Sponsor/index.tsx} | 2 +- .../components/home/Sponsor/styles.module.css | 12 ++ .../Sponsors/index.tsx | 2 +- .../Sponsors/styles.module.css | 0 packages/website/src/pages/index.tsx | 199 +++--------------- packages/website/src/pages/styles.module.css | 64 +++--- packages/website/static/manifest.json | 2 +- yarn.lock | 10 + 25 files changed, 564 insertions(+), 275 deletions(-) create mode 100644 packages/website/plugins/recent-blog-posts/index.ts delete mode 100644 packages/website/src/components/FinancialContributors/index.tsx create mode 100644 packages/website/src/components/home/ExplainerSpotlight/index.tsx create mode 100644 packages/website/src/components/home/ExplainerSpotlight/styles.module.css create mode 100644 packages/website/src/components/home/Explainers/index.tsx create mode 100644 packages/website/src/components/home/Explainers/styles.module.css create mode 100644 packages/website/src/components/home/Feature.module.css create mode 100644 packages/website/src/components/home/FinancialContributors/index.tsx rename packages/website/src/components/{ => home}/FinancialContributors/styles.module.css (79%) rename packages/website/src/components/{ => home}/FinancialContributors/types.ts (100%) create mode 100644 packages/website/src/components/home/RecentBlogPosts/index.tsx create mode 100644 packages/website/src/components/home/RecentBlogPosts/styles.module.css rename packages/website/src/components/{FinancialContributors/Sponsor.tsx => home/Sponsor/index.tsx} (90%) create mode 100644 packages/website/src/components/home/Sponsor/styles.module.css rename packages/website/src/components/{FinancialContributors => home}/Sponsors/index.tsx (91%) rename packages/website/src/components/{FinancialContributors => home}/Sponsors/styles.module.css (100%) diff --git a/.gitignore b/.gitignore index 20ab952ba246..bf83f8f9300a 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ docs/packages/*/generated packages/website/.docusaurus packages/website/.cache-loader packages/website/build +packages/website/data/recent-blog-posts.json packages/website/static/sandbox # Runtime data diff --git a/README.md b/README.md index 1656a4bc2c6d..f04ca16d3800 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

typescript-eslint

-

Monorepo for the tooling that enables ESLint and Prettier to support TypeScript

+

Monorepo for typescript-eslint: powerful static analysis for JavaScript and TypeScript

CI diff --git a/docs/maintenance/Branding.mdx b/docs/maintenance/Branding.mdx index d4e84d90deae..5ab5af30f691 100644 --- a/docs/maintenance/Branding.mdx +++ b/docs/maintenance/Branding.mdx @@ -22,7 +22,7 @@ Combining lowercase with a dash helps differentiate us. ### Slogan -> The tooling that enables ESLint and Prettier to support TypeScript. +> Powerful static analysis for JavaScript and TypeScript. ## Visuals diff --git a/packages/website/docusaurus.config.mts b/packages/website/docusaurus.config.mts index 3fb7fe565efa..3e6ff8e252f4 100644 --- a/packages/website/docusaurus.config.mts +++ b/packages/website/docusaurus.config.mts @@ -351,8 +351,7 @@ const redirects: PluginRedirectOptions = { const config: Config = { baseUrl: '/', - tagline: - 'The tooling that enables ESLint and Prettier to support TypeScript.', + tagline: 'Powerful static analysis for JavaScript and TypeScript.', title: 'typescript-eslint', url: 'https://typescript-eslint.io', @@ -368,6 +367,7 @@ const config: Config = { onBrokenMarkdownLinks: 'throw', organizationName: 'typescript-eslint', plugins: [ + './plugins/recent-blog-posts/index.ts', ...['ast-spec', 'project-service', 'tsconfig-utils', 'type-utils'].map( packageName => [ 'docusaurus-plugin-typedoc', diff --git a/packages/website/package.json b/packages/website/package.json index eb0fd1bafcce..4be5cceafed7 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -40,6 +40,7 @@ "clsx": "^2.1.0", "docusaurus-plugin-typedoc": "^1.4.0", "eslint": "^9.15.0", + "gray-matter": "^4.0.3", "json5": "^2.2.3", "konamimojisplosion": "^0.5.2", "lz-string": "^1.5.0", @@ -49,10 +50,12 @@ "react-dom": "^18.2.0", "react-markdown": "^10.0.0", "react-resizable-panels": "^3.0.0", + "reading-time": "^1.5.0", "semver": "^7.6.0", "typedoc": "^0.28.4", "typedoc-plugin-markdown": "^4.6.3", - "typescript": "*" + "typescript": "*", + "zod": "^3.25.67" }, "devDependencies": { "@docusaurus/module-type-aliases": "^3.2.1", diff --git a/packages/website/plugins/recent-blog-posts/index.ts b/packages/website/plugins/recent-blog-posts/index.ts new file mode 100644 index 000000000000..1647d3d7954d --- /dev/null +++ b/packages/website/plugins/recent-blog-posts/index.ts @@ -0,0 +1,48 @@ +import type { Plugin } from '@docusaurus/types'; + +import matter from 'gray-matter'; +import * as fs from 'node:fs/promises'; +import readingTime from 'reading-time'; +import { z } from 'zod'; + +const storageDirectory = 'data'; +const storageFile = `data/recent-blog-posts.json`; + +const matterSchema = z.object({ + description: z.string(), + slug: z.string(), + title: z.string(), +}); + +export default async function blogPluginEnhanced(): Promise { + const blogHandles = (await fs.readdir('blog', { withFileTypes: true })) + .filter(handle => handle.isFile() && /.mdx?$/.test(handle.name)) + .map(handle => ({ + date: new Date(/\d+-\d+-\d+/.exec(handle.name)?.[0] || '1970-01-01'), + handle, + })) + .sort((a, b) => b.date.getTime() - a.date.getTime()) + .slice(0, 3); + + const blogPosts = await Promise.all( + blogHandles.map(async ({ date, handle }) => { + const content = await fs.readFile(`blog/${handle.name}`, 'utf-8'); + const data = matterSchema.parse(matter(content).data); + + return { + date, + description: data.description, + readingTime: Math.round(readingTime(content).minutes), + slug: data.slug, + title: data.title, + }; + }), + ); + + await fs.mkdir(storageDirectory, { recursive: true }); + await fs.writeFile(storageFile, JSON.stringify(blogPosts, null, 2)); + + return { + name: 'recent-blog-posts', + }; +} diff --git a/packages/website/src/components/FinancialContributors/index.tsx b/packages/website/src/components/FinancialContributors/index.tsx deleted file mode 100644 index 03190cd70e13..000000000000 --- a/packages/website/src/components/FinancialContributors/index.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import Link from '@docusaurus/Link'; -import sponsors from '@site/data/sponsors.json'; -import clsx from 'clsx'; -import React from 'react'; - -import { Sponsors } from './Sponsors'; -import styles from './styles.module.css'; - -export function FinancialContributors(): React.JSX.Element { - return ( - <> -

- The typescript-eslint project would not be possible without the generous - support of our financial contributors. -

-
- - - -
-
- - Become a financial sponsor - -
- - See all financial sponsors - - - Docs - -
-
- - ); -} diff --git a/packages/website/src/components/home/ExplainerSpotlight/index.tsx b/packages/website/src/components/home/ExplainerSpotlight/index.tsx new file mode 100644 index 000000000000..57d45524c3bb --- /dev/null +++ b/packages/website/src/components/home/ExplainerSpotlight/index.tsx @@ -0,0 +1,26 @@ +import Heading from '@theme/Heading'; +import React from 'react'; + +import styles from './styles.module.css'; + +export interface ExplainerSpotlightProps extends React.PropsWithChildren { + header: string; + emoji: string; + href: string; +} + +export function ExplainerSpotlight({ + children, + emoji, + header, + href, +}: ExplainerSpotlightProps): React.JSX.Element { + return ( + + + {header} {emoji} + +
{children}
+
+ ); +} diff --git a/packages/website/src/components/home/ExplainerSpotlight/styles.module.css b/packages/website/src/components/home/ExplainerSpotlight/styles.module.css new file mode 100644 index 000000000000..c10751a2879f --- /dev/null +++ b/packages/website/src/components/home/ExplainerSpotlight/styles.module.css @@ -0,0 +1,24 @@ +.explainerSpotlight { + background: var(--ifm-color-emphasis-100); + border-radius: var(--ifm-global-radius); + color: var(--ifm-heading-color); + padding: 1rem 1.5rem; + text-decoration: none; + transition: box-shadow 0.3s ease; + width: 100%; +} + +[data-theme='dark'] .explainerSpotlight { + background: var(--ifm-color-emphasis-200); +} + +.explainerSpotlight:hover { + color: var(--ifm-heading-color); + text-decoration: none; + box-shadow: 0 3px 3px 0 var(--gray-border-shadow); +} + +.heading { + display: flex; + justify-content: space-between; +} diff --git a/packages/website/src/components/home/Explainers/index.tsx b/packages/website/src/components/home/Explainers/index.tsx new file mode 100644 index 000000000000..9545ebc6552c --- /dev/null +++ b/packages/website/src/components/home/Explainers/index.tsx @@ -0,0 +1,83 @@ +import Link from '@docusaurus/Link'; +import useBaseUrl from '@docusaurus/useBaseUrl'; +import Heading from '@theme/Heading'; +import clsx from 'clsx'; +import React from 'react'; + +import { ExplainerSpotlight } from '../ExplainerSpotlight'; +import styles from './styles.module.css'; + +const explanations = [ + { + children: + 'The parser and services for linting TypeScript code with ESLint, as well as how tools such as Prettier read TypeScript code.', + emoji: '⚙️', + header: 'Language Support', + href: '/getting-started', + }, + { + children: + 'Over 100 rules that check for best practices, likely bugs, and stylistic consistency in modern JavaScript and TypeScript codebases.', + emoji: '🧠', + header: 'Standard Rules', + href: '/rules', + }, + { + children: + "Industry-leading services that use TypeScript's type APIs to make a more powerful breed of lint rules for deeper insights into code.", + emoji: '⚡️', + header: 'Typed Linting', + href: '/getting-started/typed-linting', + }, +]; + +export function Explainers(): React.JSX.Element { + return ( +
+ + typescript-eslint enables ESLint, Prettier, and more to + support TypeScript code. + + +
+

+ ESLint is a linter. It runs a set of rules to find + likely problems and suggested fixes to improve your code. +

+

+ TypeScript is a language and a type checker. The + language adds syntax for types to JavaScript. +
+ The type checker analyzes code to find mismatches between uses of + values and types. +

+

+ typescript-eslint is necessary for JavaScript tools + such as ESLint to work with TypeScript's new syntax. +
+ It also adds lint rules for TypeScript, including many that use the + power of types to better analyze code. +

+
+ +
+ + Learn More + + + See the Rules + +
+
+ ); +} diff --git a/packages/website/src/components/home/Explainers/styles.module.css b/packages/website/src/components/home/Explainers/styles.module.css new file mode 100644 index 000000000000..62ad16abf89d --- /dev/null +++ b/packages/website/src/components/home/Explainers/styles.module.css @@ -0,0 +1,52 @@ +.explainers { + --ifm-button-size-multiplier: 1.3; + + align-items: center; + display: flex; + flex-direction: column; + margin: 1rem; +} + +.explainerTexts { + font-size: 1.1rem; + margin: 1rem 2rem; + text-align: left; + display: flex; + gap: 1rem; + flex-direction: column; +} + +.explainerTexts p { + margin: 0; +} + +.explainerSpotlights { + display: flex; + flex-direction: column; + gap: 1rem; + margin: 2rem auto 2.5rem; +} + +.buttons { + margin: 1rem auto 0; + display: flex; + flex-direction: column; + gap: 1rem; +} + +@media (width >= 996px) { + .explainerSpotlights { + flex-direction: row; + max-width: var(--ifm-container-width); + } + + .explainerTexts { + margin: 0.5rem 2rem 2rem; + text-align: center; + } + + .buttons { + flex-direction: row; + gap: 2rem; + } +} diff --git a/packages/website/src/components/home/Feature.module.css b/packages/website/src/components/home/Feature.module.css new file mode 100644 index 000000000000..e807de939ad6 --- /dev/null +++ b/packages/website/src/components/home/Feature.module.css @@ -0,0 +1,6 @@ +.buttons { + align-items: center; + display: flex; + width: 100%; + justify-content: center; +} diff --git a/packages/website/src/components/home/FinancialContributors/index.tsx b/packages/website/src/components/home/FinancialContributors/index.tsx new file mode 100644 index 000000000000..2efdc0976fe2 --- /dev/null +++ b/packages/website/src/components/home/FinancialContributors/index.tsx @@ -0,0 +1,77 @@ +import Link from '@docusaurus/Link'; +import sponsors from '@site/data/sponsors.json'; +import Heading from '@theme/Heading'; +import clsx from 'clsx'; +import React from 'react'; + +import { Sponsors } from '../Sponsors'; +import styles from './styles.module.css'; + +export function FinancialContributors(): React.JSX.Element { + return ( +
+
+ + Financial Contributors + +

+ The typescript-eslint project would not be possible without the + generous support of our financial contributors. +

+
+ + + +
+

+ Financial sponsors allow us to keep development of typescript-eslint + going, including maintaining and improving the project, providing + support to users, and pushing web ecosystem static analysis forward + with advances in typed linting. +

+
+ + Become a financial sponsor + +
+ + All sponsors + + + Sponsorship docs + +
+
+
+
+ ); +} diff --git a/packages/website/src/components/FinancialContributors/styles.module.css b/packages/website/src/components/home/FinancialContributors/styles.module.css similarity index 79% rename from packages/website/src/components/FinancialContributors/styles.module.css rename to packages/website/src/components/home/FinancialContributors/styles.module.css index c30c1163c341..dcb965fac306 100644 --- a/packages/website/src/components/FinancialContributors/styles.module.css +++ b/packages/website/src/components/home/FinancialContributors/styles.module.css @@ -1,8 +1,15 @@ -.sponsorLink { - display: inline-flex; - flex-direction: column; - gap: 8px; - height: 100%; +.financialContributors { + align-items: center; + background: var(--ifm-color-emphasis-0); + display: flex; + text-align: center; + width: 100%; +} + +.details { + font-size: 1.2rem; + max-width: 70vw; + margin: 2rem auto; } .linksArea { @@ -57,10 +64,6 @@ grid-area: 2 / 2 / 3 / 3; } - .sponsorLink { - display: flex; - } - .linksArea { margin: 24px; } diff --git a/packages/website/src/components/FinancialContributors/types.ts b/packages/website/src/components/home/FinancialContributors/types.ts similarity index 100% rename from packages/website/src/components/FinancialContributors/types.ts rename to packages/website/src/components/home/FinancialContributors/types.ts diff --git a/packages/website/src/components/home/RecentBlogPosts/index.tsx b/packages/website/src/components/home/RecentBlogPosts/index.tsx new file mode 100644 index 000000000000..94ccd1929217 --- /dev/null +++ b/packages/website/src/components/home/RecentBlogPosts/index.tsx @@ -0,0 +1,48 @@ +import Link from '@docusaurus/Link'; +import recentPosts from '@site/data/recent-blog-posts.json'; +import Heading from '@theme/Heading'; +import clsx from 'clsx'; +import React from 'react'; +import Markdown from 'react-markdown'; + +import styles from './styles.module.css'; + +export function RecentBlogPosts(): React.JSX.Element { + return ( +
+
+ + Recent Blog Posts + + + + See all blog posts + +
+
+ ); +} diff --git a/packages/website/src/components/home/RecentBlogPosts/styles.module.css b/packages/website/src/components/home/RecentBlogPosts/styles.module.css new file mode 100644 index 000000000000..26478b682905 --- /dev/null +++ b/packages/website/src/components/home/RecentBlogPosts/styles.module.css @@ -0,0 +1,84 @@ +.blogPosts { + background: var(--ifm-color-emphasis-100); + padding: 1rem 0; +} + +.postsList { + display: flex; + flex-direction: column; + gap: 1rem; + list-style: none; + margin: 2.5rem 0 1.5rem; + padding-left: 0; +} + +.post { + background: var(--ifm-color-emphasis-0); + border-radius: var(--ifm-global-radius); + display: flex; + flex-direction: column; + flex: 1; + padding: 1rem; + text-align: left; + transition: box-shadow 0.3s ease; +} + +[data-theme='dark'] .post { + background: var(--ifm-color-emphasis-200); +} + +.post:hover { + color: var(--ifm-heading-color); + text-decoration: none; + box-shadow: 0 3px 3px 0 var(--gray-border-shadow); +} + +.postLink, +.postLink:focus, +.postLink:hover { + color: initial; + text-decoration: none; + display: contents; +} + +.post p { + margin: 0; +} + +.postTitle { + font-weight: bold; + font-size: 1.2rem; + line-height: 1.25; + margin-bottom: 0.5rem; +} + +.postTiming { + align-items: flex-end; + display: flex; + flex-grow: 2; + font-size: 0.75rem; + font-style: italic; + gap: 0.35rem; + margin-top: 0.5rem; +} + +.seeAll { + font-size: 1.25rem; + padding: 0.75rem 1.75rem; + margin-top: 1.5rem; +} + +@media (width >= 996px) { + .blogPosts { + padding: 1rem 0 2rem; + } + + .postsList { + flex-direction: row; + gap: 2rem; + } + + .postTitle { + margin-bottom: 1rem; + } +} diff --git a/packages/website/src/components/FinancialContributors/Sponsor.tsx b/packages/website/src/components/home/Sponsor/index.tsx similarity index 90% rename from packages/website/src/components/FinancialContributors/Sponsor.tsx rename to packages/website/src/components/home/Sponsor/index.tsx index 3f3ce6d8036f..a2c90f871b02 100644 --- a/packages/website/src/components/FinancialContributors/Sponsor.tsx +++ b/packages/website/src/components/home/Sponsor/index.tsx @@ -1,7 +1,7 @@ import Link from '@docusaurus/Link'; import React from 'react'; -import type { SponsorData } from './types'; +import type { SponsorData } from '../FinancialContributors/types'; import styles from './styles.module.css'; diff --git a/packages/website/src/components/home/Sponsor/styles.module.css b/packages/website/src/components/home/Sponsor/styles.module.css new file mode 100644 index 000000000000..c722560fd076 --- /dev/null +++ b/packages/website/src/components/home/Sponsor/styles.module.css @@ -0,0 +1,12 @@ +.sponsorLink { + display: inline-flex; + flex-direction: column; + gap: 8px; + height: 100%; +} + +@media screen and (width >= 1150px) { + .sponsorLink { + display: flex; + } +} diff --git a/packages/website/src/components/FinancialContributors/Sponsors/index.tsx b/packages/website/src/components/home/Sponsors/index.tsx similarity index 91% rename from packages/website/src/components/FinancialContributors/Sponsors/index.tsx rename to packages/website/src/components/home/Sponsors/index.tsx index 68fc7cac4bfe..b3cf28471467 100644 --- a/packages/website/src/components/FinancialContributors/Sponsors/index.tsx +++ b/packages/website/src/components/home/Sponsors/index.tsx @@ -1,7 +1,7 @@ import clsx from 'clsx'; import React from 'react'; -import type { SponsorData } from '../types'; +import type { SponsorData } from '../FinancialContributors/types'; import { Sponsor } from '../Sponsor'; import styles from './styles.module.css'; diff --git a/packages/website/src/components/FinancialContributors/Sponsors/styles.module.css b/packages/website/src/components/home/Sponsors/styles.module.css similarity index 100% rename from packages/website/src/components/FinancialContributors/Sponsors/styles.module.css rename to packages/website/src/components/home/Sponsors/styles.module.css diff --git a/packages/website/src/pages/index.tsx b/packages/website/src/pages/index.tsx index 68befd7f8db2..5fd5fb883df0 100644 --- a/packages/website/src/pages/index.tsx +++ b/packages/website/src/pages/index.tsx @@ -1,188 +1,55 @@ import Link from '@docusaurus/Link'; import useBaseUrl from '@docusaurus/useBaseUrl'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import Heading from '@theme/Heading'; import Layout from '@theme/Layout'; import clsx from 'clsx'; import React from 'react'; -import { FinancialContributors } from '../components/FinancialContributors'; +import { Explainers } from '../components/home/Explainers'; +import { FinancialContributors } from '../components/home/FinancialContributors'; +import { RecentBlogPosts } from '../components/home/RecentBlogPosts'; import styles from './styles.module.css'; -interface FeatureItem { - description: React.JSX.Element; - imageUrl?: string; - title: string; -} - -const features: FeatureItem[] = [ - { - description: ( - <> -
-
- eslint -
-
-

- ESLint is an awesome linter for JavaScript code. -

-

- ESLint statically analyzes your code to quickly find problems. It - allows creating a series of assertions called lint rules around - what your code should look or behave like, as well as auto-fixer - suggestions to improve your code for you, and loading in lint - rules from shared plugins. -

-
-
-
-
- TypeScript -
-
-

- TypeScript is a strongly typed programming language that - builds on JavaScript. -

-

- TypeScript adds additional syntax to JavaScript that allows you to - declare the shapes of objects and functions in code. It provides a - set of language services that allow for running powerful - inferences and automations with that type information. -

-
-
- - ), - title: 'What are ESLint and TypeScript, and how do they compare?', - }, - { - description: ( -
-
-

- - typescript-eslint enables ESLint to run on TypeScript code. - {' '} - It brings in the best of both tools to help you write the best - JavaScript or TypeScript code you possibly can. -

-
-
-

- ESLint and TypeScript represent code differently internally. - ESLint's default JavaScript parser cannot natively read in - TypeScript-specific syntax and its rules don't natively have access - to TypeScript's type information. -

-
-
- typescript-eslint: -
    -
  • allows ESLint to parse TypeScript syntax
  • -
  • - creates a set of tools for ESLint rules to be able to use - TypeScript's type information -
  • -
  • - provides a large list of lint rules that are specific to - TypeScript and/or use that type information -
  • -
-
-
- ), - title: 'Why does this project exist?', - }, -]; - -function Feature({ description, title }: FeatureItem): React.JSX.Element { - return ( -
-
- - {title} - -
- {description} -
- - Get Started - -
-
- ); -} - function Home(): React.JSX.Element { const { siteConfig } = useDocusaurusContext(); return (
-
- Hero Logo -

{siteConfig.title}

-

{siteConfig.tagline}

-
- - Get Started - - - Playground - +
+
+

{siteConfig.title}

+

+ {siteConfig.tagline.replace(' code', '')} +

+
+ + Get Started + + + Playground + +
+
+
+ Hero Logo
- {features.map((props, idx) => ( -
-
-
- -
-
-
- ))} -
-
- - Financial Contributors - - -
-
+ + +
); diff --git a/packages/website/src/pages/styles.module.css b/packages/website/src/pages/styles.module.css index ee93e62557c6..2198015cabf8 100644 --- a/packages/website/src/pages/styles.module.css +++ b/packages/website/src/pages/styles.module.css @@ -18,9 +18,13 @@ text-align: center; } -.hero__logo { - height: 10rem; - width: 10rem; +.heroContainer { + display: flex; + justify-content: center; +} + +.heroRight { + display: none; } .hero__subtitle { @@ -34,17 +38,12 @@ flex-wrap: wrap; align-items: center; justify-content: center; + gap: 1rem; } .buttons a { --ifm-font-color-base: var(--ifm-color-white); --ifm-button-color: var(--ifm-color-white); - - margin: 1rem; -} - -.buttonCentered { - margin: auto; } .buttonPrimary { @@ -59,22 +58,33 @@ border: var(--ifm-button-border-width) solid var(--ifm-button-color); } -.lightBackground { - background: var(--ifm-color-emphasis-100); -} - -.features, -.sponsors { - display: flex; - align-items: center; - width: 100%; -} - -.sponsors { - text-align: center; -} - -.featureImage { - height: 7rem; - width: 7rem; +@media (width >= 996px) { + .heroContainer { + flex-direction: row; + gap: clamp(1rem, 10vw, 6rem); + } + + .heroLeft { + display: flex; + flex-direction: column; + justify-content: center; + text-align: left; + padding-bottom: 1rem; + } + + .buttons { + justify-content: flex-start; + } + + .heroRight { + display: initial; + } + + .heroLogo { + --hero-logo-size: clamp(5rem, 15vw, 15rem); + + height: var(--hero-logo-size); + user-select: none; + width: var(--hero-logo-size); + } } diff --git a/packages/website/static/manifest.json b/packages/website/static/manifest.json index 3eccbd4b2369..1b482ca36b80 100644 --- a/packages/website/static/manifest.json +++ b/packages/website/static/manifest.json @@ -1,6 +1,6 @@ { "background_color": "#443FD4", - "description": "Documentation for typescript-eslint: the tooling that enables ESLint to support TypeScript.", + "description": "Documentation for typescript-eslint: powerful static analysis for JavaScript and TypeScript.", "display": "standalone", "icons": [ { diff --git a/yarn.lock b/yarn.lock index d9e67a848c5e..2d5e7f9e5a19 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19535,6 +19535,7 @@ __metadata: cross-fetch: "*" docusaurus-plugin-typedoc: ^1.4.0 eslint: ^9.15.0 + gray-matter: ^4.0.3 history: ^4.9.0 json5: ^2.2.3 konamimojisplosion: ^0.5.2 @@ -19550,6 +19551,7 @@ __metadata: react-dom: ^18.2.0 react-markdown: ^10.0.0 react-resizable-panels: ^3.0.0 + reading-time: ^1.5.0 rimraf: "*" semver: ^7.6.0 stylelint: ^16.3.1 @@ -19563,6 +19565,7 @@ __metadata: unified: ^11.0.4 vfile: ^6.0.1 webpack: ^5.91.0 + zod: ^3.25.67 languageName: unknown linkType: soft @@ -20122,6 +20125,13 @@ __metadata: languageName: node linkType: hard +"zod@npm:^3.25.67": + version: 3.25.67 + resolution: "zod@npm:3.25.67" + checksum: 56ab904d33b1cd00041ce64ae05b0628fcbfeb7e707fa31cd498a97b540135e4dfe685200c9c62aea307695ee132870b4bc34f035228ea728aa75cc96a4954cb + languageName: node + linkType: hard + "zwitch@npm:^2.0.0": version: 2.0.4 resolution: "zwitch@npm:2.0.4" From 11b3e196e6adb0ad75475357c13fdd44d31d02ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josh=20Goldberg=20=E2=9C=A8?= Date: Thu, 26 Jun 2025 08:04:31 -0400 Subject: [PATCH 2/6] Update packages/website/plugins/recent-blog-posts/index.ts --- packages/website/plugins/recent-blog-posts/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/website/plugins/recent-blog-posts/index.ts b/packages/website/plugins/recent-blog-posts/index.ts index 1647d3d7954d..368e01d9bde9 100644 --- a/packages/website/plugins/recent-blog-posts/index.ts +++ b/packages/website/plugins/recent-blog-posts/index.ts @@ -39,7 +39,6 @@ export default async function blogPluginEnhanced(): Promise { }), ); - await fs.mkdir(storageDirectory, { recursive: true }); await fs.writeFile(storageFile, JSON.stringify(blogPosts, null, 2)); return { From dd1394157014cc8831c3fcf194517fbbb3611cc8 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Thu, 26 Jun 2025 08:06:38 -0400 Subject: [PATCH 3/6] recent-blog-posts/index.ts in knip --- knip.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/knip.ts b/knip.ts index 327290d9019a..9a9404dec18b 100644 --- a/knip.ts +++ b/knip.ts @@ -137,6 +137,7 @@ export default { 'src/components/**/*.tsx', // used by Docusaurus + 'plugins/recent-blog-posts/index.ts', 'src/theme/**/*.tsx', 'src/theme/prism-include-languages.js', ], From 5f0678e109450c258761c4c948c14b6165f1334d Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Thu, 26 Jun 2025 08:46:35 -0400 Subject: [PATCH 4/6] Remove unused variable --- packages/website/plugins/recent-blog-posts/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/website/plugins/recent-blog-posts/index.ts b/packages/website/plugins/recent-blog-posts/index.ts index 368e01d9bde9..a3f37b8b0d27 100644 --- a/packages/website/plugins/recent-blog-posts/index.ts +++ b/packages/website/plugins/recent-blog-posts/index.ts @@ -5,7 +5,6 @@ import * as fs from 'node:fs/promises'; import readingTime from 'reading-time'; import { z } from 'zod'; -const storageDirectory = 'data'; const storageFile = `data/recent-blog-posts.json`; const matterSchema = z.object({ From 780c238b3b0822e998be37a8ee199dc31c021e14 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Thu, 26 Jun 2025 08:48:39 -0400 Subject: [PATCH 5/6] Deduplicate Zod --- yarn.lock | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index 36b52c47e5b1..ed1d84b3955b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -20891,14 +20891,7 @@ __metadata: languageName: node linkType: hard -"zod@npm:^3.22.4, zod@npm:^3.23.8, zod@npm:^3.24.2": - version: 3.24.3 - resolution: "zod@npm:3.24.3" - checksum: 9c3976e61cec25908f3405502abdf28ab1893afd5182c6739a30375c5c6bf4b9b6ea7e78735324e5ac63571c160ce607ebe320ff389b044223c357ccc2f8c94c - languageName: node - linkType: hard - -"zod@npm:^3.25.67": +"zod@npm:^3.22.4, zod@npm:^3.23.8, zod@npm:^3.24.2, zod@npm:^3.25.67": version: 3.25.67 resolution: "zod@npm:3.25.67" checksum: 56ab904d33b1cd00041ce64ae05b0628fcbfeb7e707fa31cd498a97b540135e4dfe685200c9c62aea307695ee132870b4bc34f035228ea728aa75cc96a4954cb From 7a2aeb5caf5592e8b61cdecf81ca63ac7579be3a Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Thu, 26 Jun 2025 08:53:07 -0400 Subject: [PATCH 6/6] Small CSS tweaks --- .../website/src/components/home/ExplainerSpotlight/index.tsx | 2 +- .../src/components/home/ExplainerSpotlight/styles.module.css | 4 ++++ .../website/src/components/home/Explainers/styles.module.css | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/website/src/components/home/ExplainerSpotlight/index.tsx b/packages/website/src/components/home/ExplainerSpotlight/index.tsx index 57d45524c3bb..56fc2b5874a1 100644 --- a/packages/website/src/components/home/ExplainerSpotlight/index.tsx +++ b/packages/website/src/components/home/ExplainerSpotlight/index.tsx @@ -18,7 +18,7 @@ export function ExplainerSpotlight({ return ( - {header} {emoji} + {header} {emoji}
{children}
diff --git a/packages/website/src/components/home/ExplainerSpotlight/styles.module.css b/packages/website/src/components/home/ExplainerSpotlight/styles.module.css index c10751a2879f..97d9bb447a70 100644 --- a/packages/website/src/components/home/ExplainerSpotlight/styles.module.css +++ b/packages/website/src/components/home/ExplainerSpotlight/styles.module.css @@ -22,3 +22,7 @@ display: flex; justify-content: space-between; } + +.emoji { + user-select: none; +} diff --git a/packages/website/src/components/home/Explainers/styles.module.css b/packages/website/src/components/home/Explainers/styles.module.css index 62ad16abf89d..6e7e07c7488a 100644 --- a/packages/website/src/components/home/Explainers/styles.module.css +++ b/packages/website/src/components/home/Explainers/styles.module.css @@ -35,6 +35,10 @@ } @media (width >= 996px) { + .explainers { + margin-bottom: 2rem; + } + .explainerSpotlights { flex-direction: row; max-width: var(--ifm-container-width); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy