Merge pull request #200 from tangly1024/feature-notion-page-link

Feature notion page link
This commit is contained in:
tangly1024
2022-04-25 16:24:59 +08:00
committed by GitHub
30 changed files with 187 additions and 104 deletions

View File

@@ -90,7 +90,7 @@ yarn run start # 本地启动NextJS服务
## 致谢
感谢Craig Hart发起的Nobelium项目
<table><tr align="left">
<td align="center"><a href="https://github.com/craigary" title="Craig Hart"><img src="https://avatars.githubusercontent.com/u/10571717" width="64px;"alt="Craig Hart"/></a><br/><a href="https://notion.so/cnotion" title="Craig Hart">Craig Hart</a></td>
<td align="center"><a href="https://github.com/craigary" title="Craig Hart"><img src="https://avatars.githubusercontent.com/u/10571717" width="64px;"alt="Craig Hart"/></a><br/><a href="https://github.com/craigary" title="Craig Hart">Craig Hart</a></td>
</tr></table>
## 贡献者

View File

@@ -10,9 +10,13 @@ const BLOG = {
NOTION_ACCESS_TOKEN: process.env.NOTION_ACCESS_TOKEN || '', // Useful if you prefer not to make your database public
DEBUG: process.env.NEXT_PUBLIC_DEBUG || false, // 是否显示调试按钮
// 一个小插件展示你的facebook fan page~ @see https://tw.andys.pro/article/add-facebook-fanpage-notionnext
FACEBOOK_PAGE_TITLE:
process.env.NEXT_PUBLIC_FACEBOOK_PAGE_TITLE || null, // 邊欄 Facebook Page widget 的標題欄,填''則無標題欄 e.g FACEBOOK 粉絲團'
FACEBOOK_PAGE:
process.env.NEXT_PUBLIC_FACEBOOK_PAGE || null, // Facebook Page 的連結 e.g https://www.facebook.com/tw.andys.pro
FACEBOOK_PAGE_ID: process.env.NEXT_PUBLIC_FACEBOOK_PAGE_ID || '', // Facebook Page ID 來啟用 messenger 聊天功能
FACEBOOK_APP_ID: process.env.NEXT_PUBLIC_FACEBOOK_APP_ID || '', // Facebook App ID 來啟用 messenger 聊天功能
FACEBOOK_PAGE: process.env.NEXT_PUBLIC_FACEBOOK_PAGE || 'https://www.facebook.com/tw.andys.pro', // Facebook Page 的連結
FACEBOOK_APP_ID: process.env.NEXT_PUBLIC_FACEBOOK_APP_ID || '', // Facebook App ID 來啟用 messenger 聊天功能 获取: https://developers.facebook.com/
THEME: process.env.NEXT_PUBLIC_THEME || 'next', // 主题, 支持 ['next','hexo',"fukasawa','medium']
THEME_SWITCH: process.env.NEXT_PUBLIC_THEME_SWITCH || false, // 是否显示切换主题按钮
@@ -120,7 +124,7 @@ const BLOG = {
process.env.NEXT_PUBLIC_DESCRIPTION || '这是一个由NotionNext生成的站点', // 站点描述被notion中的页面描述覆盖
isProd: process.env.VERCEL_ENV === 'production', // distinguish between development and production environment (ref: https://vercel.com/docs/environment-variables#system-environment-variables) isProd: process.env.VERCEL_ENV === 'production' // distinguish between development and production environment (ref: https://vercel.com/docs/environment-variables#system-environment-variables)
VERSION: '3.1.0' // 版本号
VERSION: '3.2.1' // 版本号
}
module.exports = BLOG

View File

@@ -0,0 +1,30 @@
import BLOG from '@/blog.config'
import { FacebookProvider, Page } from 'react-facebook'
import { FacebookIcon } from 'react-share'
const FacebookPage = () => {
if (!BLOG.FACEBOOK_APP_ID && !BLOG.FACEBOOK_PAGE) {
return <></>
}
return <div className="shadow-md hover:shadow-xl dark:text-gray-300 border dark:border-black rounded-xl px-2 py-4 bg-white dark:bg-hexo-black-gray lg:duration-100 justify-center">
{BLOG.FACEBOOK_PAGE && (
<div className="flex items-center pb-2">
<a
href={BLOG.FACEBOOK_PAGE}
target="_blank"
rel="noopener noreferrer"
className="p-1 pr-2 pt-0"
>
<FacebookIcon size={28} round />
</a>
<a href={BLOG.FACEBOOK_PAGE} rel="noopener noreferrer" target="_blank">
{BLOG.FACEBOOK_PAGE_TITLE}
</a>
</div>
)}
{BLOG.FACEBOOK_APP_ID && <FacebookProvider appId={BLOG.FACEBOOK_APP_ID}>
<Page href={BLOG.FACEBOOK_PAGE} tabs="timeline" />
</FacebookProvider>}
</div>
}
export default FacebookPage

View File

@@ -59,7 +59,7 @@ const NotionPage = ({ post }) => {
(zoomRef.current).attach(imgList[i])
}
}
}, [router.events])
}, [router?.events])
return <div id='container'>
<NotionRenderer
@@ -75,8 +75,14 @@ const NotionPage = ({ post }) => {
</div>
}
/**
* 将id映射成博文内部链接。
* @param {*} id
* @returns
*/
const mapPageUrl = id => {
return 'https://www.notion.so/' + id.replace(/-/g, '')
// return 'https://www.notion.so/' + id.replace(/-/g, '')
return '/article/' + id.replace(/-/g, '')
}
function getMediumZoomMargin() {

View File

@@ -1,9 +1,11 @@
import { isIterable } from '../utils'
/**
* 获取所有文章的分类
* @param allPosts
* @returns {Promise<{}|*[]>}
*/
export async function getAllCategories ({ allPosts, categoryOptions, sliceCount = 0 }) {
export async function getAllCategories({ allPosts, categoryOptions, sliceCount = 0 }) {
if (!allPosts || !categoryOptions) {
return []
}
@@ -19,12 +21,14 @@ export async function getAllCategories ({ allPosts, categoryOptions, sliceCount
}
})
const list = []
categoryOptions.forEach(c => {
const count = categoryObj[c.value]
if (count) {
list.push({ id: c.id, name: c.value, color: c.color, count })
if (isIterable(categoryOptions)) {
for (const c of categoryOptions) {
const count = categoryObj[c.value]
if (count) {
list.push({ id: c.id, name: c.value, color: c.color, count })
}
}
})
}
// 按照数量排序
// list.sort((a, b) => b.count - a.count)

View File

@@ -1,3 +1,4 @@
import { isIterable } from '../utils'
/**
* 获取所有文章的标签
@@ -6,7 +7,7 @@
* @param tagOptions tags的下拉选项
* @returns {Promise<{}|*[]>}
*/
export async function getAllTags ({ allPosts, sliceCount = 0, tagOptions }) {
export async function getAllTags({ allPosts, sliceCount = 0, tagOptions }) {
if (!allPosts || !tagOptions) {
return []
}
@@ -22,12 +23,14 @@ export async function getAllTags ({ allPosts, sliceCount = 0, tagOptions }) {
}
})
const list = []
tagOptions.forEach(c => {
const count = tagObj[c.value]
if (count) {
list.push({ id: c.id, name: c.value, color: c.color, count })
}
})
if (isIterable(tagOptions)) {
tagOptions.forEach(c => {
const count = tagObj[c.value]
if (count) {
list.push({ id: c.id, name: c.value, color: c.color, count })
}
})
}
// 按照数量排序
// list.sort((a, b) => b.count - a.count)

View File

@@ -11,12 +11,12 @@ const createFeedContent = async post => {
}
const blockMap = await getPostBlocks(post.id, 'rss-content')
if (blockMap) {
post.blockMap = blockMap
const content = ReactDOMServer.renderToString(<NotionPage post={post} />)
const regexExp =
/<div class="notion-collection-row"><div class="notion-collection-row-body"><div class="notion-collection-row-property"><div class="notion-collection-column-title"><svg.*?class="notion-collection-column-title-icon">.*?<\/svg><div class="notion-collection-column-title-body">.*?<\/div><\/div><div class="notion-collection-row-value">.*?<\/div><\/div><\/div><\/div>/g
return content.replace(regexExp, '')
}
return post.summary
}
export async function generateRss(posts) {

View File

@@ -64,10 +64,19 @@ export function mergeDeep(target, ...sources) {
}
/**
* 对象检查
* 是否对象
* @param item
* @returns {boolean}
*/
export function isObject(item) {
return (item && typeof item === 'object' && !Array.isArray(item))
}
/**
* 是否可迭代
* @param {*} obj
* @returns
*/
export function isIterable(obj) {
return obj != null && typeof obj[Symbol.iterator] === 'function'
}

View File

@@ -1,6 +1,6 @@
{
"name": "notion-next",
"version": "3.1.0",
"version": "3.2.1",
"homepage": "https://github.com/tangly1024/NotionNext.git",
"license": "MIT",
"repository": {
@@ -40,8 +40,10 @@
"react-cookies": "^0.1.1",
"react-cusdis": "^2.1.3",
"react-dom": "17.0.2",
"react-facebook": "^8.1.4",
"react-messenger-customer-chat": "^0.8.0",
"react-notion-x": "6.6.2",
"react-share": "^4.4.0",
"smoothscroll-polyfill": "^0.4.4",
"typed.js": "^2.0.12",
"use-ackee": "^3.0.0"

View File

@@ -5,6 +5,7 @@ import { useGlobal } from '@/lib/global'
import * as ThemeMap from '@/themes'
import { useEffect, useState } from 'react'
import { useRouter } from 'next/router'
import { idToUuid } from 'notion-utils'
/**
* 根据notion的slug访问页面
@@ -30,7 +31,7 @@ const Slug = props => {
}
}, 3000)
})
const meta = { title: `${props?.siteInfo?.title} | loading` }
const meta = { title: `${props?.siteInfo?.title || BLOG.TITLE} | loading` }
return <ThemeComponents.LayoutSlug {...props} showArticleInfo={true} meta={meta} />
}
@@ -92,7 +93,9 @@ export async function getStaticProps({ params: { slug } }) {
const from = `slug-props-${slug}`
const props = await getGlobalNotionData({ from, pageType: ['Post'] })
const allPosts = props.allPosts
props.post = props.allPosts.find(p => p.slug === slug)
props.post = props.allPosts.find((p) => {
return p.slug === slug || p.id === idToUuid(slug)
})
if (!props.post) {
return { props, revalidate: 1 }
}

View File

@@ -1601,7 +1601,7 @@ svg.notion-page-icon {
}
svg.notion-page-icon {
@apply hidden;
/* @apply hidden;*/
}
svg + .notion-page-title-text {

View File

@@ -38,7 +38,7 @@ export const LayoutSearch = props => {
<LayoutBase {...props}>
<h2>Search - {keyword}</h2>
<SearchInput {...props} />
{postsToShow.map(p => (
{postsToShow?.map(p => (
<div key={p.id} className="border my-12">
<Link href={`/article/${p.slug}`}>
<a className="underline cursor-pointer">{p.title}</a>

View File

@@ -3,6 +3,6 @@ import LayoutBase from './LayoutBase'
export const LayoutIndex = (props) => {
return <LayoutBase {...props}>
<BlogListPage {...props}/>
<BlogListPage {...props} />
</LayoutBase>
}

View File

@@ -14,10 +14,9 @@ export const LayoutSearch = (props) => {
const re = new RegExp(`${currentSearch}`, 'gim')
container.innerHTML = container.innerHTML.replace(re, `<span class='text-red-500 border-b border-dashed'>${currentSearch}</span>`)
}
},
100)
}, 100)
})
return <LayoutBase {...props} currentSearch={currentSearch}>
<BlogListPage {...props}/>
<BlogListPage {...props} />
</LayoutBase>
}

View File

@@ -7,7 +7,7 @@ import Card from './Card'
const BlogCard = ({ post, showSummary }) => {
const showPreview = CONFIG_FUKA.POST_LIST_PREVIEW && post.blockMap
return (
<Card className="w-full lg:max-w-sm p-2">
<Card className="w-full lg:max-w-sm p-2 h-full overflow-auto">
<div
key={post.id}
className="animate__animated animate__fadeIn flex flex-col-reverse justify-between duration-300"
@@ -15,9 +15,8 @@ const BlogCard = ({ post, showSummary }) => {
<div className="p-2 flex flex-col w-full">
<Link href={`${BLOG.SUB_PATH}/article/${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`}
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`}
>
{post.title}
</a>

View File

@@ -17,7 +17,7 @@ const BlogListPage = ({ page = 1, posts = [], postCount }) => {
const showNext = page < totalPage && posts.length === BLOG.POSTS_PER_PAGE && posts.length < postCount
const [colCount, changeCol] = useState(1)
function updateCol () {
function updateCol() {
if (window.outerWidth > 1200) {
changeCol(3)
} else {
@@ -40,7 +40,7 @@ const BlogListPage = ({ page = 1, posts = [], postCount }) => {
<div id="container">
{/* 文章列表 */}
<div style={{ columnCount: colCount }}>
{posts.map(post => (
{posts?.map(post => (
<div key={post.id} className='justify-center flex' style={{ breakInside: 'avoid' }}>
<BlogCard key={post.id} post={post} />
</div>

View File

@@ -58,7 +58,7 @@ const Catalog = ({ toc }) => {
return <div>
<div className='w-full dark:text-gray-300 mb-2'><i className='mr-1 fas fa-stream' /> 目录</div>
<div className='overflow-y-auto max-h-96 overscroll-none' ref={tRef}>
<div className='overflow-y-auto max-h-96 overscroll-none scroll-hidden' ref={tRef}>
<nav className='h-full font-sans text-black'>
{toc.map((tocItem) => {
const id = uuidToId(tocItem.id)
@@ -70,11 +70,11 @@ const Catalog = ({ toc }) => {
className={`notion-table-of-contents-item duration-300 transform font-light dark:text-gray-300
notion-table-of-contents-item-indent-level-${tocItem.indentLevel} `}
>
<span style={{ display: 'inline-block', marginLeft: tocItem.indentLevel * 16 }}
className={`${activeSection === id && ' font-bold text-red-400 underline'}`}
>
{tocItem.text}
</span>
<span style={{ display: 'inline-block', marginLeft: tocItem.indentLevel * 16 }}
className={`${activeSection === id && ' font-bold text-red-400 underline'}`}
>
{tocItem.text}
</span>
</a>
)
})}

View File

@@ -11,6 +11,7 @@ import Live2D from '@/components/Live2D'
import LoadingCover from './components/LoadingCover'
import { useGlobal } from '@/lib/global'
import BLOG from '@/blog.config'
import FacebookPage from '@/components/FacebookPage'
/**
* 基础布局 采用左右两侧布局,移动端使用顶部导航栏
@@ -18,11 +19,16 @@ import BLOG from '@/blog.config'
* @returns {JSX.Element}
* @constructor
*/
const LayoutBase = (props) => {
const LayoutBase = props => {
const { children, headerSlot, floatSlot, meta, siteInfo } = props
const [show, switchShow] = useState(false)
// const [percent, changePercent] = useState(0) // 页面阅读百分比
const rightAreaSlot = <Live2D />
const rightAreaSlot = (
<>
<FacebookPage />
<Live2D />
</>
)
const { onLoading } = useGlobal()
const scrollListener = () => {
@@ -30,7 +36,7 @@ const LayoutBase = (props) => {
const clientHeight = targetRef?.clientHeight
const scrollY = window.pageYOffset
const fullHeight = clientHeight - window.outerHeight
let per = parseFloat(((scrollY / fullHeight * 100)).toFixed(0))
let per = parseFloat(((scrollY / fullHeight) * 100).toFixed(0))
if (per > 100) per = 100
const shouldShow = scrollY > 100 && per > 0
@@ -45,37 +51,44 @@ const LayoutBase = (props) => {
return () => document.removeEventListener('scroll', scrollListener)
}, [show])
return (<div className='bg-hexo-background-gray dark:bg-black'>
<CommonHead meta={meta} />
return (
<div className="bg-hexo-background-gray dark:bg-black">
<CommonHead meta={meta} />
<TopNav {...props} />
<TopNav {...props} />
{headerSlot}
{headerSlot}
<main id='wrapper' className='w-full py-8 min-h-screen'>
<main id="wrapper" className="w-full py-8 min-h-screen">
<div
id="container-inner"
className="pt-14 w-full mx-auto lg:flex justify-center lg:space-x-4"
>
<div className="flex-grow w-full lg:max-w-4xl">
{onLoading ? <LoadingCover /> : children}
</div>
<div id='container-inner' className='pt-14 w-full mx-auto lg:flex justify-center lg:space-x-4'>
<div className='flex-grow w-full lg:max-w-4xl'>
{onLoading ? <LoadingCover /> : children}
<SideRight {...props} slot={rightAreaSlot} />
</div>
</main>
<SideRight {...props} slot={rightAreaSlot} />
{/* 右下角悬浮 */}
<div className="bottom-12 right-1 fixed justify-end z-20 font-sans text-white bg-indigo-500 dark:bg-hexo-black-gray rounded-sm">
<div
className={
(show ? 'animate__animated ' : 'hidden') +
' animate__fadeInUp justify-center duration-300 animate__faster flex flex-col items-center cursor-pointer '
}
>
<FloatDarkModeButton />
{floatSlot}
<JumpToTopButton />
</div>
</div>
</main>
{/* 右下角悬浮 */}
<div className='bottom-12 right-1 fixed justify-end z-20 font-sans text-white bg-indigo-500 dark:bg-hexo-black-gray rounded-sm'>
<div className={(show ? 'animate__animated ' : 'hidden') + ' animate__fadeInUp justify-center duration-300 animate__faster flex flex-col items-center cursor-pointer '}>
<FloatDarkModeButton />
{floatSlot}
<JumpToTopButton />
</div>
<Footer title={siteInfo?.title || BLOG.TITLE} />
</div>
<Footer title={siteInfo?.title || BLOG.TITLE} />
</div>)
)
}
export default LayoutBase

View File

@@ -1,10 +1,12 @@
import BLOG from '@/blog.config'
import BlogPostListPage from './components/BlogPostListPage'
import BlogPostListScroll from './components/BlogPostListScroll'
import Header from './components/Header'
import CONFIG_HEXO from './config_hexo'
import LayoutBase from './LayoutBase'
export const LayoutIndex = (props) => {
return <LayoutBase {...props} headerSlot={CONFIG_HEXO.HOME_BANNER_ENABLE && <Header {...props}/>}>
<BlogPostListPage {...props}/>
return <LayoutBase {...props} headerSlot={CONFIG_HEXO.HOME_BANNER_ENABLE && <Header {...props} />}>
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
</LayoutBase>
}

View File

@@ -13,23 +13,21 @@ export const LayoutSearch = props => {
const { locale } = useGlobal()
const router = useRouter()
const currentSearch = keyword || router?.query?.s
let handleTextColor = false
const cRef = useRef(null)
useEffect(() => {
setTimeout(() => {
// 自动聚焦到搜索框
cRef?.current?.focus()
if (currentSearch && !handleTextColor) {
if (currentSearch) {
const targets = document.getElementsByClassName('replace')
for (const container of targets) {
if (container && container.innerHTML) {
const re = new RegExp(`${currentSearch}`, 'gim')
container.innerHTML = container.innerHTML.replace(
re,
`<span class='text-red-500 border-b border-dashed'>${currentSearch}</span>`
`<span class='text-red-500 border-b border-dashed'>${currentSearch}</span>`
)
handleTextColor = true
}
}
}
@@ -46,7 +44,7 @@ export const LayoutSearch = props => {
{locale.COMMON.CATEGORY}:
</div>
<div id="category-list" className="duration-200 flex flex-wrap mx-8">
{categories.map(category => {
{categories?.map(category => {
return (
<Link
key={category.name}
@@ -73,7 +71,7 @@ export const LayoutSearch = props => {
{locale.COMMON.TAGS}:
</div>
<div id="tags-list" className="duration-200 flex flex-wrap ml-8">
{tags.map(tag => {
{tags?.map(tag => {
return (
<div key={tag.name} className="p-2">
<TagItemMini key={tag.name} tag={tag} />

View File

@@ -38,13 +38,22 @@ const BlogPostCard = ({ post, showSummary }) => {
</Link>
</div>
{(!showPreview || showSummary) && (
{(!showPreview || showSummary) && !post.results && (
<p style={{ overflow: 'hidden', textOverflow: 'ellipsis', display: '-webkit-box', WebkitLineClamp: '4', WebkitBoxOrient: 'vertical' }}
className="replace h-full max-h-32 my-4 text-gray-700 dark:text-gray-300 text-sm font-light leading-7">
{post.summary}
</p>
)}
{/* 搜索结果 */}
{post.results && (
<p className="mt-4 text-gray-700 dark:text-gray-300 text-sm font-light leading-7">
{post.results.map(r => (
<span key={r}>{r}</span>
))}
</p>
)}
{showPreview && (
<div className="overflow-ellipsis truncate">
<NotionPage post={post} />
@@ -69,7 +78,7 @@ const BlogPostCard = ({ post, showSummary }) => {
</div>
</div>
{CONFIG_HEXO.POST_LIST_COVER && !showPreview && post?.page_cover && (
{CONFIG_HEXO.POST_LIST_COVER && !showPreview && post?.page_cover && !post.results && (
<Link href={`${BLOG.SUB_PATH}/article/${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 */}

View File

@@ -60,9 +60,9 @@ const Catalog = ({ toc }) => {
return <div className='px-3'>
<div className='w-full'><i className='mr-1 fas fa-stream' /> 目录</div>
<div className='w-full py-3'>
<Progress/>
<Progress />
</div>
<div className='overflow-y-auto max-h-36 lg:max-h-96 overscroll-none' ref={tRef}>
<div className='overflow-y-auto max-h-36 lg:max-h-96 overscroll-none scroll-hidden' ref={tRef}>
<nav className='h-full font-sans text-black'>
{toc.map((tocItem) => {
const id = uuidToId(tocItem.id)
@@ -75,7 +75,7 @@ const Catalog = ({ toc }) => {
notion-table-of-contents-item-indent-level-${tocItem.indentLevel} `}
>
<span style={{ display: 'inline-block', marginLeft: tocItem.indentLevel * 16 }}
className={`${activeSection === id && ' font-bold text-indigo-400 underline'}`}
className={`${activeSection === id && ' font-bold text-indigo-400 underline'}`}
>
{tocItem.text}
</span>

View File

@@ -1,8 +1,10 @@
import BLOG from '@/blog.config'
import BlogPostListPage from './components/BlogPostListPage'
import BlogPostListScroll from './components/BlogPostListScroll'
import LayoutBase from './LayoutBase'
export const LayoutIndex = (props) => {
return <LayoutBase {...props}>
<BlogPostListPage {...props}/>
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
</LayoutBase>
}

View File

@@ -65,8 +65,8 @@ const BlogPostListScroll = ({ posts = [], currentSearch }) => {
{/* 文章列表 */}
<div className='space-y-1 lg:space-y-4'>
{postsToShow.map(post => (
<BlogPostCard key={post.id} post={post} showSummary={true}/>
{postsToShow?.map(post => (
<BlogPostCard key={post.id} post={post} showSummary={true} />
))}
</div>
@@ -74,7 +74,7 @@ const BlogPostListScroll = ({ posts = [], currentSearch }) => {
<div onClick={() => {
handleGetMore()
}}
className='w-full my-4 py-4 text-center cursor-pointer glassmorphism shadow-xl rounded-xl dark:text-gray-200'
className='w-full my-4 py-4 text-center cursor-pointer dark:text-gray-200'
> {hasMore ? locale.COMMON.MORE : `${locale.COMMON.NO_MORE} 😰`} </div>
</div>
</div>
@@ -95,7 +95,7 @@ const getPostByPage = function (page, totalPosts, postsPerPage) {
)
}
function getSearchKey () {
function getSearchKey() {
const router = useRouter()
if (router.query && router.query.s) {
return router.query.s

View File

@@ -59,9 +59,9 @@ const Catalog = ({ toc }) => {
return <div className='px-3'>
<div className='w-full mt-2 mb-4'>
<Progress/>
<Progress />
</div>
<div className='overflow-y-auto max-h-96 overscroll-none' ref={tRef}>
<div className='overflow-y-auto max-h-96 overscroll-none scroll-hidden' ref={tRef}>
<nav className='h-full font-sans text-black'>
{toc.map((tocItem) => {
const id = uuidToId(tocItem.id)
@@ -73,17 +73,17 @@ const Catalog = ({ toc }) => {
className={`notion-table-of-contents-item duration-300 transform font-light dark:text-gray-300
notion-table-of-contents-item-indent-level-${tocItem.indentLevel} `}
>
<span style={{ display: 'inline-block', marginLeft: tocItem.indentLevel * 16 }}
className={`${activeSection === id && ' font-bold text-green-500 underline'}`}
>
{tocItem.text}
</span>
<span style={{ display: 'inline-block', marginLeft: tocItem.indentLevel * 16 }}
className={`${activeSection === id && ' font-bold text-green-500 underline'}`}
>
{tocItem.text}
</span>
</a>
)
})}
</nav>
</div>
<JumpToTopButton className='text-gray-400 hover:text-green-500 hover:bg-gray-100 py-1 duration-200'/>
<JumpToTopButton className='text-gray-400 hover:text-green-500 hover:bg-gray-100 py-1 duration-200' />
</div>
}

View File

@@ -8,9 +8,9 @@ const CategoryGroup = ({ currentCategory, categories }) => {
return <div id='category-list' className='pt-4'>
<div className='mb-2'><i className='mr-2 fas fa-th' />分类</div>
<div className='flex flex-wrap'>
{categories.map(category => {
{categories?.map(category => {
const selected = currentCategory === category.name
return <CategoryItem key={category.name} selected={selected} category={category.name} categoryCount={category.count}/>
return <CategoryItem key={category.name} selected={selected} category={category.name} categoryCount={category.count} />
})}
</div>
</div>

View File

@@ -13,12 +13,12 @@ const TagGroups = ({ tags, currentTag }) => {
<div id='tags-group' className='dark:border-gray-600 py-4'>
<div className='mb-2'><i className='mr-2 fas fa-tag' />标签</div>
<div className='space-y-2'>
{
tags.map(tag => {
const selected = tag.name === currentTag
return <TagItemMini key={tag.name} tag={tag} selected={selected} />
})
}
{
tags?.map(tag => {
const selected = tag.name === currentTag
return <TagItemMini key={tag.name} tag={tag} selected={selected} />
})
}
</div>
</div>
)

View File

@@ -5,6 +5,7 @@ import Card from './components/Card'
import BlogPostListScroll from './components/BlogPostListScroll'
import BlogPostListPage from './components/BlogPostListPage'
import CONFIG_NEXT from './config_next'
import BLOG from '@/blog.config'
export const LayoutIndex = (props) => {
const { latestPosts } = props
@@ -15,7 +16,7 @@ export const LayoutIndex = (props) => {
rightAreaSlot={rightAreaSlot}
{...props}
>
{CONFIG_NEXT.POST_LIST_TYPE !== 'page'
{BLOG.POST_LIST_STYLE !== 'page'
? <BlogPostListScroll {...props} showSummary={true} />
: <BlogPostListPage {...props} />
}

View File

@@ -62,7 +62,7 @@ const Toc = ({ toc }) => {
<div className='w-full pb-1'>
<Progress />
</div>
<div className='overflow-y-auto max-h-96 overscroll-none' ref={tRef}>
<div className='overflow-y-auto max-h-96 overscroll-none scroll-hidden' ref={tRef}>
<nav className='h-full font-sans text-black dark:text-gray-300'>
{toc.map((tocItem) => {
const id = uuidToId(tocItem.id)

View File

@@ -5,7 +5,6 @@ const CONFIG_NEXT = {
NAV_TYPE: 'normal', // ['fixed','autoCollapse','normal'] 分别是固定屏幕顶部、屏幕顶部自动折叠,不固定
POST_LIST_TYPE: 'page', // ['page','scroll] 文章列表样式:页码分页、单页滚动加载
POST_LIST_COVER: false, // 文章列表显示封面图
POST_LIST_PREVIEW: true, // 显示文章预览
POST_LIST_SUMMARY: false, // 显示用户自定义摘要,有预览时优先只展示预览