mirror of
https://github.com/lbr77/blog-astro.git
synced 2026-04-08 16:11:56 +00:00
2
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -11,3 +11,4 @@ pnpm-debug.log*
|
|||||||
.idea/
|
.idea/
|
||||||
teaser.pptx
|
teaser.pptx
|
||||||
~$teaser.pptx
|
~$teaser.pptx
|
||||||
|
.vercel/
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('astro:page-load', () => {
|
document.addEventListener('astro:page-load', () => {
|
||||||
function loadTwikoo() {
|
(()=>{
|
||||||
const commentsContainer = document.getElementById('tcomment');
|
const commentsContainer = document.getElementById('tcomment');
|
||||||
if (commentsContainer) {
|
if (commentsContainer) {
|
||||||
const script = document.createElement('script');
|
const script = document.createElement('script');
|
||||||
@@ -20,7 +20,6 @@
|
|||||||
};
|
};
|
||||||
document.body.appendChild(script);
|
document.body.appendChild(script);
|
||||||
}
|
}
|
||||||
}
|
})();
|
||||||
loadTwikoo();
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@@ -10,7 +10,6 @@ export interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { block } = Astro.props
|
const { block } = Astro.props
|
||||||
console.log(block)
|
|
||||||
const target = block.Bookmark || block.LinkPreview || block.Embed
|
const target = block.Bookmark || block.LinkPreview || block.Embed
|
||||||
const urlString = target?.Url
|
const urlString = target?.Url
|
||||||
|
|
||||||
|
|||||||
@@ -51,8 +51,9 @@ export type NotionBlock = {
|
|||||||
export type NotionBlockMap = Record<string, NotionBlock>
|
export type NotionBlockMap = Record<string, NotionBlock>
|
||||||
|
|
||||||
export type RemotePostPayload = {
|
export type RemotePostPayload = {
|
||||||
post: NotionPost
|
post: CollectionEntry<'blog'>
|
||||||
blockMap: NotionBlockMap
|
blockMap: NotionBlockMap
|
||||||
|
rootId: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LinkEntry {
|
export interface LinkEntry {
|
||||||
@@ -255,10 +256,20 @@ export async function fetchRemotePostContent(
|
|||||||
try {
|
try {
|
||||||
const res = await fetch(`https://notion-api.nvme0n1p.dev/v2/posts/${encodeURI(slug)}`)
|
const res = await fetch(`https://notion-api.nvme0n1p.dev/v2/posts/${encodeURI(slug)}`)
|
||||||
if (!res.ok) throw new Error(`Failed to fetch post content: ${res.status}`)
|
if (!res.ok) throw new Error(`Failed to fetch post content: ${res.status}`)
|
||||||
const data = (await res.json()) as Partial<RemotePostPayload>
|
const data = (await res.json()) as Partial<{
|
||||||
|
post: NotionPost
|
||||||
|
blockMap: NotionBlockMap
|
||||||
|
}>
|
||||||
if (!data.post || !data.blockMap) return null
|
if (!data.post || !data.blockMap) return null
|
||||||
data.post = normalizePost(data.post)
|
|
||||||
return data as RemotePostPayload
|
const rootId = data.post.id
|
||||||
|
const post = normalizePost(data.post)
|
||||||
|
|
||||||
|
return {
|
||||||
|
post,
|
||||||
|
blockMap: data.blockMap,
|
||||||
|
rootId,
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`fetchRemotePostContent error for slug "${slug}":`, error)
|
console.error(`fetchRemotePostContent error for slug "${slug}":`, error)
|
||||||
return null
|
return null
|
||||||
@@ -897,12 +908,20 @@ export function renderRemoteBlockMap(
|
|||||||
): RenderedRemoteContent {
|
): RenderedRemoteContent {
|
||||||
const headingBlocks: Block[] = []
|
const headingBlocks: Block[] = []
|
||||||
const root = blockMap[rootId]?.value
|
const root = blockMap[rootId]?.value
|
||||||
const contentOrder = Array.isArray(root?.content)
|
const fallbackRoot =
|
||||||
? root?.content
|
root ||
|
||||||
: Object.keys(blockMap)
|
Object.values(blockMap)
|
||||||
|
.map((b) => b.value)
|
||||||
|
.find(
|
||||||
|
(value) =>
|
||||||
|
Array.isArray(value?.content) &&
|
||||||
|
(value.type === 'page' || value.type === 'collection_view_page'),
|
||||||
|
)
|
||||||
|
const contentOrder = Array.isArray(fallbackRoot?.content)
|
||||||
|
? fallbackRoot.content
|
||||||
|
: []
|
||||||
|
|
||||||
const blocks = buildBlocks(contentOrder, blockMap, headingBlocks)
|
const blocks = buildBlocks(contentOrder, blockMap, headingBlocks)
|
||||||
|
|
||||||
const headings: TOCHeading[] = headingBlocks.map((block) => {
|
const headings: TOCHeading[] = headingBlocks.map((block) => {
|
||||||
const heading = block.Heading1 || block.Heading2 || block.Heading3
|
const heading = block.Heading1 || block.Heading2 || block.Heading3
|
||||||
return {
|
return {
|
||||||
@@ -933,19 +952,18 @@ export async function getTOCSections(postId: string): Promise<TOCSection[]> {
|
|||||||
const post = await getPostById(postId)
|
const post = await getPostById(postId)
|
||||||
if (!post) return []
|
if (!post) return []
|
||||||
|
|
||||||
const parentId = isSubpost(postId) ? getParentId(postId) : postId
|
const parentPost = post
|
||||||
const parentPost = isSubpost(postId) ? await getPostById(parentId) : post
|
|
||||||
|
|
||||||
if (!parentPost) return []
|
if (!parentPost) return []
|
||||||
|
|
||||||
const sections: TOCSection[] = []
|
const sections: TOCSection[] = []
|
||||||
|
|
||||||
const { headings: parentHeadings } = await render(parentPost)
|
const { headings } = await render(parentPost)
|
||||||
if (parentHeadings.length > 0) {
|
if (headings.length > 0) {
|
||||||
sections.push({
|
sections.push({
|
||||||
type: 'parent',
|
type: 'parent',
|
||||||
title: 'Overview',
|
title: 'Overview',
|
||||||
headings: parentHeadings.map((heading) => ({
|
headings: headings.map((heading) => ({
|
||||||
slug: heading.slug,
|
slug: heading.slug,
|
||||||
text: heading.text,
|
text: heading.text,
|
||||||
depth: heading.depth,
|
depth: heading.depth,
|
||||||
@@ -953,23 +971,5 @@ export async function getTOCSections(postId: string): Promise<TOCSection[]> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const subposts = await getSubpostsForParent(parentId)
|
|
||||||
for (const subpost of subposts) {
|
|
||||||
const { headings: subpostHeadings } = await render(subpost)
|
|
||||||
if (subpostHeadings.length > 0) {
|
|
||||||
sections.push({
|
|
||||||
type: 'subpost',
|
|
||||||
title: subpost.data.title,
|
|
||||||
headings: subpostHeadings.map((heading, index) => ({
|
|
||||||
slug: heading.slug,
|
|
||||||
text: heading.text,
|
|
||||||
depth: heading.depth,
|
|
||||||
isSubpostTitle: index === 0,
|
|
||||||
})),
|
|
||||||
subpostId: subpost.id,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sections
|
return sections
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { cn } from '@/lib/utils'
|
|||||||
>
|
>
|
||||||
<div class="max-w-md">
|
<div class="max-w-md">
|
||||||
<h1 class="mb-4 text-3xl font-medium">404: Page not found</h1>
|
<h1 class="mb-4 text-3xl font-medium">404: Page not found</h1>
|
||||||
<p class="prose">Oops! The page you're looking for doesn't exist.</p>
|
<p class="prose">啊哦,你好像来到了没有知识的荒原~</p>
|
||||||
</div>
|
</div>
|
||||||
<Link
|
<Link
|
||||||
href="/"
|
href="/"
|
||||||
|
|||||||
29
src/pages/500.astro
Normal file
29
src/pages/500.astro
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
import Breadcrumbs from '@/components/Breadcrumbs.astro'
|
||||||
|
import Link from '@/components/Link.astro'
|
||||||
|
import PageHead from '@/components/PageHead.astro'
|
||||||
|
import { buttonVariants } from '@/components/ui/button'
|
||||||
|
import Layout from '@/layouts/Layout.astro'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
---
|
||||||
|
|
||||||
|
<Layout class="max-w-3xl">
|
||||||
|
<PageHead slot="head" title="500" />
|
||||||
|
<Breadcrumbs items={[{ label: 'Error', icon: 'lucide:server-off' }]} />
|
||||||
|
|
||||||
|
<section class="flex flex-col items-center justify-center gap-y-4 text-center">
|
||||||
|
<div class="max-w-md">
|
||||||
|
<h1 class="mb-4 text-3xl font-medium">500: Something went wrong</h1>
|
||||||
|
<p class="prose">
|
||||||
|
服务器爆炸了!如果你能联系到博主的话提醒他一声吧!
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Link
|
||||||
|
href="/"
|
||||||
|
class={cn(buttonVariants({ variant: 'outline' }), 'flex gap-x-1.5 group')}
|
||||||
|
>
|
||||||
|
<span class="transition-transform group-hover:-translate-x-1">←</span>
|
||||||
|
Go to home page
|
||||||
|
</Link>
|
||||||
|
</section>
|
||||||
|
</Layout>
|
||||||
@@ -42,30 +42,40 @@ export async function getStaticPaths() {
|
|||||||
const currentPostId = Astro.params.id
|
const currentPostId = Astro.params.id
|
||||||
|
|
||||||
let Content: any = null
|
let Content: any = null
|
||||||
let headings
|
let headings: any[] = []
|
||||||
let remoteContent = null
|
let remoteContent: any = null
|
||||||
|
let post: any = null
|
||||||
|
let authors: any[] = []
|
||||||
|
let isCurrentSubpost = false
|
||||||
|
let navigation: any = null
|
||||||
|
let parentPost: any = null
|
||||||
|
let hasChildPosts = false
|
||||||
|
let subpostCount = 0
|
||||||
|
let tocSections: TOCSection[] = []
|
||||||
|
let heroImage: any = null
|
||||||
|
|
||||||
|
try {
|
||||||
const remote = await fetchRemotePostContent(currentPostId)
|
const remote = await fetchRemotePostContent(currentPostId)
|
||||||
if (!remote) {
|
if (!remote) {
|
||||||
// return Astro.response(null, {status: 404})
|
// return Astro.response(null, {status: 404})
|
||||||
return Astro.rewrite("/404")
|
return Astro.rewrite('/404')
|
||||||
}
|
}
|
||||||
remoteContent = remote ? renderRemoteBlockMap(remote.blockMap, remote.post.id) : null
|
|
||||||
|
remoteContent = renderRemoteBlockMap(remote.blockMap, remote.rootId)
|
||||||
headings = remoteContent?.headings ?? []
|
headings = remoteContent?.headings ?? []
|
||||||
const post = remote?.post
|
post = remote.post
|
||||||
const authors = await parseAuthors(post?.authors ?? [])
|
authors = await parseAuthors(post?.authors ?? [])
|
||||||
|
|
||||||
const isCurrentSubpost = isSubpost(currentPostId)
|
isCurrentSubpost = isSubpost(currentPostId)
|
||||||
const navigation = await getAdjacentPosts(currentPostId)
|
navigation = await getAdjacentPosts(currentPostId)
|
||||||
const parentPost = isCurrentSubpost ? await getParentPost(currentPostId) : null
|
parentPost = isCurrentSubpost ? await getParentPost(currentPostId) : null
|
||||||
|
|
||||||
const hasChildPosts = await hasSubposts(currentPostId)
|
hasChildPosts = await hasSubposts(currentPostId)
|
||||||
const subpostCount = !isCurrentSubpost
|
subpostCount = !isCurrentSubpost
|
||||||
? await getSubpostCount(currentPostId)
|
? await getSubpostCount(currentPostId)
|
||||||
: 0
|
: 0
|
||||||
|
|
||||||
const tocSections: TOCSection[] = remoteContent
|
tocSections = remoteContent
|
||||||
? remoteContent.headings.length > 0
|
? remoteContent.headings.length > 0
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
@@ -76,7 +86,11 @@ const tocSections: TOCSection[] = remoteContent
|
|||||||
]
|
]
|
||||||
: []
|
: []
|
||||||
: await getTOCSections(currentPostId)
|
: await getTOCSections(currentPostId)
|
||||||
const heroImage = post?.data?.banner
|
heroImage = post?.data?.banner
|
||||||
|
} catch (error) {
|
||||||
|
console.error('blog page render failed:', error)
|
||||||
|
return Astro.rewrite('/500')
|
||||||
|
}
|
||||||
export const prerender = false;
|
export const prerender = false;
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ const page = await fetch(`https://notion-api.nvme0n1p.dev/v2/posts/?page=${nowPa
|
|||||||
lastPage: totalPages,
|
lastPage: totalPages,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
console.log(page);
|
|
||||||
// fetch page
|
// fetch page
|
||||||
if(page.lastPage < page.currentPage) {
|
if(page.lastPage < page.currentPage) {
|
||||||
console.log("redirect to 404")
|
console.log("redirect to 404")
|
||||||
|
|||||||
Reference in New Issue
Block a user