Merge pull request #26 from tangly1024/theme-Next

提交Readme
This commit is contained in:
tangly1024
2022-01-13 16:45:45 +08:00
committed by GitHub
17 changed files with 82 additions and 63 deletions

View File

@@ -44,20 +44,21 @@
- 使用 Tailwind CSS轻松实现二次开发
**🕸  网址美观、搜索引擎优化**
- 更多特性、欢迎移步[我的博客](https://tangly1024.com/article/notion-next)查看
## 更新日志
请移步 [更新文档](https://docs.tangly1024.com/zh/changelog)查看
## 更多特性
欢迎移步[我的博客](https://tangly1024.com/article/notion-next)查看
## 快速起步
- 给这个项目点个小星星 😉
- 将 [这个 Notion 模板](https://tanghh.notion.site/02ab3b8678004aa69e9e415905ef32a5) 制作副本,并分享这个页面给所有人
- [Fork](https://github.com/tangly1024/NotionNext/fork) 这个项目
-`blog.config.js` 配置相关选项,更多关于配置的说明,请移步[NotionNext文档](https://docs.tangly1024.com/zh)
- _(可选)_ 用自己的图片替换 `/public` 文件夹里的 `avatar.jpg``favicon.svg``favicon.ico`
- 在 [Vercel](https://vercel.com) 上部署这个项目, 设定一下环境变量:
- `NOTION_PAGE_ID`: 你刚刚分享出去的 Notion 页面网址中的页面 ID通常是网址中工作区地址后的 32 位字符串
- `NOTION_ACCESS_TOKEN`(可选): 如果你决定不分享你的数据库,你可以使用 token 来让网页从 Notion 数据库中抓取数据。你可以在你的浏览器 cookies 中找到它,名称是 `token_v2'。
- Notion token 的有效期只有 180 天,请确保在 Vercel Dashboard 上手动更新,我们可能会在未来切换到官方 API 来解决这个问题。此外如果数据库是非公开到Notion 中的图片可能无法正常显示到网页上。
- `blog.config.js` 配置相关选项,更多关于配置的说明,请移步[NotionNext文档](https://docs.tangly1024.com/zh)
- **稍微等等就可以访问了!** 简单吗?
@@ -76,10 +77,10 @@ yarn run start # 本地启动NextJS服务
## 引用技术
- **生成**: Next.js SSG 和 Incremental Static Regeneration
- **页面渲染**: [React-notion-x](https://github.com/NotionX/react-notion-x)
- **样式**: Tailwind CSS 和 `@tailwindcss/jit` compiler
- **评论**: Gitalk,Cusdis,Utterances
- **框架**: Next.js
- **渲染**: [React-notion-x](https://github.com/NotionX/react-notion-x)
- **样式**: [Tailwind CSS](https://www.tailwindcss.cn/)`@tailwindcss/jit` compiler
- **评论**: Gitalk, Cusdis, Utterances
- **图标**[fontawesome](https://fontawesome.com/v5.15/icons?d=gallery)
## 页面样式主题

View File

@@ -6,14 +6,15 @@ import Image from 'next/image'
import Link from 'next/link'
import React from 'react'
import { Code, Collection, CollectionRow, Equation, NotionRenderer } from 'react-notion-x'
import Card from './Card'
import TagItemMini from './TagItemMini'
const BlogPostCard = ({ post, showSummary }) => {
const { locale } = useGlobal()
const showPreview = BLOG.home?.showPreview && post.blockMap
return (
<div key={post.id} className='shadow border animate__animated animate__fadeIn flex flex-col-reverse justify-between md:hover:shadow-xl duration-300
w-full bg-white dark:bg-gray-800 dark:hover:bg-gray-700 dark:border-gray-600'>
<Card className='w-full'>
<div key={post.id} className='animate__animated animate__fadeIn flex flex-col-reverse justify-between duration-300'>
<div className='lg:p-8 p-4 flex flex-col w-full'>
<Link href={`${BLOG.path}/article/${post.slug}`} passHref>
@@ -74,6 +75,8 @@ const BlogPostCard = ({ post, showSummary }) => {
</Link>
)}
</div >
</Card>
)
}

9
components/Card.js Normal file
View File

@@ -0,0 +1,9 @@
const Card = ({ children, headerSlot, className }) => {
return <div className={className}>
<>{headerSlot}</>
<section className="shadow mb-5 px-2 py-4 bg-white dark:bg-gray-800 hover:shadow-xl duration-200">
{children}
</section>
</div>
}
export default Card

View File

@@ -12,7 +12,7 @@ const CategoryGroup = ({ currentCategory, categories }) => {
<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-3 mx-2 cursor-pointer py-1 font-light'}>
' text-sm w-full items-center duration-300 px-2 cursor-pointer py-1 font-light'}>
<FontAwesomeIcon icon={selected ? faFolderOpen : faFolder} className={`${selected ? 'text-white' : 'text-gray-400'} mr-2`} />{category}({categories[category]})
</a>
</Link>

View File

@@ -28,7 +28,7 @@ const Collapse = props => {
}
}, [props.isOpen])
return (
<div ref={collapseRef} className=' overflow-hidden duration-200'>
<div ref={collapseRef} className='overflow-hidden duration-200'>
{props.children}
</div>
)

View File

@@ -1,7 +1,6 @@
import { faCopyright, faEye, faShieldAlt, faUsers } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import React from 'react'
import Link from 'next/link'
import BLOG from '@/blog.config'
const Footer = ({ title }) => {
@@ -14,7 +13,7 @@ const Footer = ({ title }) => {
<FontAwesomeIcon icon={faCopyright} /> {` ${y}`} <span> <a href={BLOG.link} className='underline font-bold text-gray-500 dark:text-gray-300 '>{BLOG.author}</a>. Powered by <a href='https://notion.so' className='underline font-bold text-gray-500 dark:text-gray-300'>Notion</a> & <a href='https://github.com/tangly1024/NotionNext' className='underline font-bold text-gray-500 dark:text-gray-300'>NotionNext</a>.</span>
<br />
<FontAwesomeIcon icon={faShieldAlt} /> <a href='https://beian.miit.gov.cn/' className='ml-1 font-bold'>闽ICP备20010331号</a>
<span > <Link href='/article/privacy-policy' ><a className='ml-1 mr-1 font-bold underline'>隐私政策</a></Link></span>
{/* <span > <Link href='/article/privacy-policy' ><a className='ml-1 mr-1 font-bold underline'>隐私政策</a></Link></span> */}
<span className='hidden busuanzi_container_site_pv'>
<FontAwesomeIcon icon={faEye}/><span className='px-1 busuanzi_value_site_pv'> </span>pv

View File

@@ -19,16 +19,16 @@ const LatestPostsGroup = ({ posts }) => {
const currentPath = useRouter().asPath
const { locale } = useGlobal()
return <section className='mt-8'>
<div className='text-sm pb-4 px-5 flex flex-nowrap justify-between'>
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'><FontAwesomeIcon icon={faArchive} className='mr-2' />{locale.COMMON.LATEST_POSTS}</div>
</div>
{posts.map(post => {
const selected = currentPath === `${BLOG.path}/article/${post.slug}`
return (
<Link key={post.id} title={post.title} href={`${BLOG.path}/article/${post.slug}`} passHref>
<a className={ 'my-1 px-2 flex font-light'}>
<div className={ (selected ? 'text-white bg-gray-600 ' : 'text-gray-500 dark:text-gray-400 ') + ' text-xs py-1.5 flex overflow-x-hidden whitespace-nowrap hover:bg-gray-500 px-3 w-full ' +
<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 overflow-x-hidden whitespace-nowrap hover:bg-gray-500 px-2 duration-200 w-full ' +
'hover:text-white dark:hover:text-white cursor-pointer' }>
<FontAwesomeIcon icon={faFileAlt} className='mr-2'/>
<div className='truncate'>{post.title}</div>
@@ -37,6 +37,6 @@ const LatestPostsGroup = ({ posts }) => {
</Link>
)
})}
</section>
</>
}
export default LatestPostsGroup

View File

@@ -23,7 +23,7 @@ const MenuButtonGroup = ({ allowCollapse = false, postCount }) => {
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 className={'py-2 px-5 mx-2 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 ' +
<a 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 '>
<FontAwesomeIcon icon={link.icon} />

View File

@@ -8,6 +8,7 @@ import Analytics from './Analytics'
import Tabs from '@/components/Tabs'
import BLOG from '@/blog.config'
import Logo from './Logo'
import Card from './Card'
/**
* 侧边平铺
@@ -30,17 +31,16 @@ const SideAreaLeft = ({ title, tags, currentTag, post, postCount, categories, cu
{/* 菜单 */}
<section className='shadow hidden lg:block mb-5 pb-4 bg-white dark:bg-gray-800 hover:shadow-xl duration-200'>
<Logo/>
<div className='pt-2 font-sans'>
<div className='pt-2 px-2 font-sans'>
<MenuButtonGroup allowCollapse={true} postCount={postCount} />
</div>
{BLOG.menu.showSearch && <div className='px-5 pt-2 font-sans'>
{BLOG.menu.showSearch && <div className='px-2 pt-2 font-sans'>
<SearchInput currentTag={currentTag} currentSearch={currentSearch} />
</div>}
</section>
</section>
<section className='sticky top-4'>
<Card className='sticky top-4'>
<Tabs>
{showToc && (
<div key={locale.COMMON.TABLE_OF_CONTENTS} className='dark:text-gray-400 text-gray-600 bg-white dark:bg-gray-800 duration-200'>
@@ -53,7 +53,7 @@ const SideAreaLeft = ({ title, tags, currentTag, post, postCount, categories, cu
<Analytics postCount={postCount}/>
</div>
</Tabs>
</section>
</Card>
</aside>
}

View File

@@ -1,9 +1,10 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import { faAngleDoubleRight, faAngleRight, faTags, faThList } from '@fortawesome/free-solid-svg-icons'
import { faAngleDoubleRight, faAngleRight, faTag, faThList } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Link from 'next/link'
import React from 'react'
import Card from './Card'
import CategoryGroup from './CategoryGroup'
import TagGroups from './TagGroups'
@@ -38,25 +39,25 @@ const SideAreaRight = ({
return (<aside id='right' className='hidden 2xl:block flex-col w-60 ml-4'>
<section className="shadow mb-5 py-4 px-2 bg-white dark:bg-gray-800 hover:shadow-xl duration-200">
{/* 展示广告 */}
<ins
className="adsbygoogle"
style={{ display: 'block' }}
data-adtest="on"
data-ad-client="ca-pub-2708419466378217"
data-ad-slot="8807314373"
data-ad-format="auto"
data-full-width-responsive="true"
></ins>
</section>
<Card>
{/* 展示广告 */}
<ins
className="adsbygoogle"
style={{ display: 'block' }}
data-adtest="on"
data-ad-client="ca-pub-2708419466378217"
data-ad-slot="8807314373"
data-ad-format="auto"
data-full-width-responsive="true"
></ins>
</Card>
<div className="sticky top-8">
<div className="sticky top-4">
{/* 分类 */}
{widget?.showCategoryList && categories && (
<section className='shadow py-4 mb-5 bg-white dark:bg-gray-800 hover:shadow-xl duration-200'>
<div className='text-sm px-5 mb-2 flex flex-nowrap justify-between font-light'>
<Card>
<div className='text-sm px-2 flex flex-nowrap justify-between font-light'>
<div className='pb-1 text-gray-600 dark:text-gray-300'><FontAwesomeIcon icon={faThList} className='mr-2' />{locale.COMMON.CATEGORY}</div>
<Link href='/category' passHref>
<a className='text-gray-400 hover:text-black dark:text-gray-400 dark:hover:text-white hover:underline cursor-pointer'>
@@ -65,16 +66,16 @@ const SideAreaRight = ({
</Link>
</div>
<CategoryGroup currentCategory={currentCategory} categories={categories} />
</section>
</Card>
)}
{slot}
{widget?.showTagList && tags && (
<section className="shadow py-4 mb-5 bg-white dark:bg-gray-800 hover:shadow-xl duration-200">
<div className="text-sm pb-1 px-5 flex flex-nowrap justify-between font-light dark:text-gray-200">
<Card>
<div className="text-sm pb-1 px-2 flex flex-nowrap justify-between font-light dark:text-gray-200">
<div className="text-gray-600 dark:text-gray-200">
<FontAwesomeIcon icon={faTags} className="mr-2" />
<FontAwesomeIcon icon={faTag} className="mr-2" />
{locale.COMMON.TAGS}
</div>
<Link href="/tag" passHref>
@@ -84,10 +85,10 @@ const SideAreaRight = ({
</a>
</Link>
</div>
<div className="px-5 pt-2">
<div className="px-2 pt-2">
<TagGroups tags={tags} currentTag={currentTag} />
</div>
</section>
</Card>
)}
</div>

View File

@@ -18,7 +18,7 @@ const Tabs = ({ children }) => {
})
if (count === 1) {
return <section className='shadow hover:shadow-xl duration-200'>
return <section className='duration-200'>
{children}
</section>
}
@@ -29,11 +29,11 @@ const Tabs = ({ children }) => {
}
return (
<section >
{<div className='shadow hidden lg:block mb-5 py-4 px-5 bg-white dark:bg-gray-800 hover:shadow-xl duration-200'>
< >
{<div className='hidden lg:block mb-5 bg-white dark:bg-gray-800 duration-200'>
<ul className='flex justify-center space-x-5 pb-4 dark:text-gray-400 text-gray-600'>
{children.map((item, index) => {
return <li key={index} className={currentTab === index ? 'font-black border-b-2 border-red-400 text-red-400 animate__animated animate__jello ' : 'font-extralight cursor-pointer'} onClick={() => { tabClickHandle(index) }}>
return <li key={index} className={(currentTab === index ? 'font-black border-b-2 border-red-400 text-red-400 animate__animated animate__jello ' : 'font-extralight cursor-pointer') + ' text-sm font-sans '} onClick={() => { tabClickHandle(index) }}>
{item?.key}
</li>
})}
@@ -45,7 +45,7 @@ const Tabs = ({ children }) => {
})}
</div>}
</section>)
</>)
}
export default Tabs

View File

@@ -52,8 +52,8 @@ const Toc = ({ toc }) => {
setActiveSection(currentSectionId)
}, throttleMs))
return <>
<div className='w-full'>
return <div className='px-3'>
<div className='w-full pb-1'>
<Progress/>
</div>
<nav className='font-sans overflow-y-auto scroll-hidden'>
@@ -79,7 +79,7 @@ const Toc = ({ toc }) => {
)
})}
</nav>
</>
</div>
}
export default Toc

View File

@@ -22,17 +22,17 @@ const TocDrawer = ({ post, cRef }) => {
}
const { locale } = useGlobal()
return <>
<div className='fixed top-0 right-0 z-40'>
<div className='fixed top-0 right-0 z-40 '>
{/* 侧边菜单 */}
<div
className={(showDrawer ? 'animate__slideInRight ' : ' -mr-72 animate__slideOutRight') +
' shadow-card animate__animated animate__faster max-h-96 ' +
' w-60 duration-200 fixed right-4 top-16 rounded overflow-y-auto'}>
' shadow-card animate__animated animate__faster max-h-96 ' +
' w-60 duration-200 fixed right-4 top-16 rounded overflow-y-auto py-2 bg-white dark:bg-gray-600'}>
{post && <>
<div className='text-xl font-bold text-center text-black dark:text-white bg-white dark:bg-gray-600 py-2 px-6'>
<div className='font-bold pb-2 text-center text-black dark:text-white '>
{locale.COMMON.TABLE_OF_CONTENTS}
</div>
<div className='p-6 dark:text-gray-400 text-gray-600 bg-white dark:bg-gray-800'>
<div className='dark:text-gray-400 text-gray-600 dark:bg-gray-800'>
<Toc toc={post.toc}/>
</div>
</>

View File

@@ -111,7 +111,7 @@ const TopNav = ({ tags, currentTag, post, slot, categories, currentCategory, aut
</div>
<Collapse isOpen={isOpen}>
<div className='bg-white py-1'>
<div className='bg-white py-1 px-5'>
<MenuButtonGroup postCount={postCount}/>
</div>
</Collapse>

View File

@@ -1,5 +1,7 @@
import BLOG from '@/blog.config'
import ArticleDetail from '@/components/ArticleDetail'
import Card from '@/components/Card'
import LatestPostsGroup from '@/components/LatestPostsGroup'
import Live2D from '@/components/Live2D'
import TocDrawer from '@/components/TocDrawer'
import TocDrawerButton from '@/components/TocDrawerButton'
@@ -50,6 +52,9 @@ const Slug = ({
latestPosts={latestPosts}
categories={categories}
floatSlot={floatSlot}
rightAreaSlot={
BLOG.widget?.showLatestPost && <Card><LatestPostsGroup posts={latestPosts} /></Card>
}
>
<ArticleDetail
post={post}

View File

@@ -1,6 +1,7 @@
import BLOG from '@/blog.config'
import BlogPostListPage from '@/components/BlogPostListPage'
import BlogPostListScroll from '@/components/BlogPostListScroll'
import Card from '@/components/Card'
import Header from '@/components/Header'
import LatestPostsGroup from '@/components/LatestPostsGroup'
import BaseLayout from '@/layouts/BaseLayout'
@@ -56,7 +57,7 @@ const Index = ({ posts, tags, meta, categories, postCount, latestPosts }) => {
tags={tags}
sideBarSlot={<LatestPostsGroup posts={latestPosts} />}
rightAreaSlot={
BLOG.widget?.showLatestPost && <LatestPostsGroup posts={latestPosts} />
BLOG.widget?.showLatestPost && <Card><LatestPostsGroup posts={latestPosts} /></Card>
}
postCount={postCount}
categories={categories}

BIN
public/avatar.jpg Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 78 KiB