Skip to content

Commit

Permalink
add movie review
Browse files Browse the repository at this point in the history
  • Loading branch information
randxie committed Apr 28, 2024
1 parent ffbc587 commit 65a5154
Show file tree
Hide file tree
Showing 9 changed files with 271 additions and 13 deletions.
2 changes: 1 addition & 1 deletion app/blog/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default function BlogPage() {
posts={posts}
initialDisplayPosts={initialDisplayPosts}
pagination={pagination}
title="All Posts"
title="Tags"
/>
)
}
131 changes: 131 additions & 0 deletions app/random/[...slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import 'css/prism.css'
import 'katex/dist/katex.css'

import PageTitle from '@/components/PageTitle'
import { components } from '@/components/MDXComponents'
import { MDXLayoutRenderer } from 'pliny/mdx-components'
import { sortPosts, coreContent, allCoreContent } from 'pliny/utils/contentlayer'
import { allAuthors, allRandomThoughts } from 'contentlayer/generated'
import type { Authors, RandomThoughts } from 'contentlayer/generated'
import PostSimple from '@/layouts/PostSimple'
import PostLayout from '@/layouts/PostLayout'
import PostBanner from '@/layouts/PostBanner'
import { Metadata } from 'next'
import siteMetadata from '@/data/siteMetadata'

const defaultLayout = 'PostLayout'
const layouts = {
PostSimple,
PostLayout,
PostBanner,
}

export async function generateMetadata({
params,
}: {
params: { slug: string[] }
}): Promise<Metadata | undefined> {
const slug = decodeURI(params.slug.join('/'))
const post = allRandomThoughts.find((p) => p.slug === slug)
const authorList = post?.authors || ['default']
const authorDetails = authorList.map((author) => {
const authorResults = allAuthors.find((p) => p.slug === author)
return coreContent(authorResults as Authors)
})
if (!post) {
return
}

const publishedAt = new Date(post.date).toISOString()
const modifiedAt = new Date(post.lastmod || post.date).toISOString()
const authors = authorDetails.map((author) => author.name)
let imageList = [siteMetadata.socialBanner]
if (post.images) {
imageList = typeof post.images === 'string' ? [post.images] : post.images
}
const ogImages = imageList.map((img) => {
console.log(img)
return {
url: img.includes('http') ? img : siteMetadata.siteUrl + img,
}
})

return {
title: post.title,
description: post.summary,
openGraph: {
title: post.title,
description: post.summary,
siteName: siteMetadata.title,
locale: 'en_US',
type: 'article',
publishedTime: publishedAt,
modifiedTime: modifiedAt,
url: './',
images: ogImages,
authors: authors.length > 0 ? authors : [siteMetadata.author],
},
twitter: {
card: 'summary_large_image',
title: post.title,
description: post.summary,
images: imageList,
},
}
}

export const generateStaticParams = async () => {
const paths = allRandomThoughts.map((p) => ({ slug: p.slug.split('/') }))

return paths
}

export default async function Page({ params }: { params: { slug: string[] } }) {
const slug = decodeURI(params.slug.join('/'))
// Filter out drafts in production
const sortedCoreContents = allCoreContent(sortPosts(allRandomThoughts))
const postIndex = sortedCoreContents.findIndex((p) => p.slug === slug)
if (postIndex === -1) {
return (
<div className="mt-24 text-center">
<PageTitle>
Under Construction{' '}
<span role="img" aria-label="roadwork sign">
🚧
</span>
</PageTitle>
</div>
)
}

const prev = sortedCoreContents[postIndex + 1]
const next = sortedCoreContents[postIndex - 1]
const post = allRandomThoughts.find((p) => p.slug === slug) as RandomThoughts
const authorList = post?.authors || ['default']
const authorDetails = authorList.map((author) => {
const authorResults = allAuthors.find((p) => p.slug === author)
return coreContent(authorResults as Authors)
})
const mainContent = coreContent(post)
const jsonLd = post.structuredData
jsonLd['author'] = authorDetails.map((author) => {
return {
'@type': 'Person',
name: author.name,
}
})

const Layout = layouts[post.layout || defaultLayout]

return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
<Layout content={mainContent} authorDetails={authorDetails} next={next} prev={prev}>
<MDXLayoutRenderer code={post.body.code} components={components} toc={post.toc} />
</Layout>
</>
)
}
30 changes: 30 additions & 0 deletions app/random/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import ListLayout from '@/layouts/ListLayout'
import {allCoreContent, sortPosts} from 'pliny/utils/contentlayer'
import {allRandomThoughts} from 'contentlayer/generated'
import {genPageMetadata} from 'app/seo'

const POSTS_PER_PAGE = 8

export const metadata = genPageMetadata({title: '随笔'})

