From b38851620ba4864de2a1e6090e869bf2e8712e2b Mon Sep 17 00:00:00 2001 From: Oscar Busk Date: Wed, 2 Nov 2022 09:33:29 +0100 Subject: [PATCH 001/119] Enable appDir in next configuration --- next.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/next.config.js b/next.config.js index 7368c90d..4332cd12 100644 --- a/next.config.js +++ b/next.config.js @@ -4,4 +4,5 @@ module.exports = { compiler: { emotion: true, }, + experimental: { appDir: true }, }; From f02ea0ec2631f8b4edb43d5f6d4b51f0cd44e6ec Mon Sep 17 00:00:00 2001 From: Oscar Busk Date: Wed, 2 Nov 2022 11:43:33 +0100 Subject: [PATCH 002/119] Disable emotion in compiler. It breaks app pages --- next.config.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/next.config.js b/next.config.js index 4332cd12..8d5779ec 100644 --- a/next.config.js +++ b/next.config.js @@ -1,8 +1,10 @@ /** @type {import('next').NextConfig} */ module.exports = { reactStrictMode: true, - compiler: { - emotion: true, - }, + // Does not work with appDir + // https://beta.nextjs.org/docs/styling/css-in-js + // compiler: { + // emotion: true, + // }, experimental: { appDir: true }, }; From 9959fc6343af6076e2c69224d04dfd8fc37b8a9e Mon Sep 17 00:00:00 2001 From: Oscar Busk Date: Wed, 2 Nov 2022 11:44:59 +0100 Subject: [PATCH 003/119] Add dummy app dir page --- src/app/dummy/page.tsx | 7 +++++++ src/app/layout.tsx | 13 +++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/app/dummy/page.tsx create mode 100644 src/app/layout.tsx diff --git a/src/app/dummy/page.tsx b/src/app/dummy/page.tsx new file mode 100644 index 00000000..b467708f --- /dev/null +++ b/src/app/dummy/page.tsx @@ -0,0 +1,7 @@ +import { NextPage } from "next"; + +export interface DummyPageProps {} + +const DummyPage: NextPage = () =>

App Directory!

; + +export default DummyPage; diff --git a/src/app/layout.tsx b/src/app/layout.tsx new file mode 100644 index 00000000..352d7447 --- /dev/null +++ b/src/app/layout.tsx @@ -0,0 +1,13 @@ +/* eslint-disable @next/next/no-head-element */ +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + + {children} + + ); +} From bf7e8d3fb7bcff7da28239cabbb7e70816282917 Mon Sep 17 00:00:00 2001 From: Oscar Busk Date: Wed, 2 Nov 2022 12:12:21 +0100 Subject: [PATCH 004/119] Move about over to app directory. Not working. --- src/{pages/about/api.tsx => app/about/api/page.tsx} | 3 ++- src/{pages/about/index.tsx => app/about/page.tsx} | 0 src/components/About/About.tsx | 1 + src/components/Header/NavLink.tsx | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) rename src/{pages/about/api.tsx => app/about/api/page.tsx} (97%) rename src/{pages/about/index.tsx => app/about/page.tsx} (100%) diff --git a/src/pages/about/api.tsx b/src/app/about/api/page.tsx similarity index 97% rename from src/pages/about/api.tsx rename to src/app/about/api/page.tsx index e47d16c1..30e77da9 100644 --- a/src/pages/about/api.tsx +++ b/src/app/about/api/page.tsx @@ -1,3 +1,4 @@ +"use client"; import { Code, Heading, Text, VStack } from "@chakra-ui/react"; import { GetStaticProps, NextPage } from "next"; import Layout from "^/components/Layout"; @@ -21,7 +22,7 @@ type Props = { specs: [string, string]; }; -export const getStaticProps: GetStaticProps = async ({}) => { +export const getProps: GetStaticProps = async ({}) => { const specsOrVersions = splitParts(EXAMPLE_QUERY); const { canonicalSpecs } = await destination(specsOrVersions); diff --git a/src/pages/about/index.tsx b/src/app/about/page.tsx similarity index 100% rename from src/pages/about/index.tsx rename to src/app/about/page.tsx diff --git a/src/components/About/About.tsx b/src/components/About/About.tsx index 77d520a0..e8af1f17 100644 --- a/src/components/About/About.tsx +++ b/src/components/About/About.tsx @@ -1,3 +1,4 @@ +"use client"; import { Code, Heading, diff --git a/src/components/Header/NavLink.tsx b/src/components/Header/NavLink.tsx index 32b33d27..d249dccd 100644 --- a/src/components/Header/NavLink.tsx +++ b/src/components/Header/NavLink.tsx @@ -12,7 +12,7 @@ const NavLink: FunctionComponent = ({ children, ...props }) => { - const { asPath } = useRouter(); + const { asPath } = useRouter() ?? {}; const [isActive, setIsActive] = useState(false); useEffect(() => { From cfdc3c2bfc781790363cc1e3ca778594dec03a75 Mon Sep 17 00:00:00 2001 From: Oscar Busk Date: Mon, 7 Nov 2022 14:01:34 +0100 Subject: [PATCH 005/119] Replace about/api into pages. The `getProps()` broke everything. --- src/{app/about/api/page.tsx => pages/about/api.tsx} | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) rename src/{app/about/api/page.tsx => pages/about/api.tsx} (97%) diff --git a/src/app/about/api/page.tsx b/src/pages/about/api.tsx similarity index 97% rename from src/app/about/api/page.tsx rename to src/pages/about/api.tsx index 30e77da9..e47d16c1 100644 --- a/src/app/about/api/page.tsx +++ b/src/pages/about/api.tsx @@ -1,4 +1,3 @@ -"use client"; import { Code, Heading, Text, VStack } from "@chakra-ui/react"; import { GetStaticProps, NextPage } from "next"; import Layout from "^/components/Layout"; @@ -22,7 +21,7 @@ type Props = { specs: [string, string]; }; -export const getProps: GetStaticProps = async ({}) => { +export const getStaticProps: GetStaticProps = async ({}) => { const specsOrVersions = splitParts(EXAMPLE_QUERY); const { canonicalSpecs } = await destination(specsOrVersions); From 95d3c793f3a25a8885b8fe1f1e439a1953761594 Mon Sep 17 00:00:00 2001 From: Oscar Busk Date: Mon, 7 Nov 2022 14:54:32 +0100 Subject: [PATCH 006/119] Migrate app/document into layout.tsx --- src/app/config.tsx | 15 +++++++++++++++ src/app/layout.tsx | 30 +++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 src/app/config.tsx diff --git a/src/app/config.tsx b/src/app/config.tsx new file mode 100644 index 00000000..84a9f9f7 --- /dev/null +++ b/src/app/config.tsx @@ -0,0 +1,15 @@ +"use client"; + +import { ChakraProvider, ColorModeScript } from "@chakra-ui/react"; +import { PropsWithChildren } from "react"; +import theme from "^/theme"; + +/** Configures the app with the necessary Context and scripts */ +export default function Config({ children }: PropsWithChildren<{}>) { + return ( + <> + + {children} + + ); +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 352d7447..e5e49546 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,13 +1,37 @@ /* eslint-disable @next/next/no-head-element */ + +import Config from "./config"; + export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( - - - {children} + + + + + + + + + {children} + ); } From 6134a3a5705cd3309be07b11995efa89acf20b74 Mon Sep 17 00:00:00 2001 From: Oscar Busk Date: Mon, 7 Nov 2022 14:59:31 +0100 Subject: [PATCH 007/119] remove dummy page, not needed anymore --- src/app/dummy/page.tsx | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 src/app/dummy/page.tsx diff --git a/src/app/dummy/page.tsx b/src/app/dummy/page.tsx deleted file mode 100644 index b467708f..00000000 --- a/src/app/dummy/page.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { NextPage } from "next"; - -export interface DummyPageProps {} - -const DummyPage: NextPage = () =>

App Directory!

; - -export default DummyPage; From e0e1a7fb44a6ddb74b70c5c93448fb1e66914ba8 Mon Sep 17 00:00:00 2001 From: Oscar Busk Date: Mon, 7 Nov 2022 15:05:29 +0100 Subject: [PATCH 008/119] Don't prefetch about/api pages --- src/components/Header/NavLink.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Header/NavLink.tsx b/src/components/Header/NavLink.tsx index d249dccd..f5818c4b 100644 --- a/src/components/Header/NavLink.tsx +++ b/src/components/Header/NavLink.tsx @@ -29,7 +29,7 @@ const NavLink: FunctionComponent = ({ }, [asPath, href]); return ( - + Date: Mon, 7 Nov 2022 15:12:37 +0100 Subject: [PATCH 009/119] Avoid warnings about next/image --- src/components/About/About.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/About/About.tsx b/src/components/About/About.tsx index e8af1f17..bd377292 100644 --- a/src/components/About/About.tsx +++ b/src/components/About/About.tsx @@ -76,6 +76,8 @@ const About = () => { We also use external services{" "} From 4ccb1f2f8438610c114804ed90811c1239da92ee Mon Sep 17 00:00:00 2001 From: Oscar Busk Date: Mon, 7 Nov 2022 15:28:02 +0100 Subject: [PATCH 010/119] Fix about not appearing as active in header --- src/components/Header/NavLink.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Header/NavLink.tsx b/src/components/Header/NavLink.tsx index f5818c4b..8e0ce255 100644 --- a/src/components/Header/NavLink.tsx +++ b/src/components/Header/NavLink.tsx @@ -1,5 +1,5 @@ import { Link, LinkProps } from "@chakra-ui/react"; -import { useRouter } from "next/router"; +import { usePathname } from "next/navigation"; import { FunctionComponent, useEffect, useState } from "react"; import { NextLink } from "^/components/theme"; @@ -12,7 +12,7 @@ const NavLink: FunctionComponent = ({ children, ...props }) => { - const { asPath } = useRouter() ?? {}; + const asPath = usePathname(); const [isActive, setIsActive] = useState(false); useEffect(() => { From 45bf88417c964e4b059a69777ad9db3c809173ac Mon Sep 17 00:00:00 2001 From: Oscar Busk Date: Mon, 7 Nov 2022 15:28:28 +0100 Subject: [PATCH 011/119] Revert "Don't prefetch about/api pages" This reverts commit 9110bb0673b6e99c5c507aa0183fdaa237411d8c. --- src/components/Header/NavLink.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Header/NavLink.tsx b/src/components/Header/NavLink.tsx index 8e0ce255..7d00938d 100644 --- a/src/components/Header/NavLink.tsx +++ b/src/components/Header/NavLink.tsx @@ -29,7 +29,7 @@ const NavLink: FunctionComponent = ({ }, [asPath, href]); return ( - + Date: Mon, 7 Nov 2022 15:48:26 +0100 Subject: [PATCH 012/119] Try to see if this fixes the various pre-loading issues. https://github.com/vercel/next.js/issues/42364#issuecomment-1300836034 --- src/middleware.ts | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/middleware.ts diff --git a/src/middleware.ts b/src/middleware.ts new file mode 100644 index 00000000..b6852a6e --- /dev/null +++ b/src/middleware.ts @@ -0,0 +1,8 @@ +import { NextResponse } from "next/server"; +import type { NextRequest } from "next/server"; + +export function middleware(request: NextRequest) { + // Temporary workaround to make navigation between app/pages work + // https://github.com/vercel/next.js/issues/42364#issuecomment-1300836034 + return NextResponse.rewrite(new URL(request.nextUrl.pathname, request.url)); +} From f6e73f68c24cbec7610bc2cf6450e8906fc7f129 Mon Sep 17 00:00:00 2001 From: Oscar Busk Date: Tue, 8 Nov 2022 10:23:32 +0100 Subject: [PATCH 013/119] Move index page into /app directory. Use props drilling to get FallbackSuggestions into SpecInput instead of using context. --- src/app/page.tsx | 11 ++++++++ src/components/Landing/Landing.tsx | 20 ++++++++----- src/components/Landing/MainForm/MainForm.tsx | 14 +++++++++- .../Landing/MainForm/SpecInput/SpecInput.tsx | 8 ++++-- src/lib/contexts/FallbackSuggestions.ts | 6 ---- src/pages/index.tsx | 28 ------------------- 6 files changed, 42 insertions(+), 45 deletions(-) create mode 100644 src/app/page.tsx delete mode 100644 src/lib/contexts/FallbackSuggestions.ts delete mode 100644 src/pages/index.tsx diff --git a/src/app/page.tsx b/src/app/page.tsx new file mode 100644 index 00000000..469da86f --- /dev/null +++ b/src/app/page.tsx @@ -0,0 +1,11 @@ +import Landing from "^/components/Landing"; +import fallback from "^/lib/autocomplete/fallback"; + +export interface IndexProps {} + +const IndexPage = async ({}: IndexProps) => { + const fallbackSuggestions = await fallback(); + return ; +}; + +export default IndexPage; diff --git a/src/components/Landing/Landing.tsx b/src/components/Landing/Landing.tsx index fbfce077..ebe63a6a 100644 --- a/src/components/Landing/Landing.tsx +++ b/src/components/Landing/Landing.tsx @@ -1,16 +1,20 @@ +"use client"; import { Stack, useBoolean } from "@chakra-ui/react"; -import { useRouter } from "next/router"; +import { useRouter } from "next/navigation"; import { FunctionComponent, useState } from "react"; import Layout from "^/components/Layout"; +import { AutocompleteSuggestion } from "^/lib/autocomplete"; import { DEFAULT_DIFF_FILES_GLOB } from "^/lib/default-diff-files"; import ExamplesList from "./ExamplesList"; import Intro from "./Intro"; import MainForm from "./MainForm/MainForm"; import OptionsForm from "./OptionsForm"; -export interface LandingProps {} +export interface LandingProps { + fallbackSuggestions: AutocompleteSuggestion[]; +} -const Landing: FunctionComponent = () => { +const Landing: FunctionComponent = ({ fallbackSuggestions }) => { const [overrides, setOverrides] = useState<{ a: string | null; b: string | null; @@ -41,10 +45,11 @@ const Landing: FunctionComponent = () => { const goToDiff = (a: string | undefined, b: string | undefined): void => { setLoading.on(); - router.push({ - pathname: `/${a}...${b}`, - query, - }); + router.push( + `/${a}...${b}?${Object.entries(query) + .map(([k, v]) => `${k}=${v}`) + .join("&")}`, + ); }; return ( @@ -56,6 +61,7 @@ const Landing: FunctionComponent = () => { overrideB={overrides.b} isLoading={isLoading} handleSubmit={goToDiff} + fallbackSuggestions={fallbackSuggestions} /> diff --git a/src/components/Landing/MainForm/MainForm.tsx b/src/components/Landing/MainForm/MainForm.tsx index cad014c2..9ac639a6 100644 --- a/src/components/Landing/MainForm/MainForm.tsx +++ b/src/components/Landing/MainForm/MainForm.tsx @@ -9,6 +9,7 @@ import { import npa from "npm-package-arg"; import { FormEvent, useCallback, useMemo, useRef, useState } from "react"; import { Tooltip } from "^/components/theme"; +import { AutocompleteSuggestion } from "^/lib/autocomplete"; import CenterInputAddon from "./CenterInputAddon"; import SpecInput from "./SpecInput"; @@ -19,11 +20,20 @@ export interface MainFormProps extends StackProps { overrideB: string | null; isLoading: boolean; handleSubmit: (a: string | undefined, b: string | undefined) => void; + fallbackSuggestions: AutocompleteSuggestion[]; } const MainForm = forwardRef( ( - { overrideA, overrideB, children, isLoading, handleSubmit, ...props }, + { + overrideA, + overrideB, + children, + isLoading, + handleSubmit, + fallbackSuggestions, + ...props + }, ref, ) => { const bRef = useRef(null); @@ -98,6 +108,7 @@ const MainForm = forwardRef( } : undefined), }} + fallbackSuggestions={fallbackSuggestions} > ( } : undefined), }} + fallbackSuggestions={fallbackSuggestions} > { inputProps?: Omit; inputRef?: RefObject; size: ComboboxBoxProps["size"]; + fallbackSuggestions?: AutocompleteSuggestion[]; } const SuggestionListText = ({ @@ -41,6 +42,7 @@ const SpecInput: FunctionComponent = ({ inputProps = {}, inputRef, size, + fallbackSuggestions = [], ...useNpmComboboxProps }) => { @@ -55,7 +57,7 @@ const SpecInput: FunctionComponent = ({ error, } = useNpmCombobox({ ...useNpmComboboxProps, - fallback: useContext(FallbackSuggestionsContext), + fallback: fallbackSuggestions, }); return ( diff --git a/src/lib/contexts/FallbackSuggestions.ts b/src/lib/contexts/FallbackSuggestions.ts deleted file mode 100644 index c847667f..00000000 --- a/src/lib/contexts/FallbackSuggestions.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createContext } from "react"; -import { AutocompleteSuggestion } from "^/lib/autocomplete"; - -export const FallbackSuggestionsContext = createContext< - AutocompleteSuggestion[] ->([]); diff --git a/src/pages/index.tsx b/src/pages/index.tsx deleted file mode 100644 index 95e98893..00000000 --- a/src/pages/index.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { GetStaticProps, NextPage } from "next"; -import Landing from "^/components/Landing"; -import AutocompleteSuggestion from "^/lib/autocomplete/AutocompleteSuggestion"; -import fallback from "^/lib/autocomplete/fallback"; -import { FallbackSuggestionsContext } from "^/lib/contexts/FallbackSuggestions"; - -export interface IndexProps { - fallbackSuggestions: AutocompleteSuggestion[]; -} - -export const getStaticProps: GetStaticProps = async () => { - return { - props: { - fallbackSuggestions: await fallback(), - }, - revalidate: 60 * 60, - }; -}; - -const IndexPage: NextPage = ({ fallbackSuggestions }) => { - return ( - - - - ); -}; - -export default IndexPage; From e84b02ad016f28db3ab932ddd26c3fca6ef88502 Mon Sep 17 00:00:00 2001 From: Oscar Busk Date: Tue, 8 Nov 2022 12:27:13 +0100 Subject: [PATCH 014/119] This lint-ignore should not be needed any more --- src/app/layout.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index e5e49546..b542a854 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,5 +1,3 @@ -/* eslint-disable @next/next/no-head-element */ - import Config from "./config"; export default function RootLayout({ From 303faabe69748c3455b0e5d9760478a422a160ff Mon Sep 17 00:00:00 2001 From: Oscar Busk Date: Tue, 8 Nov 2022 12:33:16 +0100 Subject: [PATCH 015/119] Move entire landing into app/ --- src/{components => app}/Landing/ExamplesList.tsx | 0 src/{components => app}/Landing/Intro.tsx | 0 src/{components => app}/Landing/Landing.tsx | 0 src/{components => app}/Landing/MainForm/CenterInputAddon.tsx | 0 src/{components => app}/Landing/MainForm/MainForm.tsx | 0 .../Landing/MainForm/SpecInput/Combobox/ComboboxBox.tsx | 0 .../Landing/MainForm/SpecInput/Combobox/ComboboxInput.tsx | 0 .../Landing/MainForm/SpecInput/Combobox/ComboboxSuggestion.tsx | 0 .../MainForm/SpecInput/Combobox/ComboboxSuggestionList.tsx | 0 .../Landing/MainForm/SpecInput/Combobox/ComboboxWrapper.tsx | 0 .../Landing/MainForm/SpecInput/Combobox/index.ts | 0 .../Landing/MainForm/SpecInput/SpecInput.tsx | 0 .../Landing/MainForm/SpecInput/Suggestion/Suggestion.tsx | 0 .../Landing/MainForm/SpecInput/Suggestion/Title.tsx | 0 .../Landing/MainForm/SpecInput/Suggestion/VersionTag.tsx | 0 .../Landing/MainForm/SpecInput/Suggestion/emphasized.tsx | 0 .../Landing/MainForm/SpecInput/Suggestion/index.ts | 0 src/{components => app}/Landing/MainForm/SpecInput/index.ts | 0 src/{components => app}/Landing/MainForm/index.ts | 0 src/{components => app}/Landing/OptionsForm.tsx | 2 +- src/{components => app}/Landing/index.ts | 0 src/app/page.tsx | 2 +- 22 files changed, 2 insertions(+), 2 deletions(-) rename src/{components => app}/Landing/ExamplesList.tsx (100%) rename src/{components => app}/Landing/Intro.tsx (100%) rename src/{components => app}/Landing/Landing.tsx (100%) rename src/{components => app}/Landing/MainForm/CenterInputAddon.tsx (100%) rename src/{components => app}/Landing/MainForm/MainForm.tsx (100%) rename src/{components => app}/Landing/MainForm/SpecInput/Combobox/ComboboxBox.tsx (100%) rename src/{components => app}/Landing/MainForm/SpecInput/Combobox/ComboboxInput.tsx (100%) rename src/{components => app}/Landing/MainForm/SpecInput/Combobox/ComboboxSuggestion.tsx (100%) rename src/{components => app}/Landing/MainForm/SpecInput/Combobox/ComboboxSuggestionList.tsx (100%) rename src/{components => app}/Landing/MainForm/SpecInput/Combobox/ComboboxWrapper.tsx (100%) rename src/{components => app}/Landing/MainForm/SpecInput/Combobox/index.ts (100%) rename src/{components => app}/Landing/MainForm/SpecInput/SpecInput.tsx (100%) rename src/{components => app}/Landing/MainForm/SpecInput/Suggestion/Suggestion.tsx (100%) rename src/{components => app}/Landing/MainForm/SpecInput/Suggestion/Title.tsx (100%) rename src/{components => app}/Landing/MainForm/SpecInput/Suggestion/VersionTag.tsx (100%) rename src/{components => app}/Landing/MainForm/SpecInput/Suggestion/emphasized.tsx (100%) rename src/{components => app}/Landing/MainForm/SpecInput/Suggestion/index.ts (100%) rename src/{components => app}/Landing/MainForm/SpecInput/index.ts (100%) rename src/{components => app}/Landing/MainForm/index.ts (100%) rename src/{components => app}/Landing/OptionsForm.tsx (93%) rename src/{components => app}/Landing/index.ts (100%) diff --git a/src/components/Landing/ExamplesList.tsx b/src/app/Landing/ExamplesList.tsx similarity index 100% rename from src/components/Landing/ExamplesList.tsx rename to src/app/Landing/ExamplesList.tsx diff --git a/src/components/Landing/Intro.tsx b/src/app/Landing/Intro.tsx similarity index 100% rename from src/components/Landing/Intro.tsx rename to src/app/Landing/Intro.tsx diff --git a/src/components/Landing/Landing.tsx b/src/app/Landing/Landing.tsx similarity index 100% rename from src/components/Landing/Landing.tsx rename to src/app/Landing/Landing.tsx diff --git a/src/components/Landing/MainForm/CenterInputAddon.tsx b/src/app/Landing/MainForm/CenterInputAddon.tsx similarity index 100% rename from src/components/Landing/MainForm/CenterInputAddon.tsx rename to src/app/Landing/MainForm/CenterInputAddon.tsx diff --git a/src/components/Landing/MainForm/MainForm.tsx b/src/app/Landing/MainForm/MainForm.tsx similarity index 100% rename from src/components/Landing/MainForm/MainForm.tsx rename to src/app/Landing/MainForm/MainForm.tsx diff --git a/src/components/Landing/MainForm/SpecInput/Combobox/ComboboxBox.tsx b/src/app/Landing/MainForm/SpecInput/Combobox/ComboboxBox.tsx similarity index 100% rename from src/components/Landing/MainForm/SpecInput/Combobox/ComboboxBox.tsx rename to src/app/Landing/MainForm/SpecInput/Combobox/ComboboxBox.tsx diff --git a/src/components/Landing/MainForm/SpecInput/Combobox/ComboboxInput.tsx b/src/app/Landing/MainForm/SpecInput/Combobox/ComboboxInput.tsx similarity index 100% rename from src/components/Landing/MainForm/SpecInput/Combobox/ComboboxInput.tsx rename to src/app/Landing/MainForm/SpecInput/Combobox/ComboboxInput.tsx diff --git a/src/components/Landing/MainForm/SpecInput/Combobox/ComboboxSuggestion.tsx b/src/app/Landing/MainForm/SpecInput/Combobox/ComboboxSuggestion.tsx similarity index 100% rename from src/components/Landing/MainForm/SpecInput/Combobox/ComboboxSuggestion.tsx rename to src/app/Landing/MainForm/SpecInput/Combobox/ComboboxSuggestion.tsx diff --git a/src/components/Landing/MainForm/SpecInput/Combobox/ComboboxSuggestionList.tsx b/src/app/Landing/MainForm/SpecInput/Combobox/ComboboxSuggestionList.tsx similarity index 100% rename from src/components/Landing/MainForm/SpecInput/Combobox/ComboboxSuggestionList.tsx rename to src/app/Landing/MainForm/SpecInput/Combobox/ComboboxSuggestionList.tsx diff --git a/src/components/Landing/MainForm/SpecInput/Combobox/ComboboxWrapper.tsx b/src/app/Landing/MainForm/SpecInput/Combobox/ComboboxWrapper.tsx similarity index 100% rename from src/components/Landing/MainForm/SpecInput/Combobox/ComboboxWrapper.tsx rename to src/app/Landing/MainForm/SpecInput/Combobox/ComboboxWrapper.tsx diff --git a/src/components/Landing/MainForm/SpecInput/Combobox/index.ts b/src/app/Landing/MainForm/SpecInput/Combobox/index.ts similarity index 100% rename from src/components/Landing/MainForm/SpecInput/Combobox/index.ts rename to src/app/Landing/MainForm/SpecInput/Combobox/index.ts diff --git a/src/components/Landing/MainForm/SpecInput/SpecInput.tsx b/src/app/Landing/MainForm/SpecInput/SpecInput.tsx similarity index 100% rename from src/components/Landing/MainForm/SpecInput/SpecInput.tsx rename to src/app/Landing/MainForm/SpecInput/SpecInput.tsx diff --git a/src/components/Landing/MainForm/SpecInput/Suggestion/Suggestion.tsx b/src/app/Landing/MainForm/SpecInput/Suggestion/Suggestion.tsx similarity index 100% rename from src/components/Landing/MainForm/SpecInput/Suggestion/Suggestion.tsx rename to src/app/Landing/MainForm/SpecInput/Suggestion/Suggestion.tsx diff --git a/src/components/Landing/MainForm/SpecInput/Suggestion/Title.tsx b/src/app/Landing/MainForm/SpecInput/Suggestion/Title.tsx similarity index 100% rename from src/components/Landing/MainForm/SpecInput/Suggestion/Title.tsx rename to src/app/Landing/MainForm/SpecInput/Suggestion/Title.tsx diff --git a/src/components/Landing/MainForm/SpecInput/Suggestion/VersionTag.tsx b/src/app/Landing/MainForm/SpecInput/Suggestion/VersionTag.tsx similarity index 100% rename from src/components/Landing/MainForm/SpecInput/Suggestion/VersionTag.tsx rename to src/app/Landing/MainForm/SpecInput/Suggestion/VersionTag.tsx diff --git a/src/components/Landing/MainForm/SpecInput/Suggestion/emphasized.tsx b/src/app/Landing/MainForm/SpecInput/Suggestion/emphasized.tsx similarity index 100% rename from src/components/Landing/MainForm/SpecInput/Suggestion/emphasized.tsx rename to src/app/Landing/MainForm/SpecInput/Suggestion/emphasized.tsx diff --git a/src/components/Landing/MainForm/SpecInput/Suggestion/index.ts b/src/app/Landing/MainForm/SpecInput/Suggestion/index.ts similarity index 100% rename from src/components/Landing/MainForm/SpecInput/Suggestion/index.ts rename to src/app/Landing/MainForm/SpecInput/Suggestion/index.ts diff --git a/src/components/Landing/MainForm/SpecInput/index.ts b/src/app/Landing/MainForm/SpecInput/index.ts similarity index 100% rename from src/components/Landing/MainForm/SpecInput/index.ts rename to src/app/Landing/MainForm/SpecInput/index.ts diff --git a/src/components/Landing/MainForm/index.ts b/src/app/Landing/MainForm/index.ts similarity index 100% rename from src/components/Landing/MainForm/index.ts rename to src/app/Landing/MainForm/index.ts diff --git a/src/components/Landing/OptionsForm.tsx b/src/app/Landing/OptionsForm.tsx similarity index 93% rename from src/components/Landing/OptionsForm.tsx rename to src/app/Landing/OptionsForm.tsx index 1418d695..fa1ee71f 100644 --- a/src/components/Landing/OptionsForm.tsx +++ b/src/app/Landing/OptionsForm.tsx @@ -6,7 +6,7 @@ import { Input, } from "@chakra-ui/react"; import { FunctionComponent } from "react"; -import ButtonExpandBox from "../theme/ButtonExpandBox"; +import ButtonExpandBox from "^/components/theme/ButtonExpandBox"; export interface OptionsFormProps extends FlexProps { files: string; diff --git a/src/components/Landing/index.ts b/src/app/Landing/index.ts similarity index 100% rename from src/components/Landing/index.ts rename to src/app/Landing/index.ts diff --git a/src/app/page.tsx b/src/app/page.tsx index 469da86f..e69bbe56 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,5 +1,5 @@ -import Landing from "^/components/Landing"; import fallback from "^/lib/autocomplete/fallback"; +import Landing from "./Landing"; export interface IndexProps {} From 569146003e7eefeaf4715f3d4b23a9a43f6b64f5 Mon Sep 17 00:00:00 2001 From: Oscar Busk Date: Sat, 12 Nov 2022 22:39:29 +0100 Subject: [PATCH 016/119] Create a clone of about/api in appdir --- src/app/about/api-2/page.client.tsx | 61 +++++++++++++++++++++++++++++ src/app/about/api-2/page.tsx | 31 +++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 src/app/about/api-2/page.client.tsx create mode 100644 src/app/about/api-2/page.tsx diff --git a/src/app/about/api-2/page.client.tsx b/src/app/about/api-2/page.client.tsx new file mode 100644 index 00000000..1c5f0c47 --- /dev/null +++ b/src/app/about/api-2/page.client.tsx @@ -0,0 +1,61 @@ +"use client"; +import { Code, Heading, Text, VStack } from "@chakra-ui/react"; +import Layout from "^/components/Layout"; +import { ExternalLink, Tooltip } from "^/components/theme"; + +export interface AboutApiPageClientProps { + diff: string; + specs: [string, string]; + exampleAbsoluteUrl: string; +} + +const AboutApiPageClient = ({ + diff, + specs, + exampleAbsoluteUrl, +}: AboutApiPageClientProps) => ( + + + + npm-diff.app API + + + npm-diff.app exposes a online API to equal{" "} + + npm diff + + , to be able to see the changes between versions of packages or + forks of packages. + + + + + GET{" "} + + + {exampleAbsoluteUrl} + + + +
+ will return the same as +
+ + npm diff --diff={specs[0]} --diff={specs[1]} + +
+ + a diff of the two provided packages + + + {diff} + +
+
+); + +export default AboutApiPageClient; diff --git a/src/app/about/api-2/page.tsx b/src/app/about/api-2/page.tsx new file mode 100644 index 00000000..0169f383 --- /dev/null +++ b/src/app/about/api-2/page.tsx @@ -0,0 +1,31 @@ +import destination from "^/lib/destination"; +import doDiff from "^/lib/diff"; +import EXAMPLES from "^/lib/examples"; +import splitParts from "^/lib/utils/splitParts"; +import AboutApiPageClient from "./page.client"; + +// TODO: Would be nice if this was dynamic. But doesn't seem possible +// https://github.com/vercel/next.js/discussions/12848 +const API_PATH = `/api` as const; +const EXAMPLE_QUERY = EXAMPLES[0]; +const EXAMPLE_RELATIVE_LINK = `${API_PATH}/${EXAMPLE_QUERY}` as const; + +const DOMAIN = "https://npm-diff.app"; +const EXAMPLE_ABSOLUTE_URL = `${DOMAIN}${EXAMPLE_RELATIVE_LINK}` as const; + +const AboutApiPage = async () => { + const specsOrVersions = splitParts(EXAMPLE_QUERY); + const { canonicalSpecs } = await destination(specsOrVersions); + + const diff = await doDiff(canonicalSpecs, {}); + + return ( + + ); +}; + +export default AboutApiPage; From 8e9ba00c4ee6c0f0ab27f1e8054312c4654fb1fa Mon Sep 17 00:00:00 2001 From: Oscar Busk Date: Tue, 15 Nov 2022 21:23:00 +0100 Subject: [PATCH 017/119] Replace pages/about/api with app/about/api --- src/app/about/{api-2 => api}/page.client.tsx | 0 src/app/about/{api-2 => api}/page.tsx | 0 src/pages/about/api.tsx | 80 -------------------- 3 files changed, 80 deletions(-) rename src/app/about/{api-2 => api}/page.client.tsx (100%) rename src/app/about/{api-2 => api}/page.tsx (100%) delete mode 100644 src/pages/about/api.tsx diff --git a/src/app/about/api-2/page.client.tsx b/src/app/about/api/page.client.tsx similarity index 100% rename from src/app/about/api-2/page.client.tsx rename to src/app/about/api/page.client.tsx diff --git a/src/app/about/api-2/page.tsx b/src/app/about/api/page.tsx similarity index 100% rename from src/app/about/api-2/page.tsx rename to src/app/about/api/page.tsx diff --git a/src/pages/about/api.tsx b/src/pages/about/api.tsx deleted file mode 100644 index e47d16c1..00000000 --- a/src/pages/about/api.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { Code, Heading, Text, VStack } from "@chakra-ui/react"; -import { GetStaticProps, NextPage } from "next"; -import Layout from "^/components/Layout"; -import { ExternalLink, Tooltip } from "^/components/theme"; -import destination from "^/lib/destination"; -import doDiff from "^/lib/diff"; -import EXAMPLES from "^/lib/examples"; -import splitParts from "^/lib/utils/splitParts"; - -// TODO: Would be nice if this was dynamic. But doesn't seem possible -// https://github.com/vercel/next.js/discussions/12848 -const API_PATH = `/api` as const; -const EXAMPLE_QUERY = EXAMPLES[0]; -const EXAMPLE_RELATIVE_LINK = `${API_PATH}/${EXAMPLE_QUERY}` as const; - -const DOMAIN = "https://npm-diff.app"; -const EXAMPLE_ABSOLUTE_URL = `${DOMAIN}${EXAMPLE_RELATIVE_LINK}` as const; - -type Props = { - diff: string; - specs: [string, string]; -}; - -export const getStaticProps: GetStaticProps = async ({}) => { - const specsOrVersions = splitParts(EXAMPLE_QUERY); - const { canonicalSpecs } = await destination(specsOrVersions); - - const diff = await doDiff(canonicalSpecs, {}); - - return { props: { diff, specs: canonicalSpecs } }; -}; - -const ApiPage: NextPage = ({ diff, specs }) => { - return ( - - - - npm-diff.app API - - - npm-diff.app exposes a online API to equal{" "} - - npm diff - - , to be able to see the changes between versions of packages - or forks of packages. - - - - - GET{" "} - - - {EXAMPLE_ABSOLUTE_URL} - - - -
- will return the same as -
- - npm diff --diff={specs[0]} --diff={specs[1]} - -
- - a diff of the two provided packages - - - {diff} - -
-
- ); -}; - -export default ApiPage; From 360b7fb34afe6185bd3238dfccfd2cc4069a3299 Mon Sep 17 00:00:00 2001 From: Oscar Busk Date: Tue, 15 Nov 2022 21:28:41 +0100 Subject: [PATCH 018/119] Move diffpage into app dir - Step 1/2 - Rename --- src/{pages/[...parts].tsx => app/[...parts]/page.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{pages/[...parts].tsx => app/[...parts]/page.tsx} (100%) diff --git a/src/pages/[...parts].tsx b/src/app/[...parts]/page.tsx similarity index 100% rename from src/pages/[...parts].tsx rename to src/app/[...parts]/page.tsx From 59773fe3da9849e4005a665c403ca2f2a6b51205 Mon Sep 17 00:00:00 2001 From: Oscar Busk Date: Wed, 16 Nov 2022 01:52:26 +0100 Subject: [PATCH 019/119] Use npm lib packages as external packages --- next.config.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/next.config.js b/next.config.js index 8d5779ec..fbe0a2bb 100644 --- a/next.config.js +++ b/next.config.js @@ -6,5 +6,8 @@ module.exports = { // compiler: { // emotion: true, // }, - experimental: { appDir: true }, + experimental: { + serverComponentsExternalPackages: ["libnpmdiff", "pacote"], + appDir: true, + }, }; From ed1cfc745444eba26a89fc9dcac14eaa23bcface Mon Sep 17 00:00:00 2001 From: Oscar Busk Date: Wed, 16 Nov 2022 01:56:52 +0100 Subject: [PATCH 020/119] Migrate ViewTypeSwitch to use next/navigation --- src/components/DiffIntro/ViewTypeSwitch.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/DiffIntro/ViewTypeSwitch.tsx b/src/components/DiffIntro/ViewTypeSwitch.tsx index 9fca2d76..be3ebe2e 100644 --- a/src/components/DiffIntro/ViewTypeSwitch.tsx +++ b/src/components/DiffIntro/ViewTypeSwitch.tsx @@ -5,9 +5,9 @@ import { ButtonProps, forwardRef, } from "@chakra-ui/react"; -import { useRouter } from "next/router"; +import { usePathname, useSearchParams } from "next/navigation"; import { ViewType } from "react-diff-view"; -import { DIFF_TYPE_PARAM_NAME } from "^/pages/[...parts]"; +import DIFF_TYPE_PARAM_NAME from "^/DIFF_TYPE_PARAM_NAME"; import { NextLink } from "../theme"; export interface ViewTypeButtonProps extends ButtonProps { @@ -18,13 +18,15 @@ export interface ViewTypeButtonProps extends ButtonProps { const ViewTypeButton = forwardRef( ({ viewType, title, currentViewType, ...props }, ref) => { - const router = useRouter(); + const searchParams = useSearchParams(); + const pathname = usePathname(); return ( Date: Wed, 16 Nov 2022 01:58:38 +0100 Subject: [PATCH 021/119] Move diffpage into app dir - Stem 2/2 - Convert --- src/DIFF_TYPE_PARAM_NAME.ts | 2 + src/app/[...parts]/page.tsx | 276 ++++++++---------------------------- src/app/[...parts]/view.tsx | 172 ++++++++++++++++++++++ 3 files changed, 232 insertions(+), 218 deletions(-) create mode 100644 src/DIFF_TYPE_PARAM_NAME.ts create mode 100644 src/app/[...parts]/view.tsx diff --git a/src/DIFF_TYPE_PARAM_NAME.ts b/src/DIFF_TYPE_PARAM_NAME.ts new file mode 100644 index 00000000..87f6562d --- /dev/null +++ b/src/DIFF_TYPE_PARAM_NAME.ts @@ -0,0 +1,2 @@ +const DIFF_TYPE_PARAM_NAME = "diff"; +export default DIFF_TYPE_PARAM_NAME; diff --git a/src/app/[...parts]/page.tsx b/src/app/[...parts]/page.tsx index b0619372..8598436b 100644 --- a/src/app/[...parts]/page.tsx +++ b/src/app/[...parts]/page.tsx @@ -1,64 +1,42 @@ -import { Center, useBreakpointValue } from "@chakra-ui/react"; -import { GetServerSideProps, NextPage } from "next"; -import { useRouter } from "next/router"; -import npa, { Result as NpaResult } from "npm-package-arg"; -import { ParsedUrlQuery } from "querystring"; -import { memo, useMemo, useState } from "react"; -import type { File } from "react-diff-view"; -import { parseDiff, ViewType } from "react-diff-view"; -import DiffFiles from "^/components/Diff/DiffFiles"; -import DiffIntro from "^/components/DiffIntro"; -import ErrorBox from "^/components/ErrorBox"; -import Layout from "^/components/Layout"; -import adjustDiff from "^/lib/adjustDiff"; -import bundlephobia, { BundlephobiaResults } from "^/lib/api/bundlephobia"; -import packagephobia, { PackagephobiaResults } from "^/lib/api/packagephobia"; +import { REDIRECT_ERROR_CODE } from "next/dist/client/components/redirect"; +import { headers } from "next/headers"; +import { redirect } from "next/navigation"; +import { ViewType } from "react-diff-view"; +import DIFF_TYPE_PARAM_NAME from "^/DIFF_TYPE_PARAM_NAME"; +import bundlephobia from "^/lib/api/bundlephobia"; +import packagephobia from "^/lib/api/packagephobia"; import TIMED_OUT from "^/lib/api/TimedOut"; import { DEFAULT_DIFF_FILES_GLOB } from "^/lib/default-diff-files"; import destination from "^/lib/destination"; import doDiff, { DiffError } from "^/lib/diff"; -import DiffOptions from "^/lib/DiffOptions"; import measuredPromise from "^/lib/measuredPromise"; -import { parseQuery, QueryParams, rawQuery } from "^/lib/query"; -import { setDefaultPageCaching, setSwrCaching } from "^/lib/utils/headers"; +import { parseQuery, QueryParams } from "^/lib/query"; import specsToDiff from "^/lib/utils/specsToDiff"; import splitParts from "^/lib/utils/splitParts"; +import DiffView from "./view"; -type Props = { - error?: string; - result?: { - diff: string; - specs: [string, string]; - packagephobiaResults: PackagephobiaResults | null; - bundlephobiaResults: BundlephobiaResults | null; - options: DiffOptions; - }; -}; - -export const DIFF_TYPE_PARAM_NAME = "diff"; - -interface Params extends ParsedUrlQuery { - parts: string | string[]; - [DIFF_TYPE_PARAM_NAME]: ViewType; -} - -export const getServerSideProps: GetServerSideProps = async ({ - params: { parts } = {}, - query = {}, - req, - res, -}) => { +const DiffPage = async ({ + params: { parts }, + searchParams, +}: { + params: { parts: string | string[] }; + searchParams: QueryParams & { [DIFF_TYPE_PARAM_NAME]: ViewType }; +}): Promise => { try { - const { diffFiles, ...optionsQuery } = query as QueryParams; + const headersList = headers(); + const { diffFiles, ...optionsQuery } = searchParams; const specsOrVersions = splitParts(parts); - const { redirect, canonicalSpecs } = await destination(specsOrVersions); + const { redirect: redirectTarget, canonicalSpecs } = await destination( + specsOrVersions, + ); - if (redirect !== "temporary") { - setDefaultPageCaching(res); - } + // TODO(#703) - implement correct caching + // if (redirect !== "temporary") { + // setDefaultPageCaching(res); + // } - if (redirect === false) { + if (redirectTarget === false) { const options = parseQuery({ // If no diffFiles is passed, use the default. // This is done here, since we don't want a fall back in the API @@ -80,13 +58,10 @@ export const getServerSideProps: GetServerSideProps = async ({ } catch (e) { const { code, error } = e as DiffError; - res.statusCode = code; + // TODO(#703) - statuscode? + // res.statusCode = code; - return { - props: { - error, - }, - }; + return ; } let [ @@ -96,13 +71,15 @@ export const getServerSideProps: GetServerSideProps = async ({ if (packagephobiaResults === TIMED_OUT) { // If packagephobia timed out, we don't want to cache forever, instead use SWR caching - setSwrCaching(res); + // TODO(#703) - implement correct caching + // setSwrCaching(res); packagephobiaResults = null; } if (bundlephobiaResults === TIMED_OUT) { // If bundlephobia timed out, we don't want to cache forever, instead use SWR cachin - setSwrCaching(res); + // TODO(#703) - implement correct caching + // setSwrCaching(res); bundlephobiaResults = null; } @@ -113,180 +90,43 @@ export const getServerSideProps: GetServerSideProps = async ({ packagephobia: packagephobiaTime, bundlephobia: bundlephobiaTime, }, - caching: res.getHeader("Cache-Control"), + caching: headersList.get("Cache-Control"), }); - return { - props: { - result: { + return ( + + ); } else { - return { - redirect: { - permanent: redirect === "permanent", - destination: - `/${specsToDiff(canonicalSpecs)}` + - rawQuery(req, "parts"), - }, - }; + // return { + // redirect: { + // permanent: redirect === "permanent", + // destination: + // `/${specsToDiff(canonicalSpecs)}` + + // rawQuery(req, "parts"), + // }, + // }; + // TODO(#703) How to do permanent? + redirect( + `/${specsToDiff(canonicalSpecs)}?${Object.entries(searchParams) + .map(([key, value]) => `${key}=${value}`) + .join("&")}`, + ); } } catch (e: any) { - return { - props: { - error: e?.message ?? e ?? "Unknown error", - }, - }; - } -}; - -const DiffPage: NextPage = ({ error, result }) => { - const { diff, packagephobiaResults, bundlephobiaResults, options } = - result!; - - const router = useRouter(); - // Even if the initial value and the first breakpoint value is the same, - // the component will re-render. This means it will _always_ render twice - // even when it shouldn't have to. - // We work around this by memoizing the rendering of the component. - const defaultViewType = useBreakpointValue( - { - base: "unified", - lg: "split", - }, - // We assume that most users are on a computer so default to "lg". - // We could use something like https://github.com/kaimallea/isMobile - // but that means cache should be different for desktop/mobile - "lg", - )!; - - const [a, b] = result?.specs ?? []; - const aNpa = useMemo(() => (a ? npa(a) : undefined), [a]); - const bNpa = useMemo(() => (b ? npa(b) : undefined), [b]); - const files = useMemo(() => { - if (diff) { - const adjustedDiff = adjustDiff(diff); - if (adjustedDiff) { - return parseDiff(adjustedDiff); - } + if (e.digest?.startsWith(REDIRECT_ERROR_CODE)) { + // We need to propagate the error to the worker + throw e; } - - return null; - }, [diff]); - - if (aNpa === undefined || bNpa === undefined) { - return ( - - Specs could not be parsed - - ); - } - - if (diff === "") { - return ( - - - - ); - } - - if (files == null) { - return ( - -
- Files could not be parsed -
-
- ); + return ; } - - if (error != null) { - return ( - -
- {error} -
-
- ); - } - - const viewType = - // If specified in URL, use that - router.query[DIFF_TYPE_PARAM_NAME] === "split" - ? "split" - : router.query[DIFF_TYPE_PARAM_NAME] === "unified" - ? "unified" - : // If not, use default based on screen size - defaultViewType; - - return ( - - - - ); }; -const DiffPageContent = ({ - aNpa, - bNpa, - files, - packagephobiaResults, - bundlephobiaResults, - options, - viewType, -}: { - aNpa: NpaResult; - bNpa: NpaResult; - files: File[]; - packagephobiaResults: PackagephobiaResults | null; - bundlephobiaResults: BundlephobiaResults | null; - options: DiffOptions; - viewType: ViewType; -}) => ( - <> - - - -); - -const MemoizedDiffPageContent = memo(DiffPageContent); - export default DiffPage; diff --git a/src/app/[...parts]/view.tsx b/src/app/[...parts]/view.tsx new file mode 100644 index 00000000..48fc9789 --- /dev/null +++ b/src/app/[...parts]/view.tsx @@ -0,0 +1,172 @@ +"use client"; +import { Center, useBreakpointValue } from "@chakra-ui/react"; +import { useSearchParams } from "next/navigation"; +import npa, { Result as NpaResult } from "npm-package-arg"; +import { FunctionComponent, memo, useMemo } from "react"; +import type { File } from "react-diff-view"; +import { parseDiff, ViewType } from "react-diff-view"; +import DiffFiles from "^/components/Diff/DiffFiles"; +import DiffIntro from "^/components/DiffIntro"; +import ErrorBox from "^/components/ErrorBox"; +import Layout from "^/components/Layout"; +import DIFF_TYPE_PARAM_NAME from "^/DIFF_TYPE_PARAM_NAME"; +import adjustDiff from "^/lib/adjustDiff"; +import { BundlephobiaResults } from "^/lib/api/bundlephobia"; +import { PackagephobiaResults } from "^/lib/api/packagephobia"; +import DiffOptions from "^/lib/DiffOptions"; + +type Props = { + error?: string; + result?: { + diff: string; + specs: [string, string]; + packagephobiaResults: PackagephobiaResults | null; + bundlephobiaResults: BundlephobiaResults | null; + options: DiffOptions; + }; +}; + +const DiffView: FunctionComponent = ({ error, result } = {}) => { + const { diff, packagephobiaResults, bundlephobiaResults, options } = + result! ?? {}; + + const searchParams = useSearchParams(); + // Even if the initial value and the first breakpoint value is the same, + // the component will re-render. This means it will _always_ render twice + // even when it shouldn't have to. + // We work around this by memoizing the rendering of the component. + const defaultViewType = useBreakpointValue( + { + base: "unified", + lg: "split", + }, + // We assume that most users are on a computer so default to "lg". + // We could use something like https://github.com/kaimallea/isMobile + // but that means cache should be different for desktop/mobile + "lg", + )!; + + const [a, b] = result?.specs ?? []; + const aNpa = useMemo(() => (a ? npa(a) : undefined), [a]); + const bNpa = useMemo(() => (b ? npa(b) : undefined), [b]); + const files = useMemo(() => { + if (diff) { + const adjustedDiff = adjustDiff(diff); + if (adjustedDiff) { + return parseDiff(adjustedDiff); + } + } + + return null; + }, [diff]); + + if (aNpa === undefined || bNpa === undefined) { + return ( + + Specs could not be parsed + + ); + } + + if (diff === "") { + return ( + + + + ); + } + + if (files == null) { + return ( + +
+ Files could not be parsed +
+
+ ); + } + + if (error != null) { + return ( + +
+ {error} +
+
+ ); + } + + const viewType = + // If specified in URL, use that + searchParams.get(DIFF_TYPE_PARAM_NAME) === "split" + ? "split" + : searchParams.get(DIFF_TYPE_PARAM_NAME) === "unified" + ? "unified" + : // If not, use default based on screen size + defaultViewType; + + return ( + + + + ); +}; + +const DiffPageContent = ({ + aNpa, + bNpa, + files, + packagephobiaResults, + bundlephobiaResults, + options, + viewType, +}: { + aNpa: NpaResult; + bNpa: NpaResult; + files: File[]; + packagephobiaResults: PackagephobiaResults | null; + bundlephobiaResults: BundlephobiaResults | null; + options: DiffOptions; + viewType: ViewType; +}) => ( + <> + + + +); + +const MemoizedDiffPageContent = memo(DiffPageContent); + +export default DiffView; From 49d456660239a00841f944e25c26a7475648bf28 Mon Sep 17 00:00:00 2001 From: Oscar Busk Date: Wed, 16 Nov 2022 02:01:20 +0100 Subject: [PATCH 022/119] Remove middleware that should no longer be needed --- src/middleware.ts | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 src/middleware.ts diff --git a/src/middleware.ts b/src/middleware.ts deleted file mode 100644 index b6852a6e..00000000 --- a/src/middleware.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { NextResponse } from "next/server"; -import type { NextRequest } from "next/server"; - -export function middleware(request: NextRequest) { - // Temporary workaround to make navigation between app/pages work - // https://github.com/vercel/next.js/issues/42364#issuecomment-1300836034 - return NextResponse.rewrite(new URL(request.nextUrl.pathname, request.url)); -} From 1d780de25b819c7a52d422448282aa1013e290b6 Mon Sep 17 00:00:00 2001 From: Oscar Busk Date: Wed, 16 Nov 2022 09:03:57 +0100 Subject: [PATCH 023/119] Delete pages/_app and pages/_document --- src/pages/_app.tsx | 13 ------------- src/pages/_document.tsx | 40 ---------------------------------------- 2 files changed, 53 deletions(-) delete mode 100644 src/pages/_app.tsx delete mode 100644 src/pages/_document.tsx diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx deleted file mode 100644 index 951c07c7..00000000 --- a/src/pages/_app.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { ChakraProvider } from "@chakra-ui/react"; -import { AppProps } from "next/app"; -import theme from "^/theme"; - -function MyApp({ Component, pageProps }: AppProps) { - return ( - - - - ); -} - -export default MyApp; diff --git a/src/pages/_document.tsx b/src/pages/_document.tsx deleted file mode 100644 index fba6ebcb..00000000 --- a/src/pages/_document.tsx +++ /dev/null @@ -1,40 +0,0 @@ -/* eslint-disable @next/next/no-document-import-in-page */ -import { ColorModeScript } from "@chakra-ui/react"; -import NextDocument, { Head, Html, Main, NextScript } from "next/document"; -import theme from "^/theme"; - -export default class Document extends NextDocument { - render() { - return ( - - - - - - - - - -
- - - - ); - } -} From 9eef0b46ebaac8a0b4bbd01ddae8ded4f1cce863 Mon Sep 17 00:00:00 2001 From: Oscar Busk Date: Wed, 16 Nov 2022 22:57:44 +0100 Subject: [PATCH 024/119] Set title and description --- src/app/Landing/Landing.tsx | 6 ++-- src/app/[...parts]/page.tsx | 3 ++ src/app/[...parts]/view.tsx | 22 ++++++------- src/app/about/api/page.client.tsx | 6 ++-- src/app/config.tsx | 15 --------- src/app/layout.client.tsx | 28 +++++++++++++++++ src/app/layout.tsx | 11 +++++-- src/components/About/About.tsx | 11 +++---- src/components/Layout.tsx | 48 ----------------------------- src/lib/metaData/MetaData.tsx | 19 ++++++++++++ src/lib/metaData/defaultMetaData.ts | 5 +++ src/lib/metaData/index.ts | 13 ++++++++ src/lib/metaData/metaDataUtil.ts | 10 ++++++ src/lib/metaData/useMetaData.ts | 23 ++++++++++++++ 14 files changed, 131 insertions(+), 89 deletions(-) delete mode 100644 src/app/config.tsx create mode 100644 src/app/layout.client.tsx delete mode 100644 src/components/Layout.tsx create mode 100644 src/lib/metaData/MetaData.tsx create mode 100644 src/lib/metaData/defaultMetaData.ts create mode 100644 src/lib/metaData/index.ts create mode 100644 src/lib/metaData/metaDataUtil.ts create mode 100644 src/lib/metaData/useMetaData.ts diff --git a/src/app/Landing/Landing.tsx b/src/app/Landing/Landing.tsx index ebe63a6a..22108dc9 100644 --- a/src/app/Landing/Landing.tsx +++ b/src/app/Landing/Landing.tsx @@ -2,9 +2,9 @@ import { Stack, useBoolean } from "@chakra-ui/react"; import { useRouter } from "next/navigation"; import { FunctionComponent, useState } from "react"; -import Layout from "^/components/Layout"; import { AutocompleteSuggestion } from "^/lib/autocomplete"; import { DEFAULT_DIFF_FILES_GLOB } from "^/lib/default-diff-files"; +import { MetaData } from "^/lib/metaData"; import ExamplesList from "./ExamplesList"; import Intro from "./Intro"; import MainForm from "./MainForm/MainForm"; @@ -53,7 +53,7 @@ const Landing: FunctionComponent = ({ fallbackSuggestions }) => { }; return ( - + = ({ fallbackSuggestions }) => { exampleClicked={() => !isLoading && exampleClicked()} queryParams={query} /> - + ); }; diff --git a/src/app/[...parts]/page.tsx b/src/app/[...parts]/page.tsx index 8598436b..1d6ffce1 100644 --- a/src/app/[...parts]/page.tsx +++ b/src/app/[...parts]/page.tsx @@ -15,6 +15,9 @@ import specsToDiff from "^/lib/utils/specsToDiff"; import splitParts from "^/lib/utils/splitParts"; import DiffView from "./view"; +// TODO: Don't use the same component for errors and diff page +// TODO: Set title and description using `head.tsx` so that they +// are set before `useEffect()` const DiffPage = async ({ params: { parts }, searchParams, diff --git a/src/app/[...parts]/view.tsx b/src/app/[...parts]/view.tsx index 48fc9789..88e5e971 100644 --- a/src/app/[...parts]/view.tsx +++ b/src/app/[...parts]/view.tsx @@ -8,12 +8,12 @@ import { parseDiff, ViewType } from "react-diff-view"; import DiffFiles from "^/components/Diff/DiffFiles"; import DiffIntro from "^/components/DiffIntro"; import ErrorBox from "^/components/ErrorBox"; -import Layout from "^/components/Layout"; import DIFF_TYPE_PARAM_NAME from "^/DIFF_TYPE_PARAM_NAME"; import adjustDiff from "^/lib/adjustDiff"; import { BundlephobiaResults } from "^/lib/api/bundlephobia"; import { PackagephobiaResults } from "^/lib/api/packagephobia"; import DiffOptions from "^/lib/DiffOptions"; +import { MetaData } from "^/lib/metaData"; type Props = { error?: string; @@ -62,15 +62,15 @@ const DiffView: FunctionComponent = ({ error, result } = {}) => { if (aNpa === undefined || bNpa === undefined) { return ( - + Specs could not be parsed - + ); } if (diff === "") { return ( - @@ -84,27 +84,27 @@ const DiffView: FunctionComponent = ({ error, result } = {}) => { viewType="unified" alignSelf="stretch" /> - + ); } if (files == null) { return ( - +
Files could not be parsed
-
+ ); } if (error != null) { return ( - +
{error}
-
+ ); } @@ -118,7 +118,7 @@ const DiffView: FunctionComponent = ({ error, result } = {}) => { defaultViewType; return ( - @@ -131,7 +131,7 @@ const DiffView: FunctionComponent = ({ error, result } = {}) => { options={options} viewType={viewType} /> - + ); }; diff --git a/src/app/about/api/page.client.tsx b/src/app/about/api/page.client.tsx index 1c5f0c47..211fb261 100644 --- a/src/app/about/api/page.client.tsx +++ b/src/app/about/api/page.client.tsx @@ -1,7 +1,7 @@ "use client"; import { Code, Heading, Text, VStack } from "@chakra-ui/react"; -import Layout from "^/components/Layout"; import { ExternalLink, Tooltip } from "^/components/theme"; +import { MetaData } from "^/lib/metaData"; export interface AboutApiPageClientProps { diff: string; @@ -14,7 +14,7 @@ const AboutApiPageClient = ({ specs, exampleAbsoluteUrl, }: AboutApiPageClientProps) => ( - + npm-diff.app API @@ -55,7 +55,7 @@ const AboutApiPageClient = ({ {diff} - + ); export default AboutApiPageClient; diff --git a/src/app/config.tsx b/src/app/config.tsx deleted file mode 100644 index 84a9f9f7..00000000 --- a/src/app/config.tsx +++ /dev/null @@ -1,15 +0,0 @@ -"use client"; - -import { ChakraProvider, ColorModeScript } from "@chakra-ui/react"; -import { PropsWithChildren } from "react"; -import theme from "^/theme"; - -/** Configures the app with the necessary Context and scripts */ -export default function Config({ children }: PropsWithChildren<{}>) { - return ( - <> - - {children} - - ); -} diff --git a/src/app/layout.client.tsx b/src/app/layout.client.tsx new file mode 100644 index 00000000..31f59623 --- /dev/null +++ b/src/app/layout.client.tsx @@ -0,0 +1,28 @@ +"use client"; + +import { ChakraProvider, ColorModeScript, Stack } from "@chakra-ui/react"; +import { PropsWithChildren } from "react"; +import Div100vh from "react-div-100vh"; +import Footer from "^/components/Footer"; +import Header from "^/components/Header"; +import theme from "^/theme"; + +const PADDING = "1em"; + +const LayoutClient = ({ children }: PropsWithChildren<{}>) => ( + <> + + + +
+ {children} +