/
[guide].tsx
111 lines (99 loc) · 4.19 KB
/
[guide].tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import { GetStaticPathsResult, GetStaticPropsContext, GetStaticPropsResult } from "next"
import Head from "next/head"
import ReactMarkdown from "react-markdown"
import FormattedLink from "../../../components/FormattedLink"
import Main from "../../../components/Main"
import YouTube from "../../../components/YouTube"
import { getGuides } from "../../../utils/data-cache"
import { Guide } from "../../../utils/types"
import { clean, getIconPath, removeBrackets, urlify } from "../../../utils/utils"
import styles from "../../style.module.css"
interface Props {
guide: Guide
pageNumber: number
}
export default function GuideWebpage({ guide, pageNumber, location }: Props & { location: string }) {
const page = guide.pages[pageNumber]
const nextPage = guide.pages[pageNumber + 1]
const prevPage = guide.pages[pageNumber - 1]
const desc = `View ${removeBrackets(page.name)} guide by ${page.credits}${page.url && page.url.startsWith("https://youtu.be/") ? " (video available!)" : ""}. \n${page.desc ? clean(page.desc) : ""}`.trim()
return (
<Main>
<Head>
<title>{page.name} | Hu Tao</title>
<meta name="twitter:card" content={page.img ? "summary_large_image" : "summary"} />
<meta property="og:title" content={`${page.name} | Hu Tao`} />
<meta property="og:description" content={desc} />
<meta property="description" content={desc} />
{page.img && <meta property="og:image" content={getIconPath(page.img)} />}
</Head>
<h2 className="font-semibold">
<FormattedLink href={`/guides/${urlify(guide.name, false)}`} location={location} className="font-semibold text-lg">
{guide.name}
</FormattedLink>
</h2>
<h1 className="text-3xl font-bold">
{page.name}
</h1>
<div className="flex justify-between text-base">
<div className="px-1">
{prevPage && <FormattedLink href={`/guides/${urlify(guide.name, false)}/${urlify(prevPage.name, true)}`} location={location} className="font-bold text-lg">
← {removeBrackets(prevPage.name)}
</FormattedLink>}
</div>
<div>
{nextPage &&
<FormattedLink href={`/guides/${urlify(guide.name, false)}/${urlify(nextPage.name, true)}`} location={location} className="font-bold text-lg">
{removeBrackets(nextPage.name)} →
</FormattedLink>}
</div>
</div>
<div>
<ReactMarkdown>{(page.desc?.replace(/ ?\$\{.*?\}/g, "") ?? "")}</ReactMarkdown>
{page.img && <ExternalImg src={page.img} />}
<div className="float-right text-sm">By {page.credits}</div>
{page.url && page.url.startsWith("https://youtu.be/") && <div>
<h2 className="text-xl font-semibold py-1">Video:</h2>
<YouTube vidID={page.url.replace("https://youtu.be/", "")} />
</div>
}
</div>
</Main>
)
}
function ExternalImg({ src }: { src: string }) {
// eslint-disable-next-line @next/next/no-img-element
return <FormattedLink href={src} target="_blank"><img className={`p-1 relative ${styles.autosize}`} decoding="async" alt="Guide Image" src={src} /></FormattedLink>
// return <div className="p-1 relative max-w-2xl">
// <Image alt="Guide Image" src={src} width={825} height={963}/>
// </div>
}
export async function getStaticProps(context: GetStaticPropsContext): Promise<GetStaticPropsResult<Props>> {
const guideName = context.params?.guide
const categoryName = context.params?.category
const data = await getGuides()
const guide = data?.find(g => urlify(g.name, false) == categoryName)
const pageNumber = guide?.pages?.findIndex(g => urlify(g.name, true) == guideName)
if (!data || !guide || pageNumber === undefined || pageNumber === -1) {
return {
notFound: true,
revalidate: 15 * 60
}
}
return {
props: {
guide, // TODO optimize
pageNumber
},
revalidate: 60 * 30
}
}
export async function getStaticPaths(): Promise<GetStaticPathsResult> {
const data = await getGuides()
return {
paths: data?.flatMap(category => category.pages.map(p => ({
params: { guide: urlify(p.name, true), category: urlify(category.name, false) }
}))) ?? [],
fallback: "blocking"
}
}