export default function BlogPage() {
const posts = allCoreContent(sortPosts(allRandomThoughts))
const pageNumber = 1
const initialDisplayPosts = posts.slice(
POSTS_PER_PAGE * (pageNumber - 1),
POSTS_PER_PAGE * pageNumber
)
const pagination = {
currentPage: pageNumber,
totalPages: Math.ceil(posts.length / POSTS_PER_PAGE),
}

return (
<ListLayout
posts={posts}
initialDisplayPosts={initialDisplayPosts}
pagination={pagination}
subtitle="生活不只有事业,还有诗和远方。"
/>
)
}
34 changes: 34 additions & 0 deletions app/random/page/[page]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import ListLayout from '@/layouts/ListLayoutWithTags'
import { allCoreContent, sortPosts } from 'pliny/utils/contentlayer'
import { allRandomThoughts } from 'contentlayer/generated'

const POSTS_PER_PAGE = 5

export const generateStaticParams = async () => {
const totalPages = Math.ceil(allRandomThoughts.length / POSTS_PER_PAGE)
const paths = Array.from({ length: totalPages }, (_, i) => ({ page: (i + 1).toString() }))

return paths
}

export default function Page({ params }: { params: { page: string } }) {
const posts = allCoreContent(sortPosts(allRandomThoughts))
const pageNumber = parseInt(params.page as string)
const initialDisplayPosts = posts.slice(
POSTS_PER_PAGE * (pageNumber - 1),
POSTS_PER_PAGE * pageNumber
)
const pagination = {
currentPage: pageNumber,
totalPages: Math.ceil(posts.length / POSTS_PER_PAGE),
}

return (
<ListLayout
posts={posts}
initialDisplayPosts={initialDisplayPosts}
pagination={pagination}
title="All Posts"
/>
)
}
2 changes: 1 addition & 1 deletion app/tag-data.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"robots":1,"functional-programming":1,"data-structure":1,"embedding":1,"search":1,"channel-pruning":1,"deployment":1,"shufflenet-v2":1,"efficient-neural-network":1,"int8":1,"quantization":1,"inference":2,"tree":1,"redisjson":1,"materialized-view":1,"feature-engineering":1,"model-serving":1,"staff-eng":1,"bear-market":2,"immigration":1,"life":2,"gpu-programming":1,"ml":1,"vc":1,"crypto-wallet":1,"industrial-research":1,"dlvm":1,"gpu":1,"low-cost":1,"chatgpt":4,"ai":1,"llm":4,"movie-review":1,"hong-kong":1,"prompt":1,"search-query":1,"search-engine":1,"career":1,"robotics":1,"gpt-4":1,"vision":1,"parenthood":1,"sampling":1,"text2sql":1}
{"text2sql":1,"sampling":1,"parenthood":1,"llm":4,"chatgpt":4,"robotics":1,"gpt-4":1,"vision":1,"career":1,"prompt":1,"search-query":1,"search-engine":1,"movie-review":1,"life":2,"hong-kong":1,"ai":1,"dlvm":1,"gpu":1,"low-cost":1,"vc":1,"crypto-wallet":1,"industrial-research":1,"gpu-programming":1,"ml":1,"bear-market":2,"immigration":1,"staff-eng":1,"materialized-view":1,"feature-engineering":1,"model-serving":1,"redisjson":1,"tree":1,"inference":2,"int8":1,"quantization":1,"shufflenet-v2":1,"efficient-neural-network":1,"channel-pruning":1,"deployment":1,"embedding":1,"search":1,"functional-programming":1,"data-structure":1,"robots":1}
39 changes: 38 additions & 1 deletion contentlayer.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,43 @@ export const Blog = defineDocumentType(() => ({
},
}))

export const RandomThoughts = defineDocumentType(() => ({
name: 'RandomThoughts',
filePathPattern: 'random/**/*.mdx',
contentType: 'mdx',
fields: {
title: { type: 'string', required: true },
date: { type: 'date', required: true },
tags: { type: 'list', of: { type: 'string' }, default: [] },
lastmod: { type: 'date' },
draft: { type: 'boolean' },
summary: { type: 'string' },
images: { type: 'list', of: { type: 'string' } },
authors: { type: 'list', of: { type: 'string' } },
layout: { type: 'string' },
bibliography: { type: 'string' },
canonicalUrl: { type: 'string' },
},
computedFields: {
...computedFields,
structuredData: {
type: 'json',
resolve: (doc) => ({
'@context': 'https://schema.org',
'@type': 'BlogPosting',
headline: doc.title,
datePublished: doc.date,
dateModified: doc.lastmod || doc.date,
description: doc.summary,
image: doc.images ? doc.images[0] : siteMetadata.socialBanner,
url: `${siteMetadata.siteUrl}/${doc._raw.flattenedPath}`,
author: doc.authors,
}),
},
},
}))


