use Next.js
This commit is contained in:
1 parent
cf94c66807
commit
20a00d5ab3
34 files changed
+7117
-1
No files matched your search
@@ -0,0 +1,20 @@
|
||||
import { THEME } from '~/assets/global'
|
||||
import Layout from '~/components/Layout'
|
||||
import Head from 'next/head'
|
||||
|
||||
// eslint-disable-next-line react/prop-types
|
||||
const MyApp = ({ Component, pageProps }) => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{THEME.title}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
</Head>
|
||||
<Layout>
|
||||
<Component {...pageProps} />
|
||||
</Layout>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default MyApp
|
||||
@@ -0,0 +1,55 @@
|
||||
import THEME from '~/build/theme.json'
|
||||
import Document, { Head, Html, Main, NextScript } from 'next/document'
|
||||
|
||||
class MyDocument extends Document {
|
||||
static async getInitialProps (ctx) {
|
||||
const initialProps = await Document.getInitialProps(ctx)
|
||||
return { ...initialProps }
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<Html lang="en">
|
||||
<Head>
|
||||
<meta httpEquiv="Content-Type" content="text/html;charset=UTF-8" />
|
||||
<meta name="description" content={THEME.description} />
|
||||
|
||||
<link
|
||||
rel="shortcut icon"
|
||||
href="/media/favicon.ico"
|
||||
type="image/x-icon"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href={
|
||||
THEME.awsm
|
||||
? `https://unpkg.com/awsm.css/dist/awsm_theme_${THEME.awsm}.min.css`
|
||||
: 'https://unpkg.com/awsm.css/dist/awsm.min.css'
|
||||
}
|
||||
/>
|
||||
|
||||
{THEME.analytics?.plausible ? (
|
||||
<script
|
||||
src="https://plausible.io/js/plausible.js"
|
||||
async
|
||||
defer
|
||||
data-domain={THEME.analytics.plausible}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
<script
|
||||
src="https://unpkg.com/@webcomponents/webcomponentsjs/webcomponents-loader.js"
|
||||
defer
|
||||
/>
|
||||
<script type="module" src="/webcomponents.js"></script>
|
||||
</Head>
|
||||
<body>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default MyDocument
|
||||
@@ -0,0 +1,12 @@
|
||||
import { doSearch } from '~/server'
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
||||
export default async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const r = await doSearch({
|
||||
q: req.query.q as string,
|
||||
tag: req.query.tag as string,
|
||||
page: parseInt(req.query.page as string) || 1
|
||||
})
|
||||
|
||||
res.json(r)
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import PostQuery from '~/components/PostQuery'
|
||||
import { doSearch } from '~/server'
|
||||
import { IPost, dbPost, initDatabase } from '~/server/db'
|
||||
import { GetStaticPaths, GetStaticProps } from 'next'
|
||||
|
||||
const BlogPagePaged = ({
|
||||
count,
|
||||
result
|
||||
}: {
|
||||
count: number
|
||||
result: IPost[]
|
||||
}) => {
|
||||
return (
|
||||
<PostQuery
|
||||
defaults={{
|
||||
posts: result,
|
||||
count
|
||||
}}
|
||||
></PostQuery>
|
||||
)
|
||||
}
|
||||
|
||||
export default BlogPagePaged
|
||||
|
||||
export const getStaticPaths: GetStaticPaths = async () => {
|
||||
await initDatabase()
|
||||
|
||||
return {
|
||||
paths: Array(
|
||||
Math.ceil(
|
||||
dbPost.find({
|
||||
date: { $exists: true } as any
|
||||
}).length / 5
|
||||
) - 1
|
||||
)
|
||||
.fill(null)
|
||||
.map((_, i) => ({
|
||||
params: {
|
||||
page: (i + 2).toString()
|
||||
}
|
||||
})),
|
||||
fallback: false
|
||||
}
|
||||
}
|
||||
|
||||
export const getStaticProps: GetStaticProps = async (ctx) => {
|
||||
return {
|
||||
props: await doSearch({
|
||||
page: parseInt(ctx.params.page as string)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import PostQuery from '~/components/PostQuery'
|
||||
import { doSearch } from '~/server'
|
||||
import { IPost } from '~/server/db'
|
||||
import { GetStaticProps } from 'next'
|
||||
|
||||
const BlogPage = ({ count, result }: { count: number; result: IPost[] }) => {
|
||||
return (
|
||||
<PostQuery
|
||||
defaults={{
|
||||
posts: result,
|
||||
count
|
||||
}}
|
||||
></PostQuery>
|
||||
)
|
||||
}
|
||||
|
||||
export default BlogPage
|
||||
|
||||
export const getStaticProps: GetStaticProps = async () => {
|
||||
return {
|
||||
props: await doSearch({})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
import '~/assets/remark42'
|
||||
|
||||
import { THEME } from '~/assets/global'
|
||||
import { formatDate } from '~/assets/util'
|
||||
import { IPost, dbPost, initDatabase } from '~/server/db'
|
||||
import styles from '~/styles/PostPage.module.css'
|
||||
import { GetStaticPaths, GetStaticProps } from 'next'
|
||||
import Head from 'next/head'
|
||||
import Link from 'next/link'
|
||||
import { createRef, useEffect } from 'react'
|
||||
|
||||
const PostPage = (post: IPost) => {
|
||||
const remark42Ref = createRef<HTMLDivElement>()
|
||||
|
||||
useEffect(() => {
|
||||
if (remark42Ref.current) {
|
||||
if (window.remark42Instance) {
|
||||
window.remark42Instance.destroy()
|
||||
}
|
||||
|
||||
window.remark42Instance = window.REMARK42.createInstance({
|
||||
node: remark42Ref.current,
|
||||
host: THEME.comment.remark42.host,
|
||||
site_id: THEME.comment.remark42.siteId
|
||||
})
|
||||
}
|
||||
}, [remark42Ref.current])
|
||||
|
||||
return (
|
||||
<section>
|
||||
<Head>
|
||||
<title>
|
||||
{post.title} - {THEME.title}
|
||||
</title>
|
||||
<meta property="og:title" content={post.title} />
|
||||
<meta property="twitter:title" content={post.title} />
|
||||
|
||||
<meta name="description" content={post.content.substr(0, 140)} />
|
||||
<meta property="og:description" content={post.content.substr(0, 140)} />
|
||||
<meta property="twitter:title" content={post.content.substr(0, 140)} />
|
||||
|
||||
{post.tag ? (
|
||||
<meta name="keywords" content={post.tag.join(',')} />
|
||||
) : null}
|
||||
|
||||
{post.image ? (
|
||||
<>
|
||||
<meta property="og:image" content={post.image} />
|
||||
<meta property="twitter:title" content={post.image} />
|
||||
</>
|
||||
) : null}
|
||||
</Head>
|
||||
<section>
|
||||
<h2>{post.title}</h2>
|
||||
|
||||
<small>
|
||||
<span>
|
||||
by{' '}
|
||||
{THEME.author.url ? (
|
||||
<a
|
||||
href={THEME.author.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{THEME.author.name}
|
||||
</a>
|
||||
) : (
|
||||
<span>{THEME.author.name}</span>
|
||||
)}
|
||||
</span>
|
||||
|
||||
{post.date ? (
|
||||
<span style={{ float: 'right' }}>{formatDate(post.date)}</span>
|
||||
) : null}
|
||||
</small>
|
||||
</section>
|
||||
|
||||
<section dangerouslySetInnerHTML={{ __html: post.contentHtml }} />
|
||||
|
||||
{post.tag ? (
|
||||
<section className={styles['tags-container']}>
|
||||
<span>Tags:</span>
|
||||
{post.tag.map((t) => (
|
||||
<span key={t}>
|
||||
<Link href={`/tag/${t}`}>
|
||||
<a>{t}</a>
|
||||
</Link>
|
||||
</span>
|
||||
))}
|
||||
</section>
|
||||
) : null}
|
||||
|
||||
{THEME.comment?.remark42 ? (
|
||||
<footer>
|
||||
<div ref={remark42Ref}></div>
|
||||
</footer>
|
||||
) : null}
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
export default PostPage
|
||||
|
||||
export const getStaticPaths: GetStaticPaths = async () => {
|
||||
await initDatabase()
|
||||
|
||||
return {
|
||||
paths: dbPost
|
||||
.find()
|
||||
.map(({ path }) => ({
|
||||
params: { path: path.split(/\//g).map(encodeURIComponent) }
|
||||
})),
|
||||
fallback: false
|
||||
}
|
||||
}
|
||||
|
||||
export const getStaticProps: GetStaticProps = async (ctx) => {
|
||||
await initDatabase()
|
||||
|
||||
return {
|
||||
props: dbPost.findOne({
|
||||
path: (ctx.params.path as string[]).join('/')
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import PostQuery from '~/components/PostQuery'
|
||||
import { doSearch } from '~/server'
|
||||
import { IPost, dbPost, initDatabase } from '~/server/db'
|
||||
import { GetStaticPaths, GetStaticProps } from 'next'
|
||||
|
||||
const TagPagePaged = ({
|
||||
count,
|
||||
result
|
||||
}: {
|
||||
count: number
|
||||
result: IPost[]
|
||||
}) => {
|
||||
return (
|
||||
<PostQuery
|
||||
defaults={{
|
||||
posts: result,
|
||||
count
|
||||
}}
|
||||
></PostQuery>
|
||||
)
|
||||
}
|
||||
|
||||
export default TagPagePaged
|
||||
|
||||
export const getStaticProps: GetStaticProps = async (ctx) => {
|
||||
return {
|
||||
props: await doSearch({
|
||||
page: parseInt(ctx.params.page as string),
|
||||
tag: ctx.params.tag as string
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const getStaticPaths: GetStaticPaths = async () => {
|
||||
await initDatabase()
|
||||
const tMap = new Map<string, number>()
|
||||
|
||||
dbPost.find().map(({ tag = [] }) => {
|
||||
return tag.map((t) => {
|
||||
return tMap.set(t, (tMap.get(t) || 0) + 1)
|
||||
})
|
||||
})
|
||||
|
||||
return {
|
||||
paths: Array.from(tMap).flatMap(([t, n]) =>
|
||||
Array(Math.ceil(n / 5) - 1)
|
||||
.fill(null)
|
||||
.map((_, i) => ({
|
||||
params: {
|
||||
tag: t,
|
||||
page: (i + 2).toString()
|
||||
}
|
||||
}))
|
||||
),
|
||||
fallback: false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import PostQuery from '~/components/PostQuery'
|
||||
import { doSearch } from '~/server'
|
||||
import { IPost, dbPost, initDatabase } from '~/server/db'
|
||||
import { GetStaticPaths, GetStaticProps } from 'next'
|
||||
|
||||
const TagPage = ({ count, result }: { count: number; result: IPost[] }) => {
|
||||
return (
|
||||
<PostQuery
|
||||
defaults={{
|
||||
posts: result,
|
||||
count
|
||||
}}
|
||||
></PostQuery>
|
||||
)
|
||||
}
|
||||
|
||||
export default TagPage
|
||||
|
||||
export const getStaticPaths: GetStaticPaths = async () => {
|
||||
await initDatabase()
|
||||
const tMap = new Map<string, number>()
|
||||
|
||||
dbPost.find().map(({ tag = [] }) => {
|
||||
return tag.map((t) => {
|
||||
return tMap.set(t, (tMap.get(t) || 0) + 1)
|
||||
})
|
||||
})
|
||||
|
||||
return {
|
||||
paths: Array.from(tMap).map(([t]) => ({
|
||||
params: {
|
||||
tag: t
|
||||
}
|
||||
})),
|
||||
fallback: false
|
||||
}
|
||||
}
|
||||
|
||||
export const getStaticProps: GetStaticProps = async (ctx) => {
|
||||
return {
|
||||
props: await doSearch({
|
||||
tag: ctx.params.tag as string
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user