mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-14 15:09:22 +00:00
Merge branch 'main' into wx
This commit is contained in:
@@ -1,2 +1,2 @@
|
||||
# 环境变量 @see https://www.nextjs.cn/docs/basic-features/environment-variables
|
||||
NEXT_PUBLIC_VERSION=3.7.3
|
||||
NEXT_PUBLIC_VERSION=3.8.0
|
||||
|
||||
@@ -19,10 +19,9 @@ export function ThemeSwitch() {
|
||||
<div className="p-2 flex items-center">
|
||||
<i className='fas fa-arrows cursor-move px-2' />
|
||||
{/* <div className='uppercase font-sans whitespace-nowrap cursor-pointer ' onClick={switchTheme}> {theme}</div> */}
|
||||
<select onChange={onSelectChange} name="cars" className='text-white bg-black uppercase cursor-pointer'>
|
||||
<select value={theme} onChange={onSelectChange} name="cars" className='text-white bg-black uppercase cursor-pointer'>
|
||||
{ALL_THEME.map(t => {
|
||||
const selected = t === theme
|
||||
return <option key={t} value={t} selected={selected}>{t}</option>
|
||||
return <option key={t} value={t}>{t}</option>
|
||||
})}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -3,9 +3,6 @@ const withBundleAnalyzer = require('@next/bundle-analyzer')({
|
||||
})
|
||||
|
||||
module.exports = withBundleAnalyzer({
|
||||
future: {
|
||||
webpack5: true
|
||||
},
|
||||
images: {
|
||||
// 图片压缩
|
||||
formats: ['image/avif', 'image/webp'],
|
||||
|
||||
10
package.json
10
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "notion-next",
|
||||
"version": "3.7.3",
|
||||
"version": "3.8.0",
|
||||
"homepage": "https://github.com/tangly1024/NotionNext.git",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -40,16 +40,16 @@
|
||||
"memory-cache": "^0.2.0",
|
||||
"mermaid": "9.2.2",
|
||||
"mongodb": "^4.6.0",
|
||||
"next": "12.1.6",
|
||||
"next": "^13.1.1",
|
||||
"notion-client": "6.15.6",
|
||||
"notion-utils": "6.15.6",
|
||||
"preact": "^10.5.15",
|
||||
"prism-themes": "1.9.0",
|
||||
"qrcode.react": "^1.0.1",
|
||||
"react": "17.0.2",
|
||||
"react": "^18.2.0",
|
||||
"react-cookies": "^0.1.1",
|
||||
"react-cusdis": "^2.1.3",
|
||||
"react-dom": "17.0.2",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-facebook": "^8.1.4",
|
||||
"react-messenger-customer-chat": "^0.8.0",
|
||||
"react-notion-x": "6.15.6",
|
||||
@@ -64,7 +64,7 @@
|
||||
"@waline/client": "^2.5.1",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"eslint": "^7.26.0",
|
||||
"eslint-config-next": "^11.0.0",
|
||||
"eslint-config-next": "^13.1.1",
|
||||
"eslint-config-standard": "^16.0.2",
|
||||
"eslint-plugin-import": "^2.23.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
|
||||
@@ -15,7 +15,7 @@ const NoFound = props => {
|
||||
}
|
||||
|
||||
export async function getStaticProps () {
|
||||
const props = await getGlobalNotionData({ from: '404' }) || {}
|
||||
const props = (await getGlobalNotionData({ from: '404' })) || {}
|
||||
return { props }
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ const Slug = props => {
|
||||
}
|
||||
}
|
||||
}, 20 * 1000)
|
||||
const meta = { title: `${props?.siteInfo?.title || BLOG.TITLE} | loading`, image: siteInfo?.pageCover }
|
||||
const meta = { title: `${props?.siteInfo?.title || BLOG.TITLE} | loading`, image: siteInfo?.pageCover || BLOG.HOME_BANNER_IMAGE }
|
||||
return <ThemeComponents.LayoutSlug {...props} showArticleInfo={true} meta={meta} />
|
||||
}
|
||||
|
||||
|
||||
@@ -45,10 +45,10 @@ export const LayoutArchive = props => {
|
||||
<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>
|
||||
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||
|
||||
{post.title}
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
@@ -4,16 +4,24 @@ import LayoutBase from './LayoutBase'
|
||||
export const LayoutCategoryIndex = (props) => {
|
||||
const { categories } = props
|
||||
|
||||
return <LayoutBase {...props}>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{categories && categories.map(category => {
|
||||
return <Link key={category.name} href={`/category/${category.name}`} passHref>
|
||||
<div
|
||||
className={'hover:text-black dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'}>
|
||||
<i className='mr-4 fas fa-folder' />{category.name}({category.count})
|
||||
</div>
|
||||
</Link>
|
||||
})}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{categories && categories.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<div
|
||||
className={'hover:text-black dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'}>
|
||||
<i className='mr-4 fas fa-folder' />{category.name}({category.count})
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,19 +3,27 @@ import LayoutBase from './LayoutBase'
|
||||
|
||||
export const LayoutTagIndex = (props) => {
|
||||
const { tags } = props
|
||||
return <LayoutBase {...props}>
|
||||
<div>
|
||||
<div id='tags-list' className='duration-200 flex flex-wrap'>
|
||||
{tags.map(tag => {
|
||||
return <div key={tag.name} className='p-2'>
|
||||
<Link key={tag} href={`/tag/${encodeURIComponent(tag.name)}`} passHref>
|
||||
<a className={`cursor-pointer inline-block rounded hover:bg-gray-500 hover:text-white duration-200
|
||||
mr-2 py-1 px-2 text-xs whitespace-nowrap dark:hover:text-white text-gray-600 hover:shadow-xl dark:border-gray-400 notion-${tag.color}_background dark:bg-gray-800`}>
|
||||
<div className='font-light dark:text-gray-400'><i className='mr-1 fas fa-tag' /> {tag.name + (tag.count ? `(${tag.count})` : '')} </div>
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
})}
|
||||
</div>
|
||||
</div> </LayoutBase>
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<div>
|
||||
<div id='tags-list' className='duration-200 flex flex-wrap'>
|
||||
{tags.map(tag => {
|
||||
return (
|
||||
<div key={tag.name} className='p-2'>
|
||||
<Link
|
||||
key={tag}
|
||||
href={`/tag/${encodeURIComponent(tag.name)}`}
|
||||
passHref
|
||||
className={`cursor-pointer inline-block rounded hover:bg-gray-500 hover:text-white duration-200
|
||||
mr-2 py-1 px-2 text-xs whitespace-nowrap dark:hover:text-white text-gray-600 hover:shadow-xl dark:border-gray-400 notion-${tag.color}_background dark:bg-gray-800`}>
|
||||
|
||||
<div className='font-light dark:text-gray-400'><i className='mr-1 fas fa-tag' /> {tag.name + (tag.count ? `(${tag.count})` : '')} </div>
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div> </LayoutBase>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,40 +8,45 @@ export const ArticleInfo = (props) => {
|
||||
const { locale } = useGlobal()
|
||||
const date = formatDate(post?.date?.start_date || post?.createdTime, locale.LOCALE)
|
||||
|
||||
return <section className="flex-wrap flex mt-2 text-gray-400 dark:text-gray-400 font-light leading-8">
|
||||
<div>
|
||||
{post?.type !== 'Page' && <>
|
||||
<Link href={`/category/${post.category}`} passHref>
|
||||
<a className="cursor-pointer text-md mr-2 hover:text-black dark:hover:text-white border-b dark:border-gray-500 border-dashed">
|
||||
return (
|
||||
<section className="flex-wrap flex mt-2 text-gray-400 dark:text-gray-400 font-light leading-8">
|
||||
<div>
|
||||
{post?.type !== 'Page' && <>
|
||||
<Link
|
||||
href={`/category/${post.category}`}
|
||||
passHref
|
||||
className="cursor-pointer text-md mr-2 hover:text-black dark:hover:text-white border-b dark:border-gray-500 border-dashed">
|
||||
|
||||
<i className="mr-1 fas fa-folder-open" />
|
||||
{post.category}
|
||||
</a>
|
||||
</Link>
|
||||
<span className='mr-2'>|</span>
|
||||
</>}
|
||||
|
||||
{post?.type !== 'Page' && (<>
|
||||
<Link
|
||||
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
||||
passHref
|
||||
>
|
||||
<a className="pl-1 mr-2 cursor-pointer hover:text-gray-700 dark:hover:text-gray-200 border-b dark:border-gray-500 border-dashed">
|
||||
</Link>
|
||||
<span className='mr-2'>|</span>
|
||||
</>}
|
||||
|
||||
{post?.type !== 'Page' && (<>
|
||||
<Link
|
||||
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
||||
passHref
|
||||
className="pl-1 mr-2 cursor-pointer hover:text-gray-700 dark:hover:text-gray-200 border-b dark:border-gray-500 border-dashed">
|
||||
|
||||
{date}
|
||||
</a>
|
||||
</Link>
|
||||
<span className='mr-2'>|</span>
|
||||
<span className='mx-2 text-gray-400 dark:text-gray-500'>
|
||||
{locale.COMMON.LAST_EDITED_TIME}: {post.lastEditedTime}
|
||||
|
||||
</Link>
|
||||
<span className='mr-2'>|</span>
|
||||
<span className='mx-2 text-gray-400 dark:text-gray-500'>
|
||||
{locale.COMMON.LAST_EDITED_TIME}: {post.lastEditedTime}
|
||||
</span>
|
||||
<span className='mr-2'>|</span>
|
||||
<span className="hidden busuanzi_container_page_pv font-light mr-2">
|
||||
<i className='mr-1 fas fa-eye' />
|
||||
|
||||
<span className="mr-2 busuanzi_value_page_pv" />
|
||||
</span>
|
||||
<span className='mr-2'>|</span>
|
||||
<span className="hidden busuanzi_container_page_pv font-light mr-2">
|
||||
<i className='mr-1 fas fa-eye' />
|
||||
|
||||
<span className="mr-2 busuanzi_value_page_pv" />
|
||||
</span>
|
||||
</>)}
|
||||
</>)}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -15,47 +15,55 @@ export const BlogListPage = props => {
|
||||
const showNext = page < totalPage
|
||||
const pagePrefix = router.asPath.replace(/\/page\/[1-9]\d*/, '').replace(/\/$/, '')
|
||||
|
||||
return <div className="w-full md:pr-12 mb-12">
|
||||
return (
|
||||
<div className="w-full md:pr-12 mb-12">
|
||||
|
||||
<div id="container">
|
||||
{posts?.map(p => (
|
||||
<article key={p.id} className="mb-12" >
|
||||
<h2 className="mb-4">
|
||||
<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>
|
||||
<div id="container">
|
||||
{posts?.map(p => (
|
||||
<article key={p.id} className="mb-12" >
|
||||
<h2 className="mb-4">
|
||||
<Link
|
||||
href={`/${p.slug}`}
|
||||
className="text-black dark:text-gray-100 text-xl md:text-2xl no-underline hover:underline">
|
||||
{p.title}
|
||||
</Link>
|
||||
</h2>
|
||||
|
||||
<div className="mb-4 text-sm text-gray-700 dark:text-gray-300">
|
||||
by <a href="#" className="text-gray-700 dark:text-gray-300">{BLOG.AUTHOR}</a> on {p.date?.start_date || p.createdTime}
|
||||
<span className="font-bold mx-1"> | </span>
|
||||
<a href="#" className="text-gray-700 dark:text-gray-300">{p.category}</a>
|
||||
{/* <span className="font-bold mx-1"> | </span> */}
|
||||
{/* <a href="#" className="text-gray-700">2 Comments</a> */}
|
||||
</div>
|
||||
<div className="mb-4 text-sm text-gray-700 dark:text-gray-300">
|
||||
by <a href="#" className="text-gray-700 dark:text-gray-300">{BLOG.AUTHOR}</a> on {p.date?.start_date || p.createdTime}
|
||||
<span className="font-bold mx-1"> | </span>
|
||||
<a href="#" className="text-gray-700 dark:text-gray-300">{p.category}</a>
|
||||
{/* <span className="font-bold mx-1"> | </span> */}
|
||||
{/* <a href="#" className="text-gray-700">2 Comments</a> */}
|
||||
</div>
|
||||
|
||||
<p className="text-gray-700 dark:text-gray-400 leading-normal">
|
||||
{p.summary}
|
||||
</p>
|
||||
{/* 搜索结果 */}
|
||||
{p.results && (
|
||||
<p className="mt-4 text-gray-700 dark:text-gray-300 text-sm font-light leading-7">
|
||||
{p.results.map(r => (
|
||||
<span key={r}>{r}</span>
|
||||
))}
|
||||
<p className="text-gray-700 dark:text-gray-400 leading-normal">
|
||||
{p.summary}
|
||||
</p>
|
||||
)}
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
{/* 搜索结果 */}
|
||||
{p.results && (
|
||||
<p className="mt-4 text-gray-700 dark:text-gray-300 text-sm font-light leading-7">
|
||||
{p.results.map(r => (
|
||||
<span key={r}>{r}</span>
|
||||
))}
|
||||
</p>
|
||||
)}
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between text-xs">
|
||||
<Link href={{ pathname: currentPage - 1 === 1 ? `${pagePrefix}/` : `${pagePrefix}/page/${currentPage - 1}`, query: router.query.s ? { s: router.query.s } : {} }}>
|
||||
<a className={`${showPrev ? 'bg-black ' : 'bg-gray pointer-events-none '} text-white no-underline py-2 px-3 rounded`}>{locale.PAGINATION.PREV}</a>
|
||||
</Link>
|
||||
<Link href={{ pathname: `${pagePrefix}/page/${currentPage + 1}`, query: router.query.s ? { s: router.query.s } : {} }}>
|
||||
<a className={`${showNext ? 'bg-black ' : 'bg-gray pointer-events-none '} text-white no-underline py-2 px-3 rounded`}>{locale.PAGINATION.NEXT}</a>
|
||||
</Link>
|
||||
<div className="flex justify-between text-xs">
|
||||
<Link
|
||||
href={{ pathname: currentPage - 1 === 1 ? `${pagePrefix}/` : `${pagePrefix}/page/${currentPage - 1}`, query: router.query.s ? { s: router.query.s } : {} }}
|
||||
className={`${showPrev ? 'bg-black ' : 'bg-gray pointer-events-none '} text-white no-underline py-2 px-3 rounded`}>
|
||||
{locale.PAGINATION.PREV}
|
||||
</Link>
|
||||
<Link
|
||||
href={{ pathname: `${pagePrefix}/page/${currentPage + 1}`, query: router.query.s ? { s: router.query.s } : {} }}
|
||||
className={`${showNext ? 'bg-black ' : 'bg-gray pointer-events-none '} text-white no-underline py-2 px-3 rounded`}>
|
||||
{locale.PAGINATION.NEXT}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -43,36 +43,40 @@ export const BlogListScroll = props => {
|
||||
}
|
||||
})
|
||||
|
||||
return <div id="container" className="w-full md:pr-12 mb-12" ref={targetRef}>
|
||||
{postsToShow.map(p => (
|
||||
<article key={p.id} className="mb-12" >
|
||||
<h2 className="mb-4">
|
||||
<Link href={`/${p.slug}`}>
|
||||
<a className="text-black text-xl md:text-2xl no-underline hover:underline"> {p.title}</a>
|
||||
</Link>
|
||||
</h2>
|
||||
return (
|
||||
<div id="container" className="w-full md:pr-12 mb-12" ref={targetRef}>
|
||||
{postsToShow.map(p => (
|
||||
<article key={p.id} className="mb-12" >
|
||||
<h2 className="mb-4">
|
||||
<Link
|
||||
href={`/${p.slug}`}
|
||||
className="text-black text-xl md:text-2xl no-underline hover:underline">
|
||||
{p.title}
|
||||
</Link>
|
||||
</h2>
|
||||
|
||||
<div className="mb-4 text-sm text-gray-700">
|
||||
by <a href="#" className="text-gray-700">{BLOG.AUTHOR}</a> on {p.date?.start_date || p.createdTime}
|
||||
<span className="font-bold mx-1"> | </span>
|
||||
<a href="#" className="text-gray-700">{p.category}</a>
|
||||
<span className="font-bold mx-1"> | </span>
|
||||
{/* <a href="#" className="text-gray-700">2 Comments</a> */}
|
||||
</div>
|
||||
<div className="mb-4 text-sm text-gray-700">
|
||||
by <a href="#" className="text-gray-700">{BLOG.AUTHOR}</a> on {p.date?.start_date || p.createdTime}
|
||||
<span className="font-bold mx-1"> | </span>
|
||||
<a href="#" className="text-gray-700">{p.category}</a>
|
||||
<span className="font-bold mx-1"> | </span>
|
||||
{/* <a href="#" className="text-gray-700">2 Comments</a> */}
|
||||
</div>
|
||||
|
||||
<p className="text-gray-700 leading-normal">
|
||||
{p.summary}
|
||||
</p>
|
||||
</article>
|
||||
))}
|
||||
<p className="text-gray-700 leading-normal">
|
||||
{p.summary}
|
||||
</p>
|
||||
</article>
|
||||
))}
|
||||
|
||||
<div
|
||||
onClick={handleGetMore}
|
||||
className="w-full my-4 py-4 text-center cursor-pointer "
|
||||
>
|
||||
{' '}
|
||||
{hasMore ? locale.COMMON.MORE : `${locale.COMMON.NO_MORE} 😰`}{' '}
|
||||
</div>
|
||||
|
||||
<div
|
||||
onClick={handleGetMore}
|
||||
className="w-full my-4 py-4 text-center cursor-pointer "
|
||||
>
|
||||
{' '}
|
||||
{hasMore ? locale.COMMON.MORE : `${locale.COMMON.NO_MORE} 😰`}{' '}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -26,10 +26,10 @@ const ExampleRecentComments = (props) => {
|
||||
{!onLoading && comments && comments.length === 0 && <div>No Comments</div>}
|
||||
{!onLoading && comments && comments.length > 0 && comments.map((comment) => <div key={comment.objectId} className='pb-2'>
|
||||
<div className='dark:text-gray-300 text-gray-600 text-xs waline-recent-content wl-content' dangerouslySetInnerHTML={{ __html: comment.comment }} />
|
||||
<div className='dark:text-gray-400 text-gray-400 font-sans text-sm text-right cursor-pointer hover:text-red-500 hover:underline pt-1'><Link href={{ pathname: comment.url, hash: comment.objectId, query: { target: 'comment' } }}><a >-- {comment.nick}</a></Link></div>
|
||||
<div className='dark:text-gray-400 text-gray-400 font-sans text-sm text-right cursor-pointer hover:text-red-500 hover:underline pt-1'><Link href={{ pathname: comment.url, hash: comment.objectId, query: { target: 'comment' } }}>--{comment.nick}</Link></div>
|
||||
</div>)}
|
||||
|
||||
</>
|
||||
</>;
|
||||
}
|
||||
|
||||
export default ExampleRecentComments
|
||||
|
||||
@@ -7,15 +7,19 @@ import Link from 'next/link'
|
||||
export const Header = (props) => {
|
||||
const { siteInfo } = props
|
||||
|
||||
return <header className="w-full px-6 bg-white dark:bg-black">
|
||||
<div className="container mx-auto max-w-4xl md:flex justify-between items-center">
|
||||
<Link href='/'>
|
||||
<a className="py-6 w-full text-center md:text-left md:w-auto text-gray-dark no-underline flex justify-center items-center">
|
||||
return (
|
||||
<header className="w-full px-6 bg-white dark:bg-black">
|
||||
<div className="container mx-auto max-w-4xl md:flex justify-between items-center">
|
||||
<Link
|
||||
href='/'
|
||||
className="py-6 w-full text-center md:text-left md:w-auto text-gray-dark no-underline flex justify-center items-center">
|
||||
|
||||
{siteInfo?.title}
|
||||
</a></Link>
|
||||
<div className="w-full md:w-auto text-center md:text-right">
|
||||
{/* 右侧文字 */}
|
||||
</Link>
|
||||
<div className="w-full md:w-auto text-center md:text-right">
|
||||
{/* 右侧文字 */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,20 +20,25 @@ export const Nav = (props) => {
|
||||
links = links.concat(customNav)
|
||||
}
|
||||
|
||||
return <nav className="w-full bg-white md:pt-0 px-6 relative z-20 border-t border-b border-gray-light dark:border-hexo-black-gray dark:bg-black">
|
||||
<div className="container mx-auto max-w-4xl md:flex justify-between items-center text-sm md:text-md md:justify-start">
|
||||
<div className="w-full md:w-2/3 text-center md:text-left py-4 flex flex-wrap justify-center items-stretch md:justify-start md:items-start">
|
||||
{links.map(link => {
|
||||
return link && <Link href={link.to} key={link.to}>
|
||||
<a className="px-2 md:pl-0 md:mr-3 md:pr-3 text-gray-700 dark:text-gray-200 no-underline md:border-r border-gray-light">
|
||||
{link.name}
|
||||
</a>
|
||||
</Link>
|
||||
})}
|
||||
return (
|
||||
<nav className="w-full bg-white md:pt-0 px-6 relative z-20 border-t border-b border-gray-light dark:border-hexo-black-gray dark:bg-black">
|
||||
<div className="container mx-auto max-w-4xl md:flex justify-between items-center text-sm md:text-md md:justify-start">
|
||||
<div className="w-full md:w-2/3 text-center md:text-left py-4 flex flex-wrap justify-center items-stretch md:justify-start md:items-start">
|
||||
{links.map(link => {
|
||||
return link && <Link
|
||||
href={link.to}
|
||||
key={link.to}
|
||||
className="px-2 md:pl-0 md:mr-3 md:pr-3 text-gray-700 dark:text-gray-200 no-underline md:border-r border-gray-light">
|
||||
|
||||
{link.name}
|
||||
|
||||
</Link>;
|
||||
})}
|
||||
</div>
|
||||
<div className="w-full md:w-1/3 text-center md:text-right">
|
||||
{/* <!-- extra links --> */}
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full md:w-1/3 text-center md:text-right">
|
||||
{/* <!-- extra links --> */}
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,48 +8,58 @@ const ExampleRecentComments = dynamic(() => import('./ExampleRecentComments'))
|
||||
export const SideBar = (props) => {
|
||||
const { locale } = useGlobal()
|
||||
const { latestPosts, categories } = props
|
||||
return <div className="w-full md:w-64 sticky top-8">
|
||||
return (
|
||||
<div className="w-full md:w-64 sticky top-8">
|
||||
|
||||
<aside className="rounded shadow overflow-hidden mb-6">
|
||||
<h3 className="text-sm bg-gray-100 text-gray-700 dark:bg-hexo-black-gray dark:text-gray-200 py-3 px-4 dark:border-hexo-black-gray border-b">{locale.COMMON.CATEGORY}</h3>
|
||||
<aside className="rounded shadow overflow-hidden mb-6">
|
||||
<h3 className="text-sm bg-gray-100 text-gray-700 dark:bg-hexo-black-gray dark:text-gray-200 py-3 px-4 dark:border-hexo-black-gray border-b">{locale.COMMON.CATEGORY}</h3>
|
||||
|
||||
<div className="p-4">
|
||||
<ul className="list-reset leading-normal">
|
||||
{categories?.map(category => {
|
||||
return <Link key={category.name} href={`/category/${category.name}`} passHref>
|
||||
<li> <a href="#" className="text-gray-darkest text-sm">{category.name}({category.count})</a></li>
|
||||
</Link>
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<ul className="list-reset leading-normal">
|
||||
{categories?.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<li> <a href="#" className="text-gray-darkest text-sm">{category.name}({category.count})</a></li>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</aside>
|
||||
</aside>
|
||||
|
||||
<aside className="rounded shadow overflow-hidden mb-6">
|
||||
<h3 className="text-sm bg-gray-100 text-gray-700 dark:bg-hexo-black-gray dark:text-gray-200 py-3 px-4 dark:border-hexo-black-gray border-b">{locale.COMMON.LATEST_POSTS}</h3>
|
||||
<aside className="rounded shadow overflow-hidden mb-6">
|
||||
<h3 className="text-sm bg-gray-100 text-gray-700 dark:bg-hexo-black-gray dark:text-gray-200 py-3 px-4 dark:border-hexo-black-gray border-b">{locale.COMMON.LATEST_POSTS}</h3>
|
||||
|
||||
<div className="p-4">
|
||||
<ul className="list-reset leading-normal">
|
||||
{latestPosts?.map(p => {
|
||||
return <Link key={p.id} href={`/${p.slug}`} passHref>
|
||||
<li> <a href="#" className="text-gray-darkest text-sm">{p.title}</a></li>
|
||||
</Link>
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
</aside>
|
||||
<div className="p-4">
|
||||
<ul className="list-reset leading-normal">
|
||||
{latestPosts?.map(p => {
|
||||
return (
|
||||
<Link key={p.id} href={`/${p.slug}`} passHref legacyBehavior>
|
||||
<li> <a href="#" className="text-gray-darkest text-sm">{p.title}</a></li>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
{BLOG.COMMENT_WALINE_SERVER_URL && BLOG.COMMENT_WALINE_RECENT && <aside className="rounded shadow overflow-hidden mb-6">
|
||||
<h3 className="text-sm bg-gray-100 text-gray-700 dark:bg-hexo-black-gray dark:text-gray-200 py-3 px-4 dark:border-hexo-black-gray border-b">{locale.COMMON.RECENT_COMMENTS}</h3>
|
||||
{BLOG.COMMENT_WALINE_SERVER_URL && BLOG.COMMENT_WALINE_RECENT && <aside className="rounded shadow overflow-hidden mb-6">
|
||||
<h3 className="text-sm bg-gray-100 text-gray-700 dark:bg-hexo-black-gray dark:text-gray-200 py-3 px-4 dark:border-hexo-black-gray border-b">{locale.COMMON.RECENT_COMMENTS}</h3>
|
||||
|
||||
<div className="p-4">
|
||||
<ExampleRecentComments/>
|
||||
</div>
|
||||
</aside>}
|
||||
<div className="p-4">
|
||||
<ExampleRecentComments/>
|
||||
</div>
|
||||
</aside>}
|
||||
|
||||
<aside className="rounded overflow-hidden mb-6">
|
||||
<Live2D />
|
||||
</aside>
|
||||
<aside className="rounded overflow-hidden mb-6">
|
||||
<Live2D />
|
||||
</aside>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,21 +5,29 @@ import LayoutBase from './LayoutBase'
|
||||
export const LayoutCategoryIndex = (props) => {
|
||||
const { locale } = useGlobal()
|
||||
const { categories } = props
|
||||
return <LayoutBase {...props}>
|
||||
<div className='bg-white dark:bg-gray-700 px-10 py-10 shadow'>
|
||||
<div className='dark:text-gray-200 mb-5'>
|
||||
<i className='mr-4 fas fa-th' />{locale.COMMON.CATEGORY}:
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<div className='bg-white dark:bg-gray-700 px-10 py-10 shadow'>
|
||||
<div className='dark:text-gray-200 mb-5'>
|
||||
<i className='mr-4 fas fa-th' />{locale.COMMON.CATEGORY}:
|
||||
</div>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{categories && categories.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<div
|
||||
className={'hover:text-black dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'}>
|
||||
<i className='mr-4 fas fa-folder' />{category.name}({category.count})
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{categories && categories.map(category => {
|
||||
return <Link key={category.name} href={`/category/${category.name}`} passHref>
|
||||
<div
|
||||
className={'hover:text-black dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'}>
|
||||
<i className='mr-4 fas fa-folder' />{category.name}({category.count})
|
||||
</div>
|
||||
</Link>
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,16 +9,24 @@ export default function ArticleAround ({ prev, next }) {
|
||||
if (!prev || !next) {
|
||||
return <></>
|
||||
}
|
||||
return <section className='text-gray-800 h-28 flex items-center justify-between space-x-5 my-4'>
|
||||
<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'>
|
||||
return (
|
||||
<section className='text-gray-800 h-28 flex items-center justify-between space-x-5 my-4'>
|
||||
<Link
|
||||
href={`/${prev.slug}`}
|
||||
passHref
|
||||
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={`/${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}
|
||||
|
||||
</Link>
|
||||
<Link
|
||||
href={`/${next.slug}`}
|
||||
passHref
|
||||
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>
|
||||
</Link>
|
||||
</section>
|
||||
|
||||
</Link>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,86 +17,91 @@ export default function ArticleDetail(props) {
|
||||
}
|
||||
const { locale } = useGlobal()
|
||||
const date = formatDate(post?.date?.start_date || post?.createdTime, locale.LOCALE)
|
||||
return (<div id="container" className="max-w-5xl overflow-x-auto flex-grow mx-auto w-screen md:w-full ">
|
||||
{post?.type && !post?.type !== 'Page' && post?.page_cover && (
|
||||
<div className="w-full relative md:flex-shrink-0 overflow-hidden">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img alt={post.title} src={post?.page_cover} className='object-center w-full' />
|
||||
</div>
|
||||
)}
|
||||
<article itemScope itemType="https://schema.org/Movie"
|
||||
className="subpixel-antialiased py-10 px-5 lg:pt-24 md:px-32 dark:border-gray-700 bg-white dark:bg-hexo-black-gray"
|
||||
>
|
||||
|
||||
<header className='animate__slideInDown animate__animated'>
|
||||
|
||||
{/* 文章Title */}
|
||||
<div className="font-bold text-3xl text-black dark:text-white font-serif pt-10">
|
||||
{post.title}
|
||||
return (
|
||||
<div id="container" className="max-w-5xl overflow-x-auto flex-grow mx-auto w-screen md:w-full ">
|
||||
{post?.type && !post?.type !== 'Page' && post?.page_cover && (
|
||||
<div className="w-full relative md:flex-shrink-0 overflow-hidden">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img alt={post.title} src={post?.page_cover} className='object-center w-full' />
|
||||
</div>
|
||||
)}
|
||||
<article itemScope itemType="https://schema.org/Movie"
|
||||
className="subpixel-antialiased py-10 px-5 lg:pt-24 md:px-32 dark:border-gray-700 bg-white dark:bg-hexo-black-gray"
|
||||
>
|
||||
|
||||
<section className="flex-wrap flex mt-2 text-gray-400 dark:text-gray-400 font-light leading-8">
|
||||
<div>
|
||||
<header className='animate__slideInDown animate__animated'>
|
||||
|
||||
{post?.category && (<>
|
||||
<Link href={`/category/${post.category}`} passHref>
|
||||
<a className="cursor-pointer text-md mr-2 hover:text-black dark:hover:text-white border-b dark:border-gray-500 border-dashed">
|
||||
<i className="mr-1 fas fa-folder-open" />
|
||||
{post.category}
|
||||
</a>
|
||||
</Link>
|
||||
<span className='mr-2'>|</span>
|
||||
</>)}
|
||||
|
||||
{post?.type !== 'Page' && (<>
|
||||
<Link
|
||||
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
||||
passHref
|
||||
>
|
||||
<a className="pl-1 mr-2 cursor-pointer hover:text-gray-700 dark:hover:text-gray-200 border-b dark:border-gray-500 border-dashed">
|
||||
{date}
|
||||
</a>
|
||||
</Link>
|
||||
<span className='mr-2'>|</span>
|
||||
<span className='mx-2 text-gray-400 dark:text-gray-500'>
|
||||
{locale.COMMON.LAST_EDITED_TIME}: {post.lastEditedTime}
|
||||
</span>
|
||||
</>)}
|
||||
|
||||
<div className=" busuanzi_container_page_pv font-light mr-2">
|
||||
<i className='mr-1 fas fa-eye' />
|
||||
|
||||
<span className="mr-2 busuanzi_value_page_pv" />
|
||||
</div>
|
||||
{/* 文章Title */}
|
||||
<div className="font-bold text-3xl text-black dark:text-white font-serif pt-10">
|
||||
{post.title}
|
||||
</div>
|
||||
|
||||
<section className="flex-wrap flex mt-2 text-gray-400 dark:text-gray-400 font-light leading-8">
|
||||
<div>
|
||||
|
||||
{post?.category && (<>
|
||||
<Link
|
||||
href={`/category/${post.category}`}
|
||||
passHref
|
||||
className="cursor-pointer text-md mr-2 hover:text-black dark:hover:text-white border-b dark:border-gray-500 border-dashed">
|
||||
|
||||
<i className="mr-1 fas fa-folder-open" />
|
||||
{post.category}
|
||||
|
||||
</Link>
|
||||
<span className='mr-2'>|</span>
|
||||
</>)}
|
||||
|
||||
{post?.type !== 'Page' && (<>
|
||||
<Link
|
||||
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
||||
passHref
|
||||
className="pl-1 mr-2 cursor-pointer hover:text-gray-700 dark:hover:text-gray-200 border-b dark:border-gray-500 border-dashed">
|
||||
|
||||
{date}
|
||||
|
||||
</Link>
|
||||
<span className='mr-2'>|</span>
|
||||
<span className='mx-2 text-gray-400 dark:text-gray-500'>
|
||||
{locale.COMMON.LAST_EDITED_TIME}: {post.lastEditedTime}
|
||||
</span>
|
||||
</>)}
|
||||
|
||||
<div className=" busuanzi_container_page_pv font-light mr-2">
|
||||
<i className='mr-1 fas fa-eye' />
|
||||
|
||||
<span className="mr-2 busuanzi_value_page_pv" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
</header>
|
||||
|
||||
{/* Notion文章主体 */}
|
||||
<section id='notion-article' className='px-1'>
|
||||
{post && <NotionPage post={post} />}
|
||||
</section>
|
||||
|
||||
</header>
|
||||
<section className="px-1 py-2 my-1 text-sm font-light overflow-auto text-gray-600 dark:text-gray-400">
|
||||
{/* 文章内嵌广告 */}
|
||||
<ins className="adsbygoogle"
|
||||
style={{ display: 'block', textAlign: 'center' }}
|
||||
data-adtest="on"
|
||||
data-ad-layout="in-article"
|
||||
data-ad-format="fluid"
|
||||
data-ad-client="ca-pub-2708419466378217"
|
||||
data-ad-slot="3806269138" />
|
||||
</section>
|
||||
|
||||
{/* Notion文章主体 */}
|
||||
<section id='notion-article' className='px-1'>
|
||||
{post && <NotionPage post={post} />}
|
||||
</section>
|
||||
</article>
|
||||
|
||||
<section className="px-1 py-2 my-1 text-sm font-light overflow-auto text-gray-600 dark:text-gray-400">
|
||||
{/* 文章内嵌广告 */}
|
||||
<ins className="adsbygoogle"
|
||||
style={{ display: 'block', textAlign: 'center' }}
|
||||
data-adtest="on"
|
||||
data-ad-layout="in-article"
|
||||
data-ad-format="fluid"
|
||||
data-ad-client="ca-pub-2708419466378217"
|
||||
data-ad-slot="3806269138" />
|
||||
</section>
|
||||
{post.type === 'Post' && <ArticleAround prev={prev} next={next} /> }
|
||||
|
||||
</article>
|
||||
|
||||
{post.type === 'Post' && <ArticleAround prev={prev} next={next} /> }
|
||||
|
||||
{/* 评论互动 */}
|
||||
<div className="duration-200 shadow px-12 w-screen md:w-full overflow-x-auto dark:border-gray-700 bg-white dark:bg-hexo-black-gray">
|
||||
<Comment frontMatter={post} />
|
||||
{/* 评论互动 */}
|
||||
<div className="duration-200 shadow px-12 w-screen md:w-full overflow-x-auto dark:border-gray-700 bg-white dark:bg-hexo-black-gray">
|
||||
<Comment frontMatter={post} />
|
||||
</div>
|
||||
</div>
|
||||
</div>)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,13 +13,14 @@ 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}/${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`}
|
||||
>
|
||||
{post.title}
|
||||
</a>
|
||||
<Link
|
||||
href={`${BLOG.SUB_PATH}/${post.slug}`}
|
||||
passHref
|
||||
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}
|
||||
|
||||
</Link>
|
||||
|
||||
{(!showPreview || showSummary) && (
|
||||
@@ -30,7 +31,7 @@ const BlogCard = ({ post, showSummary }) => {
|
||||
</div>
|
||||
|
||||
{CONFIG_FUKA.POST_LIST_COVER && post?.page_cover && (
|
||||
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} passHref>
|
||||
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} passHref legacyBehavior>
|
||||
<div className="h-40 w-full relative duration-200 cursor-pointer transform overflow-hidden">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
@@ -44,7 +45,7 @@ const BlogCard = ({ post, showSummary }) => {
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default BlogCard
|
||||
|
||||
@@ -29,10 +29,13 @@ const BlogArchiveItem = ({ posts = [], archiveTitle }) => {
|
||||
<div id={post?.date?.start_date}>
|
||||
<span className="text-gray-400">{post.date?.start_date}</span>{' '}
|
||||
|
||||
<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>
|
||||
<Link
|
||||
href={`${BLOG.SUB_PATH}/${post.slug}`}
|
||||
passHref
|
||||
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||
|
||||
{post.title}
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
@@ -10,17 +10,22 @@ function GroupCategory ({ currentCategory, categories }) {
|
||||
<div id='category-list' className='dark:border-gray-600 flex flex-wrap'>
|
||||
{categories.map(category => {
|
||||
const selected = currentCategory === category.name
|
||||
return <Link key={category.name} href={`/category/${category.name}`} passHref>
|
||||
<a className={(selected
|
||||
? 'hover:text-white dark:hover:text-white bg-gray-600 text-white '
|
||||
: 'dark:text-gray-400 text-gray-500 hover:text-white hover:bg-gray-500 dark:hover:text-white') +
|
||||
' text-sm w-full items-center duration-300 px-2 cursor-pointer py-1 font-light'}>
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
className={(selected
|
||||
? 'hover:text-white dark:hover:text-white bg-gray-600 text-white '
|
||||
: 'dark:text-gray-400 text-gray-500 hover:text-white hover:bg-gray-500 dark:hover:text-white') +
|
||||
' text-sm w-full items-center duration-300 px-2 cursor-pointer py-1 font-light'}>
|
||||
|
||||
<i className={`${selected ? 'text-white fa-folder-open' : 'fa-folder text-gray-400'} fas mr-2`} />{category.name}({category.count})
|
||||
</a>
|
||||
</Link>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
</>;
|
||||
}
|
||||
|
||||
export default GroupCategory
|
||||
|
||||
@@ -20,24 +20,32 @@ function GroupMenu ({ customNav }) {
|
||||
links = links.concat(customNav)
|
||||
}
|
||||
|
||||
return <nav id='nav' className='font-sans text-sm'>
|
||||
{links.map(link => {
|
||||
if (link.show) {
|
||||
const selected = (router.pathname === link.to) || (router.asPath === link.to)
|
||||
return <Link key={`${link.to}`} title={link.to} href={link.to} >
|
||||
<a className={'py-0.5 duration-500 justify-between text-gray-500 dark:text-gray-300 hover:text-black hover:underline cursor-pointer flex flex-nowrap items-center ' +
|
||||
(selected ? 'text-black' : ' ')} >
|
||||
<div className='my-auto items-center justify-center flex '>
|
||||
<div className={ 'hover:text-black'}>{link.name}</div>
|
||||
</div>
|
||||
{link.slot}
|
||||
</a>
|
||||
</Link>
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})}
|
||||
</nav>
|
||||
return (
|
||||
<nav id='nav' className='font-sans text-sm'>
|
||||
{links.map(link => {
|
||||
if (link.show) {
|
||||
const selected = (router.pathname === link.to) || (router.asPath === link.to)
|
||||
return (
|
||||
<Link
|
||||
key={`${link.to}`}
|
||||
title={link.to}
|
||||
href={link.to}
|
||||
className={'py-0.5 duration-500 justify-between text-gray-500 dark:text-gray-300 hover:text-black hover:underline cursor-pointer flex flex-nowrap items-center ' +
|
||||
(selected ? 'text-black' : ' ')}>
|
||||
|
||||
<div className='my-auto items-center justify-center flex '>
|
||||
<div className={ 'hover:text-black'}>{link.name}</div>
|
||||
</div>
|
||||
{link.slot}
|
||||
|
||||
</Link>
|
||||
);
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})}
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
|
||||
export default GroupMenu
|
||||
|
||||
@@ -2,11 +2,15 @@ import Link from 'next/link'
|
||||
|
||||
const Logo = props => {
|
||||
const { siteInfo } = props
|
||||
return <section className='flex'>
|
||||
<Link href='/'>
|
||||
<a className='hover:bg-black hover:text-white border-black border-2 duration-500 px-4 py-2 cursor-pointer dark:text-gray-300 dark:border-gray-300 font-black'>{siteInfo?.title}</a>
|
||||
</Link>
|
||||
</section>
|
||||
return (
|
||||
<section className='flex'>
|
||||
<Link
|
||||
href='/'
|
||||
className='hover:bg-black hover:text-white border-black border-2 duration-500 px-4 py-2 cursor-pointer dark:text-gray-300 dark:border-gray-300 font-black'>
|
||||
{siteInfo?.title}
|
||||
</Link>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default Logo
|
||||
|
||||
@@ -26,15 +26,12 @@ const PaginationSimple = ({ page, showNext }) => {
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
passHref
|
||||
>
|
||||
<a
|
||||
rel="prev"
|
||||
className={`${
|
||||
currentPage === 1 ? 'invisible' : 'visible'
|
||||
} text-center w-full duration-200 px-4 py-2 hover:border-black border-b-2 hover:font-bold`}
|
||||
>
|
||||
← {locale.PAGINATION.PREV}
|
||||
</a>
|
||||
rel="prev"
|
||||
className={`${
|
||||
currentPage === 1 ? 'invisible' : 'visible'
|
||||
} text-center w-full duration-200 px-4 py-2 hover:border-black border-b-2 hover:font-bold`}>
|
||||
←{locale.PAGINATION.PREV}
|
||||
|
||||
</Link>
|
||||
<Link
|
||||
href={{
|
||||
@@ -42,18 +39,15 @@ const PaginationSimple = ({ page, showNext }) => {
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
passHref
|
||||
>
|
||||
<a
|
||||
rel="next"
|
||||
className={`${
|
||||
showNext ? 'visible' : 'invisible'
|
||||
} text-center w-full duration-200 px-4 py-2 hover:border-black border-b-2 hover:font-bold`}
|
||||
>
|
||||
{locale.PAGINATION.NEXT} →
|
||||
</a>
|
||||
rel="next"
|
||||
className={`${
|
||||
showNext ? 'visible' : 'invisible'
|
||||
} text-center w-full duration-200 px-4 py-2 hover:border-black border-b-2 hover:font-bold`}>
|
||||
|
||||
{locale.PAGINATION.NEXT}→
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default PaginationSimple
|
||||
|
||||
@@ -8,17 +8,20 @@ const TagItem = ({ tag, selected }) => {
|
||||
<div> { locale.COMMON.NOTAG } </div>
|
||||
}
|
||||
return (
|
||||
<Link href={selected ? '/' : `/tag/${encodeURIComponent(tag.name)}`} passHref>
|
||||
<li
|
||||
className={`notion-${tag.color}_background dark:bg-gray-700 list-none cursor-pointer rounded-md
|
||||
duration-200 mr-1 my-1 px-2 py-1 text-sm whitespace-nowrap
|
||||
hover:bg-gray-200 dark:hover:bg-gray-800 `}>
|
||||
<div className='text-gray-600 dark:text-gray-300 dark:hover:text-white'>
|
||||
{selected && <i className='mr-1 fas fa-tag'/>} {`${tag.name} `} {tag.count ? `(${tag.count})` : ''}
|
||||
</div>
|
||||
</li>
|
||||
</Link>
|
||||
)
|
||||
<Link
|
||||
href={selected ? '/' : `/tag/${encodeURIComponent(tag.name)}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<li
|
||||
className={`notion-${tag.color}_background dark:bg-gray-700 list-none cursor-pointer rounded-md
|
||||
duration-200 mr-1 my-1 px-2 py-1 text-sm whitespace-nowrap
|
||||
hover:bg-gray-200 dark:hover:bg-gray-800 `}>
|
||||
<div className='text-gray-600 dark:text-gray-300 dark:hover:text-white'>
|
||||
{selected && <i className='mr-1 fas fa-tag'/>} {`${tag.name} `} {tag.count ? `(${tag.count})` : ''}
|
||||
</div>
|
||||
</li>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
export default TagItem
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
import Link from 'next/link'
|
||||
|
||||
const TagItemMini = ({ tag, selected = false }) => {
|
||||
return <Link key={tag} href={selected ? '/' : `/tag/${encodeURIComponent(tag.name)}`} passHref>
|
||||
<a className={`cursor-pointer inline-block rounded hover:bg-gray-500 hover:text-white duration-200
|
||||
mr-2 py-0.5 px-1 text-xs whitespace-nowrap dark:hover:text-white
|
||||
${selected
|
||||
? 'text-white dark:text-gray-300 bg-black dark:bg-black dark:hover:bg-gray-900'
|
||||
: `text-gray-600 hover:shadow-xl dark:border-gray-400 notion-${tag.color}_background dark:bg-gray-800`}` }>
|
||||
<div className='font-light dark:text-gray-400'>{selected && <i className='mr-1 fas fa-tag'/>} {tag.name + (tag.count ? `(${tag.count})` : '')} </div>
|
||||
</a>
|
||||
</Link>
|
||||
return (
|
||||
<Link
|
||||
key={tag}
|
||||
href={selected ? '/' : `/tag/${encodeURIComponent(tag.name)}`}
|
||||
passHref
|
||||
className={`cursor-pointer inline-block rounded hover:bg-gray-500 hover:text-white duration-200
|
||||
mr-2 py-0.5 px-1 text-xs whitespace-nowrap dark:hover:text-white
|
||||
${selected
|
||||
? 'text-white dark:text-gray-300 bg-black dark:bg-black dark:hover:bg-gray-900'
|
||||
: `text-gray-600 hover:shadow-xl dark:border-gray-400 notion-${tag.color}_background dark:bg-gray-800`}` }>
|
||||
|
||||
<div className='font-light dark:text-gray-400'>{selected && <i className='mr-1 fas fa-tag'/>} {tag.name + (tag.count ? `(${tag.count})` : '')} </div>
|
||||
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
export default TagItemMini
|
||||
|
||||
@@ -16,7 +16,11 @@ export const LayoutCategoryIndex = props => {
|
||||
<div id="category-list" className="duration-200 flex flex-wrap mx-8">
|
||||
{categories.map(category => {
|
||||
return (
|
||||
<Link key={category.name} href={`/category/${category.name}`} passHref>
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<div
|
||||
className={
|
||||
' duration-300 dark:hover:text-white px-5 cursor-pointer py-2 hover:text-indigo-400'
|
||||
|
||||
@@ -38,62 +38,62 @@ export const LayoutSearch = props => {
|
||||
}, 100)
|
||||
})
|
||||
return (
|
||||
<LayoutBase {...props} currentSearch={currentSearch}>
|
||||
{!currentSearch && <>
|
||||
<div className="my-6 px-2">
|
||||
<SearchInput cRef={cRef} {...props} />
|
||||
{/* 分类 */}
|
||||
<Card className="w-full mt-4">
|
||||
<div className="dark:text-gray-200 mb-5 mx-3">
|
||||
<i className="mr-4 fas fa-th" />
|
||||
{locale.COMMON.CATEGORY}:
|
||||
</div>
|
||||
<div id="category-list" className="duration-200 flex flex-wrap mx-8">
|
||||
{categories?.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
<LayoutBase {...props} currentSearch={currentSearch}>
|
||||
{!currentSearch && <>
|
||||
<div className="my-6 px-2">
|
||||
<SearchInput cRef={cRef} {...props} />
|
||||
{/* 分类 */}
|
||||
<Card className="w-full mt-4">
|
||||
<div className="dark:text-gray-200 mb-5 mx-3">
|
||||
<i className="mr-4 fas fa-th" />
|
||||
{locale.COMMON.CATEGORY}:
|
||||
</div>
|
||||
<div id="category-list" className="duration-200 flex flex-wrap mx-8">
|
||||
{categories?.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<div
|
||||
className={
|
||||
' duration-300 dark:hover:text-white rounded-lg px-5 cursor-pointer py-2 hover:bg-indigo-400 hover:text-white'
|
||||
}
|
||||
>
|
||||
<div
|
||||
className={
|
||||
' duration-300 dark:hover:text-white rounded-lg px-5 cursor-pointer py-2 hover:bg-indigo-400 hover:text-white'
|
||||
}
|
||||
>
|
||||
<i className="mr-4 fas fa-folder" />
|
||||
{category.name}({category.count})
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
{/* 标签 */}
|
||||
<Card className="w-full mt-4">
|
||||
<div className="dark:text-gray-200 mb-5 ml-4">
|
||||
<i className="mr-4 fas fa-tag" />
|
||||
{locale.COMMON.TAGS}:
|
||||
</div>
|
||||
<div id="tags-list" className="duration-200 flex flex-wrap ml-8">
|
||||
{tags?.map(tag => {
|
||||
return (
|
||||
<div key={tag.name} className="p-2">
|
||||
<TagItemMini key={tag.name} tag={tag} />
|
||||
<i className="mr-4 fas fa-folder" />
|
||||
{category.name}({category.count})
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</>}
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
{/* 标签 */}
|
||||
<Card className="w-full mt-4">
|
||||
<div className="dark:text-gray-200 mb-5 ml-4">
|
||||
<i className="mr-4 fas fa-tag" />
|
||||
{locale.COMMON.TAGS}:
|
||||
</div>
|
||||
<div id="tags-list" className="duration-200 flex flex-wrap ml-8">
|
||||
{tags?.map(tag => {
|
||||
return (
|
||||
<div key={tag.name} className="p-2">
|
||||
<TagItemMini key={tag.name} tag={tag} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</>}
|
||||
|
||||
{currentSearch && <>
|
||||
<div id="container">
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
||||
</div>
|
||||
</>}
|
||||
{currentSearch && <>
|
||||
<div id="container">
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
||||
</div>
|
||||
</>}
|
||||
|
||||
</LayoutBase>
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,17 +10,23 @@ export const LayoutTag = (props) => {
|
||||
return t.name === props.tag
|
||||
})
|
||||
|
||||
return <LayoutBase {...props}>
|
||||
{tag && (
|
||||
<div className="cursor-pointer px-3 py-2 mb-2 font-light hover:text-indigo-700 dark:hover:text-indigo-400 transform dark:text-white">
|
||||
<Link key={tag} href={`/tag/${encodeURIComponent(tag.name)}`} passHref>
|
||||
<a className={`cursor-pointer inline-block rounded duration-200
|
||||
mr-2 py-0.5 px-1 text-xl whitespace-nowrap ` }>
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
{tag && (
|
||||
<div className="cursor-pointer px-3 py-2 mb-2 font-light hover:text-indigo-700 dark:hover:text-indigo-400 transform dark:text-white">
|
||||
<Link
|
||||
key={tag}
|
||||
href={`/tag/${encodeURIComponent(tag.name)}`}
|
||||
passHref
|
||||
className={`cursor-pointer inline-block rounded duration-200
|
||||
mr-2 py-0.5 px-1 text-xl whitespace-nowrap ` }>
|
||||
|
||||
<div className='font-light dark:text-gray-400 dark:hover:text-white'> #{tag.name + (tag.count ? `(${tag.count})` : '')} </div>
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
||||
</LayoutBase>
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,16 +10,24 @@ export default function ArticleAdjacent ({ prev, next }) {
|
||||
if (!prev || !next || !CONFIG_HEXO.ARTICLE_ADJACENT) {
|
||||
return <></>
|
||||
}
|
||||
return <section className='text-gray-800 items-center text-xs md:text-sm flex justify-between m-1 '>
|
||||
<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'>
|
||||
return (
|
||||
<section className='text-gray-800 items-center text-xs md:text-sm flex justify-between m-1 '>
|
||||
<Link
|
||||
href={`/${prev.slug}`}
|
||||
passHref
|
||||
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={`/${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}
|
||||
|
||||
</Link>
|
||||
<Link
|
||||
href={`/${next.slug}`}
|
||||
passHref
|
||||
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>
|
||||
</Link>
|
||||
</section>
|
||||
|
||||
</Link>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -16,24 +16,26 @@ export default function ArticleCopyright () {
|
||||
})
|
||||
|
||||
const { locale } = useGlobal()
|
||||
return <section className="dark:text-gray-300 mt-6 mx-1 ">
|
||||
<ul className="overflow-x-auto whitespace-nowrap text-sm dark:bg-gray-900 bg-gray-100 p-5 leading-8 border-l-2 border-indigo-500">
|
||||
<li>
|
||||
<strong className='mr-2'>{locale.COMMON.AUTHOR}:</strong>
|
||||
<Link href={'/about'} >
|
||||
<a className="hover:underline">{BLOG.AUTHOR}</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<strong className='mr-2'>{locale.COMMON.URL}:</strong>
|
||||
<a className="hover:underline" href={path}>
|
||||
{path}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<strong className='mr-2'>{locale.COMMON.COPYRIGHT}:</strong>
|
||||
{locale.COMMON.COPYRIGHT_NOTICE}
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
return (
|
||||
<section className="dark:text-gray-300 mt-6 mx-1 ">
|
||||
<ul className="overflow-x-auto whitespace-nowrap text-sm dark:bg-gray-900 bg-gray-100 p-5 leading-8 border-l-2 border-indigo-500">
|
||||
<li>
|
||||
<strong className='mr-2'>{locale.COMMON.AUTHOR}:</strong>
|
||||
<Link href={'/about'} className="hover:underline">
|
||||
{BLOG.AUTHOR}
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<strong className='mr-2'>{locale.COMMON.URL}:</strong>
|
||||
<a className="hover:underline" href={path}>
|
||||
{path}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<strong className='mr-2'>{locale.COMMON.COPYRIGHT}:</strong>
|
||||
{locale.COMMON.COPYRIGHT_NOTICE}
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -34,32 +34,29 @@ export default function ArticleRecommend({ recommendPosts, siteInfo }) {
|
||||
: `url("${siteInfo?.pageCover}")`
|
||||
|
||||
return (
|
||||
<Link
|
||||
(<Link
|
||||
key={post.id}
|
||||
title={post.title}
|
||||
href={`${BLOG.SUB_PATH}/${post.slug}`}
|
||||
passHref
|
||||
>
|
||||
<a
|
||||
key={post.id}
|
||||
className="flex h-40 cursor-pointer overflow-hidden"
|
||||
className="flex h-40 cursor-pointer overflow-hidden">
|
||||
|
||||
<div
|
||||
className="h-full w-full bg-cover bg-center bg-no-repeat hover:scale-110 transform duration-200"
|
||||
style={{ backgroundImage: headerImage }}
|
||||
>
|
||||
<div
|
||||
className="h-full w-full bg-cover bg-center bg-no-repeat hover:scale-110 transform duration-200"
|
||||
style={{ backgroundImage: headerImage }}
|
||||
>
|
||||
<div className="flex items-center justify-center bg-black bg-opacity-60 hover:bg-opacity-10 w-full h-full duration-300 ">
|
||||
<div className=" text-sm text-white text-center shadow-text">
|
||||
<div>
|
||||
<i className="fas fa-calendar-alt mr-1" />
|
||||
{post.date?.start_date}
|
||||
</div>
|
||||
<div className="hover:underline">{post.title}</div>
|
||||
<div className="flex items-center justify-center bg-black bg-opacity-60 hover:bg-opacity-10 w-full h-full duration-300 ">
|
||||
<div className=" text-sm text-white text-center shadow-text">
|
||||
<div>
|
||||
<i className="fas fa-calendar-alt mr-1" />
|
||||
{post.date?.start_date}
|
||||
</div>
|
||||
<div className="hover:underline">{post.title}</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
</Link>)
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
@@ -29,17 +29,20 @@ const BlogPostArchive = ({ posts = [], archiveTitle }) => {
|
||||
<div id={post?.date?.start_date}>
|
||||
<span className="text-gray-400">{post.date?.start_date}</span>{' '}
|
||||
|
||||
<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>
|
||||
<Link
|
||||
href={`${BLOG.SUB_PATH}/${post.slug}`}
|
||||
passHref
|
||||
className="dark:text-gray-400 dark:hover:text-indigo-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||
|
||||
{post.title}
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,13 +20,14 @@ 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}/${post.slug}`} passHref>
|
||||
<a
|
||||
className={`replace cursor-pointer hover:underline text-2xl ${showPreview ? 'text-center' : ''
|
||||
} leading-tight text-gray-700 dark:text-gray-100 hover:text-indigo-700 dark:hover:text-indigo-400`}
|
||||
>
|
||||
{post.title}
|
||||
</a>
|
||||
<Link
|
||||
href={`${BLOG.SUB_PATH}/${post.slug}`}
|
||||
passHref
|
||||
className={`replace cursor-pointer hover:underline text-2xl ${showPreview ? 'text-center' : ''
|
||||
} leading-tight text-gray-700 dark:text-gray-100 hover:text-indigo-700 dark:hover:text-indigo-400`}>
|
||||
|
||||
{post.title}
|
||||
|
||||
</Link>
|
||||
|
||||
<div
|
||||
@@ -36,11 +37,11 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
<Link
|
||||
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
||||
passHref
|
||||
>
|
||||
<a className="font-light hover:underline cursor-pointer text-sm leading-4 mr-3">
|
||||
<i className="far fa-calendar-alt mr-1" />
|
||||
{post.date?.start_date || post.lastEditedTime}
|
||||
</a>
|
||||
className="font-light hover:underline cursor-pointer text-sm leading-4 mr-3">
|
||||
|
||||
<i className="far fa-calendar-alt mr-1" />
|
||||
{post.date?.start_date || post.lastEditedTime}
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@@ -67,11 +68,14 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
)}
|
||||
|
||||
<div className="text-gray-400 justify-between flex">
|
||||
<Link href={`/category/${post.category}`} passHref>
|
||||
<a className="cursor-pointer font-light text-sm hover:underline hover:text-indigo-700 dark:hover:text-indigo-400 transform">
|
||||
<i className="mr-1 far fa-folder" />
|
||||
{post.category}
|
||||
</a>
|
||||
<Link
|
||||
href={`/category/${post.category}`}
|
||||
passHref
|
||||
className="cursor-pointer font-light text-sm hover:underline hover:text-indigo-700 dark:hover:text-indigo-400 transform">
|
||||
|
||||
<i className="mr-1 far fa-folder" />
|
||||
{post.category}
|
||||
|
||||
</Link>
|
||||
<div className="md:flex-nowrap flex-wrap md:justify-start inline-block">
|
||||
<div>
|
||||
@@ -85,7 +89,7 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
</div>
|
||||
|
||||
{CONFIG_HEXO.POST_LIST_COVER && !showPreview && post?.page_cover && !post.results && (
|
||||
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} passHref>
|
||||
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} passHref legacyBehavior>
|
||||
<div className="flex w-full relative duration-200 rounded-t-xl lg:rounded-r-xl lg:rounded-l-none cursor-pointer transform overflow-hidden">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
@@ -99,7 +103,7 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default BlogPostCard
|
||||
|
||||
@@ -10,10 +10,6 @@ import Progress from './Progress'
|
||||
* @constructor
|
||||
*/
|
||||
const Catalog = ({ toc }) => {
|
||||
// 无目录就直接返回空
|
||||
if (!toc || toc.length < 1) {
|
||||
return <></>
|
||||
}
|
||||
// 监听滚动事件
|
||||
React.useEffect(() => {
|
||||
window.addEventListener('scroll', actionSectionScrollSpy)
|
||||
@@ -29,6 +25,7 @@ const Catalog = ({ toc }) => {
|
||||
|
||||
// 同步选中目录事件
|
||||
const [activeSection, setActiveSection] = React.useState(null)
|
||||
|
||||
const throttleMs = 100
|
||||
const actionSectionScrollSpy = React.useCallback(throttle(() => {
|
||||
const sections = document.getElementsByClassName('notion-h')
|
||||
@@ -57,6 +54,11 @@ const Catalog = ({ toc }) => {
|
||||
tRef?.current?.scrollTo({ top: 28 * index, behavior: 'smooth' })
|
||||
}, throttleMs))
|
||||
|
||||
// 无目录就直接返回空
|
||||
if (!toc || toc.length < 1) {
|
||||
return <></>
|
||||
}
|
||||
|
||||
return <div className='px-3'>
|
||||
<div className='w-full'><i className='mr-1 fas fa-stream' /> 目录</div>
|
||||
<div className='w-full py-3'>
|
||||
|
||||
@@ -9,17 +9,23 @@ const CategoryGroup = ({ currentCategory, categories }) => {
|
||||
<div id='category-list' className='dark:border-gray-600 flex flex-wrap mx-4'>
|
||||
{categories.map(category => {
|
||||
const selected = currentCategory === category.name
|
||||
return <Link key={category.name} href={`/category/${category.name}`} passHref>
|
||||
<a className={(selected
|
||||
? 'hover:text-white dark:hover:text-white bg-indigo-600 text-white '
|
||||
: 'dark:text-gray-400 text-gray-500 hover:text-white dark:hover:text-white hover:bg-indigo-600') +
|
||||
' text-sm w-full items-center duration-300 px-2 cursor-pointer py-1 font-light'}>
|
||||
<div> <i className={`mr-2 fas ${selected ? 'fa-folder-open' : 'fa-folder'}`} />{category.name}({category.count})</div>
|
||||
</a>
|
||||
</Link>
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
className={(selected
|
||||
? 'hover:text-white dark:hover:text-white bg-indigo-600 text-white '
|
||||
: 'dark:text-gray-400 text-gray-500 hover:text-white dark:hover:text-white hover:bg-indigo-600') +
|
||||
' text-sm w-full items-center duration-300 px-2 cursor-pointer py-1 font-light'}>
|
||||
|
||||
<div> <i className={`mr-2 fas ${selected ? 'fa-folder-open' : 'fa-folder'}`} />{category.name}({category.count})</div>
|
||||
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
</>;
|
||||
}
|
||||
|
||||
export default CategoryGroup
|
||||
|
||||
@@ -32,7 +32,7 @@ export default function HeaderArticle({ post, siteInfo }) {
|
||||
<section className="flex-wrap shadow-text flex text-sm justify-center mt-2 text-white dark:text-gray-400 font-light leading-8">
|
||||
<div className='dark:text-gray-200'>
|
||||
{post.category && <>
|
||||
<Link href={`/category/${post.category}`} passHref>
|
||||
<Link href={`/category/${post.category}`} passHref legacyBehavior>
|
||||
<div className="cursor-pointer mr-2 dark:hover:text-white hover:underline">
|
||||
<i className="mr-1 fas fa-folder-open" />
|
||||
{post.category}
|
||||
@@ -46,10 +46,10 @@ export default function HeaderArticle({ post, siteInfo }) {
|
||||
<Link
|
||||
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
||||
passHref
|
||||
>
|
||||
<a className="pl-1 mr-2 cursor-pointer hover:underline">
|
||||
{locale.COMMON.POST_TIME}: {date}
|
||||
</a>
|
||||
className="pl-1 mr-2 cursor-pointer hover:underline">
|
||||
|
||||
{locale.COMMON.POST_TIME}:{date}
|
||||
|
||||
</Link>
|
||||
</>
|
||||
)}
|
||||
@@ -65,5 +65,5 @@ export default function HeaderArticle({ post, siteInfo }) {
|
||||
</div>
|
||||
</header>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -24,20 +24,22 @@ const HexoRecentComments = (props) => {
|
||||
})
|
||||
}, [])
|
||||
|
||||
return <Card >
|
||||
<div className=" mb-2 px-1 justify-between">
|
||||
<i className="mr-2 fas fas fa-comment" />
|
||||
{locale.COMMON.RECENT_COMMENTS}
|
||||
</div>
|
||||
return (
|
||||
<Card >
|
||||
<div className=" mb-2 px-1 justify-between">
|
||||
<i className="mr-2 fas fas fa-comment" />
|
||||
{locale.COMMON.RECENT_COMMENTS}
|
||||
</div>
|
||||
|
||||
{onLoading && <div>Loading...<i className='ml-2 fas fa-spinner animate-spin' /></div>}
|
||||
{!onLoading && comments && comments.length === 0 && <div>No Comments</div>}
|
||||
{!onLoading && comments && comments.length > 0 && comments.map((comment) => <div key={comment.objectId} className='pb-2 pl-1'>
|
||||
<div className='dark:text-gray-200 text-sm waline-recent-content wl-content' dangerouslySetInnerHTML={{ __html: comment.comment }} />
|
||||
<div className='dark:text-gray-400 text-gray-400 text-sm text-right cursor-pointer hover:text-red-500 hover:underline pt-1 pr-2'><Link href={{ pathname: comment.url, hash: comment.objectId, query: { target: 'comment' } }}><a >-- {comment.nick}</a></Link></div>
|
||||
</div>)}
|
||||
{onLoading && <div>Loading...<i className='ml-2 fas fa-spinner animate-spin' /></div>}
|
||||
{!onLoading && comments && comments.length === 0 && <div>No Comments</div>}
|
||||
{!onLoading && comments && comments.length > 0 && comments.map((comment) => <div key={comment.objectId} className='pb-2 pl-1'>
|
||||
<div className='dark:text-gray-200 text-sm waline-recent-content wl-content' dangerouslySetInnerHTML={{ __html: comment.comment }} />
|
||||
<div className='dark:text-gray-400 text-gray-400 text-sm text-right cursor-pointer hover:text-red-500 hover:underline pt-1 pr-2'><Link href={{ pathname: comment.url, hash: comment.objectId, query: { target: 'comment' } }}>--{comment.nick}</Link></div>
|
||||
</div>)}
|
||||
|
||||
</Card>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
export default HexoRecentComments
|
||||
|
||||
@@ -18,49 +18,47 @@ const LatestPostsGroup = ({ latestPosts, siteInfo }) => {
|
||||
return <></>
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className=" mb-2 px-1 flex flex-nowrap justify-between">
|
||||
<div>
|
||||
<i className="mr-2 fas fas fa-history" />
|
||||
{locale.COMMON.LATEST_POSTS}
|
||||
</div>
|
||||
return <>
|
||||
<div className=" mb-2 px-1 flex flex-nowrap justify-between">
|
||||
<div>
|
||||
<i className="mr-2 fas fas fa-history" />
|
||||
{locale.COMMON.LATEST_POSTS}
|
||||
</div>
|
||||
{latestPosts.map(post => {
|
||||
const selected = currentPath === `${BLOG.SUB_PATH}/${post.slug}`
|
||||
const headerImage = post?.page_cover
|
||||
? `url("${post.page_cover}")`
|
||||
: `url("${siteInfo?.pageCover}")`
|
||||
</div>
|
||||
{latestPosts.map(post => {
|
||||
const selected = currentPath === `${BLOG.SUB_PATH}/${post.slug}`
|
||||
const headerImage = post?.page_cover
|
||||
? `url("${post.page_cover}")`
|
||||
: `url("${siteInfo?.pageCover}")`
|
||||
|
||||
return (
|
||||
<Link
|
||||
key={post.id}
|
||||
title={post.title}
|
||||
href={`${BLOG.SUB_PATH}/${post.slug}`}
|
||||
passHref
|
||||
return (
|
||||
(<Link
|
||||
key={post.id}
|
||||
title={post.title}
|
||||
href={`${BLOG.SUB_PATH}/${post.slug}`}
|
||||
passHref
|
||||
className={'my-2 flex'}>
|
||||
|
||||
<div
|
||||
className="w-20 h-16 bg-cover bg-center bg-no-repeat"
|
||||
style={{ backgroundImage: headerImage }}
|
||||
/>
|
||||
<div
|
||||
className={
|
||||
(selected ? ' text-indigo-400 ' : 'dark:text-gray-400 ') +
|
||||
' text-sm overflow-x-hidden hover:text-indigo-600 px-2 duration-200 w-full rounded ' +
|
||||
'hover:text-white dark:hover:text-indigo-400 cursor-pointer items-center flex'
|
||||
}
|
||||
>
|
||||
<a className={'my-2 flex'}>
|
||||
<div
|
||||
className="w-20 h-16 bg-cover bg-center bg-no-repeat"
|
||||
style={{ backgroundImage: headerImage }}
|
||||
/>
|
||||
<div
|
||||
className={
|
||||
(selected ? ' text-indigo-400 ' : 'dark:text-gray-400 ') +
|
||||
' text-sm overflow-x-hidden hover:text-indigo-600 px-2 duration-200 w-full rounded ' +
|
||||
'hover:text-white dark:hover:text-indigo-400 cursor-pointer items-center flex'
|
||||
}
|
||||
>
|
||||
<div>
|
||||
<div className='text-line-2'>{post.title}</div>
|
||||
<div className="text-gray-500">{post.lastEditedTime}</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</>
|
||||
)
|
||||
<div>
|
||||
<div className='text-line-2'>{post.title}</div>
|
||||
<div className="text-gray-500">{post.lastEditedTime}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</Link>)
|
||||
);
|
||||
})}
|
||||
</>;
|
||||
}
|
||||
export default LatestPostsGroup
|
||||
|
||||
@@ -4,10 +4,12 @@ import React from 'react'
|
||||
|
||||
const Logo = props => {
|
||||
const { siteInfo } = props
|
||||
return <Link href='/' passHref>
|
||||
<div className='flex flex-col justify-center items-center cursor-pointer space-y-3'>
|
||||
<div className=' text-lg p-1.5 rounded dark:border-white hover:scale-110 transform duration-200'> {siteInfo?.title || BLOG.TITLE}</div>
|
||||
</div>
|
||||
</Link>
|
||||
return (
|
||||
<Link href='/' passHref legacyBehavior>
|
||||
<div className='flex flex-col justify-center items-center cursor-pointer space-y-3'>
|
||||
<div className=' text-lg p-1.5 rounded dark:border-white hover:scale-110 transform duration-200'> {siteInfo?.title || BLOG.TITLE}</div>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
export default Logo
|
||||
|
||||
@@ -18,21 +18,30 @@ const MenuButtonGroupTop = (props) => {
|
||||
links = links.concat(customNav)
|
||||
}
|
||||
|
||||
return <nav id='nav' className='leading-8 flex justify-center font-light w-full'>
|
||||
{links.map(link => {
|
||||
if (link.show) {
|
||||
return <Link key={`${link.to}`} title={link.to} href={link.to} >
|
||||
<a target={link.to.indexOf('http') === 0 ? '_blank' : '_self'} className={'py-1.5 my-1 px-3 text-base justify-center items-center cursor-pointer'} >
|
||||
<div className='w-full flex text-sm items-center justify-center hover:scale-125 duration-200 transform'>
|
||||
<i className={`${link.icon} mr-1`}/>
|
||||
<div className='text-center'>{link.name}</div>
|
||||
</div>
|
||||
</a>
|
||||
</Link>
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})}
|
||||
</nav>
|
||||
return (
|
||||
<nav id='nav' className='leading-8 flex justify-center font-light w-full'>
|
||||
{links.map(link => {
|
||||
if (link.show) {
|
||||
return (
|
||||
<Link
|
||||
key={`${link.to}`}
|
||||
title={link.to}
|
||||
href={link.to}
|
||||
target={link.to.indexOf('http') === 0 ? '_blank' : '_self'}
|
||||
className={'py-1.5 my-1 px-3 text-base justify-center items-center cursor-pointer'}>
|
||||
|
||||
<div className='w-full flex text-sm items-center justify-center hover:scale-125 duration-200 transform'>
|
||||
<i className={`${link.icon} mr-1`}/>
|
||||
<div className='text-center'>{link.name}</div>
|
||||
</div>
|
||||
|
||||
</Link>
|
||||
);
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})}
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
export default MenuButtonGroupTop
|
||||
|
||||
@@ -16,21 +16,30 @@ const MenuGroupCard = (props) => {
|
||||
{ name: locale.COMMON.TAGS, to: '/tag', slot: tagSlot, show: CONFIG_HEXO.MENU_TAG }
|
||||
]
|
||||
|
||||
return <nav id='nav' className='leading-8 flex justify-center w-full'>
|
||||
{links.map(link => {
|
||||
if (link.show) {
|
||||
return <Link key={`${link.to}`} title={link.to} href={link.to} >
|
||||
<a target={link.to.indexOf('http') === 0 ? '_blank' : '_self'} className={'py-1.5 my-1 px-2 duration-300 text-base justify-center items-center cursor-pointer'} >
|
||||
<div className='w-full items-center justify-center hover:scale-105 duration-200 transform dark:hover:text-indigo-400 hover:text-indigo-600'>
|
||||
<div className='text-center'>{link.name}</div>
|
||||
<div className='text-center font-semibold'>{link.slot}</div>
|
||||
</div>
|
||||
</a>
|
||||
</Link>
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})}
|
||||
</nav>
|
||||
return (
|
||||
<nav id='nav' className='leading-8 flex justify-center w-full'>
|
||||
{links.map(link => {
|
||||
if (link.show) {
|
||||
return (
|
||||
<Link
|
||||
key={`${link.to}`}
|
||||
title={link.to}
|
||||
href={link.to}
|
||||
target={link.to.indexOf('http') === 0 ? '_blank' : '_self'}
|
||||
className={'py-1.5 my-1 px-2 duration-300 text-base justify-center items-center cursor-pointer'}>
|
||||
|
||||
<div className='w-full items-center justify-center hover:scale-105 duration-200 transform dark:hover:text-indigo-400 hover:text-indigo-600'>
|
||||
<div className='text-center'>{link.name}</div>
|
||||
<div className='text-center font-semibold'>{link.slot}</div>
|
||||
</div>
|
||||
|
||||
</Link>
|
||||
);
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})}
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
export default MenuGroupCard
|
||||
|
||||
@@ -21,24 +21,32 @@ const MenuList = (props) => {
|
||||
links = links.concat(customNav)
|
||||
}
|
||||
|
||||
return <nav id='nav' className='leading-8 text-gray-500 dark:text-gray-300 '>
|
||||
{links.map(link => {
|
||||
if (link && link.show) {
|
||||
const selected = (router.pathname === link.to) || (router.asPath === link.to)
|
||||
return <Link key={`${link.to}`} title={link.to} href={link.to} >
|
||||
<a className={'py-1.5 px-5 text-base justify-between hover:bg-indigo-400 hover:text-white hover:shadow-lg cursor-pointer font-light flex flex-nowrap items-center ' +
|
||||
(selected ? 'bg-gray-200 text-black' : ' ')} >
|
||||
<div className='my-auto items-center justify-center flex '>
|
||||
<i className={`${link.icon} w-4 text-center`} />
|
||||
<div className={'ml-4'}>{link.name}</div>
|
||||
</div>
|
||||
{link.slot}
|
||||
</a>
|
||||
</Link>
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})}
|
||||
</nav>
|
||||
return (
|
||||
<nav id='nav' className='leading-8 text-gray-500 dark:text-gray-300 '>
|
||||
{links.map(link => {
|
||||
if (link && link.show) {
|
||||
const selected = (router.pathname === link.to) || (router.asPath === link.to)
|
||||
return (
|
||||
<Link
|
||||
key={`${link.to}`}
|
||||
title={link.to}
|
||||
href={link.to}
|
||||
className={'py-1.5 px-5 text-base justify-between hover:bg-indigo-400 hover:text-white hover:shadow-lg cursor-pointer font-light flex flex-nowrap items-center ' +
|
||||
(selected ? 'bg-gray-200 text-black' : ' ')}>
|
||||
|
||||
<div className='my-auto items-center justify-center flex '>
|
||||
<i className={`${link.icon} w-4 text-center`} />
|
||||
<div className={'ml-4'}>{link.name}</div>
|
||||
</div>
|
||||
{link.slot}
|
||||
|
||||
</Link>
|
||||
);
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})}
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
export default MenuList
|
||||
|
||||
@@ -13,12 +13,21 @@ const NavButtonGroup = (props) => {
|
||||
return <></>
|
||||
}
|
||||
|
||||
return <nav id='home-nav-button' className={'md:h-52 md:mt-6 xl:mt-32 px-5 py-2 mt-8 flex flex-wrap md:max-w-5xl space-y-2 md:space-y-0 md:flex justify-center max-h-80 overflow-auto'}>
|
||||
{categories.map(category => {
|
||||
return <Link key={`${category.name}`} title={`${category.name}`} href={`/category/${category.name}`} passHref>
|
||||
<a className='text-center w-full md:mx-6 md:w-40 md:h-14 lg:h-20 h-14 justify-center items-center flex border-2 cursor-pointer rounded-lg glassmorphism hover:bg-white hover:text-black duration-200 font-bold hover:scale-110 transform'>{category.name}</a>
|
||||
</Link>
|
||||
})}
|
||||
</nav>
|
||||
return (
|
||||
<nav id='home-nav-button' className={'md:h-52 md:mt-6 xl:mt-32 px-5 py-2 mt-8 flex flex-wrap md:max-w-5xl space-y-2 md:space-y-0 md:flex justify-center max-h-80 overflow-auto'}>
|
||||
{categories.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={`${category.name}`}
|
||||
title={`${category.name}`}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
className='text-center w-full md:mx-6 md:w-40 md:h-14 lg:h-20 h-14 justify-center items-center flex border-2 cursor-pointer rounded-lg glassmorphism hover:bg-white hover:text-black duration-200 font-bold hover:scale-110 transform'>
|
||||
{category.name}
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
export default NavButtonGroup
|
||||
|
||||
@@ -16,51 +16,57 @@ const PaginationNumber = ({ page, totalPage }) => {
|
||||
const pages = generatePages(pagePrefix, page, currentPage, totalPage)
|
||||
|
||||
return (
|
||||
<div className="mt-10 mb-5 flex justify-center items-end font-medium text-black duration-500 dark:text-gray-300 py-3 space-x-2">
|
||||
{/* 上一页 */}
|
||||
<Link
|
||||
href={{
|
||||
pathname: currentPage === 2
|
||||
? `${pagePrefix}/`
|
||||
: `${pagePrefix}/page/${currentPage - 1}`,
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
>
|
||||
<a rel="prev" className={`${currentPage === 1 ? 'invisible' : 'block'} pb-0.5 border-white dark:border-indigo-700 hover:border-indigo-400 dark:hover:border-indigo-400 w-6 text-center cursor-pointer duration-200 hover:font-bold`}>
|
||||
<i className="fas fa-angle-left" />
|
||||
</a>
|
||||
</Link>
|
||||
<div className="mt-10 mb-5 flex justify-center items-end font-medium text-black duration-500 dark:text-gray-300 py-3 space-x-2">
|
||||
{/* 上一页 */}
|
||||
<Link
|
||||
href={{
|
||||
pathname: currentPage === 2
|
||||
? `${pagePrefix}/`
|
||||
: `${pagePrefix}/page/${currentPage - 1}`,
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
rel="prev"
|
||||
className={`${currentPage === 1 ? 'invisible' : 'block'} pb-0.5 border-white dark:border-indigo-700 hover:border-indigo-400 dark:hover:border-indigo-400 w-6 text-center cursor-pointer duration-200 hover:font-bold`}>
|
||||
|
||||
{pages}
|
||||
<i className="fas fa-angle-left" />
|
||||
|
||||
{/* 下一页 */}
|
||||
<Link
|
||||
href={{
|
||||
pathname: `${pagePrefix}/page/${currentPage + 1}`,
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
>
|
||||
<a rel="next" className={`${+showNext ? 'block' : 'invisible'} pb-0.5 border-b border-indigo-300 dark:border-indigo-700 hover:border-indigo-400 dark:hover:border-indigo-400 w-6 text-center cursor-pointer duration-500 hover:font-bold`}>
|
||||
<i className="fas fa-angle-right" />
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
</Link>
|
||||
|
||||
{pages}
|
||||
|
||||
{/* 下一页 */}
|
||||
<Link
|
||||
href={{
|
||||
pathname: `${pagePrefix}/page/${currentPage + 1}`,
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
rel="next"
|
||||
className={`${+showNext ? 'block' : 'invisible'} pb-0.5 border-b border-indigo-300 dark:border-indigo-700 hover:border-indigo-400 dark:hover:border-indigo-400 w-6 text-center cursor-pointer duration-500 hover:font-bold`}>
|
||||
|
||||
<i className="fas fa-angle-right" />
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function getPageElement(page, currentPage, pagePrefix) {
|
||||
return (
|
||||
<Link href={page === 1 ? `${pagePrefix}/` : `${pagePrefix}/page/${page}`} key={page} passHref>
|
||||
<a className={
|
||||
(page + '' === currentPage + ''
|
||||
? 'font-bold bg-indigo-400 dark:bg-indigo-500 text-white '
|
||||
: 'border-b duration-500 border-indigo-300 hover:border-indigo-400 ') +
|
||||
' border-white dark:border-indigo-700 dark:hover:border-indigo-400 cursor-pointer pb-0.5 w-6 text-center font-light hover:font-bold'
|
||||
} >
|
||||
{page}
|
||||
</a>
|
||||
</Link>
|
||||
)
|
||||
(<Link
|
||||
href={page === 1 ? `${pagePrefix}/` : `${pagePrefix}/page/${page}`}
|
||||
key={page}
|
||||
passHref
|
||||
className={
|
||||
(page + '' === currentPage + ''
|
||||
? 'font-bold bg-indigo-400 dark:bg-indigo-500 text-white '
|
||||
: 'border-b duration-500 border-indigo-300 hover:border-indigo-400 ') +
|
||||
' border-white dark:border-indigo-700 dark:hover:border-indigo-400 cursor-pointer pb-0.5 w-6 text-center font-light hover:font-bold'
|
||||
}>
|
||||
|
||||
{page}
|
||||
|
||||
</Link>)
|
||||
);
|
||||
}
|
||||
|
||||
function generatePages(pagePrefix, page, currentPage, totalPage) {
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
import Link from 'next/link'
|
||||
|
||||
const TagItemMini = ({ tag, selected = false }) => {
|
||||
return <Link key={tag} href={selected ? '/' : `/tag/${encodeURIComponent(tag.name)}`} passHref>
|
||||
<a className={`cursor-pointer inline-block rounded hover:bg-indigo-400 dark:hover:text-white hover:text-white duration-200
|
||||
mr-2 py-0.5 px-1 text-xs whitespace-nowrap
|
||||
${selected
|
||||
? 'text-white dark:text-gray-300 bg-black dark:bg-black dark:hover:bg-indigo-900'
|
||||
: `text-gray-600 hover:shadow-xl dark:border-gray-400 notion-${tag.color}_background `}` }>
|
||||
<div className='font-light'>{selected && <i className='mr-1 fa-tag'/>} {tag.name + (tag.count ? `(${tag.count})` : '')} </div>
|
||||
</a>
|
||||
</Link>
|
||||
return (
|
||||
<Link
|
||||
key={tag}
|
||||
href={selected ? '/' : `/tag/${encodeURIComponent(tag.name)}`}
|
||||
passHref
|
||||
className={`cursor-pointer inline-block rounded hover:bg-indigo-400 dark:hover:text-white hover:text-white duration-200
|
||||
mr-2 py-0.5 px-1 text-xs whitespace-nowrap
|
||||
${selected
|
||||
? 'text-white dark:text-gray-300 bg-black dark:bg-black dark:hover:bg-indigo-900'
|
||||
: `text-gray-600 hover:shadow-xl dark:border-gray-400 notion-${tag.color}_background `}` }>
|
||||
|
||||
<div className='font-light'>{selected && <i className='mr-1 fa-tag'/>} {tag.name + (tag.count ? `(${tag.count})` : '')} </div>
|
||||
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
export default TagItemMini
|
||||
|
||||
@@ -90,10 +90,13 @@ const TopNav = props => {
|
||||
<section className='mt-8'>
|
||||
<div className='text-sm flex flex-nowrap justify-between font-light px-2'>
|
||||
<div className='text-gray-600 dark:text-gray-200'><i className='mr-2 fas fa-th-list' />{locale.COMMON.CATEGORY}</div>
|
||||
<Link href={'/category'} passHref>
|
||||
<a className='mb-3 text-gray-400 hover:text-black dark:text-gray-400 dark:hover:text-white hover:underline cursor-pointer'>
|
||||
{locale.COMMON.MORE} <i className='fas fa-angle-double-right' />
|
||||
</a>
|
||||
<Link
|
||||
href={'/category'}
|
||||
passHref
|
||||
className='mb-3 text-gray-400 hover:text-black dark:text-gray-400 dark:hover:text-white hover:underline cursor-pointer'>
|
||||
|
||||
{locale.COMMON.MORE} <i className='fas fa-angle-double-right' />
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
<CategoryGroup currentCategory={currentCategory} categories={categories} />
|
||||
@@ -104,10 +107,13 @@ const TopNav = props => {
|
||||
<section className='mt-4'>
|
||||
<div className='text-sm py-2 px-2 flex flex-nowrap justify-between font-light dark:text-gray-200'>
|
||||
<div className='text-gray-600 dark:text-gray-200'><i className='mr-2 fas fa-tag'/>{locale.COMMON.TAGS}</div>
|
||||
<Link href={'/tag'} passHref>
|
||||
<a className='text-gray-400 hover:text-black dark:hover:text-white hover:underline cursor-pointer'>
|
||||
{locale.COMMON.MORE} <i className='fas fa-angle-double-right' />
|
||||
</a>
|
||||
<Link
|
||||
href={'/tag'}
|
||||
passHref
|
||||
className='text-gray-400 hover:text-black dark:hover:text-white hover:underline cursor-pointer'>
|
||||
|
||||
{locale.COMMON.MORE} <i className='fas fa-angle-double-right' />
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
<div className='p-2'>
|
||||
|
||||
@@ -7,30 +7,32 @@ import HeaderArticle from './components/HeaderArticle'
|
||||
|
||||
export const LayoutCategory = props => {
|
||||
const { category, categories } = props
|
||||
return <LayoutBase {...props} headerSlot={<HeaderArticle {...props} />} >
|
||||
return (
|
||||
<LayoutBase {...props} headerSlot={<HeaderArticle {...props} />} >
|
||||
|
||||
<div className='inner-wrapper'>
|
||||
<div className='inner-wrapper'>
|
||||
|
||||
<div className="drop-shadow-xl -mt-32 rounded-md mx-3 px-5 lg:border lg:rounded-xl lg:px-2 lg:py-4 bg-white dark:bg-hexo-black-gray dark:border-black">
|
||||
<div className="drop-shadow-xl -mt-32 rounded-md mx-3 px-5 lg:border lg:rounded-xl lg:px-2 lg:py-4 bg-white dark:bg-hexo-black-gray dark:border-black">
|
||||
|
||||
<div className='flex justify-center flex-wrap'>
|
||||
{categories.map(e => {
|
||||
const selected = e.name === category
|
||||
return (
|
||||
<Link key={e.name} href={`/category/${e.name}`} passHref>
|
||||
<div className='duration-300 text-md whitespace-nowrap dark:hover:text-white px-5 cursor-pointer py-2 hover:text-indigo-400' >
|
||||
<i className={`mr-4 fas ${selected ? 'fa-folder-open' : 'fa-folder'}`}/>
|
||||
{e.name}({e.count})
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
<div className='flex justify-center flex-wrap'>
|
||||
{categories.map(e => {
|
||||
const selected = e.name === category
|
||||
return (
|
||||
<Link key={e.name} href={`/category/${e.name}`} passHref legacyBehavior>
|
||||
<div className='duration-300 text-md whitespace-nowrap dark:hover:text-white px-5 cursor-pointer py-2 hover:text-indigo-400' >
|
||||
<i className={`mr-4 fas ${selected ? 'fa-folder-open' : 'fa-folder'}`}/>
|
||||
{e.name}({e.count})
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
||||
|
||||
</div>
|
||||
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
||||
|
||||
</div>
|
||||
|
||||
</LayoutBase>
|
||||
</LayoutBase>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,27 +6,27 @@ export const LayoutCategoryIndex = props => {
|
||||
const { categories } = props
|
||||
|
||||
return (
|
||||
<LayoutBase {...props} headerSlot={<HeaderArticle {...props} />} >
|
||||
<LayoutBase {...props} headerSlot={<HeaderArticle {...props} />} >
|
||||
|
||||
<div className='inner-wrapper'>
|
||||
<div className='inner-wrapper'>
|
||||
|
||||
<div className="drop-shadow-xl -mt-32 rounded-md mx-3 px-5 lg:border lg:rounded-xl lg:px-2 lg:py-4 bg-white dark:bg-hexo-black-gray dark:border-black">
|
||||
<div className="drop-shadow-xl -mt-32 rounded-md mx-3 px-5 lg:border lg:rounded-xl lg:px-2 lg:py-4 bg-white dark:bg-hexo-black-gray dark:border-black">
|
||||
|
||||
<div className='flex justify-center flex-wrap'>
|
||||
{categories.map(e => {
|
||||
return (
|
||||
<Link key={e.name} href={`/category/${e.name}`} passHref>
|
||||
<div className='duration-300 text-md whitespace-nowrap dark:hover:text-white px-5 cursor-pointer py-2 hover:text-indigo-400' >
|
||||
<i className={'mr-4 fas fa-folder'} />
|
||||
{e.name}({e.count})
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex justify-center flex-wrap'>
|
||||
{categories.map(e => {
|
||||
return (
|
||||
<Link key={e.name} href={`/category/${e.name}`} passHref legacyBehavior>
|
||||
<div className='duration-300 text-md whitespace-nowrap dark:hover:text-white px-5 cursor-pointer py-2 hover:text-indigo-400' >
|
||||
<i className={'mr-4 fas fa-folder'} />
|
||||
{e.name}({e.count})
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -38,62 +38,62 @@ export const LayoutSearch = props => {
|
||||
}, 100)
|
||||
})
|
||||
return (
|
||||
<LayoutBase {...props} currentSearch={currentSearch}>
|
||||
{!currentSearch && <>
|
||||
<div className="my-6 px-2 mt-12">
|
||||
<SearchInput cRef={cRef} {...props} />
|
||||
{/* 分类 */}
|
||||
<Card className="w-full mt-4">
|
||||
<div className="dark:text-gray-200 mb-5 mx-3">
|
||||
<i className="mr-4 fas fa-th" />
|
||||
{locale.COMMON.CATEGORY}:
|
||||
</div>
|
||||
<div id="category-list" className="duration-200 flex flex-wrap mx-8">
|
||||
{categories?.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
<LayoutBase {...props} currentSearch={currentSearch}>
|
||||
{!currentSearch && <>
|
||||
<div className="my-6 px-2 mt-12">
|
||||
<SearchInput cRef={cRef} {...props} />
|
||||
{/* 分类 */}
|
||||
<Card className="w-full mt-4">
|
||||
<div className="dark:text-gray-200 mb-5 mx-3">
|
||||
<i className="mr-4 fas fa-th" />
|
||||
{locale.COMMON.CATEGORY}:
|
||||
</div>
|
||||
<div id="category-list" className="duration-200 flex flex-wrap mx-8">
|
||||
{categories?.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<div
|
||||
className={
|
||||
' duration-300 dark:hover:text-white rounded-lg px-5 cursor-pointer py-2 hover:bg-indigo-400 hover:text-white'
|
||||
}
|
||||
>
|
||||
<div
|
||||
className={
|
||||
' duration-300 dark:hover:text-white rounded-lg px-5 cursor-pointer py-2 hover:bg-indigo-400 hover:text-white'
|
||||
}
|
||||
>
|
||||
<i className="mr-4 fas fa-folder" />
|
||||
{category.name}({category.count})
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
{/* 标签 */}
|
||||
<Card className="w-full mt-4">
|
||||
<div className="dark:text-gray-200 mb-5 ml-4">
|
||||
<i className="mr-4 fas fa-tag" />
|
||||
{locale.COMMON.TAGS}:
|
||||
</div>
|
||||
<div id="tags-list" className="duration-200 flex flex-wrap ml-8">
|
||||
{tags?.map(tag => {
|
||||
return (
|
||||
<div key={tag.name} className="p-2">
|
||||
<TagItemMini key={tag.name} tag={tag} />
|
||||
<i className="mr-4 fas fa-folder" />
|
||||
{category.name}({category.count})
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</>}
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
{/* 标签 */}
|
||||
<Card className="w-full mt-4">
|
||||
<div className="dark:text-gray-200 mb-5 ml-4">
|
||||
<i className="mr-4 fas fa-tag" />
|
||||
{locale.COMMON.TAGS}:
|
||||
</div>
|
||||
<div id="tags-list" className="duration-200 flex flex-wrap ml-8">
|
||||
{tags?.map(tag => {
|
||||
return (
|
||||
<div key={tag.name} className="p-2">
|
||||
<TagItemMini key={tag.name} tag={tag} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</>}
|
||||
|
||||
{currentSearch && <>
|
||||
<div id="container">
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
||||
</div>
|
||||
</>}
|
||||
{currentSearch && <>
|
||||
<div id="container">
|
||||
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
||||
</div>
|
||||
</>}
|
||||
|
||||
</LayoutBase>
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ export const LayoutSlug = props => {
|
||||
>
|
||||
|
||||
<div id='inner-wrapper'>
|
||||
<div className={'drop-shadow-xl max-w-4xl'}>
|
||||
<div className={'drop-shadow-xl w-full lg:max-w-3xl 2xl:max-w-4xl'}>
|
||||
<div className="-mt-32 rounded-md mx-3 lg:border lg:rounded-xl lg:py-4 bg-white dark:bg-hexo-black-gray dark:border-black">
|
||||
{lock && <ArticleLock validPassword={validPassword} />}
|
||||
|
||||
@@ -112,7 +112,7 @@ export const LayoutSlug = props => {
|
||||
data-aos-once="false"
|
||||
data-aos-anchor-placement="top-center"
|
||||
className='relative h-full'>
|
||||
<div className='float-right -mr-72 h-full mt-40'>
|
||||
<div className='float-right xl:-mr-72 xl:w-72 w-56 -mr-56 h-full mt-40'>
|
||||
<div className='sticky top-24'>
|
||||
<Catalog toc={post.toc} />
|
||||
</div>
|
||||
|
||||
@@ -16,24 +16,26 @@ export default function ArticleCopyright () {
|
||||
})
|
||||
|
||||
const { locale } = useGlobal()
|
||||
return <section className="dark:text-gray-300 mt-6 mx-1 ">
|
||||
<ul className="overflow-x-auto whitespace-nowrap text-sm dark:bg-gray-900 bg-gray-100 p-5 leading-8 border-l-2 border-indigo-500">
|
||||
<li>
|
||||
<strong className='mr-2'>{locale.COMMON.AUTHOR}:</strong>
|
||||
<Link href={'/about'} >
|
||||
<a className="hover:underline">{BLOG.AUTHOR}</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<strong className='mr-2'>{locale.COMMON.URL}:</strong>
|
||||
<a className="hover:underline" href={path}>
|
||||
{path}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<strong className='mr-2'>{locale.COMMON.COPYRIGHT}:</strong>
|
||||
{locale.COMMON.COPYRIGHT_NOTICE}
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
return (
|
||||
<section className="dark:text-gray-300 mt-6 mx-1 ">
|
||||
<ul className="overflow-x-auto whitespace-nowrap text-sm dark:bg-gray-900 bg-gray-100 p-5 leading-8 border-l-2 border-indigo-500">
|
||||
<li>
|
||||
<strong className='mr-2'>{locale.COMMON.AUTHOR}:</strong>
|
||||
<Link href={'/about'} className="hover:underline">
|
||||
{BLOG.AUTHOR}
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<strong className='mr-2'>{locale.COMMON.URL}:</strong>
|
||||
<a className="hover:underline" href={path}>
|
||||
{path}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<strong className='mr-2'>{locale.COMMON.COPYRIGHT}:</strong>
|
||||
{locale.COMMON.COPYRIGHT_NOTICE}
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,36 +10,38 @@ export const ArticleInfo = (props) => {
|
||||
const { locale } = useGlobal()
|
||||
const date = formatDate(post?.date?.start_date || post?.createdTime, locale.LOCALE)
|
||||
|
||||
return <section className='mb-3 dark:text-gray-200'>
|
||||
<div className='my-3'>
|
||||
{post.tagItems && (
|
||||
<div className="flex flex-nowrap overflow-x-auto">
|
||||
{post.tagItems.map(tag => (
|
||||
<TagItemMiddle key={tag.name} tag={tag} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
return (
|
||||
<section className='mb-3 dark:text-gray-200'>
|
||||
<div className='my-3'>
|
||||
{post.tagItems && (
|
||||
<div className="flex flex-nowrap overflow-x-auto">
|
||||
{post.tagItems.map(tag => (
|
||||
<TagItemMiddle key={tag.name} tag={tag} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className='flex flex-wrap gap-3 mt-5 text-sm'>
|
||||
{post?.type !== 'Page' && (<>
|
||||
<Link
|
||||
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
||||
passHref
|
||||
>
|
||||
<a className="cursor-pointer whitespace-nowrap">
|
||||
<i className='far fa-calendar-minus fa-fw'/> 发布日期: {date}
|
||||
</a>
|
||||
</Link>
|
||||
<span className='whitespace-nowrap'>
|
||||
<i className='far fa-calendar-check fa-fw' /> 更新日期: {post.lastEditedTime}
|
||||
</span>
|
||||
<span className="hidden busuanzi_container_page_pv font-light mr-2">
|
||||
<i className='mr-1 fas fa-eye' /><span className="busuanzi_value_page_pv" />
|
||||
</span>
|
||||
<WordCount />
|
||||
</>)}
|
||||
</div>
|
||||
<div className='flex flex-wrap gap-3 mt-5 text-sm'>
|
||||
{post?.type !== 'Page' && (<>
|
||||
<Link
|
||||
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
||||
passHref
|
||||
className="cursor-pointer whitespace-nowrap">
|
||||
|
||||
</section>
|
||||
<i className='far fa-calendar-minus fa-fw'/>发布日期:{date}
|
||||
|
||||
</Link>
|
||||
<span className='whitespace-nowrap'>
|
||||
<i className='far fa-calendar-check fa-fw' /> 更新日期: {post.lastEditedTime}
|
||||
</span>
|
||||
<span className="hidden busuanzi_container_page_pv font-light mr-2">
|
||||
<i className='mr-1 fas fa-eye' /><span className="busuanzi_value_page_pv" />
|
||||
</span>
|
||||
<WordCount />
|
||||
</>)}
|
||||
</div>
|
||||
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -34,35 +34,32 @@ export default function ArticleRecommend({ recommendPosts, siteInfo }) {
|
||||
: `url("${siteInfo?.pageCover}")`
|
||||
|
||||
return (
|
||||
<Link
|
||||
(<Link
|
||||
key={post.id}
|
||||
title={post.title}
|
||||
href={`${BLOG.SUB_PATH}/${post.slug}`}
|
||||
passHref
|
||||
>
|
||||
<a
|
||||
key={post.id}
|
||||
className="flex h-40 cursor-pointer overflow-hidden"
|
||||
className="flex h-40 cursor-pointer overflow-hidden">
|
||||
|
||||
<div
|
||||
className="h-full w-full bg-cover bg-center bg-no-repeat hover:scale-110 transform duration-200"
|
||||
style={{ backgroundImage: headerImage }}
|
||||
>
|
||||
<div
|
||||
className="h-full w-full bg-cover bg-center bg-no-repeat hover:scale-110 transform duration-200"
|
||||
style={{ backgroundImage: headerImage }}
|
||||
>
|
||||
<div className="flex items-center justify-center bg-black bg-opacity-60 hover:bg-opacity-10 w-full h-full duration-300 ">
|
||||
<div className=" text-sm text-white text-center shadow-text">
|
||||
<div>
|
||||
<i className="fas fa-calendar-alt mr-1" />
|
||||
{post.date?.start_date}
|
||||
</div>
|
||||
<div className="hover:underline">{post.title}</div>
|
||||
<div className="flex items-center justify-center bg-black bg-opacity-60 hover:bg-opacity-10 w-full h-full duration-300 ">
|
||||
<div className=" text-sm text-white text-center shadow-text">
|
||||
<div>
|
||||
<i className="fas fa-calendar-alt mr-1" />
|
||||
{post.date?.start_date}
|
||||
</div>
|
||||
<div className="hover:underline">{post.title}</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</Link>
|
||||
)
|
||||
</div>
|
||||
|
||||
</Link>)
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -29,17 +29,20 @@ const BlogPostArchive = ({ posts = [], archiveTitle }) => {
|
||||
<div id={post?.date?.start_date}>
|
||||
<span className="text-gray-400">{post.date?.start_date}</span>{' '}
|
||||
|
||||
<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>
|
||||
<Link
|
||||
href={`${BLOG.SUB_PATH}/${post.slug}`}
|
||||
passHref
|
||||
className="dark:text-gray-400 dark:hover:text-indigo-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||
|
||||
{post.title}
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,80 +7,83 @@ import CONFIG_MATERY from '../config_matery'
|
||||
const BlogPostCard = ({ post, showSummary }) => {
|
||||
const showPreview = CONFIG_MATERY.POST_LIST_PREVIEW && post.blockMap
|
||||
return (
|
||||
<div
|
||||
data-aos="fade-up"
|
||||
data-aos-duration="600"
|
||||
data-aos-easing="ease-in-out"
|
||||
data-aos-once="false"
|
||||
data-aos-anchor-placement="top-bottom"
|
||||
className="w-full mb-4 h-full overflow-auto drop-shadow-md border dark:border-black rounded-xl bg-white dark:bg-hexo-black-gray">
|
||||
<div
|
||||
data-aos="fade-up"
|
||||
data-aos-duration="600"
|
||||
data-aos-easing="ease-in-out"
|
||||
data-aos-once="false"
|
||||
data-aos-anchor-placement="top-bottom"
|
||||
className="w-full mb-4 h-full overflow-auto drop-shadow-md border dark:border-black rounded-xl bg-white dark:bg-hexo-black-gray">
|
||||
|
||||
{/* 固定高度 ,空白用图片拉升填充 */}
|
||||
<div key={post.id} className="flex flex-col h-96 justify-between">
|
||||
{/* 固定高度 ,空白用图片拉升填充 */}
|
||||
<div key={post.id} className="flex flex-col h-96 justify-between">
|
||||
|
||||
{/* 头部图片 填充卡片 */}
|
||||
{CONFIG_MATERY.POST_LIST_COVER && !showPreview && post?.page_cover && (
|
||||
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} passHref>
|
||||
<div className="flex flex-grow w-full relative duration-200 bg-black rounded-t-md cursor-pointer transform overflow-hidden">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src={post?.page_cover}
|
||||
alt={post.title}
|
||||
className="opacity-50 h-full w-full hover:scale-125 rounded-t-md transform object-cover duration-500"
|
||||
/>
|
||||
<span className='absolute bottom-0 left-0 text-white p-6 text-2xl replace' > {post.title}</span>
|
||||
</div>
|
||||
</Link>
|
||||
)}
|
||||
{/* 头部图片 填充卡片 */}
|
||||
{CONFIG_MATERY.POST_LIST_COVER && !showPreview && post?.page_cover && (
|
||||
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} passHref legacyBehavior>
|
||||
<div className="flex flex-grow w-full relative duration-200 bg-black rounded-t-md cursor-pointer transform overflow-hidden">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src={post?.page_cover}
|
||||
alt={post.title}
|
||||
className="opacity-50 h-full w-full hover:scale-125 rounded-t-md transform object-cover duration-500"
|
||||
/>
|
||||
<span className='absolute bottom-0 left-0 text-white p-6 text-2xl replace' > {post.title}</span>
|
||||
</div>
|
||||
</Link>
|
||||
)}
|
||||
|
||||
<div >
|
||||
{/* 描述 */}
|
||||
<div className="px-4 flex flex-col w-full text-gray-700 dark:text-gray-300">
|
||||
<div >
|
||||
{/* 描述 */}
|
||||
<div className="px-4 flex flex-col w-full text-gray-700 dark:text-gray-300">
|
||||
|
||||
{(!showPreview || showSummary) && post.summary && (
|
||||
<p style={{ overflow: 'hidden', textOverflow: 'ellipsis', display: '-webkit-box', WebkitLineClamp: '4', WebkitBoxOrient: 'vertical' }}
|
||||
className="replace my-2 text-sm font-light leading-7">
|
||||
{post.summary}
|
||||
</p>
|
||||
)}
|
||||
{(!showPreview || showSummary) && post.summary && (
|
||||
<p style={{ overflow: 'hidden', textOverflow: 'ellipsis', display: '-webkit-box', WebkitLineClamp: '4', WebkitBoxOrient: 'vertical' }}
|
||||
className="replace my-2 text-sm font-light leading-7">
|
||||
{post.summary}
|
||||
</p>
|
||||
)}
|
||||
|
||||
<div className='text-gray-800 justify-between flex my-2 dark:text-gray-300'>
|
||||
<Link
|
||||
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
||||
passHref
|
||||
>
|
||||
<a className="font-light hover:underline cursor-pointer text-sm leading-4 mr-3">
|
||||
<i className="far fa-clock mr-1" />
|
||||
{post.date?.start_date || post.lastEditedTime}
|
||||
</a>
|
||||
</Link>
|
||||
<Link href={`/category/${post.category}`} passHref>
|
||||
<a className="cursor-pointer font-light text-sm hover:underline hover:text-indigo-700 dark:hover:text-indigo-400 transform">
|
||||
<i className="mr-1 far fa-folder" />
|
||||
{post.category}
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<div className='text-gray-800 justify-between flex my-2 dark:text-gray-300'>
|
||||
<Link
|
||||
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
||||
passHref
|
||||
className="font-light hover:underline cursor-pointer text-sm leading-4 mr-3">
|
||||
|
||||
{post?.tagItems && post?.tagItems.length > 0 && (<>
|
||||
<hr />
|
||||
<div className="text-gray-400 justify-between flex px-5 py-3">
|
||||
<div className="md:flex-nowrap flex-wrap md:justify-start inline-block">
|
||||
<div>
|
||||
{' '}
|
||||
{post.tagItems.map(tag => (
|
||||
<TagItemMini key={tag.name} tag={tag} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>)}
|
||||
</div>
|
||||
</div>
|
||||
<i className="far fa-clock mr-1" />
|
||||
{post.date?.start_date || post.lastEditedTime}
|
||||
|
||||
</div>
|
||||
)
|
||||
</Link>
|
||||
<Link
|
||||
href={`/category/${post.category}`}
|
||||
passHref
|
||||
className="cursor-pointer font-light text-sm hover:underline hover:text-indigo-700 dark:hover:text-indigo-400 transform">
|
||||
|
||||
<i className="mr-1 far fa-folder" />
|
||||
{post.category}
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{post?.tagItems && post?.tagItems.length > 0 && (<>
|
||||
<hr />
|
||||
<div className="text-gray-400 justify-between flex px-5 py-3">
|
||||
<div className="md:flex-nowrap flex-wrap md:justify-start inline-block">
|
||||
<div>
|
||||
{' '}
|
||||
{post.tagItems.map(tag => (
|
||||
<TagItemMini key={tag.name} tag={tag} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default BlogPostCard
|
||||
|
||||
@@ -58,12 +58,12 @@ const Catalog = ({ toc }) => {
|
||||
return <></>
|
||||
}
|
||||
|
||||
return <div className='px-3 w-72'>
|
||||
return <div className='px-3 '>
|
||||
<div className='dark:text-white'><i className='mr-1 fas fa-stream' /> 目录</div>
|
||||
<div className='w-full py-3'>
|
||||
<Progress />
|
||||
</div>
|
||||
<div className='overflow-y-auto overscroll-none scroll-hidden' ref={tRef}>
|
||||
<div className='overflow-y-auto overscroll-none max-h-36 lg:max-h-96 scroll-hidden' ref={tRef}>
|
||||
<nav className='h-full text-black'>
|
||||
{toc.map((tocItem) => {
|
||||
const id = uuidToId(tocItem.id)
|
||||
@@ -76,7 +76,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-green-500 underline'}`}
|
||||
className={`${activeSection === id && ' font-bold text-green-500 underline overflow-ellipsis truncate'}`}
|
||||
>
|
||||
{tocItem.text}
|
||||
</span>
|
||||
|
||||
@@ -9,17 +9,23 @@ const CategoryGroup = ({ currentCategory, categories }) => {
|
||||
<div id='category-list' className='dark:border-gray-600 flex flex-wrap mx-4'>
|
||||
{categories.map(category => {
|
||||
const selected = currentCategory === category.name
|
||||
return <Link key={category.name} href={`/category/${category.name}`} passHref>
|
||||
<a className={(selected
|
||||
? 'hover:text-white dark:hover:text-white bg-indigo-600 text-white '
|
||||
: 'dark:text-gray-400 text-gray-500 hover:text-white dark:hover:text-white hover:bg-indigo-600') +
|
||||
' text-sm w-full items-center duration-300 px-2 cursor-pointer py-1 font-light'}>
|
||||
<div> <i className={`mr-2 fas ${selected ? 'fa-folder-open' : 'fa-folder'}`} />{category.name}({category.count})</div>
|
||||
</a>
|
||||
</Link>
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
className={(selected
|
||||
? 'hover:text-white dark:hover:text-white bg-indigo-600 text-white '
|
||||
: 'dark:text-gray-400 text-gray-500 hover:text-white dark:hover:text-white hover:bg-indigo-600') +
|
||||
' text-sm w-full items-center duration-300 px-2 cursor-pointer py-1 font-light'}>
|
||||
|
||||
<div> <i className={`mr-2 fas ${selected ? 'fa-folder-open' : 'fa-folder'}`} />{category.name}({category.count})</div>
|
||||
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
</>;
|
||||
}
|
||||
|
||||
export default CategoryGroup
|
||||
|
||||
@@ -24,20 +24,22 @@ const HexoRecentComments = (props) => {
|
||||
})
|
||||
}, [])
|
||||
|
||||
return <Card >
|
||||
<div className=" mb-2 px-1 justify-between">
|
||||
<i className="mr-2 fas fas fa-comment" />
|
||||
{locale.COMMON.RECENT_COMMENTS}
|
||||
</div>
|
||||
return (
|
||||
<Card >
|
||||
<div className=" mb-2 px-1 justify-between">
|
||||
<i className="mr-2 fas fas fa-comment" />
|
||||
{locale.COMMON.RECENT_COMMENTS}
|
||||
</div>
|
||||
|
||||
{onLoading && <div>Loading...<i className='ml-2 fas fa-spinner animate-spin' /></div>}
|
||||
{!onLoading && comments && comments.length === 0 && <div>No Comments</div>}
|
||||
{!onLoading && comments && comments.length > 0 && comments.map((comment) => <div key={comment.objectId} className='pb-2 pl-1'>
|
||||
<div className='dark:text-gray-200 text-sm waline-recent-content wl-content' dangerouslySetInnerHTML={{ __html: comment.comment }} />
|
||||
<div className='dark:text-gray-400 text-gray-400 text-sm text-right cursor-pointer hover:text-red-500 hover:underline pt-1 pr-2'><Link href={{ pathname: comment.url, hash: comment.objectId, query: { target: 'comment' } }}><a >-- {comment.nick}</a></Link></div>
|
||||
</div>)}
|
||||
{onLoading && <div>Loading...<i className='ml-2 fas fa-spinner animate-spin' /></div>}
|
||||
{!onLoading && comments && comments.length === 0 && <div>No Comments</div>}
|
||||
{!onLoading && comments && comments.length > 0 && comments.map((comment) => <div key={comment.objectId} className='pb-2 pl-1'>
|
||||
<div className='dark:text-gray-200 text-sm waline-recent-content wl-content' dangerouslySetInnerHTML={{ __html: comment.comment }} />
|
||||
<div className='dark:text-gray-400 text-gray-400 text-sm text-right cursor-pointer hover:text-red-500 hover:underline pt-1 pr-2'><Link href={{ pathname: comment.url, hash: comment.objectId, query: { target: 'comment' } }}>--{comment.nick}</Link></div>
|
||||
</div>)}
|
||||
|
||||
</Card>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
export default HexoRecentComments
|
||||
|
||||
@@ -18,49 +18,47 @@ const LatestPostsGroup = ({ latestPosts, siteInfo }) => {
|
||||
return <></>
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className=" mb-2 px-1 flex flex-nowrap justify-between">
|
||||
<div>
|
||||
<i className="mr-2 fas fas fa-history" />
|
||||
{locale.COMMON.LATEST_POSTS}
|
||||
</div>
|
||||
return <>
|
||||
<div className=" mb-2 px-1 flex flex-nowrap justify-between">
|
||||
<div>
|
||||
<i className="mr-2 fas fas fa-history" />
|
||||
{locale.COMMON.LATEST_POSTS}
|
||||
</div>
|
||||
{latestPosts.map(post => {
|
||||
const selected = currentPath === `${BLOG.SUB_PATH}/${post.slug}`
|
||||
const headerImage = post?.page_cover
|
||||
? `url("${post.page_cover}")`
|
||||
: `url("${siteInfo?.pageCover}")`
|
||||
</div>
|
||||
{latestPosts.map(post => {
|
||||
const selected = currentPath === `${BLOG.SUB_PATH}/${post.slug}`
|
||||
const headerImage = post?.page_cover
|
||||
? `url("${post.page_cover}")`
|
||||
: `url("${siteInfo?.pageCover}")`
|
||||
|
||||
return (
|
||||
<Link
|
||||
key={post.id}
|
||||
title={post.title}
|
||||
href={`${BLOG.SUB_PATH}/${post.slug}`}
|
||||
passHref
|
||||
return (
|
||||
(<Link
|
||||
key={post.id}
|
||||
title={post.title}
|
||||
href={`${BLOG.SUB_PATH}/${post.slug}`}
|
||||
passHref
|
||||
className={'my-2 flex'}>
|
||||
|
||||
<div
|
||||
className="w-20 h-16 bg-cover bg-center bg-no-repeat"
|
||||
style={{ backgroundImage: headerImage }}
|
||||
/>
|
||||
<div
|
||||
className={
|
||||
(selected ? ' text-indigo-400 ' : 'dark:text-gray-400 ') +
|
||||
' text-sm overflow-x-hidden hover:text-indigo-600 px-2 duration-200 w-full rounded ' +
|
||||
'hover:text-white dark:hover:text-indigo-400 cursor-pointer items-center flex'
|
||||
}
|
||||
>
|
||||
<a className={'my-2 flex'}>
|
||||
<div
|
||||
className="w-20 h-16 bg-cover bg-center bg-no-repeat"
|
||||
style={{ backgroundImage: headerImage }}
|
||||
/>
|
||||
<div
|
||||
className={
|
||||
(selected ? ' text-indigo-400 ' : 'dark:text-gray-400 ') +
|
||||
' text-sm overflow-x-hidden hover:text-indigo-600 px-2 duration-200 w-full rounded ' +
|
||||
'hover:text-white dark:hover:text-indigo-400 cursor-pointer items-center flex'
|
||||
}
|
||||
>
|
||||
<div>
|
||||
<div className='text-line-2'>{post.title}</div>
|
||||
<div className="text-gray-500">{post.lastEditedTime}</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</>
|
||||
)
|
||||
<div>
|
||||
<div className='text-line-2'>{post.title}</div>
|
||||
<div className="text-gray-500">{post.lastEditedTime}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</Link>)
|
||||
);
|
||||
})}
|
||||
</>;
|
||||
}
|
||||
export default LatestPostsGroup
|
||||
|
||||
@@ -4,10 +4,12 @@ import React from 'react'
|
||||
|
||||
const Logo = props => {
|
||||
const { siteInfo } = props
|
||||
return <Link href='/' passHref>
|
||||
<div className='flex flex-col justify-center items-center cursor-pointer space-y-3'>
|
||||
<div className=' text-lg p-1.5 rounded dark:border-white hover:scale-110 transform duration-200'> {siteInfo?.title || BLOG.TITLE}</div>
|
||||
</div>
|
||||
</Link>
|
||||
return (
|
||||
<Link href='/' passHref legacyBehavior>
|
||||
<div className='flex flex-col justify-center items-center cursor-pointer space-y-3'>
|
||||
<div className=' text-lg p-1.5 rounded dark:border-white hover:scale-110 transform duration-200'> {siteInfo?.title || BLOG.TITLE}</div>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
export default Logo
|
||||
|
||||
@@ -18,21 +18,30 @@ const MenuButtonGroupTop = (props) => {
|
||||
links = customNav.concat(links)
|
||||
}
|
||||
|
||||
return <nav id='nav' className='leading-8 flex justify-center font-light w-full'>
|
||||
{links.map(link => {
|
||||
if (link.show) {
|
||||
return <Link key={`${link.to}`} title={link.to} href={link.to} >
|
||||
<a target={link.to.indexOf('http') === 0 ? '_blank' : '_self'} className={'py-1.5 my-1 px-3 text-base justify-center items-center cursor-pointer'} >
|
||||
<div className='w-full flex text-sm items-center justify-center hover:scale-125 duration-200 transform'>
|
||||
<i className={`${link.icon} mr-1`}/>
|
||||
<div className='text-center'>{link.name}</div>
|
||||
</div>
|
||||
</a>
|
||||
</Link>
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})}
|
||||
</nav>
|
||||
return (
|
||||
<nav id='nav' className='leading-8 flex justify-center font-light w-full'>
|
||||
{links.map(link => {
|
||||
if (link.show) {
|
||||
return (
|
||||
<Link
|
||||
key={`${link.to}`}
|
||||
title={link.to}
|
||||
href={link.to}
|
||||
target={link.to.indexOf('http') === 0 ? '_blank' : '_self'}
|
||||
className={'py-1.5 my-1 px-3 text-base justify-center items-center cursor-pointer'}>
|
||||
|
||||
<div className='w-full flex text-sm items-center justify-center hover:scale-125 duration-200 transform'>
|
||||
<i className={`${link.icon} mr-1`}/>
|
||||
<div className='text-center'>{link.name}</div>
|
||||
</div>
|
||||
|
||||
</Link>
|
||||
);
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})}
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
export default MenuButtonGroupTop
|
||||
|
||||
@@ -16,21 +16,30 @@ const MenuGroupCard = (props) => {
|
||||
{ name: locale.COMMON.TAGS, to: '/tag', slot: tagSlot, show: CONFIG_MATERY.MENU_TAG }
|
||||
]
|
||||
|
||||
return <nav id='nav' className='leading-8 flex justify-center w-full'>
|
||||
{links.map(link => {
|
||||
if (link.show) {
|
||||
return <Link key={`${link.to}`} title={link.to} href={link.to} >
|
||||
<a target={link.to.indexOf('http') === 0 ? '_blank' : '_self'} className={'py-1.5 my-1 px-2 duration-300 text-base justify-center items-center cursor-pointer'} >
|
||||
<div className='w-full items-center justify-center hover:scale-105 duration-200 transform dark:hover:text-indigo-400 hover:text-indigo-600'>
|
||||
<div className='text-center'>{link.name}</div>
|
||||
<div className='text-center font-semibold'>{link.slot}</div>
|
||||
</div>
|
||||
</a>
|
||||
</Link>
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})}
|
||||
</nav>
|
||||
return (
|
||||
<nav id='nav' className='leading-8 flex justify-center w-full'>
|
||||
{links.map(link => {
|
||||
if (link.show) {
|
||||
return (
|
||||
<Link
|
||||
key={`${link.to}`}
|
||||
title={link.to}
|
||||
href={link.to}
|
||||
target={link.to.indexOf('http') === 0 ? '_blank' : '_self'}
|
||||
className={'py-1.5 my-1 px-2 duration-300 text-base justify-center items-center cursor-pointer'}>
|
||||
|
||||
<div className='w-full items-center justify-center hover:scale-105 duration-200 transform dark:hover:text-indigo-400 hover:text-indigo-600'>
|
||||
<div className='text-center'>{link.name}</div>
|
||||
<div className='text-center font-semibold'>{link.slot}</div>
|
||||
</div>
|
||||
|
||||
</Link>
|
||||
);
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})}
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
export default MenuGroupCard
|
||||
|
||||
@@ -21,24 +21,32 @@ const MenuList = (props) => {
|
||||
links = links.concat(customNav)
|
||||
}
|
||||
|
||||
return <nav id='nav' className='leading-8 text-gray-500 dark:text-gray-300 '>
|
||||
{links.map(link => {
|
||||
if (link && link.show) {
|
||||
const selected = (router.pathname === link.to) || (router.asPath === link.to)
|
||||
return <Link key={`${link.to}`} title={link.to} href={link.to} >
|
||||
<a className={'py-1.5 px-5 text-base justify-between hover:bg-indigo-400 hover:text-white hover:shadow-lg cursor-pointer font-light flex flex-nowrap items-center ' +
|
||||
(selected ? 'bg-gray-200 text-black' : ' ')} >
|
||||
<div className='my-auto items-center justify-center flex '>
|
||||
<i className={`${link.icon} w-4 text-center`} />
|
||||
<div className={'ml-4'}>{link.name}</div>
|
||||
</div>
|
||||
{link.slot}
|
||||
</a>
|
||||
</Link>
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})}
|
||||
</nav>
|
||||
return (
|
||||
<nav id='nav' className='leading-8 text-gray-500 dark:text-gray-300 '>
|
||||
{links.map(link => {
|
||||
if (link && link.show) {
|
||||
const selected = (router.pathname === link.to) || (router.asPath === link.to)
|
||||
return (
|
||||
<Link
|
||||
key={`${link.to}`}
|
||||
title={link.to}
|
||||
href={link.to}
|
||||
className={'py-1.5 px-5 text-base justify-between hover:bg-indigo-400 hover:text-white hover:shadow-lg cursor-pointer font-light flex flex-nowrap items-center ' +
|
||||
(selected ? 'bg-gray-200 text-black' : ' ')}>
|
||||
|
||||
<div className='my-auto items-center justify-center flex '>
|
||||
<i className={`${link.icon} w-4 text-center`} />
|
||||
<div className={'ml-4'}>{link.name}</div>
|
||||
</div>
|
||||
{link.slot}
|
||||
|
||||
</Link>
|
||||
);
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})}
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
export default MenuList
|
||||
|
||||
@@ -13,12 +13,21 @@ const NavButtonGroup = (props) => {
|
||||
return <></>
|
||||
}
|
||||
|
||||
return <nav id='home-nav-button' className={'md:h-52 md:mt-6 xl:mt-32 px-5 py-2 mt-8 flex flex-wrap md:max-w-5xl space-y-2 md:space-y-0 md:flex justify-center max-h-80 overflow-auto'}>
|
||||
{categories.map(category => {
|
||||
return <Link key={`${category.name}`} title={`${category.name}`} href={`/category/${category.name}`} passHref>
|
||||
<a className='text-center w-full md:mx-6 md:w-40 md:h-14 lg:h-20 h-14 justify-center items-center flex border-2 cursor-pointer rounded-lg glassmorphism hover:bg-white hover:text-black duration-200 font-bold hover:scale-110 transform'>{category.name}</a>
|
||||
</Link>
|
||||
})}
|
||||
</nav>
|
||||
return (
|
||||
<nav id='home-nav-button' className={'md:h-52 md:mt-6 xl:mt-32 px-5 py-2 mt-8 flex flex-wrap md:max-w-5xl space-y-2 md:space-y-0 md:flex justify-center max-h-80 overflow-auto'}>
|
||||
{categories.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={`${category.name}`}
|
||||
title={`${category.name}`}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
className='text-center w-full md:mx-6 md:w-40 md:h-14 lg:h-20 h-14 justify-center items-center flex border-2 cursor-pointer rounded-lg glassmorphism hover:bg-white hover:text-black duration-200 font-bold hover:scale-110 transform'>
|
||||
{category.name}
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
export default NavButtonGroup
|
||||
|
||||
@@ -16,51 +16,57 @@ const PaginationNumber = ({ page, totalPage }) => {
|
||||
const pages = generatePages(pagePrefix, page, currentPage, totalPage)
|
||||
|
||||
return (
|
||||
<div className="mt-10 mb-5 flex justify-center items-end font-medium text-black duration-500 dark:text-gray-300 py-3 space-x-2">
|
||||
{/* 上一页 */}
|
||||
<Link
|
||||
href={{
|
||||
pathname: currentPage === 2
|
||||
? `${pagePrefix}/`
|
||||
: `${pagePrefix}/page/${currentPage - 1}`,
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
>
|
||||
<a rel="prev" className={`${currentPage === 1 ? 'invisible' : 'block'} pb-0.5 border-white dark:border-indigo-700 hover:border-indigo-400 dark:hover:border-indigo-400 w-6 text-center cursor-pointer duration-200 hover:font-bold`}>
|
||||
<i className="fas fa-angle-left" />
|
||||
</a>
|
||||
</Link>
|
||||
<div className="mt-10 mb-5 flex justify-center items-end font-medium text-black duration-500 dark:text-gray-300 py-3 space-x-2">
|
||||
{/* 上一页 */}
|
||||
<Link
|
||||
href={{
|
||||
pathname: currentPage === 2
|
||||
? `${pagePrefix}/`
|
||||
: `${pagePrefix}/page/${currentPage - 1}`,
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
rel="prev"
|
||||
className={`${currentPage === 1 ? 'invisible' : 'block'} pb-0.5 border-white dark:border-indigo-700 hover:border-indigo-400 dark:hover:border-indigo-400 w-6 text-center cursor-pointer duration-200 hover:font-bold`}>
|
||||
|
||||
{pages}
|
||||
<i className="fas fa-angle-left" />
|
||||
|
||||
{/* 下一页 */}
|
||||
<Link
|
||||
href={{
|
||||
pathname: `${pagePrefix}/page/${currentPage + 1}`,
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
>
|
||||
<a rel="next" className={`${+showNext ? 'block' : 'invisible'} pb-0.5 border-b border-indigo-300 dark:border-indigo-700 hover:border-indigo-400 dark:hover:border-indigo-400 w-6 text-center cursor-pointer duration-500 hover:font-bold`}>
|
||||
<i className="fas fa-angle-right" />
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
</Link>
|
||||
|
||||
{pages}
|
||||
|
||||
{/* 下一页 */}
|
||||
<Link
|
||||
href={{
|
||||
pathname: `${pagePrefix}/page/${currentPage + 1}`,
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
rel="next"
|
||||
className={`${+showNext ? 'block' : 'invisible'} pb-0.5 border-b border-indigo-300 dark:border-indigo-700 hover:border-indigo-400 dark:hover:border-indigo-400 w-6 text-center cursor-pointer duration-500 hover:font-bold`}>
|
||||
|
||||
<i className="fas fa-angle-right" />
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function getPageElement(page, currentPage, pagePrefix) {
|
||||
return (
|
||||
<Link href={page === 1 ? `${pagePrefix}/` : `${pagePrefix}/page/${page}`} key={page} passHref>
|
||||
<a className={
|
||||
(page + '' === currentPage + ''
|
||||
? 'font-bold bg-indigo-400 dark:bg-indigo-500 text-white '
|
||||
: 'border-b duration-500 border-indigo-300 hover:border-indigo-400 ') +
|
||||
' border-white dark:border-indigo-700 dark:hover:border-indigo-400 cursor-pointer pb-0.5 w-6 text-center font-light hover:font-bold'
|
||||
} >
|
||||
{page}
|
||||
</a>
|
||||
</Link>
|
||||
)
|
||||
(<Link
|
||||
href={page === 1 ? `${pagePrefix}/` : `${pagePrefix}/page/${page}`}
|
||||
key={page}
|
||||
passHref
|
||||
className={
|
||||
(page + '' === currentPage + ''
|
||||
? 'font-bold bg-indigo-400 dark:bg-indigo-500 text-white '
|
||||
: 'border-b duration-500 border-indigo-300 hover:border-indigo-400 ') +
|
||||
' border-white dark:border-indigo-700 dark:hover:border-indigo-400 cursor-pointer pb-0.5 w-6 text-center font-light hover:font-bold'
|
||||
}>
|
||||
|
||||
{page}
|
||||
|
||||
</Link>)
|
||||
);
|
||||
}
|
||||
|
||||
function generatePages(pagePrefix, page, currentPage, totalPage) {
|
||||
|
||||
@@ -25,7 +25,7 @@ const PaginationSimple = ({ page, totalPage }) => {
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
passHref
|
||||
>
|
||||
legacyBehavior>
|
||||
<button
|
||||
rel="prev"
|
||||
className={`${
|
||||
@@ -40,7 +40,7 @@ const PaginationSimple = ({ page, totalPage }) => {
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
passHref
|
||||
>
|
||||
legacyBehavior>
|
||||
<button
|
||||
rel="next"
|
||||
className={`${
|
||||
@@ -51,7 +51,7 @@ const PaginationSimple = ({ page, totalPage }) => {
|
||||
</button>
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default PaginationSimple
|
||||
|
||||
@@ -30,36 +30,42 @@ const SideBar = (props) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div id='side-bar' className=''>
|
||||
<div className="mh-48 w-full bg-indigo-700">
|
||||
<div className='mx-5 pt-6 pb-2'>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img src={siteInfo?.icon} className='cursor-pointer rounded-full' width={80} alt={BLOG.AUTHOR} />
|
||||
<div className='text-white text-xl my-1'>{siteInfo?.title}</div>
|
||||
<div className='text-xs my-1 text-gray-300'>{siteInfo?.description}</div>
|
||||
</div>
|
||||
</div>
|
||||
<nav>
|
||||
{links.map(link => {
|
||||
if (link && link.show) {
|
||||
const selected = (router.pathname === link.to) || (router.asPath === link.to)
|
||||
return <Link key={link.to} title={link.to} href={link.to} >
|
||||
<a target={link.to.indexOf('http') === 0 ? '_blank' : '_self'}
|
||||
className={'py-2 px-5 duration-300 text-base justify-between hover:bg-gray-700 hover:text-white hover:shadow-lg cursor-pointer font-light flex flex-nowrap items-center ' +
|
||||
(selected ? 'bg-indigo-500 text-white ' : ' text-black dark:text-white ')} >
|
||||
<div className='my-auto items-center justify-between flex '>
|
||||
<i className={`${link.icon} w-4 ml-3 mr-6 text-center`} />
|
||||
<div >{link.name}</div>
|
||||
</div>
|
||||
{link.slot}
|
||||
</a>
|
||||
</Link>
|
||||
} else {
|
||||
return <></>
|
||||
}
|
||||
})}
|
||||
</nav>
|
||||
</div>
|
||||
<div id='side-bar' className=''>
|
||||
<div className="mh-48 w-full bg-indigo-700">
|
||||
<div className='mx-5 pt-6 pb-2'>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img src={siteInfo?.icon} className='cursor-pointer rounded-full' width={80} alt={BLOG.AUTHOR} />
|
||||
<div className='text-white text-xl my-1'>{siteInfo?.title}</div>
|
||||
<div className='text-xs my-1 text-gray-300'>{siteInfo?.description}</div>
|
||||
</div>
|
||||
</div>
|
||||
<nav>
|
||||
{links.map(link => {
|
||||
if (link && link.show) {
|
||||
const selected = (router.pathname === link.to) || (router.asPath === link.to)
|
||||
return (
|
||||
<Link
|
||||
key={link.to}
|
||||
title={link.to}
|
||||
href={link.to}
|
||||
target={link.to.indexOf('http') === 0 ? '_blank' : '_self'}
|
||||
className={'py-2 px-5 duration-300 text-base justify-between hover:bg-gray-700 hover:text-white hover:shadow-lg cursor-pointer font-light flex flex-nowrap items-center ' +
|
||||
(selected ? 'bg-indigo-500 text-white ' : ' text-black dark:text-white ')}>
|
||||
|
||||
<div className='my-auto items-center justify-between flex '>
|
||||
<i className={`${link.icon} w-4 ml-3 mr-6 text-center`} />
|
||||
<div >{link.name}</div>
|
||||
</div>
|
||||
{link.slot}
|
||||
|
||||
</Link>
|
||||
)
|
||||
} else {
|
||||
return <></>
|
||||
}
|
||||
})}
|
||||
</nav>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
import Link from 'next/link'
|
||||
|
||||
const TagItemMiddle = ({ tag, selected = false }) => {
|
||||
return <Link key={tag} href={selected ? '/' : `/tag/${encodeURIComponent(tag.name)}`} passHref>
|
||||
<a className={`cursor-pointer inline-block rounded-xl hover:text-white duration-200
|
||||
mr-2 py-0.5 px-2 text-md whitespace-nowrap text-white ${selected ? 'bg-black' : 'bg-indigo-700'}`}>
|
||||
<div className='font-light'>
|
||||
{selected && <i className='mr-1 fas fa-tag' />}
|
||||
{tag.name + (tag.count ? `(${tag.count})` : '')} </div>
|
||||
</a>
|
||||
</Link>
|
||||
return (
|
||||
<Link
|
||||
key={tag}
|
||||
href={selected ? '/' : `/tag/${encodeURIComponent(tag.name)}`}
|
||||
passHref
|
||||
className={`cursor-pointer inline-block rounded-xl hover:text-white duration-200
|
||||
mr-2 py-0.5 px-2 text-md whitespace-nowrap text-white ${selected ? 'bg-black' : 'bg-indigo-700'}`}>
|
||||
|
||||
<div className='font-light'>
|
||||
{selected && <i className='mr-1 fas fa-tag' />}
|
||||
{tag.name + (tag.count ? `(${tag.count})` : '')} </div>
|
||||
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
export default TagItemMiddle
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
import Link from 'next/link'
|
||||
|
||||
const TagItemMini = ({ tag, selected = false }) => {
|
||||
return <Link key={tag} href={selected ? '/' : `/tag/${encodeURIComponent(tag.name)}`} passHref>
|
||||
<a className={`cursor-pointer inline-block rounded-xl hover:text-white duration-200
|
||||
mr-2 py-0.5 px-2 text-xs whitespace-nowrap text-white bg-indigo-700`}>
|
||||
<div className='font-light'>{selected && <i className='mr-1 fa-tag'/>} {tag.name + (tag.count ? `(${tag.count})` : '')} </div>
|
||||
</a>
|
||||
</Link>
|
||||
return (
|
||||
<Link
|
||||
key={tag}
|
||||
href={selected ? '/' : `/tag/${encodeURIComponent(tag.name)}`}
|
||||
passHref
|
||||
className={`cursor-pointer inline-block rounded-xl hover:text-white duration-200
|
||||
mr-2 py-0.5 px-2 text-xs whitespace-nowrap text-white bg-indigo-700`}>
|
||||
|
||||
<div className='font-light'>{selected && <i className='mr-1 fa-tag'/>} {tag.name + (tag.count ? `(${tag.count})` : '')} </div>
|
||||
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
export default TagItemMini
|
||||
|
||||
@@ -90,10 +90,13 @@ const TopNav = props => {
|
||||
<section className='mt-8'>
|
||||
<div className='text-sm flex flex-nowrap justify-between font-light px-2'>
|
||||
<div className='text-gray-600 dark:text-gray-200'><i className='mr-2 fas fa-th-list' />{locale.COMMON.CATEGORY}</div>
|
||||
<Link href={'/category'} passHref>
|
||||
<a className='mb-3 text-gray-400 hover:text-black dark:text-gray-400 dark:hover:text-white hover:underline cursor-pointer'>
|
||||
{locale.COMMON.MORE} <i className='fas fa-angle-double-right' />
|
||||
</a>
|
||||
<Link
|
||||
href={'/category'}
|
||||
passHref
|
||||
className='mb-3 text-gray-400 hover:text-black dark:text-gray-400 dark:hover:text-white hover:underline cursor-pointer'>
|
||||
|
||||
{locale.COMMON.MORE} <i className='fas fa-angle-double-right' />
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
<CategoryGroup currentCategory={currentCategory} categories={categories} />
|
||||
@@ -104,10 +107,13 @@ const TopNav = props => {
|
||||
<section className='mt-4'>
|
||||
<div className='text-sm py-2 px-2 flex flex-nowrap justify-between font-light dark:text-gray-200'>
|
||||
<div className='text-gray-600 dark:text-gray-200'><i className='mr-2 fas fa-tag' />{locale.COMMON.TAGS}</div>
|
||||
<Link href={'/tag'} passHref>
|
||||
<a className='text-gray-400 hover:text-black dark:hover:text-white hover:underline cursor-pointer'>
|
||||
{locale.COMMON.MORE} <i className='fas fa-angle-double-right' />
|
||||
</a>
|
||||
<Link
|
||||
href={'/tag'}
|
||||
passHref
|
||||
className='text-gray-400 hover:text-black dark:hover:text-white hover:underline cursor-pointer'>
|
||||
|
||||
{locale.COMMON.MORE} <i className='fas fa-angle-double-right' />
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
<div className='p-2'>
|
||||
@@ -117,39 +123,41 @@ const TopNav = props => {
|
||||
)}
|
||||
</>
|
||||
|
||||
return (<div id='top-nav'>
|
||||
<SearchDrawer cRef={searchDrawer} slot={searchDrawerSlot} />
|
||||
return (
|
||||
<div id='top-nav'>
|
||||
<SearchDrawer cRef={searchDrawer} slot={searchDrawerSlot} />
|
||||
|
||||
{/* 导航栏 */}
|
||||
<div id='sticky-nav' className={'flex justify-center top-0 shadow-black shadow-sm fixed bg-none animate__animated animate__fadeIn dark:bg-hexo-black-gray text-gray-200 w-full z-30 transform duration-200'}>
|
||||
<div className='w-full max-w-6xl flex justify-between items-center px-4 py-2'>
|
||||
{/* 左侧功能 */}
|
||||
<div className='justify-start items-center block lg:hidden '>
|
||||
<div onClick={toggleMenuOpen} className='w-8 justify-center items-center h-8 cursor-pointer flex lg:hidden'>
|
||||
{isOpen ? <i className='fas fa-times' /> : <i className='fas fa-bars' />}
|
||||
{/* 导航栏 */}
|
||||
<div id='sticky-nav' className={'flex justify-center top-0 shadow-black shadow-sm fixed bg-none animate__animated animate__fadeIn dark:bg-hexo-black-gray text-gray-200 w-full z-30 transform duration-200'}>
|
||||
<div className='w-full max-w-6xl flex justify-between items-center px-4 py-2'>
|
||||
{/* 左侧功能 */}
|
||||
<div className='justify-start items-center block lg:hidden '>
|
||||
<div onClick={toggleMenuOpen} className='w-8 justify-center items-center h-8 cursor-pointer flex lg:hidden'>
|
||||
{isOpen ? <i className='fas fa-times' /> : <i className='fas fa-bars' />}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='flex'>
|
||||
<Logo {...props} />
|
||||
</div>
|
||||
|
||||
{/* 右侧功能 */}
|
||||
<div className='mr-1 justify-end items-center '>
|
||||
<div className='hidden lg:flex'> <MenuButtonGroupTop {...props} /></div>
|
||||
<div className='block lg:hidden'><Link href={'/search'} passHref>
|
||||
<i className='fas fa-search' />
|
||||
</Link></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='flex'>
|
||||
<Logo {...props} />
|
||||
</div>
|
||||
|
||||
{/* 右侧功能 */}
|
||||
<div className='mr-1 justify-end items-center '>
|
||||
<div className='hidden lg:flex'> <MenuButtonGroupTop {...props} /></div>
|
||||
<div className='block lg:hidden'><Link href={'/search'}>
|
||||
<a><i className='fas fa-search' /></a>
|
||||
</Link></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<SideBarDrawer isOpen={isOpen} onClose={toggleMenuClose}>
|
||||
<SideBar {...props} />
|
||||
</SideBarDrawer>
|
||||
|
||||
</div>
|
||||
|
||||
<SideBarDrawer isOpen={isOpen} onClose={toggleMenuClose}>
|
||||
<SideBar {...props} />
|
||||
</SideBarDrawer>
|
||||
|
||||
</div>)
|
||||
)
|
||||
}
|
||||
|
||||
export default TopNav
|
||||
|
||||
@@ -47,10 +47,10 @@ export const LayoutArchive = props => {
|
||||
<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>
|
||||
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||
|
||||
{post.title}
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
</li>
|
||||
@@ -60,5 +60,5 @@ export const LayoutArchive = props => {
|
||||
))}
|
||||
</div>
|
||||
</LayoutBase>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,21 +5,29 @@ import LayoutBase from './LayoutBase'
|
||||
export const LayoutCategoryIndex = (props) => {
|
||||
const { categories } = props
|
||||
const { locale } = useGlobal()
|
||||
return <LayoutBase {...props}>
|
||||
<div className='bg-white dark:bg-gray-700 py-10'>
|
||||
<div className='dark:text-gray-200 mb-5'>
|
||||
<i className='mr-4 fas fa-th' />{locale.COMMON.CATEGORY}:
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<div className='bg-white dark:bg-gray-700 py-10'>
|
||||
<div className='dark:text-gray-200 mb-5'>
|
||||
<i className='mr-4 fas fa-th' />{locale.COMMON.CATEGORY}:
|
||||
</div>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{categories && categories.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<div
|
||||
className={'hover:text-black dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'}>
|
||||
<i className='mr-4 fas fa-folder' />{category.name}({category.count})
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{categories && categories.map(category => {
|
||||
return <Link key={category.name} href={`/category/${category.name}`} passHref>
|
||||
<div
|
||||
className={'hover:text-black dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'}>
|
||||
<i className='mr-4 fas fa-folder' />{category.name}({category.count})
|
||||
</div>
|
||||
</Link>
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,16 +9,24 @@ export default function ArticleAround ({ prev, next }) {
|
||||
if (!prev || !next) {
|
||||
return <></>
|
||||
}
|
||||
return <section className='text-gray-800 dark:text-gray-400 h-12 flex items-center justify-between space-x-5 my-4'>
|
||||
<Link href={`/${prev.slug}`} passHref>
|
||||
<a className='text-sm cursor-pointer justify-start items-center flex hover:underline duration-300'>
|
||||
return (
|
||||
<section className='text-gray-800 dark:text-gray-400 h-12 flex items-center justify-between space-x-5 my-4'>
|
||||
<Link
|
||||
href={`/${prev.slug}`}
|
||||
passHref
|
||||
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={`/${next.slug}`} passHref>
|
||||
<a className='text-sm cursor-pointer justify-end items-center flex hover:underline duration-300'>{next.title}
|
||||
|
||||
</Link>
|
||||
<Link
|
||||
href={`/${next.slug}`}
|
||||
passHref
|
||||
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>
|
||||
</Link>
|
||||
</section>
|
||||
|
||||
</Link>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,59 +18,61 @@ export const ArticleDetail = props => {
|
||||
post?.date?.start_date || post?.createdTime,
|
||||
locale.LOCALE
|
||||
)
|
||||
return <div id='container'>
|
||||
return (
|
||||
<div id='container'>
|
||||
|
||||
{/* title */}
|
||||
<h1 className="text-3xl pt-12 font-sans dark:text-gray-300">{post?.title}</h1>
|
||||
{/* title */}
|
||||
<h1 className="text-3xl pt-12 font-sans dark:text-gray-300">{post?.title}</h1>
|
||||
|
||||
{/* meta */}
|
||||
<section className="py-2 items-center text-sm font-sans px-1">
|
||||
<div className='flex flex-wrap text-gray-500 py-1 dark:text-gray-600'>
|
||||
<span className='whitespace-nowrap'> <i className='far fa-calendar mr-2' />{date}</span>
|
||||
<span className='mx-1'>|</span>
|
||||
<span className='whitespace-nowrap mr-2'><i className='far fa-calendar-check mr-2'/>{post.lastEditedTime}</span>
|
||||
<div className="hidden busuanzi_container_page_pv font-light mr-2 whitespace-nowrap">
|
||||
<i className="mr-1 fas fa-eye" /><span className="busuanzi_value_page_pv" />
|
||||
</div>
|
||||
</div>
|
||||
<Link href="/about" passHref>
|
||||
<div className='flex pt-2'>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img src={siteInfo?.icon} className='rounded-full cursor-pointer' width={22} alt={BLOG.AUTHOR} />
|
||||
|
||||
<div className="mr-3 ml-2 my-auto text-green-500 cursor-pointer">
|
||||
{BLOG.AUTHOR}
|
||||
{/* meta */}
|
||||
<section className="py-2 items-center text-sm font-sans px-1">
|
||||
<div className='flex flex-wrap text-gray-500 py-1 dark:text-gray-600'>
|
||||
<span className='whitespace-nowrap'> <i className='far fa-calendar mr-2' />{date}</span>
|
||||
<span className='mx-1'>|</span>
|
||||
<span className='whitespace-nowrap mr-2'><i className='far fa-calendar-check mr-2'/>{post.lastEditedTime}</span>
|
||||
<div className="hidden busuanzi_container_page_pv font-light mr-2 whitespace-nowrap">
|
||||
<i className="mr-1 fas fa-eye" /><span className="busuanzi_value_page_pv" />
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</section>
|
||||
{/* Notion文章主体 */}
|
||||
<section id="notion-article" className="px-1 max-w-5xl">
|
||||
{post && (<NotionPage post={post} />)}
|
||||
</section>
|
||||
<Link href="/about" passHref legacyBehavior>
|
||||
<div className='flex pt-2'>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img src={siteInfo?.icon} className='rounded-full cursor-pointer' width={22} alt={BLOG.AUTHOR} />
|
||||
|
||||
<section className="px-1 py-2 my-1 text-sm font-light overflow-auto text-gray-600 dark:text-gray-400">
|
||||
{/* 文章内嵌广告 */}
|
||||
<ins
|
||||
className="adsbygoogle"
|
||||
style={{ display: 'block', textAlign: 'center' }}
|
||||
data-adtest="on"
|
||||
data-ad-layout="in-article"
|
||||
data-ad-format="fluid"
|
||||
data-ad-client="ca-pub-2708419466378217"
|
||||
data-ad-slot="3806269138"
|
||||
/>
|
||||
</section>
|
||||
<div className="mr-3 ml-2 my-auto text-green-500 cursor-pointer">
|
||||
{BLOG.AUTHOR}
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</section>
|
||||
{/* Notion文章主体 */}
|
||||
<section id="notion-article" className="px-1 max-w-5xl">
|
||||
{post && (<NotionPage post={post} />)}
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div className='flex justify-between'>
|
||||
{CONFIG_MEDIUM.POST_DETAIL_CATEGORY && post.category && <CategoryItem category={post.category} />}
|
||||
<div>
|
||||
{CONFIG_MEDIUM.POST_DETAIL_TAG && post?.tagItems?.map(tag => <TagItemMini key={tag.name} tag={tag} />)}
|
||||
<section className="px-1 py-2 my-1 text-sm font-light overflow-auto text-gray-600 dark:text-gray-400">
|
||||
{/* 文章内嵌广告 */}
|
||||
<ins
|
||||
className="adsbygoogle"
|
||||
style={{ display: 'block', textAlign: 'center' }}
|
||||
data-adtest="on"
|
||||
data-ad-layout="in-article"
|
||||
data-ad-format="fluid"
|
||||
data-ad-client="ca-pub-2708419466378217"
|
||||
data-ad-slot="3806269138"
|
||||
/>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div className='flex justify-between'>
|
||||
{CONFIG_MEDIUM.POST_DETAIL_CATEGORY && post.category && <CategoryItem category={post.category} />}
|
||||
<div>
|
||||
{CONFIG_MEDIUM.POST_DETAIL_TAG && post?.tagItems?.map(tag => <TagItemMini key={tag.name} tag={tag} />)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{post.type === 'Post' && <ArticleAround prev={prev} next={next} />}
|
||||
<Comment frontMatter={post} />
|
||||
</section>
|
||||
</div>
|
||||
{post.type === 'Post' && <ArticleAround prev={prev} next={next} />}
|
||||
<Comment frontMatter={post} />
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -16,14 +16,15 @@ 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:py-8 py-4 flex flex-col w-full">
|
||||
<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-300 hover:text-green-500 dark:hover:text-green-400'
|
||||
}
|
||||
>
|
||||
{post.title}
|
||||
</a>
|
||||
<Link
|
||||
href={`${BLOG.SUB_PATH}/${post.slug}`}
|
||||
passHref
|
||||
className={
|
||||
'cursor-pointer font-bold font-sans hover:underline text-3xl leading-tight text-gray-700 dark:text-gray-300 hover:text-green-500 dark:hover:text-green-400'
|
||||
}>
|
||||
|
||||
{post.title}
|
||||
|
||||
</Link>
|
||||
|
||||
<div
|
||||
@@ -54,11 +55,14 @@ 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}/${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" />
|
||||
</a>
|
||||
<Link
|
||||
href={`${BLOG.SUB_PATH}/${post.slug}`}
|
||||
passHref
|
||||
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" />
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
@@ -66,7 +70,7 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default BlogPostCard
|
||||
|
||||
@@ -6,12 +6,12 @@ export default function BottomMenuBar ({ className }) {
|
||||
return (
|
||||
<div className={'sticky bottom-0 w-full h-12 bg-white dark:bg-hexo-black-gray ' + className}>
|
||||
<div className='flex justify-between h-full shadow-card'>
|
||||
<Link href='/' passHref>
|
||||
<Link href='/' passHref legacyBehavior>
|
||||
<div className='flex w-full items-center justify-center cursor-pointer'>
|
||||
<i className='fas fa-home' />
|
||||
</div>
|
||||
</Link>
|
||||
<Link href='/search' passHref>
|
||||
<Link href='/search' passHref legacyBehavior>
|
||||
<div className='flex w-full items-center justify-center cursor-pointer'>
|
||||
<i className='fas fa-search'/>
|
||||
</div>
|
||||
@@ -21,5 +21,5 @@ export default function BottomMenuBar ({ className }) {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
import Link from 'next/link'
|
||||
|
||||
export default function CategoryItem ({ selected, category, categoryCount }) {
|
||||
return <Link href={`/category/${category}`} passHref>
|
||||
<a className={(selected
|
||||
? 'hover:text-white dark:hover:text-white bg-green-600 text-white '
|
||||
: 'dark:text-green-400 text-gray-500 hover:text-white dark:hover:text-white hover:bg-green-600') +
|
||||
' flex text-sm items-center duration-300 cursor-pointer py-1 font-light px-2 whitespace-nowrap'}>
|
||||
return (
|
||||
<Link
|
||||
href={`/category/${category}`}
|
||||
passHref
|
||||
className={(selected
|
||||
? 'hover:text-white dark:hover:text-white bg-green-600 text-white '
|
||||
: 'dark:text-green-400 text-gray-500 hover:text-white dark:hover:text-white hover:bg-green-600') +
|
||||
' flex text-sm items-center duration-300 cursor-pointer py-1 font-light px-2 whitespace-nowrap'}>
|
||||
|
||||
<div><i className={`mr-2 fas ${selected ? 'fa-folder-open' : 'fa-folder'}`} />{category} {categoryCount && `(${categoryCount})`}
|
||||
</div>
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,24 +20,32 @@ function GroupMenu ({ customNav }) {
|
||||
links = links.concat(customNav)
|
||||
}
|
||||
|
||||
return <nav id='nav' className='font-sans text-md'>
|
||||
{links.map(link => {
|
||||
if (link.show) {
|
||||
const selected = (router.pathname === link.to) || (router.asPath === link.to)
|
||||
return <Link key={`${link.to}`} title={link.to} href={link.to} >
|
||||
<a className={'py-0.5 duration-500 justify-between text-gray-500 dark:text-gray-300 hover:text-black hover:underline cursor-pointer flex flex-nowrap items-center ' +
|
||||
(selected ? 'text-black' : ' ')} >
|
||||
<div className='my-auto items-center justify-center flex '>
|
||||
<div className={ 'hover:text-black'}>{link.name}</div>
|
||||
</div>
|
||||
{link.slot}
|
||||
</a>
|
||||
</Link>
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})}
|
||||
</nav>
|
||||
return (
|
||||
<nav id='nav' className='font-sans text-md'>
|
||||
{links.map(link => {
|
||||
if (link.show) {
|
||||
const selected = (router.pathname === link.to) || (router.asPath === link.to)
|
||||
return (
|
||||
<Link
|
||||
key={`${link.to}`}
|
||||
title={link.to}
|
||||
href={link.to}
|
||||
className={'py-0.5 duration-500 justify-between text-gray-500 dark:text-gray-300 hover:text-black hover:underline cursor-pointer flex flex-nowrap items-center ' +
|
||||
(selected ? 'text-black' : ' ')}>
|
||||
|
||||
<div className='my-auto items-center justify-center flex '>
|
||||
<div className={ 'hover:text-black'}>{link.name}</div>
|
||||
</div>
|
||||
{link.slot}
|
||||
|
||||
</Link>
|
||||
);
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})}
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
|
||||
export default GroupMenu
|
||||
|
||||
@@ -2,13 +2,15 @@ import Link from 'next/link'
|
||||
import React from 'react'
|
||||
|
||||
export default function LeftMenuBar () {
|
||||
return <div className='w-20 border-r hidden lg:block pt-12'>
|
||||
<section>
|
||||
<Link href='/'>
|
||||
<div className='text-center cursor-pointer hover:text-black'>
|
||||
<i className='fas fa-home text-gray-500'/>
|
||||
</div>
|
||||
</Link>
|
||||
</section>
|
||||
</div>
|
||||
return (
|
||||
<div className='w-20 border-r hidden lg:block pt-12'>
|
||||
<section>
|
||||
<Link href='/' legacyBehavior>
|
||||
<div className='text-center cursor-pointer hover:text-black'>
|
||||
<i className='fas fa-home text-gray-500'/>
|
||||
</div>
|
||||
</Link>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ import Link from 'next/link'
|
||||
|
||||
export default function LogoBar (props) {
|
||||
const { siteInfo } = props
|
||||
return <div id='top-wrapper' className='w-full flex items-center font-sans'>
|
||||
<Link href='/'>
|
||||
<a className='text-md md:text-xl dark:text-gray-200'>{siteInfo?.title}</a>
|
||||
</Link>
|
||||
</div>
|
||||
return (
|
||||
<div id='top-wrapper' className='w-full flex items-center font-sans'>
|
||||
<Link href='/' className='text-md md:text-xl dark:text-gray-200'>
|
||||
{siteInfo?.title}
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -27,15 +27,12 @@ const PaginationSimple = ({ page, totalPage }) => {
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
passHref
|
||||
>
|
||||
<a
|
||||
rel="prev"
|
||||
className={`${
|
||||
currentPage === 1 ? 'invisible' : 'block'
|
||||
} text-center w-full duration-200 px-4 py-2 hover:border-green-500 border-b-2 hover:font-bold`}
|
||||
>
|
||||
← {locale.PAGINATION.PREV}
|
||||
</a>
|
||||
rel="prev"
|
||||
className={`${
|
||||
currentPage === 1 ? 'invisible' : 'block'
|
||||
} text-center w-full duration-200 px-4 py-2 hover:border-green-500 border-b-2 hover:font-bold`}>
|
||||
←{locale.PAGINATION.PREV}
|
||||
|
||||
</Link>
|
||||
<Link
|
||||
href={{
|
||||
@@ -43,18 +40,15 @@ const PaginationSimple = ({ page, totalPage }) => {
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
passHref
|
||||
>
|
||||
<a
|
||||
rel="next"
|
||||
className={`${
|
||||
+showNext ? 'block' : 'invisible'
|
||||
} text-center w-full duration-200 px-4 py-2 hover:border-green-500 border-b-2 hover:font-bold`}
|
||||
>
|
||||
{locale.PAGINATION.NEXT} →
|
||||
</a>
|
||||
rel="next"
|
||||
className={`${
|
||||
+showNext ? 'block' : 'invisible'
|
||||
} text-center w-full duration-200 px-4 py-2 hover:border-green-500 border-b-2 hover:font-bold`}>
|
||||
|
||||
{locale.PAGINATION.NEXT}→
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default PaginationSimple
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
import Link from 'next/link'
|
||||
|
||||
const TagItemMini = ({ tag, selected = false }) => {
|
||||
return <Link key={tag} href={selected ? '/' : `/tag/${encodeURIComponent(tag.name)}`} passHref>
|
||||
<a className={`cursor-pointer inline-block rounded hover:bg-gray-500 hover:text-white duration-200
|
||||
mr-2 py-1 px-2 text-xs whitespace-nowrap dark:hover:text-white
|
||||
${selected
|
||||
? 'text-white dark:text-gray-300 bg-black dark:bg-black dark:hover:bg-gray-900'
|
||||
: `text-gray-600 hover:shadow-xl dark:border-gray-400 notion-${tag.color}_background dark:bg-gray-800`}` }>
|
||||
<div className='font-light dark:text-gray-400'>{selected && <i className='mr-1 fas fa-tag'/>} {tag.name + (tag.count ? `(${tag.count})` : '')} </div>
|
||||
</a>
|
||||
</Link>
|
||||
return (
|
||||
<Link
|
||||
key={tag}
|
||||
href={selected ? '/' : `/tag/${encodeURIComponent(tag.name)}`}
|
||||
passHref
|
||||
className={`cursor-pointer inline-block rounded hover:bg-gray-500 hover:text-white duration-200
|
||||
mr-2 py-1 px-2 text-xs whitespace-nowrap dark:hover:text-white
|
||||
${selected
|
||||
? 'text-white dark:text-gray-300 bg-black dark:bg-black dark:hover:bg-gray-900'
|
||||
: `text-gray-600 hover:shadow-xl dark:border-gray-400 notion-${tag.color}_background dark:bg-gray-800`}` }>
|
||||
|
||||
<div className='font-light dark:text-gray-400'>{selected && <i className='mr-1 fas fa-tag'/>} {tag.name + (tag.count ? `(${tag.count})` : '')} </div>
|
||||
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
export default TagItemMini
|
||||
|
||||
@@ -32,46 +32,55 @@ export default function TopNavBar(props) {
|
||||
changeShow(!isOpen)
|
||||
}
|
||||
|
||||
return <div id='top-nav' className={'sticky top-0 lg:relative w-full z-40 ' + className}>
|
||||
{/* 折叠菜单 */}
|
||||
<Collapse type='vertical' isOpen={isOpen} className='md:hidden'>
|
||||
<div className='bg-white dark:bg-hexo-black-gray pt-1 py-2 px-7 lg:hidden '>
|
||||
<GroupMenu {...props} />
|
||||
</div>
|
||||
</Collapse>
|
||||
|
||||
<div className='flex w-full h-12 shadow bg-white dark:bg-hexo-black-gray px-7 items-between'>
|
||||
|
||||
{/* 图标Logo */}
|
||||
<LogoBar {...props} />
|
||||
|
||||
{/* 右侧功能 */}
|
||||
<div className='mr-1 flex md:hidden justify-end items-center text-sm space-x-4 font-serif dark:text-gray-200'>
|
||||
<div onClick={toggleMenuOpen} className='cursor-pointer'>
|
||||
{isOpen ? <i className='fas fa-times' /> : <i className='fas fa-bars' />}
|
||||
return (
|
||||
<div id='top-nav' className={'sticky top-0 lg:relative w-full z-40 ' + className}>
|
||||
{/* 折叠菜单 */}
|
||||
<Collapse type='vertical' isOpen={isOpen} className='md:hidden'>
|
||||
<div className='bg-white dark:bg-hexo-black-gray pt-1 py-2 px-7 lg:hidden '>
|
||||
<GroupMenu {...props} />
|
||||
</div>
|
||||
</div>
|
||||
</Collapse>
|
||||
|
||||
<div className='flex w-full h-12 shadow bg-white dark:bg-hexo-black-gray px-7 items-between'>
|
||||
|
||||
{/* 图标Logo */}
|
||||
<LogoBar {...props} />
|
||||
|
||||
{/* 右侧功能 */}
|
||||
<div className='mr-1 flex md:hidden justify-end items-center text-sm space-x-4 font-serif dark:text-gray-200'>
|
||||
<div onClick={toggleMenuOpen} className='cursor-pointer'>
|
||||
{isOpen ? <i className='fas fa-times' /> : <i className='fas fa-bars' />}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 顶部菜单 */}
|
||||
<div className='hidden md:flex'>
|
||||
{navs && navs.map(link => {
|
||||
if (link?.show) {
|
||||
const selected = (router.pathname === link.to) || (router.asPath === link.to)
|
||||
return (
|
||||
<Link
|
||||
key={`${link.id}-${link.to}`}
|
||||
title={link.to}
|
||||
href={link.to}
|
||||
target={link.to.indexOf('http') === 0 ? '_blank' : '_self'}
|
||||
className={'px-2 duration-300 text-sm justify-between dark:text-gray-300 cursor-pointer flex flex-nowrap items-center ' +
|
||||
(selected ? 'bg-green-600 text-white hover:text-white' : 'hover:text-green-600')}>
|
||||
|
||||
{/* 顶部菜单 */}
|
||||
<div className='hidden md:flex'>
|
||||
{navs && navs.map(link => {
|
||||
if (link?.show) {
|
||||
const selected = (router.pathname === link.to) || (router.asPath === link.to)
|
||||
return <Link key={`${link.id}-${link.to}`} title={link.to} href={link.to} >
|
||||
<a target={link.to.indexOf('http') === 0 ? '_blank' : '_self'} className={'px-2 duration-300 text-sm justify-between dark:text-gray-300 cursor-pointer flex flex-nowrap items-center ' +
|
||||
(selected ? 'bg-green-600 text-white hover:text-white' : 'hover:text-green-600')} >
|
||||
<div className='items-center justify-center flex '>
|
||||
<i className={link.icon} />
|
||||
<div className='ml-2 whitespace-nowrap'>{link.name}</div>
|
||||
</div>
|
||||
{link.slot}
|
||||
</a>
|
||||
</Link>
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})}
|
||||
|
||||
</Link>
|
||||
);
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,21 +5,29 @@ import Link from 'next/link'
|
||||
export const LayoutCategoryIndex = (props) => {
|
||||
const { allPosts, categories } = props
|
||||
const { locale } = useGlobal()
|
||||
return <LayoutBase totalPosts={allPosts} {...props}>
|
||||
<div className='bg-white dark:bg-hexo-black-gray px-10 py-10 shadow h-full'>
|
||||
<div className='dark:text-gray-200 mb-5'>
|
||||
<i className='mr-4 fas faTh' />{locale.COMMON.CATEGORY}:
|
||||
return (
|
||||
<LayoutBase totalPosts={allPosts} {...props}>
|
||||
<div className='bg-white dark:bg-hexo-black-gray px-10 py-10 shadow h-full'>
|
||||
<div className='dark:text-gray-200 mb-5'>
|
||||
<i className='mr-4 fas faTh' />{locale.COMMON.CATEGORY}:
|
||||
</div>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{categories.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<div
|
||||
className={'hover:text-black dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'}>
|
||||
<i className='mr-4 fas fa-folder' />{category.name}({category.count})
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{categories.map(category => {
|
||||
return <Link key={category.name} href={`/category/${category.name}`} passHref>
|
||||
<div
|
||||
className={'hover:text-black dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'}>
|
||||
<i className='mr-4 fas fa-folder' />{category.name}({category.count})
|
||||
</div>
|
||||
</Link>
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
</LayoutBase>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,24 +7,26 @@ export default function ArticleCopyright ({ author, url }) {
|
||||
return <></>
|
||||
}
|
||||
const { locale } = useGlobal()
|
||||
return <section className="dark:text-gray-300 mt-6">
|
||||
<ul className="overflow-x-auto whitespace-nowrap text-sm dark:bg-gray-700 bg-gray-100 p-5 leading-8 border-l-2 border-blue-500">
|
||||
<li>
|
||||
<strong className='mr-2'>{locale.COMMON.AUTHOR}:</strong>
|
||||
<Link href={'/about'} >
|
||||
<a className="hover:underline">{author}</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<strong className='mr-2'>{locale.COMMON.URL}:</strong>
|
||||
<a className="hover:underline" href={url}>
|
||||
{url}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<strong className='mr-2'>{locale.COMMON.COPYRIGHT}:</strong>
|
||||
{locale.COMMON.COPYRIGHT_NOTICE}
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
return (
|
||||
<section className="dark:text-gray-300 mt-6">
|
||||
<ul className="overflow-x-auto whitespace-nowrap text-sm dark:bg-gray-700 bg-gray-100 p-5 leading-8 border-l-2 border-blue-500">
|
||||
<li>
|
||||
<strong className='mr-2'>{locale.COMMON.AUTHOR}:</strong>
|
||||
<Link href={'/about'} className="hover:underline">
|
||||
{author}
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<strong className='mr-2'>{locale.COMMON.URL}:</strong>
|
||||
<a className="hover:underline" href={url}>
|
||||
{url}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<strong className='mr-2'>{locale.COMMON.COPYRIGHT}:</strong>
|
||||
{locale.COMMON.COPYRIGHT_NOTICE}
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -25,115 +25,120 @@ export default function ArticleDetail(props) {
|
||||
const { locale } = useGlobal()
|
||||
const date = formatDate(post?.date?.start_date || post?.createdTime, locale.LOCALE)
|
||||
|
||||
return (<div id="container"
|
||||
data-aos="fade-down"
|
||||
data-aos-duration="600"
|
||||
data-aos-easing="ease-in-out"
|
||||
data-aos-once="false"
|
||||
data-aos-anchor-placement="top-bottom"
|
||||
return (
|
||||
<div id="container"
|
||||
data-aos="fade-down"
|
||||
data-aos-duration="600"
|
||||
data-aos-easing="ease-in-out"
|
||||
data-aos-once="false"
|
||||
data-aos-anchor-placement="top-bottom"
|
||||
|
||||
className="shadow md:hover:shadow-2xl overflow-x-auto flex-grow mx-auto w-screen md:w-full ">
|
||||
<div itemScope itemType="https://schema.org/Movie"
|
||||
className="subpixel-antialiased py-10 px-5 lg:pt-24 md:px-24 dark:border-gray-700 bg-white dark:bg-hexo-black-gray"
|
||||
>
|
||||
className="shadow md:hover:shadow-2xl overflow-x-auto flex-grow mx-auto w-screen md:w-full ">
|
||||
<div itemScope itemType="https://schema.org/Movie"
|
||||
className="subpixel-antialiased py-10 px-5 lg:pt-24 md:px-24 dark:border-gray-700 bg-white dark:bg-hexo-black-gray"
|
||||
>
|
||||
|
||||
{showArticleInfo && <header className='animate__slideInDown animate__animated'>
|
||||
{/* 头图 */}
|
||||
{CONFIG_NEXT.POST_HEADER_IMAGE_VISIBLE && post?.type && !post?.type !== 'Page' && post?.page_cover && (
|
||||
<div className="w-full relative md:flex-shrink-0 overflow-hidden">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img alt={post.title} src={post?.page_cover} className='object-center w-full' />
|
||||
{showArticleInfo && <header className='animate__slideInDown animate__animated'>
|
||||
{/* 头图 */}
|
||||
{CONFIG_NEXT.POST_HEADER_IMAGE_VISIBLE && post?.type && !post?.type !== 'Page' && post?.page_cover && (
|
||||
<div className="w-full relative md:flex-shrink-0 overflow-hidden">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img alt={post.title} src={post?.page_cover} className='object-center w-full' />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* title */}
|
||||
<div className=" text-center font-bold text-3xl text-black dark:text-white font-serif pt-6">
|
||||
<NotionIcon icon={post.pageIcon} />{post.title}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* title */}
|
||||
<div className=" text-center font-bold text-3xl text-black dark:text-white font-serif pt-6">
|
||||
<NotionIcon icon={post.pageIcon} />{post.title}
|
||||
</div>
|
||||
{/* meta */}
|
||||
<section className="mt-2 text-gray-400 dark:text-gray-400 font-light leading-7 text-sm">
|
||||
<div className='flex flex-wrap justify-center'>
|
||||
{post?.type !== 'Page' && (<>
|
||||
<Link
|
||||
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<div className="pl-1 mr-2 cursor-pointer hover:text-gray-700 dark:hover:text-gray-200 border-b dark:border-gray-500 border-dashed">
|
||||
<i className='far fa-calendar mr-1' /> {date}
|
||||
</div>
|
||||
</Link>
|
||||
<span className='mr-2'> | <i className='far fa-calendar-check mr-2' />{post.lastEditedTime} </span>
|
||||
|
||||
{/* meta */}
|
||||
<section className="mt-2 text-gray-400 dark:text-gray-400 font-light leading-7 text-sm">
|
||||
<div className='flex flex-wrap justify-center'>
|
||||
{post?.type !== 'Page' && (<>
|
||||
<Link href={`/archive#${post?.date?.start_date?.substr(0, 7)}`} passHref>
|
||||
<div className="pl-1 mr-2 cursor-pointer hover:text-gray-700 dark:hover:text-gray-200 border-b dark:border-gray-500 border-dashed">
|
||||
<i className='far fa-calendar mr-1' /> {date}
|
||||
<div className="hidden busuanzi_container_page_pv font-light mr-2">
|
||||
<i className='mr-1 fas fa-eye' />
|
||||
<span className="mr-2 busuanzi_value_page_pv" />
|
||||
</div>
|
||||
</Link>
|
||||
<span className='mr-2'> | <i className='far fa-calendar-check mr-2' />{post.lastEditedTime} </span>
|
||||
|
||||
<div className="hidden busuanzi_container_page_pv font-light mr-2">
|
||||
<i className='mr-1 fas fa-eye' />
|
||||
<span className="mr-2 busuanzi_value_page_pv" />
|
||||
</div>
|
||||
|
||||
</>)}
|
||||
</div>
|
||||
|
||||
<WordCount />
|
||||
</section>
|
||||
|
||||
</header>}
|
||||
|
||||
{/* Notion内容主体 */}
|
||||
<article id='notion-article' className='px-1'>
|
||||
{post && (<NotionPage post={post} />)}
|
||||
</article>
|
||||
|
||||
<section className="px-1 py-2 my-1 text-sm font-light overflow-auto text-gray-600 dark:text-gray-400">
|
||||
{/* 文章内嵌广告 */}
|
||||
<ins className="adsbygoogle"
|
||||
style={{ display: 'block', textAlign: 'center' }}
|
||||
data-adtest="on"
|
||||
data-ad-layout="in-article"
|
||||
data-ad-format="fluid"
|
||||
data-ad-client="ca-pub-2708419466378217"
|
||||
data-ad-slot="3806269138" />
|
||||
</section>
|
||||
|
||||
{showArticleInfo && <>
|
||||
{/* 版权声明 */}
|
||||
{post.type === 'Post' && <ArticleCopyright author={BLOG.AUTHOR} url={url} />}
|
||||
|
||||
{/* 推荐文章 */}
|
||||
{post.type === 'Post' && <RecommendPosts currentPost={post} recommendPosts={recommendPosts} />}
|
||||
|
||||
<section className="flex justify-between">
|
||||
{/* 分类 */}
|
||||
{post.category && <>
|
||||
<div className="cursor-pointer my-auto text-md mr-2 hover:text-black dark:hover:text-white border-b dark:text-gray-500 border-dashed">
|
||||
<Link href={`/category/${post.category}`} passHref>
|
||||
<><i className="mr-1 far fa-folder-open" /> {post.category}</>
|
||||
</Link>
|
||||
</>)}
|
||||
</div>
|
||||
|
||||
</>}
|
||||
<WordCount />
|
||||
</section>
|
||||
|
||||
{/* 标签列表 */}
|
||||
{post.type === 'Post' && (
|
||||
<>
|
||||
{post.tagItems && (
|
||||
<div className="flex flex-nowrap leading-8 p-1 py-4 overflow-x-auto">
|
||||
<div className="hidden md:block dark:text-gray-300 whitespace-nowrap">
|
||||
{locale.COMMON.TAGS}:
|
||||
</div>
|
||||
{post.tagItems.map(tag => (
|
||||
<TagItem key={tag.name} tag={tag} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<ShareBar post={post} />
|
||||
</>
|
||||
)}
|
||||
</header>}
|
||||
|
||||
{/* Notion内容主体 */}
|
||||
<article id='notion-article' className='px-1'>
|
||||
{post && (<NotionPage post={post} />)}
|
||||
</article>
|
||||
|
||||
<section className="px-1 py-2 my-1 text-sm font-light overflow-auto text-gray-600 dark:text-gray-400">
|
||||
{/* 文章内嵌广告 */}
|
||||
<ins className="adsbygoogle"
|
||||
style={{ display: 'block', textAlign: 'center' }}
|
||||
data-adtest="on"
|
||||
data-ad-layout="in-article"
|
||||
data-ad-format="fluid"
|
||||
data-ad-client="ca-pub-2708419466378217"
|
||||
data-ad-slot="3806269138" />
|
||||
</section>
|
||||
{post.type === 'Post' && <BlogAround prev={prev} next={next} />}
|
||||
</>}
|
||||
|
||||
{/* 评论互动 */}
|
||||
<div className="duration-200 w-full dark:border-gray-700 bg-white dark:bg-hexo-black-gray">
|
||||
<Comment frontMatter={post} />
|
||||
{showArticleInfo && <>
|
||||
{/* 版权声明 */}
|
||||
{post.type === 'Post' && <ArticleCopyright author={BLOG.AUTHOR} url={url} />}
|
||||
|
||||
{/* 推荐文章 */}
|
||||
{post.type === 'Post' && <RecommendPosts currentPost={post} recommendPosts={recommendPosts} />}
|
||||
|
||||
<section className="flex justify-between">
|
||||
{/* 分类 */}
|
||||
{post.category && <>
|
||||
<div className="cursor-pointer my-auto text-md mr-2 hover:text-black dark:hover:text-white border-b dark:text-gray-500 border-dashed">
|
||||
<Link href={`/category/${post.category}`} passHref legacyBehavior>
|
||||
<><i className="mr-1 far fa-folder-open" /> {post.category}</>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
</>}
|
||||
|
||||
{/* 标签列表 */}
|
||||
{post.type === 'Post' && (
|
||||
<>
|
||||
{post.tagItems && (
|
||||
<div className="flex flex-nowrap leading-8 p-1 py-4 overflow-x-auto">
|
||||
<div className="hidden md:block dark:text-gray-300 whitespace-nowrap">
|
||||
{locale.COMMON.TAGS}:
|
||||
</div>
|
||||
{post.tagItems.map(tag => (
|
||||
<TagItem key={tag.name} tag={tag} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<ShareBar post={post} />
|
||||
</>
|
||||
)}
|
||||
</section>
|
||||
{post.type === 'Post' && <BlogAround prev={prev} next={next} />}
|
||||
</>}
|
||||
|
||||
{/* 评论互动 */}
|
||||
<div className="duration-200 w-full dark:border-gray-700 bg-white dark:bg-hexo-black-gray">
|
||||
<Comment frontMatter={post} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>)
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,16 +9,24 @@ export default function BlogAround ({ prev, next }) {
|
||||
if (!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={`/${prev.slug}`} passHref>
|
||||
<a className='text-sm py-3 text-gray-400 hover:underline cursor-pointer'>
|
||||
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={`/${prev.slug}`}
|
||||
passHref
|
||||
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={`/${next.slug}`} passHref>
|
||||
<a className='text-sm flex py-3 text-gray-400 hover:underline cursor-pointer'>{next.title}
|
||||
|
||||
</Link>}
|
||||
{next && <Link
|
||||
href={`/${next.slug}`}
|
||||
passHref
|
||||
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>
|
||||
</Link>}
|
||||
</section>
|
||||
|
||||
</Link>}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -29,17 +29,20 @@ const BlogPostArchive = ({ posts = [], archiveTitle }) => {
|
||||
<div id={post?.date?.start_date}>
|
||||
<span className="text-gray-400">{post.date?.start_date}</span>{' '}
|
||||
|
||||
<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>
|
||||
<Link
|
||||
href={`${BLOG.SUB_PATH}/${post.slug}`}
|
||||
passHref
|
||||
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||
|
||||
{post.title}
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,13 +19,14 @@ 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}/${post.slug}`} passHref>
|
||||
<a
|
||||
className={`cursor-pointer 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`}
|
||||
>
|
||||
<NotionIcon icon={post.pageIcon} /> {post.title}
|
||||
</a>
|
||||
<Link
|
||||
href={`${BLOG.SUB_PATH}/${post.slug}`}
|
||||
passHref
|
||||
className={`cursor-pointer 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`}>
|
||||
|
||||
<NotionIcon icon={post.pageIcon} /> {post.title}
|
||||
|
||||
</Link>
|
||||
|
||||
<div
|
||||
@@ -35,11 +36,14 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
<div>
|
||||
{post.category && (
|
||||
<>
|
||||
<Link href={`/category/${post.category}`} passHref>
|
||||
<a className="cursor-pointer font-light text-sm hover:underline transform">
|
||||
<i className="mr-1 fas fa-folder" />
|
||||
{post.category}
|
||||
</a>
|
||||
<Link
|
||||
href={`/category/${post.category}`}
|
||||
passHref
|
||||
className="cursor-pointer font-light text-sm hover:underline transform">
|
||||
|
||||
<i className="mr-1 fas fa-folder" />
|
||||
{post.category}
|
||||
|
||||
</Link>
|
||||
<span className="mx-2">|</span>
|
||||
</>
|
||||
@@ -47,10 +51,10 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
<Link
|
||||
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
||||
passHref
|
||||
>
|
||||
<a className="font-light hover:underline cursor-pointer text-sm leading-4 mr-3">
|
||||
{post.date?.start_date}
|
||||
</a>
|
||||
className="font-light hover:underline cursor-pointer text-sm leading-4 mr-3">
|
||||
|
||||
{post.date?.start_date}
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
<div className="md:flex-nowrap flex-wrap md:justify-start inline-block">
|
||||
@@ -85,17 +89,19 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
)}
|
||||
|
||||
<div className="text-right border-t pt-8 border-dashed">
|
||||
<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 cursor-pointer">
|
||||
{locale.COMMON.ARTICLE_DETAIL}
|
||||
<i className="ml-1 fas fa-angle-right" />
|
||||
</a>
|
||||
<Link
|
||||
href={`${BLOG.SUB_PATH}/${post.slug}`}
|
||||
className="hover:bg-opacity-100 hover:underline transform duration-300 p-3 text-white bg-gray-800 cursor-pointer">
|
||||
|
||||
{locale.COMMON.ARTICLE_DETAIL}
|
||||
<i className="ml-1 fas fa-angle-right" />
|
||||
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{CONFIG_NEXT.POST_LIST_COVER && post?.page_cover && (
|
||||
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} passHref>
|
||||
<Link href={`${BLOG.SUB_PATH}/${post.slug}`} passHref legacyBehavior>
|
||||
<div className="h-72 w-full relative duration-200 cursor-pointer transform overflow-hidden">
|
||||
<Image
|
||||
className="hover:scale-105 transform duration-500"
|
||||
@@ -110,7 +116,7 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default BlogPostCard
|
||||
|
||||
@@ -7,17 +7,22 @@ const CategoryGroup = ({ currentCategory, categories }) => {
|
||||
<div id='category-list' className='dark:border-gray-600 flex flex-wrap'>
|
||||
{categories.map(category => {
|
||||
const selected = currentCategory === category.name
|
||||
return <Link key={category.name} href={`/category/${category.name}`} passHref>
|
||||
<a className={(selected
|
||||
? 'hover:text-white dark:hover:text-white bg-gray-600 text-white '
|
||||
: 'dark:text-gray-400 text-gray-500 hover:text-white hover:bg-gray-500 dark:hover:text-white') +
|
||||
' text-sm w-full items-center duration-300 px-2 cursor-pointer py-1 font-light'}>
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
className={(selected
|
||||
? 'hover:text-white dark:hover:text-white bg-gray-600 text-white '
|
||||
: 'dark:text-gray-400 text-gray-500 hover:text-white hover:bg-gray-500 dark:hover:text-white') +
|
||||
' text-sm w-full items-center duration-300 px-2 cursor-pointer py-1 font-light'}>
|
||||
|
||||
<i className={`${selected ? 'text-white fa-folder-open ' : 'text-gray-400 fa-folder '} mr-2 fas`} />{category.name}({category.count})
|
||||
</a>
|
||||
</Link>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
</>;
|
||||
}
|
||||
|
||||
export default CategoryGroup
|
||||
|
||||
@@ -8,27 +8,34 @@ const CategoryList = ({ currentCategory, categories }) => {
|
||||
}
|
||||
const { locale } = useGlobal()
|
||||
|
||||
return <ul className='flex py-1 space-x-3'>
|
||||
<li className='w-16 py-2 dark:text-gray-200 whitespace-nowrap'>{locale.COMMON.CATEGORY}</li>
|
||||
{categories.map(category => {
|
||||
const selected = category.name === currentCategory
|
||||
return (
|
||||
<Link key={category.name} href={`/category/${category.name}`} passHref>
|
||||
<li
|
||||
className={`cursor-pointer border rounded-xl duration-200 mr-1 my-1 px-2 py-1 font-light text-sm whitespace-nowrap dark:text-gray-300
|
||||
${selected
|
||||
? 'text-white bg-gray-500 dark:hover:bg-gray-900 dark:bg-gray-500 dark:border-gray-800'
|
||||
: 'bg-gray-100 text-gray-600 hover:bg-gray-300 dark:hover:bg-gray-700 dark:bg-gray-600 dark:border-gray-600'
|
||||
}`}
|
||||
>
|
||||
<a>
|
||||
<i className={`${selected ? 'fa-folder-open ' : 'fa-folder '} fas mr-1`}/>
|
||||
{`${category.name} (${category.count})`}
|
||||
</a>
|
||||
</li>
|
||||
</Link>)
|
||||
})}
|
||||
</ul>
|
||||
return (
|
||||
<ul className='flex py-1 space-x-3'>
|
||||
<li className='w-16 py-2 dark:text-gray-200 whitespace-nowrap'>{locale.COMMON.CATEGORY}</li>
|
||||
{categories.map(category => {
|
||||
const selected = category.name === currentCategory
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<li
|
||||
className={`cursor-pointer border rounded-xl duration-200 mr-1 my-1 px-2 py-1 font-light text-sm whitespace-nowrap dark:text-gray-300
|
||||
${selected
|
||||
? 'text-white bg-gray-500 dark:hover:bg-gray-900 dark:bg-gray-500 dark:border-gray-800'
|
||||
: 'bg-gray-100 text-gray-600 hover:bg-gray-300 dark:hover:bg-gray-700 dark:bg-gray-600 dark:border-gray-600'
|
||||
}`}
|
||||
>
|
||||
<a>
|
||||
<i className={`${selected ? 'fa-folder-open ' : 'fa-folder '} fas mr-1`}/>
|
||||
{`${category.name} (${category.count})`}
|
||||
</a>
|
||||
</li>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
export default CategoryList
|
||||
|
||||
@@ -8,15 +8,17 @@ import Link from 'next/link'
|
||||
*/
|
||||
const ContactButton = () => {
|
||||
return (
|
||||
<Link href='/about'>
|
||||
<a className={'fixed right-10 bottom-40 animate__fadeInRight animate__animated animate__faster'}>
|
||||
(<Link
|
||||
href='/about'
|
||||
className={'fixed right-10 bottom-40 animate__fadeInRight animate__animated animate__faster'}>
|
||||
|
||||
<span
|
||||
className='dark:bg-black bg-white px-5 py-3 cursor-pointer shadow-card text-xl hover:bg-blue-500 transform duration-200 hover:text-white hover:shadow'>
|
||||
<i className='dark:text-gray-200 fas fa-info' title='about' />
|
||||
</span>
|
||||
</a>
|
||||
</Link>
|
||||
)
|
||||
|
||||
</Link>)
|
||||
);
|
||||
}
|
||||
|
||||
export default ContactButton
|
||||
|
||||
@@ -18,40 +18,38 @@ const LatestPostsGroup = ({ latestPosts }) => {
|
||||
return <></>
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="text-sm pb-1 px-2 flex flex-nowrap justify-between">
|
||||
<div className="font-light text-gray-600 dark:text-gray-200">
|
||||
<i className="mr-2 fas fa-history" />
|
||||
{locale.COMMON.LATEST_POSTS}
|
||||
</div>
|
||||
return <>
|
||||
<div className="text-sm pb-1 px-2 flex flex-nowrap justify-between">
|
||||
<div className="font-light text-gray-600 dark:text-gray-200">
|
||||
<i className="mr-2 fas fa-history" />
|
||||
{locale.COMMON.LATEST_POSTS}
|
||||
</div>
|
||||
{latestPosts.map(post => {
|
||||
const selected = currentPath === `${BLOG.SUB_PATH}/${post.slug}`
|
||||
return (
|
||||
<Link
|
||||
key={post.id}
|
||||
title={post.title}
|
||||
href={`${BLOG.SUB_PATH}/${post.slug}`}
|
||||
passHref
|
||||
</div>
|
||||
{latestPosts.map(post => {
|
||||
const selected = currentPath === `${BLOG.SUB_PATH}/${post.slug}`
|
||||
return (
|
||||
(<Link
|
||||
key={post.id}
|
||||
title={post.title}
|
||||
href={`${BLOG.SUB_PATH}/${post.slug}`}
|
||||
passHref
|
||||
className={'my-1 flex font-light'}>
|
||||
|
||||
<div
|
||||
className={
|
||||
(selected
|
||||
? 'text-white bg-gray-600 '
|
||||
: 'text-gray-500 dark:text-gray-400 ') +
|
||||
' text-xs py-1.5 flex hover:bg-gray-500 px-2 duration-200 w-full ' +
|
||||
'hover:text-white dark:hover:text-white cursor-pointer'
|
||||
}
|
||||
>
|
||||
<a className={'my-1 flex font-light'}>
|
||||
<div
|
||||
className={
|
||||
(selected
|
||||
? 'text-white bg-gray-600 '
|
||||
: 'text-gray-500 dark:text-gray-400 ') +
|
||||
' text-xs py-1.5 flex hover:bg-gray-500 px-2 duration-200 w-full ' +
|
||||
'hover:text-white dark:hover:text-white cursor-pointer'
|
||||
}
|
||||
>
|
||||
<li className="text-line-2">{post.title}</li>
|
||||
</div>
|
||||
</a>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</>
|
||||
)
|
||||
<li className="text-line-2">{post.title}</li>
|
||||
</div>
|
||||
|
||||
</Link>)
|
||||
);
|
||||
})}
|
||||
</>;
|
||||
}
|
||||
export default LatestPostsGroup
|
||||
|
||||
@@ -3,11 +3,13 @@ import React from 'react'
|
||||
|
||||
const Logo = props => {
|
||||
const { siteInfo, className } = props
|
||||
return <Link href='/' passHref>
|
||||
<div className={'flex flex-col justify-center items-center cursor-pointer bg-black dark:bg-gray-800 space-y-3 font-bold ' + className}>
|
||||
<div className='font-serif text-xl text-white'> {siteInfo?.title}</div>
|
||||
<div className='text-sm text-gray-300 font-light text-center'> {siteInfo?.description}</div>
|
||||
</div>
|
||||
</Link>
|
||||
return (
|
||||
<Link href='/' passHref legacyBehavior>
|
||||
<div className={'flex flex-col justify-center items-center cursor-pointer bg-black dark:bg-gray-800 space-y-3 font-bold ' + className}>
|
||||
<div className='font-serif text-xl text-white'> {siteInfo?.title}</div>
|
||||
<div className='text-sm text-gray-300 font-light text-center'> {siteInfo?.description}</div>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
export default Logo
|
||||
|
||||
@@ -21,24 +21,33 @@ const MenuButtonGroup = (props) => {
|
||||
links = defaultLinks.concat(customNav)
|
||||
}
|
||||
|
||||
return <nav id='nav' className='leading-8 text-gray-500 dark:text-gray-400 font-sans'>
|
||||
{links.map(link => {
|
||||
if (link && link.show) {
|
||||
const selected = (router.pathname === link.to) || (router.asPath === link.to)
|
||||
return <Link key={link.to} title={link.to} href={link.to} >
|
||||
<a target={link.to.indexOf('http') === 0 ? '_blank' : '_self'} className={'py-1.5 px-5 duration-300 text-base justify-between hover:bg-gray-700 hover:text-white hover:shadow-lg cursor-pointer font-light flex flex-nowrap items-center ' +
|
||||
(selected ? 'bg-gray-200 text-black' : ' ')} >
|
||||
<div className='my-auto items-center justify-center flex '>
|
||||
<i className={`${link.icon} w-4 text-center`} />
|
||||
<div className={'ml-4'}>{link.name}</div>
|
||||
</div>
|
||||
{link.slot}
|
||||
</a>
|
||||
</Link>
|
||||
} else {
|
||||
return <></>
|
||||
}
|
||||
})}
|
||||
</nav>
|
||||
return (
|
||||
<nav id='nav' className='leading-8 text-gray-500 dark:text-gray-400 font-sans'>
|
||||
{links.map(link => {
|
||||
if (link && link.show) {
|
||||
const selected = (router.pathname === link.to) || (router.asPath === link.to)
|
||||
return (
|
||||
<Link
|
||||
key={link.to}
|
||||
title={link.to}
|
||||
href={link.to}
|
||||
target={link.to.indexOf('http') === 0 ? '_blank' : '_self'}
|
||||
className={'py-1.5 px-5 duration-300 text-base justify-between hover:bg-gray-700 hover:text-white hover:shadow-lg cursor-pointer font-light flex flex-nowrap items-center ' +
|
||||
(selected ? 'bg-gray-200 text-black' : ' ')}>
|
||||
|
||||
<div className='my-auto items-center justify-center flex '>
|
||||
<i className={`${link.icon} w-4 text-center`} />
|
||||
<div className={'ml-4'}>{link.name}</div>
|
||||
</div>
|
||||
{link.slot}
|
||||
|
||||
</Link>
|
||||
);
|
||||
} else {
|
||||
return <></>
|
||||
}
|
||||
})}
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
export default MenuButtonGroup
|
||||
|
||||
@@ -26,10 +26,10 @@ const NextRecentComments = (props) => {
|
||||
{!onLoading && comments && comments.length === 0 && <div>No Comments</div>}
|
||||
{!onLoading && comments && comments.length > 0 && comments.map((comment) => <div key={comment.objectId} className='pb-2'>
|
||||
<div className='dark:text-gray-300 text-gray-600 text-xs waline-recent-content wl-content' dangerouslySetInnerHTML={{ __html: comment.comment }} />
|
||||
<div className='dark:text-gray-400 text-gray-400 font-sans text-sm text-right cursor-pointer hover:text-red-500 hover:underline pt-1'><Link href={{ pathname: comment.url, hash: comment.objectId, query: { target: 'comment' } } }><a >-- {comment.nick}</a></Link></div>
|
||||
<div className='dark:text-gray-400 text-gray-400 font-sans text-sm text-right cursor-pointer hover:text-red-500 hover:underline pt-1'><Link href={{ pathname: comment.url, hash: comment.objectId, query: { target: 'comment' } } }>--{comment.nick}</Link></div>
|
||||
</div>)}
|
||||
|
||||
</>
|
||||
</>;
|
||||
}
|
||||
|
||||
export default NextRecentComments
|
||||
|
||||
@@ -16,68 +16,72 @@ const PaginationNumber = ({ page, totalPage }) => {
|
||||
const pages = generatePages(pagePrefix, page, currentPage, totalPage)
|
||||
|
||||
return (
|
||||
<div
|
||||
data-aos="fade-down"
|
||||
data-aos-duration="600"
|
||||
data-aos-easing="ease-in-out"
|
||||
data-aos-once="false"
|
||||
data-aos-anchor-placement="top-bottom"
|
||||
className="my-5 flex justify-center items-end font-medium text-black hover:shadow-xl duration-500 bg-white dark:bg-hexo-black-gray dark:text-gray-300 py-3 shadow space-x-2">
|
||||
{/* 上一页 */}
|
||||
<Link
|
||||
href={{
|
||||
pathname:
|
||||
currentPage - 1 === 1
|
||||
? `${pagePrefix}/`
|
||||
: `${pagePrefix}/page/${currentPage - 1}`,
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
passHref
|
||||
<div
|
||||
data-aos="fade-down"
|
||||
data-aos-duration="600"
|
||||
data-aos-easing="ease-in-out"
|
||||
data-aos-once="false"
|
||||
data-aos-anchor-placement="top-bottom"
|
||||
className="my-5 flex justify-center items-end font-medium text-black hover:shadow-xl duration-500 bg-white dark:bg-hexo-black-gray dark:text-gray-300 py-3 shadow space-x-2">
|
||||
{/* 上一页 */}
|
||||
<Link
|
||||
href={{
|
||||
pathname:
|
||||
currentPage - 1 === 1
|
||||
? `${pagePrefix}/`
|
||||
: `${pagePrefix}/page/${currentPage - 1}`,
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<div
|
||||
rel="prev"
|
||||
className={`${currentPage === 1 ? 'invisible' : 'block'
|
||||
} border-white dark:border-gray-700 hover:border-gray-400 dark:hover:border-gray-400 w-6 text-center cursor-pointer duration-200 hover:font-bold`}
|
||||
>
|
||||
<div
|
||||
rel="prev"
|
||||
className={`${currentPage === 1 ? 'invisible' : 'block'
|
||||
} border-white dark:border-gray-700 hover:border-gray-400 dark:hover:border-gray-400 w-6 text-center cursor-pointer duration-200 hover:font-bold`}
|
||||
>
|
||||
<i className="fas fa-angle-left" />
|
||||
</div>
|
||||
</Link>
|
||||
<i className="fas fa-angle-left" />
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
{pages}
|
||||
{pages}
|
||||
|
||||
{/* 下一页 */}
|
||||
<Link
|
||||
href={{
|
||||
pathname: `${pagePrefix}/page/${currentPage + 1}`,
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
passHref
|
||||
{/* 下一页 */}
|
||||
<Link
|
||||
href={{
|
||||
pathname: `${pagePrefix}/page/${currentPage + 1}`,
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<div
|
||||
rel="next"
|
||||
className={`${+showNext ? 'block' : 'invisible'
|
||||
} border-t-2 border-white dark:border-gray-700 hover:border-gray-400 dark:hover:border-gray-400 w-6 text-center cursor-pointer duration-500 hover:font-bold`}
|
||||
>
|
||||
<div
|
||||
rel="next"
|
||||
className={`${+showNext ? 'block' : 'invisible'
|
||||
} border-t-2 border-white dark:border-gray-700 hover:border-gray-400 dark:hover:border-gray-400 w-6 text-center cursor-pointer duration-500 hover:font-bold`}
|
||||
>
|
||||
<i className="fas fa-angle-right" />
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
<i className="fas fa-angle-right" />
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function getPageElement(pagePrefix, page, currentPage) {
|
||||
return (
|
||||
<Link href={page === 1 ? `${pagePrefix}/` : `${pagePrefix}/page/${page}`} key={page} passHref>
|
||||
<a className={
|
||||
(page + '' === currentPage + ''
|
||||
? 'font-bold bg-gray-500 dark:bg-gray-400 text-white '
|
||||
: 'border-t-2 duration-500 border-white hover:border-gray-400 ') +
|
||||
' border-white dark:border-gray-700 dark:hover:border-gray-400 cursor-pointer w-6 text-center font-light hover:font-bold'
|
||||
} >
|
||||
{page}
|
||||
</a>
|
||||
</Link>
|
||||
)
|
||||
(<Link
|
||||
href={page === 1 ? `${pagePrefix}/` : `${pagePrefix}/page/${page}`}
|
||||
key={page}
|
||||
passHref
|
||||
className={
|
||||
(page + '' === currentPage + ''
|
||||
? 'font-bold bg-gray-500 dark:bg-gray-400 text-white '
|
||||
: 'border-t-2 duration-500 border-white hover:border-gray-400 ') +
|
||||
' border-white dark:border-gray-700 dark:hover:border-gray-400 cursor-pointer w-6 text-center font-light hover:font-bold'
|
||||
}>
|
||||
|
||||
{page}
|
||||
|
||||
</Link>)
|
||||
);
|
||||
}
|
||||
function generatePages(pagePrefix, page, currentPage, totalPage) {
|
||||
const pages = []
|
||||
|
||||
@@ -31,7 +31,7 @@ const PaginationSimple = ({ page, showNext }) => {
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
passHref
|
||||
>
|
||||
legacyBehavior>
|
||||
<button
|
||||
rel="prev"
|
||||
className={`${
|
||||
@@ -47,7 +47,7 @@ const PaginationSimple = ({ page, showNext }) => {
|
||||
query: router.query.s ? { s: router.query.s } : {}
|
||||
}}
|
||||
passHref
|
||||
>
|
||||
legacyBehavior>
|
||||
<button
|
||||
rel="next"
|
||||
className={`${
|
||||
@@ -58,7 +58,7 @@ const PaginationSimple = ({ page, showNext }) => {
|
||||
</button>
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default PaginationSimple
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user