export const Authors = defineDocumentType(() => ({
name: 'Authors',
filePathPattern: 'authors/**/*.mdx',
Expand All @@ -132,7 +169,7 @@ export const Authors = defineDocumentType(() => ({

export default makeSource({
contentDirPath: 'data',
documentTypes: [Blog, Authors],
documentTypes: [Blog, Authors, RandomThoughts],
mdx: {
cwd: process.cwd(),
remarkPlugins: [
Expand Down
7 changes: 4 additions & 3 deletions data/headerNavLinks.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
const headerNavLinks = [
{ href: '/', title: 'Home' },
{ href: '/about', title: 'About' },
{ href: '/blog', title: 'Blog' },
{ href: '/services', title: 'Services' },
{ href: '/tags', title: 'Tags' },
// { href: '/tags', title: 'Tags' },
{ href: '/projects', title: 'Projects' },
{ href: '/speaking', title: 'Speaking' },
{ href: '/about', title: 'Who am I' },
{ href: '/services', title: 'Services' },
{ href: '/random', title: '随笔' },
]

export default headerNavLinks
21 changes: 21 additions & 0 deletions data/random/2024-04-27-let-life-slow-down.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
title: 让生活慢一点
date: '2024-04-27'
tags: ['Movie']
draft: false
---

当一个人经常用二倍速看视频, 听podcast, 看电影简评, 就会越来越难静下心来欣赏一部电影. 今天, 走路去Dr.Ink买了一杯咖啡回到家, 突然心血来潮想好好地看一部电影. 于是, 就完整得看完了2023年出品的"不虚此行". 缓慢的节奏, 莫名得让我的内心平静下来了. 所以想记录一下自己的感想.

电影讲述了一个编剧转型去写悼词, 并从中看到不同人的人生故事. 写悼词的故事主角有餐厅老板, 有患癌症的病人, 有因抑郁症去世的配音网红, 有传统中国父亲形象的小学老师. 每个人都普普通通, 但通过他们亲人, 朋友, 同事的描述拼凑出一个个有血有肉的人. 整部电影的叙事风格就像是平静的水面下藏着很多暗涌. 在这个追求快节奏, 刺激观感的年代, 是非常难能可贵的.

我感受最深的是那位为父亲预约悼词的王先生. 这是一个很典型的中国父子关系. 儿子从乡下来到了北京打拼, 父亲非常想和儿子多交流, 却因为儿子太忙直到去世都没有多少机会. 在胡歌采访这位王先生的时候, 王先生都拿着两部手机在处理工作. 胡歌通过王先生父亲的遗物察觉到了父子交流太少的这个遗憾, 也从王先生的儿子侧面得到了更多的信息. 于是他在悼词里面悄悄地放进去了自己的观察. 可惜电影没有给出具体的悼词, 里面写了什么也不得而知. 如果有机会的话, 大家还是要珍惜每次跟父母交流的机会, 减少日后的遗憾.

最后, 用一小段诗总结一下:

```
被快进键控制的世界
被忽略的细腻情感
让生活慢一点
故事的完结, 不应仓促
```
18 changes: 11 additions & 7 deletions layouts/ListLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
'use client'

import { useState } from 'react'
import { usePathname } from 'next/navigation'
import { formatDate } from 'pliny/utils/formatDate'
import { CoreContent } from 'pliny/utils/contentlayer'
import type { Blog } from 'contentlayer/generated'
import {useState} from 'react'
import {usePathname} from 'next/navigation'
import {formatDate} from 'pliny/utils/formatDate'
import {CoreContent} from 'pliny/utils/contentlayer'
import type {Blog} from 'contentlayer/generated'
import Link from '@/components/Link'
import Tag from '@/components/Tag'
import siteMetadata from '@/data/siteMetadata'
Expand All @@ -20,7 +20,7 @@ interface ListLayoutProps {
pagination?: PaginationProps
}

function Pagination({ totalPages, currentPage }: PaginationProps) {
function Pagination({totalPages, currentPage}: PaginationProps) {
const pathname = usePathname()
const basePath = pathname.split('/')[1]
const prevPage = currentPage - 1 > 0
Expand Down Expand Up @@ -65,6 +65,7 @@ export default function ListLayout({
title,
initialDisplayPosts = [],
pagination,
subtitle = '',
}: ListLayoutProps) {
const [searchValue, setSearchValue] = useState('')
const filteredBlogPosts = posts.filter((post) => {
Expand All @@ -83,6 +84,9 @@ export default function ListLayout({
<h1 className="text-3xl font-extrabold leading-9 tracking-tight text-gray-900 dark:text-gray-100 sm:text-4xl sm:leading-10 md:text-6xl md:leading-14">
{title}
</h1>
<div>
{subtitle && <p>{subtitle}</p>}
</div>
<div className="relative max-w-lg">
<label>
<span className="sr-only">Search articles</span>
Expand Down Expand Up @@ -113,7 +117,7 @@ export default function ListLayout({
<ul>
{!filteredBlogPosts.length && 'No posts found.'}
{displayPosts.map((post) => {
const { path, date, title, summary, tags } = post
const {path, date, title, summary, tags} = post
return (
<li key={path} className="py-4">
<article className="space-y-2 xl:grid xl:grid-cols-4 xl:items-baseline xl:space-y-0">
Expand Down

0 comments on commit 65a5154

Please sign in to comment.