mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-12 09:33:32 +01:00
refactor(website,guide): cloudflare workers support (#11204)
This commit is contained in:
@@ -3,8 +3,6 @@
|
||||
import { ImageResponse } from 'next/og';
|
||||
import { resolveKind } from '@/util/resolveNodeKind';
|
||||
|
||||
export const runtime = 'edge';
|
||||
|
||||
export const size = {
|
||||
width: 1_200,
|
||||
height: 630,
|
||||
@@ -12,6 +10,22 @@ export const size = {
|
||||
|
||||
export const contentType = 'image/png';
|
||||
|
||||
async function loadGoogleFont(font: string, text: string) {
|
||||
const url = `https://fonts.googleapis.com/css2?family=${font}&text=${encodeURIComponent(text)}`;
|
||||
const css = await (await fetch(url)).text();
|
||||
// eslint-disable-next-line prefer-named-capture-group
|
||||
const resource = /src: url\((.+)\) format\('(opentype|truetype)'\)/.exec(css);
|
||||
|
||||
if (resource) {
|
||||
const response = await fetch(resource[1]!);
|
||||
if (response.status === 200) {
|
||||
return response.arrayBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error('failed to load font data');
|
||||
}
|
||||
|
||||
export default async function Image({
|
||||
params,
|
||||
}: {
|
||||
@@ -19,14 +33,6 @@ export default async function Image({
|
||||
}) {
|
||||
const { item, packageName, version } = await params;
|
||||
|
||||
const [fontDataBold, fontDataBlack] = await Promise.all([
|
||||
fetch(new URL('../../../../../../assets/Geist-Bold.ttf', import.meta.url), {
|
||||
next: { revalidate: 604_800 },
|
||||
}).then(async (res) => res.arrayBuffer()),
|
||||
fetch(new URL('../../../../../../assets/Geist-Black.ttf', import.meta.url), {
|
||||
next: { revalidate: 604_800 },
|
||||
}).then(async (res) => res.arrayBuffer()),
|
||||
]);
|
||||
const normalizeItem = item.split(encodeURIComponent(':')).join('.').toLowerCase();
|
||||
|
||||
const isMain = version === 'main';
|
||||
@@ -107,13 +113,13 @@ export default async function Image({
|
||||
fonts: [
|
||||
{
|
||||
name: 'Geist',
|
||||
data: fontDataBold,
|
||||
data: await loadGoogleFont('Geist:wght@700', node.displayName),
|
||||
weight: 700,
|
||||
style: 'normal',
|
||||
},
|
||||
{
|
||||
name: 'Geist',
|
||||
data: fontDataBlack,
|
||||
data: await loadGoogleFont('Geist:wght@900', node.displayName),
|
||||
weight: 900,
|
||||
style: 'normal',
|
||||
},
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { join } from 'node:path';
|
||||
import rehypeShikiFromHighlighter from '@shikijs/rehype/core';
|
||||
import type { Metadata } from 'next';
|
||||
import { notFound } from 'next/navigation';
|
||||
import { MDXRemote } from 'next-mdx-remote-client/rsc';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import { SafeMdxRenderer } from 'safe-mdx';
|
||||
import { mdxParse } from 'safe-mdx/parse';
|
||||
import { DocItem } from '@/components/DocItem';
|
||||
import { PACKAGES_WITH_ENTRY_POINTS } from '@/util/constants';
|
||||
import { SyntaxHighlighter } from '@/components/SyntaxHighlighter';
|
||||
// import { PACKAGES_WITH_ENTRY_POINTS } from '@/util/constants';
|
||||
import { fetchNode } from '@/util/fetchNode';
|
||||
import { parseDocsPathParams } from '@/util/parseDocsPathParams';
|
||||
import { getSingletonHighlighter } from '@/util/shiki.bundle';
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
@@ -52,48 +49,38 @@ export default async function Page({
|
||||
const { entryPoints: parsedEntrypoints, foundItem } = parseDocsPathParams(item);
|
||||
|
||||
if (!foundItem) {
|
||||
const hasEntryPoint = PACKAGES_WITH_ENTRY_POINTS.includes(packageName);
|
||||
// const hasEntryPoint = PACKAGES_WITH_ENTRY_POINTS.includes(packageName);
|
||||
|
||||
if (hasEntryPoint) {
|
||||
return <>Placeholder</>;
|
||||
}
|
||||
// if (hasEntryPoint) {
|
||||
// return <>Placeholder</>;
|
||||
// }
|
||||
|
||||
let fileContent: string;
|
||||
|
||||
try {
|
||||
fileContent = await readFile(join(process.cwd(), `src/assets/readme/${packageName}/home-README.md`), 'utf8');
|
||||
} catch (error: any) {
|
||||
if ('code' in error && error.code === 'ENOENT') {
|
||||
notFound();
|
||||
}
|
||||
|
||||
throw error;
|
||||
fileContent = await fetch(`${process.env.CF_R2_README_BUCKET_URL}/${packageName}/home-README.md`).then(
|
||||
async (res) => res.text(),
|
||||
);
|
||||
} catch {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const mdast = mdxParse(fileContent);
|
||||
|
||||
return (
|
||||
<div className="prose prose-neutral dark:prose-invert prose-a:[&>img]:inline-block prose-a:[&>img]:m-0 prose-a:[&>img[height='44']]:h-11 prose-p:my-2 prose-pre:py-3 prose-pre:rounded-sm prose-pre:px-0 prose-pre:border prose-pre:border-[#d4d4d4] dark:prose-pre:border-[#404040] prose-code:font-normal prose-a:text-[#5865F2] prose-a:no-underline prose-a:hover:text-[#3d48c3] dark:prose-a:hover:text-[#7782fa] mx-auto max-w-screen-xl px-6 py-6 break-words [&_code_span:last-of-type:empty]:hidden [&_div[align='center']_p_a+a]:ml-2">
|
||||
<MDXRemote
|
||||
options={{
|
||||
mdxOptions: {
|
||||
remarkPlugins: [remarkGfm],
|
||||
rehypePlugins: [
|
||||
[
|
||||
rehypeShikiFromHighlighter,
|
||||
await getSingletonHighlighter({
|
||||
langs: ['typescript', 'javascript', 'shellscript'],
|
||||
themes: ['github-light', 'github-dark-dimmed'],
|
||||
}),
|
||||
{
|
||||
themes: {
|
||||
light: 'github-light',
|
||||
dark: 'github-dark-dimmed',
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
<SafeMdxRenderer
|
||||
markdown={fileContent}
|
||||
mdast={mdast}
|
||||
renderNode={(node) => {
|
||||
if (node.type === 'code') {
|
||||
const language = node.lang ?? 'text';
|
||||
|
||||
return <SyntaxHighlighter code={node.value} lang={language} />;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}}
|
||||
source={fileContent}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
import { ImageResponse } from 'next/og';
|
||||
|
||||
export const runtime = 'edge';
|
||||
|
||||
export const size = {
|
||||
width: 1_200,
|
||||
height: 630,
|
||||
@@ -11,11 +9,23 @@ export const size = {
|
||||
|
||||
export const contentType = 'image/png';
|
||||
|
||||
export default async function Image() {
|
||||
const fontData = await fetch(new URL('../assets/Geist-Black.ttf', import.meta.url), { cache: 'force-cache' }).then(
|
||||
async (res) => res.arrayBuffer(),
|
||||
);
|
||||
async function loadGoogleFont(font: string, text: string) {
|
||||
const url = `https://fonts.googleapis.com/css2?family=${font}&text=${encodeURIComponent(text)}`;
|
||||
const css = await (await fetch(url)).text();
|
||||
// eslint-disable-next-line prefer-named-capture-group
|
||||
const resource = /src: url\((.+)\) format\('(opentype|truetype)'\)/.exec(css);
|
||||
|
||||
if (resource) {
|
||||
const response = await fetch(resource[1]!);
|
||||
if (response.status === 200) {
|
||||
return response.arrayBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error('failed to load font data');
|
||||
}
|
||||
|
||||
export default async function Image() {
|
||||
return new ImageResponse(
|
||||
(
|
||||
<div tw="flex bg-[#121214] h-full w-full">
|
||||
@@ -39,7 +49,7 @@ export default async function Image() {
|
||||
fonts: [
|
||||
{
|
||||
name: 'Geist',
|
||||
data: fontData,
|
||||
data: await loadGoogleFont('Geist:wght@900', 'The most popular way to build Discord bots.'),
|
||||
weight: 900,
|
||||
style: 'normal',
|
||||
},
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -43,12 +43,12 @@ export function CmdK({ dependencies }: { readonly dependencies: string[] }) {
|
||||
value={item.id}
|
||||
>
|
||||
{resolveKind(item.kind)}
|
||||
<div className="flex flex-grow flex-col">
|
||||
<div className="flex grow flex-col">
|
||||
<span className="font-semibold wrap-anywhere">{item.name}</span>
|
||||
<span className={cx('truncate text-sm', isMobile ? 'max-w-[30ch]' : 'max-w-[40ch]')}>{item.summary}</span>
|
||||
<span className={cx('truncate text-xs', isMobile ? 'max-w-[30ch]' : 'max-w-[40ch]')}>{item.path}</span>
|
||||
</div>
|
||||
<ArrowRight aria-hidden className="flex-shrink-0" />
|
||||
<ArrowRight aria-hidden className="shrink-0" />
|
||||
</Command.Item>
|
||||
)) ?? [];
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import Cloudflare from 'cloudflare';
|
||||
// import Cloudflare from 'cloudflare';
|
||||
import { ENV } from './env';
|
||||
|
||||
const client = new Cloudflare({
|
||||
apiToken: process.env.CF_D1_DOCS_API_KEY,
|
||||
});
|
||||
// const client = new Cloudflare({
|
||||
// apiToken: process.env.CF_D1_DOCS_API_KEY,
|
||||
// });
|
||||
|
||||
export async function fetchVersions(packageName: string) {
|
||||
if (ENV.IS_LOCAL_DEV) {
|
||||
@@ -11,13 +11,32 @@ export async function fetchVersions(packageName: string) {
|
||||
}
|
||||
|
||||
try {
|
||||
const { result } = await client.d1.database.query(process.env.CF_D1_DOCS_ID!, {
|
||||
account_id: process.env.CF_ACCOUNT_ID!,
|
||||
sql: `select version from documentation where name = ? order by version desc;`,
|
||||
params: [packageName],
|
||||
});
|
||||
// const { result } = await client.d1.database.query(process.env.CF_D1_DOCS_ID!, {
|
||||
// account_id: process.env.CF_ACCOUNT_ID!,
|
||||
// sql: `select version from documentation where name = ? order by version desc;`,
|
||||
// params: [packageName],
|
||||
// });
|
||||
|
||||
return (result[0]?.results as { version: string }[] | undefined) ?? [];
|
||||
// return (result[0]?.results as { version: string }[] | undefined) ?? [];
|
||||
|
||||
const response = await fetch(
|
||||
`https://api.cloudflare.com/client/v4/accounts/${process.env.CF_ACCOUNT_ID}/d1/database/${process.env.CF_D1_DOCS_ID}/query`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${process.env.CF_D1_DOCS_API_KEY}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
sql: `select version from documentation where name = ? order by version desc;`,
|
||||
params: [packageName],
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
return data.result[0]?.results;
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user