文章路由支持配置,完善自定义Notion字段配置

This commit is contained in:
tangly
2022-10-18 16:30:38 +08:00
parent c5efc841ba
commit 1fcafeb214
32 changed files with 91 additions and 187 deletions

View File

@@ -31,6 +31,9 @@ const BLOG = {
BACKGROUND_DARK: '#000000', // use hex value, don't forget '#'
SUB_PATH: '', // leave this empty unless you want to deploy in a folder
POST_URL_PREFIX: process.env.NEXT_PUBLIC_POST_URL_PREFIX || 'article', // POST类型文章的默认路径前缀例如默认POST类型的路径是 /article/[slug]
// 如果此项配置为 '' 空, 则文章将没有前缀路径,使用场景: 希望 文章前缀路径为 /post 的情况 支持多级
POST_LIST_STYLE: 'page', // ['page','scroll] 文章列表样式:页码分页、单页滚动加载
POST_LIST_PREVIEW: process.env.NEXT_PUBLIC_POST_PREVIEW || 'false', // 是否在列表加载文章预览
POST_PREVIEW_LINES: 12, // 预览博客行数

View File

@@ -44,7 +44,7 @@ const CommonHead = ({ meta, children }) => {
<meta name="twitter:description" content={description} />
<meta name="twitter:title" content={title} />
{JSON.parse(BLOG.ANALYTICS_BUSUANZI_ENABLE) && <meta name="referrer" content="no-referrer-when-downgrade" />}
{meta?.type === 'article' && (
{meta?.type === 'Post' && (
<>
<meta
property="article:published_time"

View File

@@ -164,7 +164,7 @@ function fixCopy(codeCopy) {
*/
const mapPageUrl = id => {
// return 'https://www.notion.so/' + id.replace(/-/g, '')
return '/article/' + id.replace(/-/g, '')
return '/' + id.replace(/-/g, '')
}
function getMediumZoomMargin() {

View File

@@ -7,7 +7,9 @@ import { isIterable } from '../utils'
* @param tagOptions tags的下拉选项
* @returns {Promise<{}|*[]>}
*/
export function getAllTags({ allPosts, sliceCount = 0, tagOptions }) {
export function getAllTags({ allPages, sliceCount = 0, tagOptions }) {
const allPosts = allPages.filter(page => page.type === 'Post')
if (!allPosts || !tagOptions) {
return []
}

View File

@@ -21,8 +21,7 @@ import getPageProperties from './getPageProperties'
*/
export async function getGlobalNotionData({
pageId = BLOG.NOTION_PAGE_ID,
from,
pageType = ['Post']
from
}) {
// 获取Notion数据
const notionPageData = deepClone(await getNotionPageData({ pageId, from }))
@@ -42,7 +41,9 @@ export async function getGlobalNotionData({
* @param {*}} param0
* @returns
*/
function getLatestPosts({ allPosts, from, latestPostCount }) {
function getLatestPosts({ allPages, from, latestPostCount }) {
const allPosts = allPages.filter(page => page.type === 'Post')
const latestPosts = Object.create(allPosts).sort((a, b) => {
const dateA = new Date(a?.lastEditedTime || a?.createdTime || a?.date?.start_date)
const dateB = new Date(b?.lastEditedTime || b?.createdTime || b?.date?.start_date)
@@ -82,7 +83,7 @@ function getCustomNav({ allPages }) {
const customNav = []
if (allPages && allPages.length > 0) {
allPages.forEach(p => {
if (p?.status?.[0] === 'Published') {
if (p?.status === 'Published' && p?.type === 'Page') {
if (p?.slug?.indexOf('http') === 0) {
customNav.push({ icon: p.icon || null, name: p.title, to: p.slug, show: true })
} else {
@@ -101,7 +102,7 @@ function getCustomNav({ allPages }) {
*/
function getTagOptions(schema) {
if (!schema) return {}
const tagSchema = Object.values(schema).find(e => e.name === 'tags')
const tagSchema = Object.values(schema).find(e => e.name === BLOG.NOTION_PROPERTY_NAME.tags)
return tagSchema?.options || []
}
@@ -112,7 +113,7 @@ function getTagOptions(schema) {
*/
function getCategoryOptions(schema) {
if (!schema) return {}
const categorySchema = Object.values(schema).find(e => e.name === 'category')
const categorySchema = Object.values(schema).find(e => e.name === BLOG.NOTION_PROPERTY_NAME.category)
return categorySchema?.options || []
}
@@ -121,7 +122,8 @@ function getCategoryOptions(schema) {
* @param allPosts
* @returns {Promise<{}|*[]>}
*/
function getAllCategories({ allPosts, categoryOptions, sliceCount = 0 }) {
function getAllCategories({ allPages, categoryOptions, sliceCount = 0 }) {
const allPosts = allPages.filter(page => page.type === 'Post')
if (!allPosts || !categoryOptions) {
return []
}
@@ -220,7 +222,7 @@ async function getPageRecordMapByNotionAPI({ pageId, from }) {
// Check Type Page-Database和Inline-Database
if (
rawMetadata?.type !== 'collection_view_page' &&
rawMetadata?.type !== 'collection_view'
rawMetadata?.type !== 'collection_view'
) {
console.warn(`pageId "${pageId}" is not a database`)
return null
@@ -252,24 +254,23 @@ async function getPageRecordMapByNotionAPI({ pageId, from }) {
}
}
// 读取映射 配置
console.log('当前Notion映射配置-(在blog.config.js中配置)', BLOG.NOTION_PROPERTY_NAME)
const { type, status } = BLOG.NOTION_PROPERTY_NAME
let postCount = 0
const allPages = collectionData.filter(post => {
return post && post[type] &&
['Page'].indexOf(post[type]?.[0]) > -1 &&
(post[status]?.[0] === 'Published' || post[status]?.[0] === 'Invisible')
})
const allPosts = collectionData.filter(post => {
return post && post[status] &&
['Post'].indexOf(post[type]?.[0]) > -1 &&
post[status]?.[0] === 'Published'
})
console.log('全部单页', allPages.length, '全部博客', allPosts.length)
if (post.type === 'Post' && (post.status === 'Published' || post.status === 'Invisible')) {
postCount++
}
return post &&
post.type &&
(post.type === 'Post' || post.type === 'Page') &&
(post.status === 'Published' || post.status === 'Invisible')
}
)
// Sort by date
if (BLOG.POSTS_SORT_BY === 'date') {
allPosts.sort((a, b) => {
allPages.sort((a, b) => {
const dateA = new Date(a?.date?.start_date || a.createdTime)
const dateB = new Date(b?.date?.start_date || b.createdTime)
return dateB - dateA
@@ -277,15 +278,13 @@ async function getPageRecordMapByNotionAPI({ pageId, from }) {
}
const customNav = getCustomNav({ allPages })
const postCount = allPosts?.length || 0
const categories = getAllCategories({ allPosts, categoryOptions, sliceCount: BLOG.PREVIEW_CATEGORY_COUNT })
const tags = getAllTags({ allPosts, tagOptions, sliceCount: BLOG.PREVIEW_TAG_COUNT })
const latestPosts = getLatestPosts({ allPosts, from, latestPostCount: 5 })
const categories = getAllCategories({ allPages, categoryOptions, sliceCount: BLOG.PREVIEW_CATEGORY_COUNT })
const tags = getAllTags({ allPages, tagOptions, sliceCount: BLOG.PREVIEW_TAG_COUNT })
const latestPosts = getLatestPosts({ allPages, from, latestPostCount: 5 })
return {
siteInfo,
allPages,
allPosts,
collection,
collectionQuery,
collectionId,

View File

@@ -58,6 +58,7 @@ async function getPageProperties(id, block, schema, authToken, tagOptions, siteI
}
}
}
// 设置自定义字段
const fieldNames = BLOG.NOTION_PROPERTY_NAME
if (fieldNames) {
@@ -65,7 +66,16 @@ async function getPageProperties(id, block, schema, authToken, tagOptions, siteI
if (fieldNames[key] && properties[fieldNames[key]]) properties[key] = properties[fieldNames[key]]
})
}
properties.slug = properties.slug ?? properties.id
properties.type = properties.type[0]
properties.status = properties.status[0]
if (properties.type === 'Post') {
properties.slug = BLOG.POST_URL_PREFIX + '/' + (properties.slug ?? properties.id)
} else {
properties.slug = (properties.slug ?? properties.id)
}
properties.createdTime = formatDate(new Date(value.created_time).toString(), BLOG.LANG)
properties.lastEditedTime = formatDate(new Date(value?.last_edited_time).toString(), BLOG.LANG)
properties.fullWidth = value.format?.page_full_width ?? false

View File

@@ -38,7 +38,7 @@ export async function generateRss(posts) {
feed.addItem({
title: post.title,
guid: `${post.id}`,
link: `${BLOG.LINK}/article/${post.slug}`,
link: `${BLOG.LINK}/${post.slug}`,
description: post.summary,
content: await createFeedContent(post),
date: new Date(post?.date?.start_date || post?.createdTime)

View File

@@ -62,8 +62,8 @@ const Slug = props => {
const meta = {
title: `${post?.title} | ${siteInfo?.title}`,
description: post?.summary,
type: 'article',
slug: 'article/' + post?.slug,
type: post.type,
slug: post?.slug,
image: post?.page_cover,
category: post?.category?.[0],
tags: post?.tags
@@ -95,13 +95,16 @@ export async function getStaticPaths() {
}
export async function getStaticProps({ params: { slug } }) {
const from = `slug-props-${slug}`
// slug 是个数组
const fullSlug = slug.join('/')
const from = `slug-props-${fullSlug}`
const props = await getGlobalNotionData({ from, pageType: ['Post'] })
const allPosts = props.allPosts
props.post = props.allPosts.find((p) => {
return p.slug === slug || p.id === idToUuid(slug)
const allPosts = props.allPages.filter(page => page.type === 'Post')
props.post = allPosts.find((p) => {
return p.slug === fullSlug || p.id === idToUuid(fullSlug)
})
if (!props.post) {
console.warn('无效地址', fullSlug)
return { props, revalidate: 1 }
}
props.post.blockMap = await getPostBlocks(props.post.id, 'slug')
@@ -114,6 +117,7 @@ export async function getStaticProps({ params: { slug } }) {
allPosts,
BLOG.POST_RECOMMEND_COUNT
)
delete props.allPages
return {
props,
revalidate: 1

View File

@@ -1,115 +0,0 @@
import BLOG from '@/blog.config'
import { getPostBlocks } from '@/lib/notion'
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
import { useGlobal } from '@/lib/global'
import * as ThemeMap from '@/themes'
import React from 'react'
import { useRouter } from 'next/router'
import { isBrowser } from '@/lib/utils'
/**
* 根据notion的slug访问页面针对类型为Page的页面
* @param {*} props
* @returns
*/
const Slug = props => {
const { theme, changeLoadingState } = useGlobal()
const ThemeComponents = ThemeMap[theme]
const { post } = props
if (!post) {
changeLoadingState(true)
const router = useRouter()
setTimeout(() => {
if (isBrowser()) {
const article = document.getElementById('container')
if (!article) {
router.push('/404').then(() => {
console.warn('找不到页面', router.asPath)
})
}
}
}, 5000)
const meta = { title: `${props?.siteInfo?.title || BLOG.TITLE} | loading` }
return <ThemeComponents.LayoutSlug {...props} showArticleInfo={true} meta={meta} />
}
changeLoadingState(false)
// 文章锁🔐
const [lock, setLock] = React.useState(post.password && post.password !== '')
React.useEffect(() => {
if (post.password && post.password !== '') {
setLock(true)
} else {
setLock(false)
}
}, [post])
/**
* 验证文章密码
* @param {*} result
*/
const validPassword = result => {
if (result) {
setLock(false)
}
}
const { siteInfo } = props
const meta = {
title: `${post?.title} | ${siteInfo?.title}`,
description: post?.summary,
type: 'article',
slug: 'article/' + post?.slug,
image: post?.page_cover,
category: post?.category?.[0],
tags: post?.tags
}
props = { ...props, meta, lock, setLock, validPassword }
return <ThemeComponents.LayoutSlug {...props} showArticleInfo={false} />
}
export async function getStaticPaths() {
if (!BLOG.isProd) {
return {
paths: [],
fallback: true
}
}
const from = 'slug-paths'
const { allPages } = await getGlobalNotionData({ from, pageType: ['Page'] })
return {
paths: allPages.map(row => ({ params: { slug: row.slug } })),
fallback: true
}
}
export async function getStaticProps({ params: { slug } }) {
const from = `slug-props-${slug}`
const props = await getGlobalNotionData({ from, pageType: ['Page'] })
const { allPages } = props
const page = allPages?.find(p => p.slug === slug)
if (!page) {
return { props: {}, revalidate: 1 }
}
try {
page.blockMap = await getPostBlocks(page.id, 'slug')
} catch (error) {
console.error('获取文章详情失败', error)
}
props.post = page
return {
props,
revalidate: 1
}
}
export default Slug

View File

@@ -11,8 +11,9 @@ const Index = props => {
export async function getStaticProps() {
const from = 'index'
const props = await getGlobalNotionData({ from, pageType: ['Post'] })
const { allPosts, siteInfo } = props
const props = await getGlobalNotionData({ from })
const { allPages, siteInfo } = props
const allPosts = allPages.filter(page => page.type === 'Post')
const meta = {
title: `${siteInfo?.title} | ${siteInfo?.description}`,
description: siteInfo?.description,

View File

@@ -43,7 +43,7 @@ export const LayoutArchive = props => {
</span>{' '}
&nbsp;
<Link
href={`${BLOG.SUB_PATH}/article/${post.slug}`}
href={`${BLOG.SUB_PATH}/${post.slug}`}
passHref
>
<a className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">

View File

@@ -30,7 +30,7 @@ export const LayoutCategory = props => {
{postsToShow.map(p => (
<article key={p.id} className="mb-12" >
<h2 className="mb-4">
<Link href={`/article/${p.slug}`}>
<Link href={`/${p.slug}`}>
<a className="text-black text-xl md:text-2xl no-underline hover:underline"> {p.title}</a>
</Link>
</h2>

View File

@@ -62,7 +62,7 @@ export const LayoutSearch = props => {
{postsToShow.map(p => (
<article key={p.id} className="mb-12" >
<h2 className="mb-4">
<Link href={`/article/${p.slug}`}>
<Link href={`/${p.slug}`}>
<a className="text-black text-xl md:text-2xl no-underline hover:underline replace"> {p.title}</a>
</Link>
</h2>

View File

@@ -28,7 +28,7 @@ export const LayoutTag = props => {
{postsToShow.map(p => (
<article key={p.id} className="mb-12" >
<h2 className="mb-4">
<Link href={`/article/${p.slug}`}>
<Link href={`/${p.slug}`}>
<a className="text-black text-xl md:text-2xl no-underline hover:underline"> {p.title}</a>
</Link>
</h2>

View File

@@ -23,7 +23,7 @@ export const BlogList = (props) => {
{posts.map(p => (
<article key={p.id} className="mb-12" >
<h2 className="mb-4">
<Link href={`/article/${p.slug}`}>
<Link href={`/${p.slug}`}>
<a className="text-black dark:text-gray-100 text-xl md:text-2xl no-underline hover:underline"> {p.title}</a>
</Link>
</h2>

View File

@@ -30,7 +30,7 @@ export const SideBar = (props) => {
<div className="p-4">
<ul className="list-reset leading-normal">
{latestPosts?.map(p => {
return <Link key={p.id} href={`/article/${p.slug}`} passHref>
return <Link key={p.id} href={`/${p.slug}`} passHref>
<li> <a href="#" className="text-gray-darkest text-sm">{p.title}</a></li>
</Link>
})}

View File

@@ -10,12 +10,12 @@ export default function ArticleAround ({ prev, next }) {
return <></>
}
return <section className='text-gray-800 h-28 flex items-center justify-between space-x-5 my-4'>
<Link href={`/article/${prev.slug}`} passHref>
<Link href={`/${prev.slug}`} passHref>
<a className='text-sm cursor-pointer justify-center items-center flex w-full h-full bg-white bg-opacity-40 hover:bg-hexo-black-gray dark:bg-hexo-black-gray dark:text-gray-200 hover:text-white duration-300'>
<i className='mr-1 fas fa-angle-double-left' />{prev.title}
</a>
</Link>
<Link href={`/article/${next.slug}`} passHref>
<Link href={`/${next.slug}`} passHref>
<a className='text-sm cursor-pointer justify-center items-center flex w-full h-full bg-white bg-opacity-40 hover:bg-hexo-black-gray dark:bg-hexo-black-gray dark:text-gray-200 hover:text-white duration-300'>{next.title}
<i className='ml-1 my-1 fas fa-angle-double-right' />
</a>

View File

@@ -13,7 +13,7 @@ const BlogCard = ({ post, showSummary }) => {
className="animate__animated animate__fadeIn flex flex-col-reverse justify-between duration-300"
>
<div className="p-2 flex flex-col w-full">
<Link href={`${BLOG.SUB_PATH}/article/${post.slug}`} passHref>
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} passHref>
<a
className={`cursor-pointer font-bold hover:underline text-xl ${showPreview ? 'justify-center' : 'justify-start'
} leading-tight text-gray-700 dark:text-gray-100 hover:text-blue-500 dark:hover:text-blue-400`}
@@ -30,7 +30,7 @@ const BlogCard = ({ post, showSummary }) => {
</div>
{CONFIG_FUKA.POST_LIST_COVER && post?.page_cover && (
<Link href={`${BLOG.SUB_PATH}/article/${post.slug}`} passHref>
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} passHref>
<div className="h-40 w-full relative duration-200 cursor-pointer transform overflow-hidden">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img

View File

@@ -29,7 +29,7 @@ const BlogArchiveItem = ({ posts = [], archiveTitle }) => {
<div id={post?.date?.start_date}>
<span className="text-gray-400">{post.date?.start_date}</span>{' '}
&nbsp;
<Link href={`${BLOG.SUB_PATH}/article/${post.slug}`} passHref>
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} passHref>
<a className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
{post.title}
</a>

View File

@@ -11,12 +11,12 @@ export default function ArticleAdjacent ({ prev, next }) {
return <></>
}
return <section className='text-gray-800 items-center text-xs md:text-sm flex justify-between m-1 '>
<Link href={`/article/${prev.slug}`} passHref>
<Link href={`/${prev.slug}`} passHref>
<a className='py-1 cursor-pointer hover:underline justify-start items-center dark:text-white flex w-full h-full duration-200'>
<i className='mr-1 fas fa-angle-left' />{prev.title}
</a>
</Link>
<Link href={`/article/${next.slug}`} passHref>
<Link href={`/${next.slug}`} passHref>
<a className='py-1 cursor-pointer hover:underline justify-end items-center dark:text-white flex w-full h-full duration-200'>{next.title}
<i className='ml-1 my-1 fas fa-angle-right' />
</a>

View File

@@ -35,7 +35,7 @@ export default function ArticleRecommend({ recommendPosts, siteInfo }) {
<Link
key={post.id}
title={post.title}
href={`${BLOG.SUB_PATH}/article/${post.slug}`}
href={`${BLOG.SUB_PATH}/${post.slug}`}
passHref
>
<a

View File

@@ -29,7 +29,7 @@ const BlogPostArchive = ({ posts = [], archiveTitle }) => {
<div id={post?.date?.start_date}>
<span className="text-gray-400">{post.date?.start_date}</span>{' '}
&nbsp;
<Link href={`${BLOG.SUB_PATH}/article/${post.slug}`} passHref>
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} passHref>
<a className="dark:text-gray-400 dark:hover:text-indigo-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
{post.title}
</a>

View File

@@ -14,7 +14,7 @@ const BlogPostCard = ({ post, showSummary }) => {
className="animate__animated animate__fadeIn flex flex-col-reverse lg:flex-row justify-between duration-300"
>
<div className="lg:p-8 p-4 flex flex-col w-full">
<Link href={`${BLOG.SUB_PATH}/article/${post.slug}`} passHref>
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} passHref>
<a
className={`replace cursor-pointer hover:underline text-2xl font-sans ${showPreview ? 'text-center' : ''
} leading-tight text-gray-700 dark:text-gray-100 hover:text-indigo-700 dark:hover:text-indigo-400`}
@@ -79,7 +79,7 @@ const BlogPostCard = ({ post, showSummary }) => {
</div>
{CONFIG_HEXO.POST_LIST_COVER && !showPreview && post?.page_cover && !post.results && (
<Link href={`${BLOG.SUB_PATH}/article/${post.slug}`} passHref>
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} passHref>
<div className="flex w-full relative duration-200 rounded-t-xl lg:rounded-r-xl lg:rounded-t-none cursor-pointer transform overflow-hidden">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img

View File

@@ -25,7 +25,7 @@ const LatestPostsGroup = ({ latestPosts, siteInfo }) => {
</div>
</div>
{latestPosts.map(post => {
const selected = currentPath === `${BLOG.SUB_PATH}/article/${post.slug}`
const selected = currentPath === `${BLOG.SUB_PATH}/${post.slug}`
const headerImage = post?.page_cover
? `url("${post.page_cover}")`
: `url("${siteInfo?.pageCover}")`
@@ -34,7 +34,7 @@ const LatestPostsGroup = ({ latestPosts, siteInfo }) => {
<Link
key={post.id}
title={post.title}
href={`${BLOG.SUB_PATH}/article/${post.slug}`}
href={`${BLOG.SUB_PATH}/${post.slug}`}
passHref
>
<a className={'my-1 flex font-sans'}>

View File

@@ -45,7 +45,7 @@ export const LayoutArchive = props => {
</span>{' '}
&nbsp;
<Link
href={`${BLOG.SUB_PATH}/article/${post.slug}`}
href={`${BLOG.SUB_PATH}/${post.slug}`}
passHref
>
<a className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">

View File

@@ -10,12 +10,12 @@ export default function ArticleAround ({ prev, next }) {
return <></>
}
return <section className='text-gray-800 h-12 flex items-center justify-between space-x-5 my-4'>
<Link href={`/article/${prev.slug}`} passHref>
<Link href={`/${prev.slug}`} passHref>
<a className='text-sm cursor-pointer justify-start items-center flex hover:underline duration-300'>
<i className='mr-1 fas fa-angle-double-left' />{prev.title}
</a>
</Link>
<Link href={`/article/${next.slug}`} passHref>
<Link href={`/${next.slug}`} passHref>
<a className='text-sm cursor-pointer justify-end items-center flex hover:underline duration-300'>{next.title}
<i className='ml-1 my-1 fas fa-angle-double-right' />
</a>

View File

@@ -16,7 +16,7 @@ const BlogPostCard = ({ post, showSummary }) => {
className="animate__animated animate__fadeIn duration-300 mb-6 max-w-7xl border-b dark:border-gray-800 "
>
<div className="lg:p-8 p-4 flex flex-col w-full">
<Link href={`${BLOG.SUB_PATH}/article/${post.slug}`} passHref>
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} passHref>
<a
className={
'cursor-pointer font-bold font-sans hover:underline text-3xl leading-tight text-gray-700 dark:text-gray-100 hover:text-green-500 dark:hover:text-green-400'
@@ -54,7 +54,7 @@ const BlogPostCard = ({ post, showSummary }) => {
<NotionPage post={post} />
<div className="pointer-events-none border-t pt-8 border-dashed">
<div className="w-full justify-start flex">
<Link href={`${BLOG.SUB_PATH}/article/${post.slug}`} passHref>
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} passHref>
<a className="hover:bg-opacity-100 hover:scale-105 duration-200 pointer-events-auto transform font-bold text-green-500 cursor-pointer">
{locale.COMMON.ARTICLE_DETAIL}
<i className="ml-1 fas fa-angle-right" />

View File

@@ -10,12 +10,12 @@ export default function BlogAround ({ prev, next }) {
return <></>
}
return <section className='text-gray-800 border-t dark:text-gray-300 flex flex-wrap lg:flex-nowrap lg:space-x-10 justify-between py-2'>
{prev && <Link href={`/article/${prev.slug}`} passHref>
{prev && <Link href={`/${prev.slug}`} passHref>
<a className='text-sm py-3 text-gray-400 hover:underline cursor-pointer'>
<i className='mr-1 fas fa-angle-double-left' />{prev.title}
</a>
</Link>}
{next && <Link href={`/article/${next.slug}`} passHref>
{next && <Link href={`/${next.slug}`} passHref>
<a className='text-sm flex py-3 text-gray-400 hover:underline cursor-pointer'>{next.title}
<i className='ml-1 my-1 fas fa-angle-double-right' />
</a>

View File

@@ -29,7 +29,7 @@ const BlogPostArchive = ({ posts = [], archiveTitle }) => {
<div id={post?.date?.start_date}>
<span className="text-gray-400">{post.date?.start_date}</span>{' '}
&nbsp;
<Link href={`${BLOG.SUB_PATH}/article/${post.slug}`} passHref>
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} passHref>
<a className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
{post.title}
</a>

View File

@@ -18,7 +18,7 @@ const BlogPostCard = ({ post, showSummary }) => {
className="flex flex-col-reverse justify-between duration-300"
>
<div className="lg:p-8 p-4 flex flex-col w-full">
<Link href={`${BLOG.SUB_PATH}/article/${post.slug}`} passHref>
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} passHref>
<a
className={`cursor-pointer font-bold hover:underline text-3xl ${showPreview ? 'text-center' : ''
} leading-tight text-gray-700 dark:text-gray-100 hover:text-blue-500 dark:hover:text-blue-400`}
@@ -84,7 +84,7 @@ const BlogPostCard = ({ post, showSummary }) => {
)}
<div className="text-right border-t pt-8 border-dashed">
<Link href={`${BLOG.SUB_PATH}/article/${post.slug}`}>
<Link href={`${BLOG.SUB_PATH}/${post.slug}`}>
<a className="hover:bg-opacity-100 hover:underline transform duration-300 p-3 text-white bg-gray-800 dark:bg-black cursor-pointer">
{locale.COMMON.ARTICLE_DETAIL}
<i className="ml-1 fas fa-angle-right" />
@@ -94,7 +94,7 @@ const BlogPostCard = ({ post, showSummary }) => {
</div>
{CONFIG_NEXT.POST_LIST_COVER && post?.page_cover && (
<Link href={`${BLOG.SUB_PATH}/article/${post.slug}`} passHref>
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} passHref>
<div className="h-72 w-full relative duration-200 cursor-pointer transform overflow-hidden">
<Image
className="hover:scale-105 transform duration-500"

View File

@@ -26,12 +26,12 @@ const LatestPostsGroup = ({ latestPosts }) => {
</div>
</div>
{latestPosts.map(post => {
const selected = currentPath === `${BLOG.SUB_PATH}/article/${post.slug}`
const selected = currentPath === `${BLOG.SUB_PATH}/${post.slug}`
return (
<Link
key={post.id}
title={post.title}
href={`${BLOG.SUB_PATH}/article/${post.slug}`}
href={`${BLOG.SUB_PATH}/${post.slug}`}
passHref
>
<a className={'my-1 flex font-light'}>

View File

@@ -18,7 +18,7 @@ const RecommendPosts = ({ recommendPosts }) => {
<ul className="font-light text-sm">
{recommendPosts.map(post => (
<li className="py-1" key={post.id}>
<Link href={`/article/${post.slug}`}>
<Link href={`/${post.slug}`}>
<a className="cursor-pointer hover:underline">
{post.title}
</a>