Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to v2! #80

Merged
merged 12 commits into from
Dec 12, 2023
83 changes: 58 additions & 25 deletions app/components/doc-route.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
import type { LoaderArgs, MetaFunction, SerializeFrom } from "@remix-run/node";
import type {
LoaderFunctionArgs,
SerializeFrom,
MetaFunction,
} from "@remix-run/node";
import * as React from "react";
import { json, Response } from "@remix-run/node";
import { useLoaderData, useParams } from "@remix-run/react";
import { json } from "@remix-run/node";
import {
isRouteErrorResponse,
useLoaderData,
useParams,
useRouteError,
} from "@remix-run/react";
import invariant from "tiny-invariant";
import type { Doc } from "~/modules/gh-docs";
import { getRepoDoc } from "~/modules/gh-docs";
import { CACHE_CONTROL, whyDoWeNotHaveGoodMiddleWareYetRyan } from "~/http";
import { seo } from "~/seo";
import { useDelegatedReactRouterLinks } from "./delegate-markdown-links";
import iconsHref from "~/icons.svg";
import { type loader as rootLoader } from "~/root";
import { type loader as langRefLoader } from "~/routes/$lang.$ref";

export let loader = async ({ params, request }: LoaderArgs) => {
export let loader = async ({ params, request }: LoaderFunctionArgs) => {
await whyDoWeNotHaveGoodMiddleWareYetRyan(request);

invariant(params.ref, "expected `ref` params");
Expand All @@ -30,14 +41,21 @@ export function headers() {
};
}

export let meta: MetaFunction = ({ data, parentsData }) => {
if (!data) return { title: "Not Found" };
let parentData = parentsData["routes/$lang.$ref"];
if (!parentData) return {};
export const meta: MetaFunction<
typeof loader,
{
root: typeof rootLoader;
"routes/$lang.$ref": typeof langRefLoader;
}
> = ({ data, matches }) => {
if (!data) return [{ title: "Not Found" }];
let parentMatch = matches.find((m) => m.id === "routes/$lang.$ref");
let parentData = parentMatch ? parentMatch.data : undefined;
if (!parentData || !("latestVersion" in parentData)) return [];

let rootData = parentsData["root"];
let rootMatch = matches.find((m) => m.id === "root");
let rootData = rootMatch ? rootMatch.data : undefined;

let { doc } = data;
let { latestVersion, releaseBranch, branches, currentGitHubRef } = parentData;

let titleRef =
Expand All @@ -49,7 +67,13 @@ export let meta: MetaFunction = ({ data, parentsData }) => {
? currentGitHubRef
: `v${currentGitHubRef}`;

let title = doc.attrs.title + ` ${titleRef}`;
let title =
typeof data === "object" &&
typeof data.doc === "object" &&
typeof data.doc.attrs === "object" &&
typeof data.doc.attrs.title === "string"
? data.doc.attrs.title + ` ${titleRef}`
: "";

// seo: only want to index the main branch
let isMainBranch = currentGitHubRef === releaseBranch;
Expand All @@ -61,15 +85,18 @@ export let meta: MetaFunction = ({ data, parentsData }) => {
});

let robots =
rootData.isProductionHost && isMainBranch
rootData &&
"isProductionHost" in rootData &&
rootData.isProductionHost &&
isMainBranch
? "index,follow"
: "noindex,nofollow";

return {
return [
...meta,
robots: robots,
googlebot: robots,
};
{ name: "robots", content: robots },
{ name: "googlebot", content: robots },
];
};

export default function DocPage() {
Expand Down Expand Up @@ -145,14 +172,20 @@ function SmallOnThisPage({ doc }: { doc: SerializeFrom<Doc> }) {
);
}

export function CatchBoundary() {
export function ErrorBoundary() {
let error = useRouteError();
let params = useParams();
return (
<div className="flex h-[50vh] flex-col items-center justify-center">
<h1 className="text-9xl font-bold">404</h1>
<p className="text-lg">
There is no doc for <i className="text-gray-500">{params["*"]}</i>
</p>
</div>
);

if (isRouteErrorResponse(error)) {
return (
<div className="flex h-[50vh] flex-col items-center justify-center">
<h1 className="text-9xl font-bold">404</h1>
<p className="text-lg">
There is no doc for <i className="text-gray-500">{params["*"]}</i>
</p>
</div>
);
}

throw error;
}
12 changes: 7 additions & 5 deletions app/modules/color-scheme/components.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { useLayoutEffect, useMemo } from "react";
import { useMatches, useTransition } from "@remix-run/react";
import type { SerializeFrom } from "@remix-run/node";
import { useMatches, useNavigation } from "@remix-run/react";
import type { loader as rootLoader } from "../../root";
import type { ColorScheme } from "./types";

export function useColorScheme(): ColorScheme {
let rootLoaderData = useMatches()[0].data;
let { submission } = useTransition();
let rootLoaderData = useMatches()[0].data as SerializeFrom<typeof rootLoader>;
let { formData } = useNavigation();
let optimisticColorScheme =
submission && submission.formData.has("colorScheme")
? (submission.formData.get("colorScheme") as ColorScheme)
formData && formData.has("colorScheme")
? (formData.get("colorScheme") as ColorScheme)
: null;
return optimisticColorScheme || rootLoaderData.colorScheme;
}
Expand Down
8 changes: 4 additions & 4 deletions app/modules/details-menu/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useLocation, useTransition } from "@remix-run/react";
import { useLocation, useNavigation } from "@remix-run/react";
import * as React from "react";

/**
Expand All @@ -12,15 +12,15 @@ export let DetailsMenu = React.forwardRef<
let { onToggle, onMouseDown, onTouchStart, onFocus, open, ...rest } = props;
let [isOpen, setIsOpen] = React.useState(false);
let location = useLocation();
let transition = useTransition();
let navigation = useNavigation();
let clickRef = React.useRef<boolean>(false);
let focusRef = React.useRef<boolean>(false);

React.useEffect(() => {
if (transition.submission) {
if (navigation.formData) {
setIsOpen(false);
}
}, [transition]);
}, [navigation]);

React.useEffect(() => {
setIsOpen(false);
Expand Down
6 changes: 3 additions & 3 deletions app/modules/gh-docs/docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { processMarkdown } from "@ryanflorence/md";
import LRUCache from "lru-cache";
import parseYamlHeader from "gray-matter";
import invariant from "tiny-invariant";
import { getRepoContent } from "./repo-content";
import { getRepoTarballStream } from "./repo-tarball";
import { createTarFileProcessor } from "./tarball";
import { getRepoContent } from "./repo-content.server";
import { getRepoTarballStream } from "./repo-tarball.server";
import { createTarFileProcessor } from "./tarball.server";
import { load as $ } from "cheerio";

export interface MenuDoc {
Expand Down
4 changes: 2 additions & 2 deletions app/modules/gh-docs/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { getDoc, getMenu } from "./docs";
import { getBranches } from "./branches";
import { getLatestVersion, getTags } from "./tags";
import { getLatestVersion, getTags } from "./tags.server";
import invariant from "tiny-invariant";

export { validateParams } from "./params";
export { getRepoTarballStream } from "./repo-tarball";
export { getRepoTarballStream } from "./repo-tarball.server";

export type { Doc } from "./docs";

Expand Down
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion app/modules/gh-docs/tarball.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import fs from "fs";
import path from "path";
import { createTarFileProcessor } from "./tarball";
import { createTarFileProcessor } from "./tarball.server";

describe("createTarFileProcessor", () => {
it("extracts and processes files one-by-one", async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { redirect } from "@remix-run/node";
import type { Redirect } from "./read-file";
import type { Redirect } from "./read-file.server";

export async function checkUrl(url: string, redirects: Redirect[]) {
for (let r of redirects) {
Expand Down
6 changes: 3 additions & 3 deletions app/modules/redirects/check-url.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import path from "path";
import { checkUrl } from "./check-url";
import { readRedirectsFile } from "./read-file";
import type { Redirect } from "./read-file";
import { checkUrl } from "./check-url.server";
import { readRedirectsFile } from "./read-file.server";
import type { Redirect } from "./read-file.server";

describe("handleRedirects", () => {
let redirects: Redirect[];
Expand Down
4 changes: 2 additions & 2 deletions app/modules/redirects/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { checkUrl } from "./check-url";
import { readRedirectsFile } from "./read-file";
import { checkUrl } from "./check-url.server";
import { readRedirectsFile } from "./read-file.server";

/**
* Super basic redirects handling with a redirects file.
Expand Down
56 changes: 40 additions & 16 deletions app/modules/remix-seo/seo.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ describe("getSeo", () => {
let seo = getSeo({});
expect(seo({})).toMatchInlineSnapshot(`
[
{},
[],
[],
]
`);
Expand All @@ -15,9 +15,11 @@ describe("getSeo", () => {
let seo = getSeo({ defaultTitle: "Test default title" });
expect(seo({})).toMatchInlineSnapshot(`
[
{
"title": "Test default title",
},
[
{
"title": "Test default title",
},
],
[],
]
`);
Expand All @@ -28,17 +30,24 @@ describe("getSeo", () => {
let TITLE = "real title";
let seo = getSeo({ defaultTitle: DEFAULT_TITLE });
let [meta] = seo({ title: TITLE });
expect(meta.title).toBe(TITLE);
let titleMeta = meta.find((m) => "title" in m && m.title != null);
expect("title" in titleMeta! ? titleMeta.title : null).toBe(TITLE);
});

it("defaults the description for everybody who who hates the normal description", () => {
let seo = getSeo({});
let [meta] = seo({ description: "Heyooo" });
expect(meta).toMatchInlineSnapshot(`
{
"description": "Heyooo",
"og:description": "Heyooo",
}
[
{
"content": "Heyooo",
"name": "description",
},
{
"content": "Heyooo",
"name": "og:description",
},
]
`);
});

Expand All @@ -49,13 +58,28 @@ describe("getSeo", () => {
twitter: { image: { url: "/beef.jpg", alt: "beef!" } },
});
expect(meta).toMatchInlineSnapshot(`
{
"og:image": "test://example.com/beef.jpg",
"og:image:alt": "beef!",
"twitter:card": "summary",
"twitter:image": "test://example.com/beef.jpg",
"twitter:image:alt": "beef!",
}
[
{
"content": "test://example.com/beef.jpg",
"name": "twitter:image",
},
{
"content": "beef!",
"name": "twitter:image:alt",
},
{
"content": "summary",
"name": "twitter:card",
},
{
"content": "test://example.com/beef.jpg",
"name": "og:image",
},
{
"content": "beef!",
"name": "og:image:alt",
},
]
`);
});
});
Loading