Merge branch 'main' into theme-next

# Conflicts:
#	themes/NEXT/components/Footer.js
#	themes/NEXT/components/MenuButtonGroup.js
This commit is contained in:
tangly1024
2022-02-28 12:40:53 +08:00
105 changed files with 520 additions and 612 deletions

View File

@@ -9,10 +9,10 @@ import { delCacheData } from '@/lib/cache/cache_manager'
* 获取所有文章列表
* @param notionPageData
* @param from
* @param includePage 是否包含Page类型
* @param pageType 页面类型数组 ['Post','Page']
* @returns {Promise<*[]>}
*/
export async function getAllPosts ({ notionPageData, from, includePage = false }) {
export async function getAllPosts ({ notionPageData, from, pageType }) {
if (!notionPageData) {
notionPageData = await getNotionPageData({ from })
}
@@ -31,8 +31,8 @@ export async function getAllPosts ({ notionPageData, from, includePage = false }
const id = pageIds[i]
const properties = (await getPageProperties(id, pageBlock, schema)) || null
properties.slug = properties.slug ?? properties.id
properties.createdTime = new Date(pageBlock[id].value?.created_time).toString()
properties.lastEditedTime = new Date(pageBlock[id].value?.last_edited_time).toString()
properties.createdTime = new Date(pageBlock[id].value?.created_time).toString() // FIXME 似乎没有created_time 字段了
properties.lastEditedTime = new Date(pageBlock[id].value?.last_edited_time).toString() // FIXME 似乎没有created_time 字段了
properties.fullWidth = pageBlock[id].value?.format?.page_full_width ?? false
properties.page_cover = getPostCover(id, pageBlock) ?? null
properties.content = pageBlock[id].value?.content ?? []
@@ -45,19 +45,7 @@ export async function getAllPosts ({ notionPageData, from, includePage = false }
// remove all the the items doesn't meet requirements
const posts = data.filter(post => {
if (includePage) {
return (
post.title && post.slug &&
post?.status?.[0] === 'Published' &&
(post?.type?.[0] === 'Post' || post?.type?.[0] === 'Page')
)
} else {
return (
post.title && post.slug &&
post?.status?.[0] === 'Published' &&
(post?.type?.[0] === 'Post')
)
}
return post.title && post?.status?.[0] === 'Published' && pageType.indexOf(post?.type?.[0]) > -1
})
if (!posts || posts.length === 0) {
@@ -65,6 +53,7 @@ export async function getAllPosts ({ notionPageData, from, includePage = false }
const cacheKey = 'page_block_' + BLOG.NOTION_PAGE_ID
await delCacheData(cacheKey)
}
// Sort by date
if (BLOG.POSTS_SORT_BY === 'date') {
posts.sort((a, b) => {
@@ -84,3 +73,19 @@ function getPostCover (id, block) {
if (pageCover.startsWith('http')) return defaultMapImageUrl(pageCover, block[id].value)
}
}
/**
* 获取博文总数
* @param {*} param0
* @returns
*/
export async function getAllPostCount ({ notionPageData, from }) {
if (!notionPageData) {
notionPageData = await getNotionPageData({ from })
}
if (!notionPageData) {
return []
}
const allPosts = await getAllPosts({ notionPageData, from, pageType: ['Post'] })
return allPosts?.length || 0
}

View File

@@ -3,7 +3,7 @@ import { getDataFromCache, setDataToCache } from '@/lib/cache/cache_manager'
import { getPostBlocks } from '@/lib/notion/getPostBlocks'
import { idToUuid } from 'notion-utils'
import { getAllCategories } from './getAllCategories'
import { getAllPosts } from './getAllPosts'
import { getAllPosts, getAllPostCount } from './getAllPosts'
import { getAllTags } from './getAllTags'
/**
@@ -12,23 +12,29 @@ import { getAllTags } from './getAllTags'
* @param {*} from
* @param latestPostCount 截取最新文章数量
* @param tagsCount 截取标签数量
* @param includePage 是否包含PAGE类型
* @returns {}
* allPosts 所有博客
* categories 所有分类
* tags 所有标签
* @param pageType 过滤的文章类型,数组格式 ['Page','Post']
* @returns {
allPosts, 所有博客
latestPosts,
categories, 所有分类
postCount,
customNav, 自定义导航菜单
tags 所有标签
}
*
*/
export async function getGlobalNotionData ({
pageId = BLOG.NOTION_PAGE_ID,
from,
latestPostCount = 5,
tagsCount = 16,
includePage
pageType = ['Post']
}) {
const notionPageData = await getNotionPageData({ pageId, from })
const tagOptions = notionPageData.tagOptions
const allPosts = await getAllPosts({ notionPageData, from, includePage })
const postCount = allPosts?.length
const allPosts = await getAllPosts({ notionPageData, from, pageType })
const postCount = await getAllPostCount({ notionPageData, from })
const customNav = await getCustomNav({ notionPageData })
const categories = await getAllCategories(allPosts)
const tags = await getAllTags({ allPosts, tagOptions, sliceCount: tagsCount })
// 深拷贝
@@ -47,6 +53,7 @@ export async function getGlobalNotionData ({
latestPosts,
categories,
postCount,
customNav,
tags
}
}
@@ -73,6 +80,23 @@ export async function getNotionPageData ({ pageId, from }) {
return pageRecordMap
}
async function getCustomNav ({ notionPageData }) {
if (!notionPageData) {
notionPageData = await getNotionPageData({ from: 'custom-nav' })
}
if (!notionPageData) {
return []
}
const allPage = await getAllPosts({ notionPageData, from: 'custom-nav', pageType: ['Page'] })
const customNav = []
if (allPage && allPage.length > 0) {
allPage.forEach(p => {
customNav.push({ icon: p.icon || null, name: p.title, to: '/' + p.slug, show: true })
})
}
return customNav
}
/**
* 获取标签选项
* @param schema

View File

@@ -4,14 +4,14 @@ import BLOG from '@/blog.config'
export function generateRss (posts) {
const year = new Date().getFullYear()
const feed = new Feed({
TITLE: BLOG.TITLE,
DESCRIPTION: BLOG.DESCRIPTION,
title: BLOG.TITLE,
description: BLOG.DESCRIPTION,
id: `${BLOG.LINK}/${BLOG.PATH}`,
LINK: `${BLOG.LINK}/${BLOG.PATH}`,
link: `${BLOG.LINK}/${BLOG.PATH}`,
language: BLOG.LANG,
favicon: `${BLOG.LINK}/favicon.png`,
copyright: `All rights reserved ${year}, ${BLOG.AUTHOR}`,
AUTHOR: {
author: {
name: BLOG.AUTHOR,
email: BLOG.CONTACT_EMAIL,
link: BLOG.LINK

View File

@@ -19,10 +19,6 @@
"post-build": "next-sitemap --config next-sitemap.config.js"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.36",
"@fortawesome/free-brands-svg-icons": "^5.15.4",
"@fortawesome/free-solid-svg-icons": "^5.15.4",
"@fortawesome/react-fontawesome": "^0.1.16",
"@popperjs/core": "^2.9.3",
"animate.css": "^4.1.1",
"axios": ">=0.21.1",
@@ -33,15 +29,15 @@
"lodash.throttle": "^4.1.1",
"memory-cache": "^0.2.0",
"next": "^12.0.5",
"notion-client": "4.14.1",
"notion-utils": "4.14.1",
"notion-client": "4.16.0",
"notion-utils": "4.16.0",
"preact": "^10.5.15",
"qrcode.react": "^1.0.1",
"react": "17.0.2",
"react-cookies": "^0.1.1",
"react-cusdis": "^2.1.3",
"react-dom": "17.0.2",
"react-notion-x": "4.14.2",
"react-notion-x": "4.16.0",
"smoothscroll-polyfill": "^0.4.4",
"typed.js": "^2.0.12",
"use-ackee": "^3.0.0"

58
pages/[slug].js Normal file
View File

@@ -0,0 +1,58 @@
import BLOG from '@/blog.config'
import { getPostBlocks } from '@/lib/notion'
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
import { LayoutSlug } from '@/themes'
import Custom404 from '@/pages/404'
/**
* 根据notion的slug访问页面针对类型为Page的页面
* @param {*} props
* @returns
*/
const Slug = (props) => {
if (!props.post) {
return <Custom404 {...props} />
}
return <LayoutSlug {...props} showArticleInfo={false}/>
}
export async function getStaticPaths () {
if (!BLOG.isProd) {
return {
paths: [],
fallback: true
}
}
const from = 'slug-paths'
const { allPosts } = await getGlobalNotionData({ from, pageType: ['Page'] })
return {
paths: allPosts.map(row => ({ params: { slug: row.slug } })),
fallback: true
}
}
export async function getStaticProps ({ params: { slug } }) {
const from = `slug-props-${slug}`
const { allPosts, categories, tags, postCount, latestPosts, customNav } = await getGlobalNotionData({ from, pageType: ['Page'] })
const post = allPosts.find(p => p.slug === slug)
if (!post) {
return { props: {}, revalidate: 1 }
}
post.blockMap = await getPostBlocks(post.id, 'slug')
return {
props: {
post,
tags,
categories,
postCount,
latestPosts,
customNav
},
revalidate: 1
}
}
export default Slug

View File

@@ -14,9 +14,6 @@ import 'prismjs/themes/prism-okaidia.css'
import 'katex/dist/katex.min.css'
import dynamic from 'next/dynamic'
import { GlobalContextProvider } from '@/lib/global'
import { config } from '@fortawesome/fontawesome-svg-core'
import '@fortawesome/fontawesome-svg-core/styles.css'
config.autoAddCss = false
const Ackee = dynamic(() => import('@/components/Ackee'), { ssr: false })
const Gtag = dynamic(() => import('@/components/Gtag'), { ssr: false })
@@ -30,6 +27,7 @@ const MyApp = ({ Component, pageProps }) => {
{BLOG.ANALYTICS_GOOGLE_ID && <Gtag />}
{JSON.parse(BLOG.ANALYTICS_BUSUANZI_ENABLE) && <Busuanzi/>}
{BLOG.ADSENSE_GOOGLE_ID && <GoogleAdsense/>}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" integrity="sha512-1ycn6IcaQQ40/MKBW2W4Rhis/DbILU74C1vSrLJxCq57o941Ym01SwNsOMqvEBFlcgUa6xLiPY/NS5R+E6ztJQ==" crossOrigin="anonymous" referrerPolicy="no-referrer" />
<Component {...pageProps} />
</GlobalContextProvider>
)

View File

@@ -1,60 +0,0 @@
import { getPostBlocks } from '@/lib/notion'
import { getGlobalNotionData } from '@/lib/notion/getNotionData'
import Custom404 from '@/pages/404'
import React from 'react'
import { LayoutSlug } from '@/themes'
/**
* 关于页面默认取notion中slug为about的文章
* @param {*} props
* @returns
*/
const About = (props) => {
if (!props.post) {
return <Custom404 {...props} />
}
return <LayoutSlug {...props} />
}
export async function getStaticProps () {
const from = 'about-props'
const {
allPosts,
categories,
tags,
postCount,
latestPosts
} = await getGlobalNotionData({
from,
includePage: true
})
const post = allPosts.find(p => p.slug === 'about')
if (!post) {
return {
props: {},
revalidate: 1
}
}
post.blockMap = await getPostBlocks(post.id, 'slug')
const index = allPosts.indexOf(post)
const prev = allPosts.slice(index - 1, index)[0] ?? allPosts.slice(-1)[0]
const next = allPosts.slice(index + 1, index + 2)[0] ?? allPosts[0]
return {
props: {
post,
tags,
prev,
next,
categories,
postCount,
latestPosts
},
revalidate: 1
}
}
export default About

View File

@@ -13,7 +13,7 @@ const Slug = (props) => {
if (!props.post) {
return <Custom404 {...props} />
}
return <LayoutSlug {...props} />
return <LayoutSlug {...props} showArticleInfo={true}/>
}
export async function getStaticPaths () {
@@ -25,7 +25,7 @@ export async function getStaticPaths () {
}
const from = 'slug-paths'
const { allPosts } = await getGlobalNotionData({ from, includePage: true })
const { allPosts } = await getGlobalNotionData({ from })
return {
paths: allPosts.map(row => ({ params: { slug: row.slug } })),
fallback: true
@@ -34,8 +34,8 @@ export async function getStaticPaths () {
export async function getStaticProps ({ params: { slug } }) {
const from = `slug-props-${slug}`
const { allPosts, categories, tags, postCount, latestPosts } =
await getGlobalNotionData({ from, includePage: true })
const { customNav, allPosts, categories, tags, postCount, latestPosts } =
await getGlobalNotionData({ from, pageType: ['Post'] })
const post = allPosts.find(p => p.slug === slug)
@@ -45,10 +45,9 @@ export async function getStaticProps ({ params: { slug } }) {
post.blockMap = await getPostBlocks(post.id, 'slug')
const posts = allPosts.filter(post => post?.type?.[0] === 'Post')
const index = posts.indexOf(post)
const prev = posts.slice(index - 1, index)[0] ?? posts.slice(-1)[0]
const next = posts.slice(index + 1, index + 2)[0] ?? posts[0]
const index = allPosts.indexOf(post)
const prev = allPosts.slice(index - 1, index)[0] ?? allPosts.slice(-1)[0]
const next = allPosts.slice(index + 1, index + 2)[0] ?? allPosts[0]
const recommendPosts = getRecommendPost(post, allPosts)
@@ -61,29 +60,33 @@ export async function getStaticProps ({ params: { slug } }) {
recommendPosts,
categories,
postCount,
latestPosts
latestPosts,
customNav
},
revalidate: 1
}
}
/**
*
* 获取文章的关联推荐文章列表,目前根据标签关联性筛选
* @param post
* @param {*} allPosts
* @param {*} count
* @returns
*/
function getRecommendPost (post, allPosts, count = 5) {
let filteredPosts = Object.create(allPosts)
// 筛选同标签
let filteredPosts = []
for (const i in allPosts) {
const p = allPosts[i]
filteredPosts.push(Object.assign(p))
}
if (post.tags && post.tags.length) {
const currentTag = post.tags[0]
filteredPosts = filteredPosts.filter(
p => p && p.tags && p.tags.includes(currentTag) && p.slug !== post.slug && p.type === 'post'
p => p && p.slug !== post.slug && p.tags && p.tags?.includes(currentTag) && p.type === ['Post']
)
}
shuffleSort(filteredPosts)
// 筛选前5个
if (filteredPosts.length > count) {
@@ -92,21 +95,4 @@ function getRecommendPost (post, allPosts, count = 5) {
return filteredPosts
}
/**
* 洗牌乱序:从数组的最后位置开始,从前面随机一个位置,对两个数进行交换,直到循环完毕
* @param arr
* @returns {*}
*/
function shuffleSort (arr) {
let i = arr.length - 1
while (i > 0) {
const rIndex = Math.floor(Math.random() * i)
const temp = arr[rIndex]
arr[rIndex] = arr[i]
arr[i] = temp
i--
}
return arr
}
export default Slug

View File

@@ -9,7 +9,7 @@ const Index = (props) => {
export async function getStaticProps () {
const from = 'index'
const { allPosts, latestPosts, categories, tags, postCount } = await getGlobalNotionData({ from })
const { allPosts, latestPosts, categories, tags, postCount, customNav } = await getGlobalNotionData({ from, pageType: ['Post'] })
const meta = {
title: `${BLOG.TITLE}`,
description: BLOG.DESCRIPTION,
@@ -45,7 +45,8 @@ export async function getStaticProps () {
postCount,
tags,
categories,
meta
meta,
customNav
},
revalidate: 1
}

View File

@@ -8,7 +8,7 @@ export async function getStaticProps () {
tags,
postCount,
latestPosts
} = await getGlobalNotionData({ from: 'search-props' })
} = await getGlobalNotionData({ from: 'search-props', pageType: ['Post'] })
return {
props: {
posts: allPosts,

View File

@@ -50,10 +50,7 @@ function getTagNames (tags) {
export async function getStaticPaths () {
const from = 'tag-static-path'
const { tags } = await getGlobalNotionData({
from,
tagsCount: 0
})
const { tags } = await getGlobalNotionData({ from, tagsCount: 0 })
const tagNames = getTagNames(tags)
return {

View File

@@ -8,16 +8,7 @@ const TagIndex = (props) => {
export async function getStaticProps () {
const from = 'tag-index-props'
const {
categories,
tags,
postCount,
latestPosts
} = await getGlobalNotionData({
from,
includePage: false,
tagsCount: 0
})
const { categories, tags, postCount, latestPosts } = await getGlobalNotionData({ from, tagsCount: 0 })
return {
props: {

View File

@@ -1,4 +1,4 @@
import LayoutBase from '../Hexo/LayoutBase'
import LayoutBase from '../Empty/LayoutBase'
export const LayoutPage = (props) => {
const { page } = props

View File

@@ -20,17 +20,13 @@ const LayoutBase = (props) => {
const {
children,
headerSlot,
tags,
meta,
currentCategory,
currentTag,
categories
meta
} = props
return (<>
<CommonHead meta={meta} />
<TopNav {...props}/>
<div className='flex'>
<AsideLeft tags={tags} currentTag={currentTag} categories={categories} currentCategory={currentCategory}/>
<AsideLeft {...props}/>
<main id='wrapper' className='flex w-full py-8 justify-center'>
<div className='2xl:max-w-6xl md:max-w-3xl w-full'>
<div> {headerSlot} </div>

View File

@@ -1,7 +1,5 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import { faFolder, faTh } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Link from 'next/link'
import LayoutBase from './LayoutBase'
@@ -16,14 +14,14 @@ export const LayoutCategoryIndex = (props) => {
return <LayoutBase {...props} meta={meta}>
<div className='bg-white dark:bg-gray-700 px-10 py-10 shadow'>
<div className='dark:text-gray-200 mb-5'>
<FontAwesomeIcon icon={faTh} className='mr-4' />{locale.COMMON.CATEGORY}:
<i className='mr-4 fas fa-th' />{locale.COMMON.CATEGORY}:
</div>
<div id='category-list' className='duration-200 flex flex-wrap'>
{Object.keys(categories).map(category => {
return <Link key={category} href={`/category/${category}`} 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'}>
<FontAwesomeIcon icon={faFolder} className='mr-4' />{category}({categories[category]})
<i className='mr-4 fas fa-folder' />{category}({categories[category]})
</div>
</Link>
})}

View File

@@ -1,4 +1,5 @@
import BLOG from '@/blog.config'
import { getPageTableOfContents } from 'notion-utils'
import 'prismjs'
import 'prismjs/components/prism-bash'
import 'prismjs/components/prism-javascript'
@@ -17,6 +18,11 @@ export const LayoutSlug = (props) => {
tags: post.tags
}
if (post?.blockMap?.block) {
post.content = Object.keys(post.blockMap.block)
post.toc = getPageTableOfContents(post, post.blockMap)
}
return (
<LayoutBase meta={meta} {...props} >
<ArticleDetail {...props} />

View File

@@ -1,7 +1,5 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import { faTag } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import TagItem from './components/TagItem'
import LayoutBase from './LayoutBase'
@@ -16,7 +14,7 @@ export const LayoutTagIndex = (props) => {
return <LayoutBase {...props} meta={meta}>
<div className='bg-white dark:bg-gray-700 px-10 py-10 shadow'>
<div className='dark:text-gray-200 mb-5'><FontAwesomeIcon icon={faTag} className='mr-4'/>{locale.COMMON.TAGS}:</div>
<div className='dark:text-gray-200 mb-5'><i className='mr-4 fas fa-tag'/>{locale.COMMON.TAGS}:</div>
<div id='tags-list' className='duration-200 flex flex-wrap'>
{ tags.map(tag => {
return <div key={tag.name} className='p-2'><TagItem key={tag.name} tag={tag} /></div>

View File

@@ -1,6 +1,4 @@
import Link from 'next/link'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faAngleDoubleLeft, faAngleDoubleRight } from '@fortawesome/free-solid-svg-icons'
/**
* 上一篇,下一篇文章
@@ -14,12 +12,12 @@ export default function ArticleAround ({ prev, next }) {
return <section className='text-gray-800 h-28 flex items-center justify-between space-x-5 my-4'>
<Link href={`/article/${prev.slug}`} passHref>
<a className='text-sm cursor-pointer justify-center items-center flex w-full h-full bg-gray-400 bg-opacity-40 hover:bg-gray-700 hover:text-white duration-300'>
<FontAwesomeIcon icon={faAngleDoubleLeft} className='mr-1' />{prev.title}
<i className='mr-1 fas fa-angle-double-left' />{prev.title}
</a>
</Link>
<Link href={`/article/${next.slug}`} passHref>
<a className='text-sm cursor-pointer justify-center items-center flex w-full h-full bg-gray-400 bg-opacity-40 hover:bg-gray-700 hover:text-white duration-300'>{next.title}
<FontAwesomeIcon icon={faAngleDoubleRight} className='ml-1 my-1' />
<i className='ml-1 my-1 fas fa-angle-double-right' />
</a>
</Link>
</section>

View File

@@ -1,8 +1,6 @@
import Comment from '@/components/Comment'
import formatDate from '@/lib/formatDate'
import { useGlobal } from '@/lib/global'
import { faEye, faFolderOpen } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import mediumZoom from 'medium-zoom'
import Link from 'next/link'
import 'prismjs'
@@ -64,7 +62,7 @@ export default function ArticleDetail ({ post, recommendPosts, prev, next }) {
<div>
<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">
<FontAwesomeIcon icon={faFolderOpen} className="mr-1" />
<i className="mr-1 fas fa-folder-open" />
{post.category}
</a>
</Link>
@@ -83,7 +81,7 @@ export default function ArticleDetail ({ post, recommendPosts, prev, next }) {
</>)}
<div className="hidden busuanzi_container_page_pv font-light mr-2">
<FontAwesomeIcon icon={faEye} className='mr-1'/>
<i className='mr-1 fas fa-eye'/>
&nbsp;
<span className="mr-2 busuanzi_value_page_pv"/>
<span className='mr-2'>|</span>

View File

@@ -5,15 +5,18 @@ import GroupMenu from './GroupMenu'
import GroupTag from './GroupTag'
import SearchInput from './SearchInput'
import SiteInfo from './SiteInfo'
import Catalog from './Catalog'
function AsideLeft (props) {
const { tags, currentTag, categories, currentCategory, post } = props
console.log(post)
function AsideLeft ({ tags, currentTag, categories, currentCategory }) {
return <div className='w-72 bg-white min-h-screen px-10 py-14 hidden lg:block'>
<Logo />
<section className='flex flex-col text-gray-600'>
<hr className='w-12 my-8' />
<GroupMenu/>
<GroupMenu {...props}/>
</section>
<section className='flex flex-col text-gray-600'>
@@ -41,6 +44,10 @@ function AsideLeft ({ tags, currentTag, categories, currentCategory }) {
<SiteInfo/>
</section>
<section className='sticky top-0 pt-12'>
<Catalog toc={post?.toc}/>
</section>
</div>
}

View File

@@ -0,0 +1,81 @@
import React from 'react'
import throttle from 'lodash.throttle'
import { uuidToId } from 'notion-utils'
/**
* 目录导航组件
* @param toc
* @returns {JSX.Element}
* @constructor
*/
const Catalog = ({ toc }) => {
// 无目录就直接返回空
if (!toc || toc.length < 1) {
return <></>
}
// 监听滚动事件
React.useEffect(() => {
window.addEventListener('scroll', actionSectionScrollSpy)
actionSectionScrollSpy()
return () => {
window.removeEventListener('scroll', actionSectionScrollSpy)
}
}, [])
// 同步选中目录事件
const [activeSection, setActiveSection] = React.useState(null)
const throttleMs = 100
const actionSectionScrollSpy = React.useCallback(throttle(() => {
const sections = document.getElementsByClassName('notion-h')
let prevBBox = null
let currentSectionId = activeSection
for (let i = 0; i < sections.length; ++i) {
const section = sections[i]
if (!section || !(section instanceof Element)) continue
if (!currentSectionId) {
currentSectionId = section.getAttribute('data-id')
}
const bbox = section.getBoundingClientRect()
const prevHeight = prevBBox ? bbox.top - prevBBox.bottom : 0
const offset = Math.max(150, prevHeight / 4)
// GetBoundingClientRect returns values relative to viewport
if (bbox.top - offset < 0) {
currentSectionId = section.getAttribute('data-id')
prevBBox = bbox
continue
}
// No need to continue loop, if last element has been detected
break
}
setActiveSection(currentSectionId)
}, throttleMs))
return <div>
<div className='w-full'><i className='mr-1 fas fa-stream' /> 目录</div>
<nav className='font-sans overflow-y-auto scroll-hidden text-black'>
{toc.map((tocItem) => {
const id = uuidToId(tocItem.id)
return (
<a
key={id}
href={`#${id}`}
className={`notion-table-of-contents-item duration-300 transform font-light
notion-table-of-contents-item-indent-level-${tocItem.indentLevel} `}
>
<span
style={{
display: 'inline-block',
marginLeft: tocItem.indentLevel * 16
}}
className={`${activeSection === id && ' font-bold text-red-400 underline'}`}
>
{tocItem.text}
</span>
</a>
)
})}
</nav>
</div>
}
export default Catalog

View File

@@ -1,5 +1,3 @@
import { faFolder, faFolderOpen } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Link from 'next/link'
import React from 'react'
@@ -17,7 +15,7 @@ function GroupCategory ({ currentCategory, categories }) {
? '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'}>
<FontAwesomeIcon icon={selected ? faFolderOpen : faFolder} className={`${selected ? 'text-white' : 'text-gray-400'} mr-2`} />{category}({categories[category]})
<i className={`${selected ? 'text-white fa-folder-open' : 'fa-folder text-gray-400'} fas mr-2`} />{category}({categories[category]})
</a>
</Link>
})}

View File

@@ -4,22 +4,26 @@ import { useRouter } from 'next/router'
import { useGlobal } from '@/lib/global'
import CONFIG_FUKA from '../config_fuka'
function GroupMenu () {
function GroupMenu ({ customNav }) {
const { locale } = useGlobal()
const router = useRouter()
const links = [
{ id: 0, name: locale.NAV.INDEX, to: '/' || '/', show: true },
{ id: 1, name: locale.COMMON.CATEGORY, to: '/category', show: CONFIG_FUKA.MENU_CATEGORY },
{ id: 2, name: locale.COMMON.TAGS, to: '/tag', show: CONFIG_FUKA.MENU_TAG },
{ id: 3, name: locale.NAV.ARCHIVE, to: '/archive', show: CONFIG_FUKA.MENU_ARCHIVE },
{ id: 4, name: locale.NAV.ABOUT, to: '/about', show: CONFIG_FUKA.MENU_ABOUT }
let links = [
{ name: locale.NAV.INDEX, to: '/' || '/', show: true },
{ name: locale.COMMON.CATEGORY, to: '/category', show: CONFIG_FUKA.MENU_CATEGORY },
{ name: locale.COMMON.TAGS, to: '/tag', show: CONFIG_FUKA.MENU_TAG },
{ name: locale.NAV.ARCHIVE, to: '/archive', show: CONFIG_FUKA.MENU_ARCHIVE }
]
if (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.id}-${link.to}`} title={link.to} href={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 hover:text-black cursor-pointer flex flex-nowrap items-center ' +
(selected ? 'text-black' : ' ')} >
<div className='my-auto items-center justify-center flex '>

View File

@@ -1,7 +1,5 @@
import { useRouter } from 'next/router'
import { useImperativeHandle, useRef, useState } from 'react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faSearch, faSpinner, faTimes } from '@fortawesome/free-solid-svg-icons'
const SearchInput = ({ currentTag, currentSearch, cRef }) => {
const [searchKey, setSearchKey] = useState(currentSearch || '')
@@ -54,12 +52,12 @@ const SearchInput = ({ currentTag, currentSearch, cRef }) => {
<div className='-ml-8 cursor-pointer dark:bg-gray-600 dark:hover:bg-gray-800 float-right items-center justify-center py-2'
onClick={() => { handleSearch(searchKey) }}>
<FontAwesomeIcon spin={onLoading} icon={onLoading ? faSpinner : faSearch} className='hover:text-black transform duration-200 text-gray-500 cursor-pointer' />
<i className={`hover:text-black transform duration-200 text-gray-500 cursor-pointer fas ${onLoading ? 'fa-spinner animate-spin' : 'fa-search'}`} />
</div>
{(searchKey && searchKey.length &&
<div className='-ml-12 cursor-pointer dark:bg-gray-600 dark:hover:bg-gray-800 float-right items-center justify-center py-2'>
<FontAwesomeIcon icon={faTimes} className='hover:text-black transform duration-200 text-gray-400 cursor-pointer' onClick={cleanSearch} />
<i className='hover:text-black transform duration-200 text-gray-400 cursor-pointer fas fa-times' onClick={cleanSearch} />
</div>
)}
</div>

View File

@@ -1,6 +1,4 @@
import BLOG from '@/blog.config'
import { faEye, faShieldAlt, faUsers } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
function SiteInfo ({ title }) {
const d = new Date()
@@ -14,10 +12,10 @@ function SiteInfo ({ title }) {
<span>Powered by <a href='https://github.com/tangly1024/NotionNext' className='underline font-bold text-gray-500 dark:text-gray-300'>NotionNext</a>.</span><br /></span>
{BLOG.BEI_AN && <><FontAwesomeIcon icon={faShieldAlt} /> <a href='https://beian.miit.gov.cn/' className='mr-2'>{BLOG.BEI_AN}</a><br/></>}
{BLOG.BEI_AN && <><i className='fas fa-shield-alt' /> <a href='https://beian.miit.gov.cn/' className='mr-2'>{BLOG.BEI_AN}</a><br/></>}
<span className='hidden busuanzi_container_site_pv'> <FontAwesomeIcon icon={faEye} /><span className='px-1 busuanzi_value_site_pv'> </span> </span>
<span className='pl-2 hidden busuanzi_container_site_uv'> <FontAwesomeIcon icon={faUsers} /> <span className='px-1 busuanzi_value_site_uv'> </span> </span>
<span className='hidden busuanzi_container_site_pv'> <i className='fas fa-eye' /><span className='px-1 busuanzi_value_site_pv'> </span> </span>
<span className='pl-2 hidden busuanzi_container_site_uv'> <i className='fas fa-users' /> <span className='px-1 busuanzi_value_site_uv'> </span> </span>
<br />
<h1>{title}</h1>
</footer>

View File

@@ -1,5 +1,3 @@
import { faTag } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Link from 'next/link'
import React from 'react'
import { useGlobal } from '@/lib/global'
@@ -16,7 +14,7 @@ const TagItem = ({ tag, selected }) => {
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 && <FontAwesomeIcon icon={faTag} className='mr-1'/>} {`${tag.name} `} {tag.count ? `(${tag.count})` : ''}
{selected && <i className='mr-1 fas fa-tag'/>} {`${tag.name} `} {tag.count ? `(${tag.count})` : ''}
</div>
</li>
</Link>

View File

@@ -1,5 +1,3 @@
import { faTag } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Link from 'next/link'
const TagItemMini = ({ tag, selected = false }) => {
@@ -9,7 +7,7 @@ const TagItemMini = ({ tag, selected = false }) => {
${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 && <FontAwesomeIcon icon={faTag} className='mr-1'/>} {tag.name + (tag.count ? `(${tag.count})` : '')} </div>
<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>
}

View File

@@ -1,5 +1,3 @@
import { faBars, faTimes } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { useState } from 'react'
import Collapse from './Collapse'
import GroupMenu from './GroupMenu'
@@ -10,7 +8,7 @@ import Logo from './Logo'
* @param {*} param0
* @returns
*/
const TopNav = ({ tags, currentTag, categories, currentCategory, postCount }) => {
const TopNav = (props) => {
const [isOpen, changeShow] = useState(false)
const toggleMenuOpen = () => {
@@ -23,23 +21,21 @@ const TopNav = ({ tags, currentTag, categories, currentCategory, postCount }) =>
<div id='sticky-nav' className={'lg:relative w-full top-0 z-20 transform duration-500'}>
<Collapse isOpen={isOpen}>
<div className='bg-white py-1 px-5'>
<GroupMenu/>
<GroupMenu {...props}/>
</div>
</Collapse>
<div className='w-full flex justify-between items-center p-4 bg-white'>
{/* 左侧LOGO 标题 */}
<div className='flex flex-none flex-grow-0'>
<Logo/>
<Logo/>
</div>
<div className='flex'>
</div>
{/* 右侧功能 */}
<div className='mr-1 flex justify-end items-center text-sm space-x-4 font-serif dark:text-gray-200'>
<div onClick={toggleMenuOpen} className='w-18 cursor-pointer'>
菜单 { isOpen ? <FontAwesomeIcon icon={faTimes} size={'lg'}/> : <FontAwesomeIcon icon={faBars} size={'lg'}/> }
菜单 { isOpen ? <i className='fas fa-times'/> : <i className='fas fa-bars'/> }
</div>
</div>
</div>

View File

@@ -1,6 +1,4 @@
import BLOG from '@/blog.config'
import { faSpinner } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { useRouter } from 'next/router'
import { useEffect } from 'react'
import LayoutBase from './LayoutBase'
@@ -26,7 +24,7 @@ export const Layout404 = props => {
<div className="text-black w-full h-screen text-center justify-center content-center items-center flex flex-col">
<div className="dark:text-gray-200">
<h2 className="inline-block border-r-2 border-gray-600 mr-2 px-3 py-2 align-top">
<FontAwesomeIcon icon={faSpinner} spin={true} className="mr-2" />
<i className="mr-2 fas fa-spinner animate-spin" />
404
</h2>
<div className="inline-block text-left h-32 leading-10 items-center">

View File

@@ -44,9 +44,9 @@ const LayoutBase = (props) => {
{headerSlot}
<main id='wrapper' className='mt-12 lg:mt-0 flex w-full justify-center py-8 min-h-screen'>
<main id='wrapper' className='flex w-full justify-center py-8 min-h-screen'>
<div id='container-inner' className='w-full mx-auto flex justify-between space-x-4 max-w-6xl'>
<div id='container-inner' className='pt-14 w-full mx-auto flex justify-between space-x-4 max-w-6xl'>
<div className='flex-grow w-full'>{children}</div>
<SideRight {...props}/>
</div>

View File

@@ -1,7 +1,5 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import { faFolder, faTh } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Link from 'next/link'
import Card from './components/Card'
import LayoutBase from './LayoutBase'
@@ -18,7 +16,7 @@ export const LayoutCategoryIndex = props => {
<LayoutBase {...props} meta={meta}>
<Card className="bg-white dark:bg-gray-700 w-full min-h-screen">
<div className="dark:text-gray-200 mb-5 mx-3">
<FontAwesomeIcon icon={faTh} className="mr-4" />
<i className="mr-4 fas fa-th" />
{locale.COMMON.CATEGORY}:
</div>
<div id="category-list" className="duration-200 flex flex-wrap mx-8">
@@ -30,7 +28,7 @@ export const LayoutCategoryIndex = props => {
' duration-300 dark:hover:text-white rounded-lg px-5 cursor-pointer py-2 hover:bg-blue-600 hover:text-white'
}
>
<FontAwesomeIcon icon={faFolder} className="mr-4" />
<i className="mr-4 fas fa-folder" />
{category}({categories[category]})
</div>
</Link>

View File

@@ -1,7 +1,5 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import { faTag } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Card from './components/Card'
import TagItemMini from './components/TagItemMini'
import LayoutBase from './LayoutBase'
@@ -18,7 +16,7 @@ export const LayoutTagIndex = props => {
<LayoutBase {...props} meta={meta}>
<Card className='w-full'>
<div className="dark:text-gray-200 mb-5 ml-4">
<FontAwesomeIcon icon={faTag} className="mr-4" />
<i className="mr-4 fas fa-tag" />
{locale.COMMON.TAGS}:
</div>
<div id="tags-list" className="duration-200 flex flex-wrap ml-8">

View File

@@ -1,6 +1,4 @@
import BLOG from '@/blog.config'
import { faFolder } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Image from 'next/image'
import Link from 'next/link'
import React from 'react'
@@ -51,7 +49,7 @@ const BlogPostCard = ({ post, showSummary }) => {
<Link href={`/category/${post.category}`} passHref>
<a className='cursor-pointer font-light text-sm hover:underline transform'>
<FontAwesomeIcon icon={faFolder} className='mr-1' />{post.category}
<i className='mr-1 fas fa-folder' />{post.category}
</a>
</Link>
<div className='md:flex-nowrap flex-wrap md:justify-start inline-block'>

View File

@@ -2,9 +2,6 @@ import React from 'react'
import throttle from 'lodash.throttle'
import { uuidToId } from 'notion-utils'
import Progress from './Progress'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faStream } from '@fortawesome/free-solid-svg-icons'
// import { cs } from 'react-notion-x'
/**
* 目录导航组件
@@ -55,7 +52,7 @@ const Catalog = ({ toc }) => {
}, throttleMs))
return <div className='px-3'>
<div className='w-full'><FontAwesomeIcon className='mr-1' icon={faStream}/> 目录</div>
<div className='w-full'><i className='mr-1 fas fa-stream' /> 目录</div>
<div className='w-full py-1'>
<Progress/>
</div>

View File

@@ -1,5 +1,3 @@
import { faFolder, faFolderOpen } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Link from 'next/link'
import React from 'react'
@@ -16,7 +14,7 @@ const CategoryGroup = ({ currentCategory, categories }) => {
? 'hover:text-white dark:hover:text-white bg-blue-600 text-white '
: 'dark:text-gray-400 text-gray-500 hover:text-white dark:hover:text-white hover:bg-blue-600') +
' text-sm w-full items-center duration-300 px-2 cursor-pointer py-1 font-light'}>
<div> <FontAwesomeIcon icon={selected ? faFolderOpen : faFolder} className={'mr-2'} />{category}({categories[category]})</div>
<div> <i className={`mr-2 fas ${selected ? 'fa-folder-open' : 'fa-folder'}`} />{category}({categories[category]})</div>
</a>
</Link>
})}

View File

@@ -1,5 +1,3 @@
import { faCopyright, faEye, faShieldAlt, faUsers, faHeart } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import React from 'react'
import BLOG from '@/blog.config'
@@ -11,16 +9,16 @@ const Footer = ({ title }) => {
<footer
className='dark:bg-gray-900 flex-shrink-0 justify-center text-center m-auto w-full leading-6 text-gray-400 text-sm p-6'
>
<FontAwesomeIcon icon={faCopyright} /> {`${startYear}${currentYear}`} <span><FontAwesomeIcon icon={faHeart} className='mx-1 animate-pulse'/> <a href={BLOG.LINK} className='underline font-bold text-gray-500 dark:text-gray-300 '>{BLOG.AUTHOR}</a>.
<i className='fas fa-copyright' /> {`${startYear}${currentYear}`} <span><i className='mx-1 animate-pulse fas fa-heart'/> <a href={BLOG.LINK} className='underline font-bold text-gray-500 dark:text-gray-300 '>{BLOG.AUTHOR}</a>.
<br/>
<span>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></span>
{BLOG.BEI_AN && <><br /><FontAwesomeIcon icon={faShieldAlt} /> <a href='https://beian.miit.gov.cn/' className='mr-2'>{BLOG.BEI_AN}</a><br/></>}
{BLOG.BEI_AN && <><br /><i className='fas fa-shield-alt' /> <a href='https://beian.miit.gov.cn/' className='mr-2'>{BLOG.BEI_AN}</a><br/></>}
<span className='hidden busuanzi_container_site_pv'>
<FontAwesomeIcon icon={faEye}/><span className='px-1 busuanzi_value_site_pv'> </span> </span>
<i className='fas fa-eye'/><span className='px-1 busuanzi_value_site_pv'> </span> </span>
<span className='pl-2 hidden busuanzi_container_site_uv'>
<FontAwesomeIcon icon={faUsers}/> <span className='px-1 busuanzi_value_site_uv'> </span> </span>
<i className='fas fa-users'/> <span className='px-1 busuanzi_value_site_uv'> </span> </span>
<br/>
<h1>{title}</h1>
</footer>

View File

@@ -1,7 +1,5 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import { faAngleDown } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { useEffect, useState } from 'react'
import Typed from 'typed.js'
import CONFIG_HEXO from '../config_hexo'
@@ -116,7 +114,7 @@ export default function Header () {
}}
className="cursor-pointer w-full text-center py-4 text-3xl absolute bottom-10 text-white"
>
<FontAwesomeIcon icon={faAngleDown} className='animate-bounce'/>
<i className='animate-bounce fas fa-angle-down'/>
</div>
</header>
)

View File

@@ -1,5 +1,3 @@
import { faFolderOpen } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Link from 'next/link'
import { useGlobal } from '@/lib/global'
import formatDate from '@/lib/formatDate'
@@ -50,13 +48,15 @@ export default function HeaderArticle ({ post }) {
<section className="flex-wrap shadow-text flex justify-center mt-2 text-white dark:text-gray-400 font-light leading-8">
<div>
<Link href={`/category/${post.category}`} passHref>
{post.category && <>
<Link href={`/category/${post.category}`} passHref>
<a className="cursor-pointer text-md mr-2 dark:hover:text-white border-b dark:border-gray-500 border-dashed">
<FontAwesomeIcon icon={faFolderOpen} className="mr-1" />
<i className="mr-1 fas fa-folder-open" />
{post.category}
</a>
</Link>
<span className="mr-2">|</span>
</Link>
<span className="mr-2">|</span>
</>}
{post.type[0] !== 'Page' && (
<>

View File

@@ -1,6 +1,4 @@
import { useGlobal } from '@/lib/global'
import { faArrowUp } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import React from 'react'
import CONFIG_HEXO from '../config_hexo'
@@ -19,7 +17,7 @@ const JumpToTopButton = ({ showPercent = true, percent }) => {
const { locale } = useGlobal()
return (<div className='flex space-x-1 items-center transform hover:scale-105 duration-200 py-2 px-3' onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })} >
<div className='dark:text-gray-200' title={locale.POST.TOP} >
<FontAwesomeIcon icon={faArrowUp} />
<i className='fas fa-arrow-up' />
</div>
{showPercent && (<div className='text-xs dark:text-gray-200 block lg:hidden'>{percent}%</div>)}
</div>)

View File

@@ -1,7 +1,5 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import { faArchive, faFileAlt } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Link from 'next/link'
import { useRouter } from 'next/router'
@@ -21,7 +19,7 @@ const LatestPostsGroup = ({ posts }) => {
return <>
<div className='font-sans mb-2 px-1 flex flex-nowrap justify-between'>
<div><FontAwesomeIcon icon={faArchive} className='mr-2' />{locale.COMMON.LATEST_POSTS}</div>
<div><i className='mr-2 fas fa-archive' />{locale.COMMON.LATEST_POSTS}</div>
</div>
{posts.map(post => {
const selected = currentPath === `${BLOG.PATH}/article/${post.slug}`
@@ -30,7 +28,7 @@ const LatestPostsGroup = ({ posts }) => {
<a className={ 'my-1 flex font-light'}>
<div className={ (selected ? 'text-white bg-blue-600 ' : 'text-gray-500 dark:text-gray-400 ') + ' text-xs py-1.5 flex overflow-x-hidden whitespace-nowrap hover:bg-blue-600 px-2 duration-200 w-full ' +
'hover:text-white dark:hover:text-white cursor-pointer' }>
<FontAwesomeIcon icon={faFileAlt} className='mr-2'/>
<i className='mr-2 fas fa-file-alt'/>
<div className='truncate'>{post.title}</div>
</div>
</a>

View File

@@ -2,22 +2,24 @@ import React from 'react'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useGlobal } from '@/lib/global'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faArchive, faHome, faTag, faTh, faUser } from '@fortawesome/free-solid-svg-icons'
import CONFIG_HEXO from '../config_hexo'
const MenuButtonGroup = ({ postCount }) => {
const MenuButtonGroup = (props) => {
const { postCount, customNav } = props
const { locale } = useGlobal()
const router = useRouter()
const archiveSlot = <div className='bg-blue-300 dark:bg-blue-500 rounded-md text-gray-50 px-1 text-xs'>{postCount}</div>
const links = [
{ id: 0, icon: faHome, name: locale.NAV.INDEX, to: '/' || '/', show: true },
{ id: 1, icon: faTh, name: locale.COMMON.CATEGORY, to: '/category', show: CONFIG_HEXO.MENU_CATEGORY },
{ id: 2, icon: faTag, name: locale.COMMON.TAGS, to: '/tag', show: CONFIG_HEXO.MENU_TAG },
{ id: 3, icon: faArchive, name: locale.NAV.ARCHIVE, to: '/archive', slot: archiveSlot, show: CONFIG_HEXO.MENU_ARCHIVE },
{ id: 4, icon: faUser, name: locale.NAV.ABOUT, to: '/about', show: CONFIG_HEXO.MENU_ABOUT }
let links = [
{ id: 0, icon: 'fas fa-home', name: locale.NAV.INDEX, to: '/' || '/', show: true },
{ id: 1, icon: 'fas fa-th', name: locale.COMMON.CATEGORY, to: '/category', show: CONFIG_HEXO.MENU_CATEGORY },
{ id: 2, icon: 'fas fa-tag', name: locale.COMMON.TAGS, to: '/tag', show: CONFIG_HEXO.MENU_TAG },
{ id: 3, icon: 'fas fa-archive', name: locale.NAV.ARCHIVE, to: '/archive', slot: archiveSlot, show: CONFIG_HEXO.MENU_ARCHIVE },
{ id: 4, icon: 'fas fa-user', name: locale.NAV.ABOUT, to: '/about', show: CONFIG_HEXO.MENU_ABOUT }
]
if (customNav) {
links = links.concat(customNav)
}
return <nav id='nav' className='leading-8 text-gray-500 dark:text-gray-400 font-sans w-full'>
{links.map(link => {
if (link.show) {
@@ -26,7 +28,7 @@ const MenuButtonGroup = ({ postCount }) => {
<a className={'py-1.5 my-1 px-5 duration-300 text-base justify-between hover:bg-blue-600 hover:text-white hover:shadow-lg cursor-pointer flex flex-nowrap items-center ' +
(selected ? 'bg-blue-600 text-white' : ' ')} >
<div className='my-auto items-center justify-center flex '>
<FontAwesomeIcon icon={link.icon} />
<i className={link.icon} />
<div className={'ml-4'}>{link.name}</div>
</div>
{link.slot}

View File

@@ -1,8 +1,6 @@
import BLOG from '@/blog.config'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faAngleLeft, faAngleRight } from '@fortawesome/free-solid-svg-icons'
/**
* 数字翻页插件
@@ -29,7 +27,7 @@ const PaginationNumber = ({ page, totalPage }) => {
rel='prev'
className={`${currentPage === 1 ? 'invisible' : 'block'} pb-0.5 border-white dark:border-blue-700 hover:border-blue-400 dark:hover:border-blue-400 w-6 text-center cursor-pointer duration-200 hover:font-bold`}
>
<FontAwesomeIcon icon={faAngleLeft}/>
<i className='fas fa-angle-left'/>
</div>
</Link>
@@ -41,7 +39,7 @@ const PaginationNumber = ({ page, totalPage }) => {
rel='next'
className={`${+showNext ? 'block' : 'invisible'} pb-0.5 border-t-2 border-white dark:border-blue-700 hover:border-blue-400 dark:hover:border-blue-400 w-6 text-center cursor-pointer duration-500 hover:font-bold`}
>
<FontAwesomeIcon icon={faAngleRight}/>
<i className='fas fa-angle-right'/>
</div>
</Link>
</div>

View File

@@ -1,7 +1,5 @@
import { useRouter } from 'next/router'
import { useImperativeHandle, useRef, useState } from 'react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faSearch, faSpinner, faTimes } from '@fortawesome/free-solid-svg-icons'
const SearchInput = ({ currentTag, currentSearch, cRef }) => {
const [searchKey, setSearchKey] = useState(currentSearch || '')
@@ -46,7 +44,7 @@ const SearchInput = ({ currentTag, currentSearch, cRef }) => {
<input
ref={searchInputRef}
type='text'
className={'w-full rounded-lg bg-white text-sm pl-2 transition focus:shadow-lg font-light leading-10 text-black bg-gray-100'}
className={'w-full rounded-lg text-sm pl-2 transition focus:shadow-lg font-light leading-10 text-black bg-gray-100'}
onKeyUp={handleKeyUp}
onChange={e => updateSearchKey(e.target.value)}
defaultValue={searchKey}
@@ -54,12 +52,12 @@ const SearchInput = ({ currentTag, currentSearch, cRef }) => {
<div className='-ml-8 cursor-pointer dark:hover:bg-gray-800 float-right items-center justify-center py-2'
onClick={() => { handleSearch(searchKey) }}>
<FontAwesomeIcon spin={onLoading} icon={onLoading ? faSpinner : faSearch} className='hover:text-black transform duration-200 text-gray-500 cursor-pointer' />
<i className={`hover:text-black transform duration-200 text-gray-500 cursor-pointer fas ${onLoading ? 'fa-spinner animate-spin' : 'fa-search'}`} />
</div>
{(searchKey && searchKey.length &&
<div className='-ml-12 cursor-pointer dark:hover:bg-gray-800 float-right items-center justify-center py-2'>
<FontAwesomeIcon icon={faTimes} className='hover:text-black transform duration-200 text-gray-400 cursor-pointer' onClick={cleanSearch} />
<i className='hover:text-black transform duration-200 text-gray-400 cursor-pointer fas fa-times' onClick={cleanSearch} />
</div>
)}
</div>

View File

@@ -4,8 +4,6 @@ import BLOG from '@/blog.config'
import Card from './Card'
import MenuButtonGroup from './MenuButtonGroup'
import SearchInput from './SearchInput'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faChartArea, faTh } from '@fortawesome/free-solid-svg-icons'
import CategoryGroup from './CategoryGroup'
import LatestPostsGroup from './LatestPostsGroup'
import TagGroups from './TagGroups'
@@ -51,7 +49,7 @@ export default function SideRight (props) {
</Card>
<Card>
<div className='ml-2 mb-3 font-sans'>
<FontAwesomeIcon icon={faChartArea} /> 统计
<i className='fas fa-chart-area' /> 统计
</div>
<div className='text-xs font-sans font-light justify-center mx-7'>
<div className='inline'>
@@ -78,7 +76,7 @@ export default function SideRight (props) {
{showCategory && (
<Card>
<div className='ml-2 mb-1 font-sans'>
<FontAwesomeIcon icon={faTh} /> 分类
<i className='fas fa-th'/> 分类
</div>
<CategoryGroup
currentCategory={currentCategory}
@@ -96,7 +94,7 @@ export default function SideRight (props) {
</Card>}
{post && post.toc && (
<Card className='sticky top-4'>
<Card className='sticky top-12'>
<Catalog toc={post.toc} />
</Card>
)}

View File

@@ -1,7 +1,4 @@
import BLOG from '@/blog.config'
import { faGithub, faTelegram, faTwitter, faWeibo } from '@fortawesome/free-brands-svg-icons'
import { faEnvelope, faRss } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import React from 'react'
/**
@@ -13,22 +10,22 @@ const SocialButton = () => {
return <div className='w-full justify-center flex-wrap flex'>
<div className='space-x-3 text-xl text-gray-600 dark:text-gray-400 '>
{BLOG.CONTACT_GITHUB && <a target='_blank' rel='noreferrer' title={'github'} href={BLOG.CONTACT_GITHUB} >
<FontAwesomeIcon icon={faGithub} className='transform hover:scale-125 duration-150'/>
<i className='transform hover:scale-125 duration-150 fab fa-github'/>
</a>}
{BLOG.CONTACT_TWITTER && <a target='_blank' rel='noreferrer' title={'twitter'} href={BLOG.CONTACT_TWITTER} >
<FontAwesomeIcon icon={faTwitter} className='transform hover:scale-125 duration-150'/>
<i className='transform hover:scale-125 duration-150 fab fa-twitter'/>
</a>}
{BLOG.CONTACT_TELEGRAM && <a target='_blank' rel='noreferrer' href={BLOG.CONTACT_TELEGRAM} title={'telegram'} >
<FontAwesomeIcon icon={faTelegram} className='transform hover:scale-125 duration-150'/>
<i className='transform hover:scale-125 duration-150 fab fa-telegram'/>
</a>}
{BLOG.CONTACT_WEIBO && <a target='_blank' rel='noreferrer' title={'weibo'} href={BLOG.CONTACT_WEIBO} >
<FontAwesomeIcon icon={faWeibo} className='transform hover:scale-125 duration-150'/>
<i className='transform hover:scale-125 duration-150 fab fa-weibo'/>
</a>}
{BLOG.CONTACT_EMAIL && <a target='_blank' rel='noreferrer' title={'email'} href={`mailto:${BLOG.CONTACT_EMAIL}`} >
<FontAwesomeIcon icon={faEnvelope} className='transform hover:scale-125 duration-150'/>
<i className='transform hover:scale-125 duration-150 fas fa-envelope'/>
</a>}
<a target='_blank' rel='noreferrer' title={'RSS'} href={'/feed'} >
<FontAwesomeIcon icon={faRss} className='transform hover:scale-125 duration-150'/>
<i className='transform hover:scale-125 duration-150 fas fa-rss'/>
</a>
</div>
</div>

View File

@@ -1,5 +1,3 @@
import { faTag } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import TagItemMini from './TagItemMini'
/**
@@ -13,7 +11,7 @@ const TagGroups = ({ tags, currentTag }) => {
if (!tags) return <></>
return (
<div id='tags-group' className='dark:border-gray-600 space-y-2'>
<div className='font-light text-xs ml-2 mb-2'><FontAwesomeIcon icon={faTag} className='mr-1' />标签</div>
<div className='font-light text-xs ml-2 mb-2'><i className='mr-1 fas fa-tag' />标签</div>
<div className='px-4'>
{
tags.map(tag => {

View File

@@ -1,5 +1,3 @@
import { faTag } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Link from 'next/link'
const TagItemMini = ({ tag, selected = false }) => {
@@ -9,7 +7,7 @@ const TagItemMini = ({ tag, selected = false }) => {
${selected
? 'text-white dark:text-gray-300 bg-black dark:bg-black dark:hover:bg-blue-900'
: `text-gray-600 hover:shadow-xl dark:border-gray-400 notion-${tag.color}_background dark:bg-blue-800`}` }>
<div className='font-light dark:text-gray-400'>{selected && <FontAwesomeIcon icon={faTag} className='mr-1'/>} {tag.name + (tag.count ? `(${tag.count})` : '')} </div>
<div className='font-light dark:text-gray-400'>{selected && <i className='mr-1 fa-tag'/>} {tag.name + (tag.count ? `(${tag.count})` : '')} </div>
</a>
</Link>
}

View File

@@ -1,6 +1,4 @@
import { useGlobal } from '@/lib/global'
import { faListOl } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import React from 'react'
import CONFIG_HEXO from '../config_hexo'
@@ -17,7 +15,7 @@ const TocDrawerButton = (props) => {
}
const { locale } = useGlobal()
return (<div onClick={props.onClick} className='py-2 px-3 cursor-pointer dark:text-gray-200 text-center transform hover:scale-150 duration-200 flex justify-center items-center' title={locale.POST.TOP} >
<FontAwesomeIcon icon={faListOl}/>
<i className='fas fa-list-ol'/>
</div>)
}

View File

@@ -1,6 +1,4 @@
import { useGlobal } from '@/lib/global'
import { faAngleDoubleRight, faBars, faTag, faThList, faTimes } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import throttle from 'lodash.throttle'
import Link from 'next/link'
import { useEffect, useRef, useState } from 'react'
@@ -60,10 +58,10 @@ const TopNav = ({ tags, currentTag, categories, currentCategory, postCount }) =>
{ categories && (
<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'><FontAwesomeIcon icon={faThList} className='mr-2' />{locale.COMMON.CATEGORY}</div>
<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} <FontAwesomeIcon icon={faAngleDoubleRight} />
{locale.COMMON.MORE} <i className='fas fa-angle-double-right' />
</a>
</Link>
</div>
@@ -74,10 +72,10 @@ const TopNav = ({ tags, currentTag, categories, currentCategory, postCount }) =>
{ tags && (
<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'><FontAwesomeIcon icon={faTag} className='mr-2'/>{locale.COMMON.TAGS}</div>
<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} <FontAwesomeIcon icon={faAngleDoubleRight} />
{locale.COMMON.MORE} <i className='fas fa-angle-double-right' />
</a>
</Link>
</div>
@@ -92,8 +90,8 @@ const TopNav = ({ tags, currentTag, categories, currentCategory, postCount }) =>
<SearchDrawer cRef={searchDrawer} slot={searchDrawerSlot}/>
{/* 导航栏 */}
<div id='sticky-nav' className={`${CONFIG_HEXO.NAV_TYPE !== 'normal' ? 'fixed' : ''} bg-white bg-opacity-70 text-black w-full top-0 z-20 transform duration-500 font-sans`}>
<div className='w-full flex justify-between items-center p-4 shadow-md'>
<div id='sticky-nav' className={`${CONFIG_HEXO.NAV_TYPE !== 'normal' ? 'fixed bg-white' : ' bg-none -mb-10'} bg-opacity-70 text-black w-full top-0 z-20 transform duration-500 font-sans`}>
<div className='w-full flex justify-between items-center px-4 py-2 shadow-md'>
<div className='flex'>
<Logo/>
</div>
@@ -101,7 +99,7 @@ const TopNav = ({ tags, currentTag, categories, currentCategory, postCount }) =>
{/* 右侧功能 */}
<div className='mr-1 flex lg:hidden justify-end items-center text-sm space-x-4 font-serif dark:text-gray-200'>
<div onClick={toggleMenuOpen} className='w-8 cursor-pointer'>
{ isOpen ? <FontAwesomeIcon icon={faTimes} size={'lg'}/> : <FontAwesomeIcon icon={faBars} size={'lg'}/> }
{ isOpen ? <i className='fas fa-times'/> : <i className='fas fa-bars'/> }
</div>
</div>
</div>

View File

@@ -29,8 +29,8 @@ const LayoutBase = props => {
<div className='w-full'>
{/* 移动端顶部菜单 */}
<TopNavBar />
<div className='px-5 max-w-5xl justify-center mx-auto'>
<TopNavBar {...props}/>
<div className='px-5 max-w-5xl justify-center mx-auto min-h-screen'>
{slotTop}
{children}
</div>

View File

@@ -1,11 +1,9 @@
import LayoutBase from './LayoutBase'
import BlogPostListScroll from './components/BlogPostListScroll'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faTh } from '@fortawesome/free-solid-svg-icons'
export const LayoutCategory = (props) => {
const { category } = props
const slotTop = <div className='flex items-center font-sans p-8'><div className='text-xl'><FontAwesomeIcon icon={faTh} className='mr-2'/>分类</div>{category}</div>
const slotTop = <div className='flex items-center font-sans p-8'><div className='text-xl'><i className='mr-2 fas fa-th'/>分类</div>{category}</div>
return <LayoutBase {...props} slotTop={slotTop}>
<BlogPostListScroll {...props} />

View File

@@ -23,8 +23,6 @@ import mediumZoom from 'medium-zoom'
import React, { useEffect, useRef } from 'react'
import ArticleAround from './components/ArticleAround'
import Catalog from './components/Catalog'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faEye } from '@fortawesome/free-solid-svg-icons'
import CategoryItem from './components/CategoryItem'
import TagItemMini from './components/TagItemMini'
import CONFIG_MEDIUM from './config_medium'
@@ -104,7 +102,7 @@ export const LayoutSlug = props => {
</Link>
<div className="text-gray-500">{date}</div>
<div className="hidden busuanzi_container_page_pv text-gray-500 font-light mr-2">
<FontAwesomeIcon icon={faEye} className="ml-3 mr-0.5" />
<i className="ml-3 mr-0.5 fas fa-eye" />
&nbsp;
<span className="mr-2 busuanzi_value_page_pv" />
</div>
@@ -139,7 +137,7 @@ export const LayoutSlug = props => {
</section>
<section>
<div className='flex justify-between'>
{ CONFIG_MEDIUM.POST_DETAIL_CATEGORY && <CategoryItem category={post.category}/>}
{ 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>

View File

@@ -1,11 +1,9 @@
import LayoutBase from './LayoutBase'
import BlogPostListScroll from './components/BlogPostListScroll'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faTag } from '@fortawesome/free-solid-svg-icons'
export const LayoutTag = (props) => {
const { tag } = props
const slotTop = <div className='flex items-center font-sans p-8'><div className='text-xl'><FontAwesomeIcon icon={faTag} className='mr-2'/>标签</div>{tag}</div>
const slotTop = <div className='flex items-center font-sans p-8'><div className='text-xl'><i className='mr-2 fas fa-tag'/>标签</div>{tag}</div>
return <LayoutBase {...props} slotTop={slotTop}>
<BlogPostListScroll {...props} />

View File

@@ -1,6 +1,4 @@
import Link from 'next/link'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faAngleDoubleLeft, faAngleDoubleRight } from '@fortawesome/free-solid-svg-icons'
/**
* 上一篇,下一篇文章
@@ -14,12 +12,12 @@ export default function ArticleAround ({ prev, next }) {
return <section className='text-gray-800 h-12 flex items-center justify-between space-x-5 my-4'>
<Link href={`/article/${prev.slug}`} passHref>
<a className='text-sm cursor-pointer justify-start items-center flex hover:underline duration-300'>
<FontAwesomeIcon icon={faAngleDoubleLeft} className='mr-1' />{prev.title}
<i className='mr-1 fas fa-angle-double-left' />{prev.title}
</a>
</Link>
<Link href={`/article/${next.slug}`} passHref>
<a className='text-sm cursor-pointer justify-end items-center flex hover:underline duration-300'>{next.title}
<FontAwesomeIcon icon={faAngleDoubleRight} className='ml-1 my-1' />
<i className='ml-1 my-1 fas fa-angle-double-right' />
</a>
</Link>
</section>

View File

@@ -1,7 +1,5 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import { faAngleRight } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Link from 'next/link'
import React from 'react'
import { Code, Collection, Equation, NotionRenderer } from 'react-notion-x'
@@ -17,7 +15,7 @@ const BlogPostCard = ({ post, showSummary }) => {
<div className='lg:p-8 p-4 flex flex-col w-full'>
<Link href={`${BLOG.PATH}/article/${post.slug}`} passHref>
<a className={'cursor-pointer font-bold font-sans hover:underline text-3xl flex justify-start leading-tight text-gray-700 dark:text-gray-100 hover:text-blue-500 dark:hover:text-blue-400'}>
<a className={'cursor-pointer font-bold font-sans hover:underline text-3xl flex justify-start leading-tight text-gray-700 dark:text-gray-100 hover:text-green-500 dark:hover:text-green-400'}>
{post.title}
</a>
</Link>
@@ -52,7 +50,7 @@ const BlogPostCard = ({ post, showSummary }) => {
<Link href={`${BLOG.PATH}/article/${post.slug}`} passHref>
<a className='hover:bg-opacity-100 hover:scale-105 duration-200 pointer-events-auto transform text-red-500 cursor-pointer'>
{locale.COMMON.ARTICLE_DETAIL}
<FontAwesomeIcon className='ml-1' icon={faAngleRight} /></a>
<i className='ml-1 fas fa-angle-right'/></a>
</Link>
</div>

View File

@@ -1,5 +1,3 @@
import { faHome, faSearch } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Link from 'next/link'
import React from 'react'
import JumpToTopButton from '@/themes/Medium/components/JumpToTopButton'
@@ -10,12 +8,12 @@ export default function BottomMenuBar ({ className }) {
<div className='flex justify-between h-full shadow-card'>
<Link href='/' passHref>
<div className='flex w-full items-center justify-center cursor-pointer'>
<FontAwesomeIcon icon={faHome} />
<i className='fas fa-home' />
</div>
</Link>
<Link href='/search' passHref>
<div className='flex w-full items-center justify-center cursor-pointer'>
<FontAwesomeIcon icon={faSearch} />
<i className='fas fa-search'/>
</div>
</Link>
<div className='flex w-full items-center justify-center cursor-pointer'>

View File

@@ -1,5 +1,3 @@
import { faTh } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import React from 'react'
import CategoryItem from './CategoryItem'
@@ -8,7 +6,7 @@ const CategoryGroup = ({ currentCategory, categories }) => {
return <></>
}
return <div id='category-list' className='pt-4'>
<div className='mb-2'><FontAwesomeIcon icon={faTh} className='mr-2' />分类</div>
<div className='mb-2'><i className='mr-2 fas fa-th' />分类</div>
<div className='flex flex-wrap'>
{Object.keys(categories).map(category => {
const selected = currentCategory === category

View File

@@ -1,15 +1,12 @@
import Link from 'next/link'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faFolderOpen, faFolder } from '@fortawesome/free-solid-svg-icons'
export default function CategoryItem ({ selected, category, categoryCount }) {
return <Link href={`/category/${category}`} 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 dark:hover:text-white hover:bg-gray-600') +
? '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><FontAwesomeIcon icon={selected ? faFolderOpen : faFolder}
className={'mr-2'} />{category} {categoryCount && (categoryCount)}
<div><i className={`mr-2 fas ${selected ? 'fa-folder-open' : 'fa-folder'}`} />{category} {categoryCount && (categoryCount)}
</div>
</a>
</Link>

View File

@@ -1,5 +1,3 @@
import { faCopyright, faEye, faShieldAlt, faUsers, faHeart } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import React from 'react'
import BLOG from '@/blog.config'
@@ -11,16 +9,16 @@ const Footer = ({ title }) => {
<footer
className='dark:bg-gray-900 flex-shrink-0 justify-center text-center m-auto w-full leading-6 text-gray-400 text-sm p-6'
>
<FontAwesomeIcon icon={faCopyright} /> {`${startYear}${currentYear}`} <span><FontAwesomeIcon icon={faHeart} className='mx-1 animate-pulse'/> <a href={BLOG.LINK} className='underline font-bold text-gray-500 dark:text-gray-300 '>{BLOG.AUTHOR}</a>.
<i className='fas fa-copyright' /> {`${startYear}${currentYear}`} <span><i className='mx-1 animate-pulse fas fa-heart'/> <a href={BLOG.LINK} className='underline font-bold text-gray-500 dark:text-gray-300 '>{BLOG.AUTHOR}</a>.
<br/>
<span>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></span>
{BLOG.BEI_AN && <><br /><FontAwesomeIcon icon={faShieldAlt} /> <a href='https://beian.miit.gov.cn/' className='mr-2'>{BLOG.BEI_AN}</a><br/></>}
{BLOG.BEI_AN && <><br /><i className='fas fa-shield-alt'/> <a href='https://beian.miit.gov.cn/' className='mr-2'>{BLOG.BEI_AN}</a><br/></>}
<span className='hidden busuanzi_container_site_pv'>
<FontAwesomeIcon icon={faEye}/><span className='px-1 busuanzi_value_site_pv'> </span> </span>
<i className='fas fa-eye'/><span className='px-1 busuanzi_value_site_pv'> </span> </span>
<span className='pl-2 hidden busuanzi_container_site_uv'>
<FontAwesomeIcon icon={faUsers}/> <span className='px-1 busuanzi_value_site_uv'> </span> </span>
<i className='fas fa-users'/> <span className='px-1 busuanzi_value_site_uv'> </span> </span>
<br/>
<h1>{title}</h1>
</footer>

View File

@@ -1,6 +1,4 @@
import { useGlobal } from '@/lib/global'
import { faArrowUp } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import React from 'react'
import CONFIG_MEDIUM from '../config_medium'
@@ -19,7 +17,7 @@ const JumpToTopButton = ({ showPercent = false, percent, className }) => {
const { locale } = useGlobal()
return (<div className={'flex space-x-1 items-center cursor-pointer w-full justify-center ' + className } onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })} >
<div title={locale.POST.TOP} >
<FontAwesomeIcon icon={faArrowUp} />
<i className='fas fa-arrow-up'/>
</div>
{showPercent && (<div className='text-xs dark:text-gray-200 block lg:hidden'>{percent}%</div>)}
</div>)

View File

@@ -1,6 +1,4 @@
import Link from 'next/link'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faHome } from '@fortawesome/free-solid-svg-icons'
import React from 'react'
export default function LeftMenuBar () {
@@ -8,7 +6,7 @@ export default function LeftMenuBar () {
<section>
<Link href='/'>
<div className='text-center cursor-pointer hover:text-black'>
<FontAwesomeIcon icon={faHome} size='lg' color='gray' />
<i className='fas fa-home text-gray-500'/>
</div>
</Link>
</section>

View File

@@ -23,7 +23,7 @@ const PaginationSimple = ({ page, totalPage }) => {
} } passHref >
<a
rel='prev'
className={`${currentPage === 1 ? 'invisible' : 'block'} text-center w-full duration-200 px-4 py-2 hover:border-black border-b-2 hover:font-bold`}
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>
@@ -31,7 +31,7 @@ const PaginationSimple = ({ page, totalPage }) => {
<Link href={ { pathname: `/page/${currentPage + 1}`, 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-black border-b-2 hover:font-bold`}
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>

View File

@@ -1,7 +1,5 @@
import { useRouter } from 'next/router'
import { useImperativeHandle, useRef, useState } from 'react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faSearch, faSpinner, faTimes } from '@fortawesome/free-solid-svg-icons'
const SearchInput = ({ currentTag, currentSearch, cRef, className }) => {
const [searchKey, setSearchKey] = useState(currentSearch || getSearchKey() || '')
@@ -55,12 +53,12 @@ const SearchInput = ({ currentTag, currentSearch, cRef, className }) => {
<div className='-ml-8 cursor-pointer dark:bg-gray-600 dark:hover:bg-gray-800 float-right items-center justify-center py-2'
onClick={() => { handleSearch(searchKey) }}>
<FontAwesomeIcon spin={onLoading} icon={onLoading ? faSpinner : faSearch} className='hover:text-black transform duration-200 text-gray-500 cursor-pointer' />
<i className={`hover:text-black transform duration-200 text-gray-500 cursor-pointer fas ${onLoading ? 'fa-spinner animate-spin' : 'fa-search'} `} />
</div>
{(searchKey && searchKey.length &&
<div className='-ml-12 cursor-pointer dark:bg-gray-600 dark:hover:bg-gray-800 float-right items-center justify-center py-2'>
<FontAwesomeIcon icon={faTimes} className='hover:text-black transform duration-200 text-gray-400 cursor-pointer' onClick={cleanSearch} />
<i className='fas fa-times hover:text-black transform duration-200 text-gray-400 cursor-pointer' onClick={cleanSearch} />
</div>
)}
</div>

View File

@@ -1,7 +1,4 @@
import BLOG from '@/blog.config'
import { faGithub, faTelegram, faTwitter, faWeibo } from '@fortawesome/free-brands-svg-icons'
import { faEnvelope, faRss } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import React from 'react'
/**
@@ -12,22 +9,22 @@ import React from 'react'
const SocialButton = () => {
return <div className='space-x-3 text-xl text-gray-600 dark:text-gray-400 flex-wrap flex justify-center '>
{BLOG.CONTACT_GITHUB && <a target='_blank' rel='noreferrer' title={'github'} href={BLOG.CONTACT_GITHUB} >
<FontAwesomeIcon icon={faGithub} className='transform hover:scale-125 duration-150'/>
<i className='fab fa-github transform hover:scale-125 duration-150 hover:text-green-600'/>
</a>}
{BLOG.CONTACT_TWITTER && <a target='_blank' rel='noreferrer' title={'twitter'} href={BLOG.CONTACT_TWITTER} >
<FontAwesomeIcon icon={faTwitter} className='transform hover:scale-125 duration-150'/>
<i className='fab fa-twitter transform hover:scale-125 duration-150 hover:text-green-600'/>
</a>}
{BLOG.CONTACT_TELEGRAM && <a target='_blank' rel='noreferrer' href={BLOG.CONTACT_TELEGRAM} title={'telegram'} >
<FontAwesomeIcon icon={faTelegram} className='transform hover:scale-125 duration-150'/>
<i className='fab fa-telegram transform hover:scale-125 duration-150 hover:text-green-600'/>
</a>}
{BLOG.CONTACT_WEIBO && <a target='_blank' rel='noreferrer' title={'weibo'} href={BLOG.CONTACT_WEIBO} >
<FontAwesomeIcon icon={faWeibo} className='transform hover:scale-125 duration-150'/>
<i className='fab fa-weibo transform hover:scale-125 duration-150 hover:text-green-600'/>
</a>}
{BLOG.CONTACT_EMAIL && <a target='_blank' rel='noreferrer' title={'email'} href={`mailto:${BLOG.CONTACT_EMAIL}`} >
<FontAwesomeIcon icon={faEnvelope} className='transform hover:scale-125 duration-150'/>
<i className='fas fa-envelope transform hover:scale-125 duration-150 hover:text-green-600'/>
</a>}
<a target='_blank' rel='noreferrer' title={'RSS'} href={'/feed'} >
<FontAwesomeIcon icon={faRss} className='transform hover:scale-125 duration-150'/>
<i className='fas fa-rss transform hover:scale-125 duration-150 hover:text-green-600'/>
</a>
</div>
}

View File

@@ -1,5 +1,3 @@
import { faTag } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import TagItemMini from './TagItemMini'
/**
@@ -13,7 +11,7 @@ const TagGroups = ({ tags, currentTag }) => {
if (!tags) return <></>
return (
<div id='tags-group' className='dark:border-gray-600 py-4'>
<div className='mb-2'><FontAwesomeIcon icon={faTag} className='mr-2' />标签</div>
<div className='mb-2'><i className='mr-2 fas fa-tag' />标签</div>
<div className='space-y-2'>
{
tags.map(tag => {

View File

@@ -1,5 +1,3 @@
import { faTag } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Link from 'next/link'
const TagItemMini = ({ tag, selected = false }) => {
@@ -9,7 +7,7 @@ const TagItemMini = ({ tag, selected = false }) => {
${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 && <FontAwesomeIcon icon={faTag} className='mr-1'/>} {tag.name + (tag.count ? `(${tag.count})` : '')} </div>
<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>
}

View File

@@ -1,9 +1,40 @@
import LogoBar from '@/themes/Medium/components/LogoBar'
import Link from 'next/link'
import { useRouter } from 'next/router'
/**
* 顶部导航栏 + 菜单
* @param {} param0
* @returns
*/
export default function TopNavBar (props) {
const { className, customNav } = props
const router = useRouter()
export default function TopNavBar ({ className }) {
return <div id='top-nav' className={'sticky top-0 lg:relative w-full z-50 ' + className}>
<div className='flex w-full h-12 shadow bg-white px-5 items-center'>
<div className='flex w-full h-12 shadow bg-white px-5 items-between'>
<LogoBar />
{/* 顶部菜单 */}
<div className='flex'>
{customNav && customNav.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 className={'px-5 duration-300 text-base justify-between hover:underline 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-4 whitespace-nowrap'>{link.name}</div>
</div>
{link.slot}
</a>
</Link>
} else {
return null
}
})}
</div>
</div>
</div>
}

View File

@@ -1,8 +1,6 @@
import { useRouter } from 'next/router'
import LayoutBase from './LayoutBase'
import BLOG from '@/blog.config'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faSpinner } from '@fortawesome/free-solid-svg-icons'
import { useEffect } from 'react'
export const Layout404 = () => {
@@ -25,7 +23,7 @@ export const Layout404 = () => {
<div
className='md:-mt-20 text-black w-full h-screen text-center justify-center content-center items-center flex flex-col'>
<div className='dark:text-gray-200'>
<h2 className='inline-block border-r-2 border-gray-600 mr-2 px-3 py-2 align-top'><FontAwesomeIcon icon={faSpinner} spin={true} className='mr-2'/>404</h2>
<h2 className='inline-block border-r-2 border-gray-600 mr-2 px-3 py-2 align-top'><i className='mr-2 fa-spinner animate-spin'/>404</h2>
<div className='inline-block text-left h-32 leading-10 items-center'>
<h2 className='m-0 p-0'>页面无法加载即将返回首页</h2>
</div>

View File

@@ -15,33 +15,11 @@ import CONFIG_NEXT from './config_next'
/**
* 基础布局 采用左右两侧布局,移动端使用顶部导航栏
* @param children
* @param layout
* @param tags
* @param meta
* @param post
* @param currentSearch
* @param currentCategory
* @param currentTag
* @param categories
* @returns {JSX.Element}
* @constructor
*/
const LayoutBase = ({
children,
headerSlot,
tags,
meta,
post,
postCount,
sideBarSlot,
floatSlot,
rightAreaSlot,
currentSearch,
currentCategory,
currentTag,
categories
}) => {
const LayoutBase = (props) => {
const { children, headerSlot, meta, sideBarSlot, floatSlot, rightAreaSlot } = props
const { onLoading } = useGlobal()
const targetRef = useRef(null)
@@ -71,23 +49,18 @@ const LayoutBase = ({
<CommonHead meta={meta} />
<TopNav tags={tags} postCount={postCount} post={post} slot={sideBarSlot} currentSearch={currentSearch} categories={categories} currentCategory={currentCategory} />
<TopNav slot={sideBarSlot} {...props}/>
<>{headerSlot}</>
<div className='h-0.5 w-full bg-gray-700 dark:bg-gray-600 hidden lg:block'/>
<main id='wrapper' className='flex justify-center flex-1 pb-12'>
<SideAreaLeft targetRef={targetRef} post={post} postCount={postCount} tags={tags} currentSearch={currentSearch} currentTag={currentTag} categories={categories} currentCategory={currentCategory}/>
<SideAreaLeft targetRef={targetRef} {...props}/>
<section id='center' className={`${CONFIG_NEXT.NAV_TYPE !== 'normal' ? 'mt-40' : ''} lg:max-w-3xl xl:max-w-4xl flex-grow md:mt-0 min-h-screen w-full`} ref={targetRef}>
{onLoading
? <LoadingCover/>
: <>
{children}
</>
}
{onLoading ? <LoadingCover/> : <> {children}</> }
</section>
<SideAreaRight targetRef={targetRef} post={post} slot={rightAreaSlot} postCount={postCount} tags={tags} currentSearch={currentSearch} currentTag={currentTag} categories={categories} currentCategory={currentCategory}/>
<SideAreaRight targetRef={targetRef} slot={rightAreaSlot} {...props}/>
</main>
{/* 右下角悬浮 */}

View File

@@ -1,8 +1,6 @@
import { useGlobal } from '@/lib/global'
import BLOG from '@/blog.config'
import LayoutBase from './LayoutBase'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faFolder, faThList } from '@fortawesome/free-solid-svg-icons'
import Link from 'next/link'
export const LayoutCategoryIndex = ({
@@ -21,14 +19,14 @@ export const LayoutCategoryIndex = ({
return <LayoutBase meta={meta} totalPosts={allPosts} tags={tags} postCount={postCount} latestPosts={latestPosts}>
<div className='bg-white dark:bg-gray-700 px-10 py-10 shadow'>
<div className='dark:text-gray-200 mb-5'>
<FontAwesomeIcon icon={faThList} className='mr-4' />{locale.COMMON.CATEGORY}:
<i className='mr-4 fas faTh' />{locale.COMMON.CATEGORY}:
</div>
<div id='category-list' className='duration-200 flex flex-wrap'>
{Object.keys(categories).map(category => {
return <Link key={category} href={`/category/${category}`} 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'}>
<FontAwesomeIcon icon={faFolder} className='mr-4' />{category}({categories[category]})
<i className='mr-4 fas fa-folder' />{category}({categories[category]})
</div>
</Link>
})}

View File

@@ -6,24 +6,18 @@ import BlogPostListScroll from './components/BlogPostListScroll'
import BlogPostListPage from './components/BlogPostListPage'
import CONFIG_NEXT from './config_next'
export const LayoutIndex = ({ posts, tags, meta, categories, postCount, latestPosts }) => {
export const LayoutIndex = (props) => {
const { latestPosts } = props
const rightAreaSlot = CONFIG_NEXT.RIGHT_LATEST_POSTS && <Card><LatestPostsGroup posts={latestPosts} /></Card>
return <LayoutBase
headerSlot={CONFIG_NEXT.HOME_BANNER && <Header />}
meta={meta}
tags={tags}
sideBarSlot={<LatestPostsGroup posts={latestPosts} />}
rightAreaSlot={
CONFIG_NEXT.RIGHT_LATEST_POSTS && <Card><LatestPostsGroup posts={latestPosts} /></Card>
}
postCount={postCount}
categories={categories}
rightAreaSlot={rightAreaSlot}
{...props}
>
{CONFIG_NEXT.POST_LIST_TYPE !== 'page'
? (
<BlogPostListScroll posts={posts} tags={tags} showSummary={true} />
)
: (
<BlogPostListPage posts={posts} tags={tags} postCount={postCount} />
)}
? <BlogPostListScroll {...props} showSummary={true} />
: <BlogPostListPage {...props} />
}
</LayoutBase>
}

View File

@@ -1,7 +1,5 @@
import LayoutBase from './LayoutBase'
import StickyBar from './components/StickyBar'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faSearch } from '@fortawesome/free-solid-svg-icons'
import BlogPostListScroll from './components/BlogPostListScroll'
import { useGlobal } from '@/lib/global'
import BLOG from '@/blog.config'
@@ -36,7 +34,7 @@ export const LayoutSearch = ({ posts, tags, categories, postCount }) => {
>
<StickyBar>
<div className="p-4 dark:text-gray-200">
<FontAwesomeIcon icon={faSearch} className="mr-1" />{' '}
<i className="mr-1 fas fa-search" />{' '}
{filteredPosts.length} {locale.COMMON.RESULT_OF_SEARCH}
</div>
</StickyBar>

View File

@@ -10,16 +10,8 @@ import Live2D from './components/Live2D'
import { useRef } from 'react'
import CONFIG_NEXT from './config_next'
export const LayoutSlug = ({
post,
tags,
prev,
next,
recommendPosts,
categories,
postCount,
latestPosts
}) => {
export const LayoutSlug = (props) => {
const { post, prev, next, recommendPosts, latestPosts, showArticleInfo } = props
const meta = {
title: `${post.title} | ${BLOG.TITLE}`,
description: post.summary,
@@ -41,12 +33,8 @@ export const LayoutSlug = ({
return (
<LayoutBase
{...props}
meta={meta}
tags={tags}
post={post}
postCount={postCount}
latestPosts={latestPosts}
categories={categories}
floatSlot={floatSlot}
rightAreaSlot={
CONFIG_NEXT.RIGHT_LATEST_POSTS && <Card><LatestPostsGroup posts={latestPosts} /></Card>
@@ -54,9 +42,10 @@ export const LayoutSlug = ({
>
<ArticleDetail
post={post}
recommendPosts={recommendPosts}
prev={prev}
next={next}
recommendPosts={recommendPosts}
showArticleInfo={showArticleInfo}
/>
{/* 悬浮目录按钮 */}

View File

@@ -1,8 +1,6 @@
import { useGlobal } from '@/lib/global'
import BLOG from '@/blog.config'
import LayoutBase from './LayoutBase'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faTags } from '@fortawesome/free-solid-svg-icons'
import TagItem from './components/TagItem'
export const LayoutTagIndex = ({ tags, categories, postCount, latestPosts }) => {
@@ -14,7 +12,7 @@ export const LayoutTagIndex = ({ tags, categories, postCount, latestPosts }) =>
}
return <LayoutBase meta={meta} categories={categories} postCount={postCount} latestPosts={latestPosts}>
<div className='bg-white dark:bg-gray-700 px-10 py-10 shadow'>
<div className='dark:text-gray-200 mb-5'><FontAwesomeIcon icon={faTags} className='mr-4'/>{locale.COMMON.TAGS}:</div>
<div className='dark:text-gray-200 mb-5'><i className='fas fa-tags mr-4'/>{locale.COMMON.TAGS}:</div>
<div id='tags-list' className='duration-200 flex flex-wrap'>
{ tags.map(tag => {
return <div key={tag.name} className='p-2'><TagItem key={tag.name} tag={tag} /></div>

View File

@@ -6,8 +6,6 @@ import ShareBar from './ShareBar'
import TagItem from './TagItem'
import formatDate from '@/lib/formatDate'
import { useGlobal } from '@/lib/global'
import { faEye, faFolderOpen } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import mediumZoom from 'medium-zoom'
import Link from 'next/link'
import { useRouter } from 'next/router'
@@ -28,7 +26,8 @@ import WordCount from './WordCount'
* @param {*} param0
* @returns
*/
export default function ArticleDetail ({ post, recommendPosts, prev, next }) {
export default function ArticleDetail (props) {
const { post, recommendPosts, prev, next, showArticleInfo } = props
const url = BLOG.LINK + useRouter().asPath
const { locale } = useGlobal()
const date = formatDate(post?.date?.start_date || post.createdTime, locale.LOCALE)
@@ -56,20 +55,11 @@ export default function ArticleDetail ({ post, recommendPosts, prev, next }) {
className="subpixel-antialiased py-10 px-5 lg:pt-24 md:px-24 dark:border-gray-700 bg-white dark:bg-gray-800"
>
<header className='animate__slideInDown animate__animated'>
{showArticleInfo && <header className='animate__slideInDown animate__animated'>
{post.type && !post.type.includes('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 className="w-full h-60 relative lg:h-96 transform duration-200 md:flex-shrink-0 overflow-hidden">
<Image
src={post?.page_cover}
loading="eager"
objectFit="cover"
layout="fill"
alt={post.title}
/>
</div> */}
</div>
)}
@@ -80,14 +70,14 @@ export default function ArticleDetail ({ post, recommendPosts, prev, next }) {
<section className="flex-wrap flex mt-2 text-gray-400 dark:text-gray-400 font-light leading-8">
<div>
<Link href={`/category/${post.category}`} passHref>
{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">
<FontAwesomeIcon icon={faFolderOpen} className="mr-1" />
{post.category}
<i className="mr-1 far fa-folder-open" /> {post.category}
</a>
</Link>
<span className='mr-2'>|</span>
</>}
{post.type[0] !== 'Page' && (<>
<Link
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
@@ -101,7 +91,7 @@ export default function ArticleDetail ({ post, recommendPosts, prev, next }) {
</>)}
<div className="hidden busuanzi_container_page_pv font-light mr-2">
<FontAwesomeIcon icon={faEye} className='mr-1'/>
<i className='mr-1 fa-eye'/>
&nbsp;
<span className="mr-2 busuanzi_value_page_pv"/>
<span className='mr-2'>|</span>
@@ -113,11 +103,9 @@ export default function ArticleDetail ({ post, recommendPosts, prev, next }) {
</section>
{/* <hr className="mt-2" /> */}
</header>}
</header>
{/* Notion文章主体 */}
{/* Notion内容主体 */}
<article id='notion-article' className='px-1'>
{post.blockMap && (
<NotionRenderer
@@ -144,6 +132,7 @@ export default function ArticleDetail ({ post, recommendPosts, prev, next }) {
data-ad-slot="3806269138"/>
</section>
{showArticleInfo && <>
{/* 版权声明 */}
<ArticleCopyright author={BLOG.AUTHOR} url={url} />
@@ -168,6 +157,7 @@ export default function ArticleDetail ({ post, recommendPosts, prev, next }) {
</section>
<BlogAround prev={prev} next={next} />
</>}
{/* 评论互动 */}
<div className="duration-200 w-full dark:border-gray-700 bg-white dark:bg-gray-800">

View File

@@ -1,6 +1,4 @@
import Link from 'next/link'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faAngleDoubleLeft, faAngleDoubleRight } from '@fortawesome/free-solid-svg-icons'
/**
* 上一篇,下一篇文章
@@ -14,12 +12,12 @@ export default function BlogAround ({ prev, next }) {
return <section className='text-gray-800 border-t dark:text-gray-300 flex flex-wrap lg:flex-nowrap lg:space-x-10 justify-between py-2'>
{prev && <Link href={`/article/${prev.slug}`} passHref>
<a className='text-sm py-3 text-gray-400 hover:underline cursor-pointer'>
<FontAwesomeIcon icon={faAngleDoubleLeft} className='mr-1' />{prev.title}
<i className='mr-1 fas fa-angle-double-left' />{prev.title}
</a>
</Link>}
{next && <Link href={`/article/${next.slug}`} passHref>
<a className='text-sm flex py-3 text-gray-400 hover:underline cursor-pointer'>{next.title}
<FontAwesomeIcon icon={faAngleDoubleRight} className='ml-1 my-1' />
<i className='ml-1 my-1 fas -fa-angle-double-right' />
</a>
</Link>}
</section>

View File

@@ -1,7 +1,5 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import { faAngleRight, faFolder } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Image from 'next/image'
import Link from 'next/link'
import React from 'react'
@@ -26,12 +24,14 @@ const BlogPostCard = ({ post, showSummary }) => {
<div className={`flex mt-2 items-center ${showPreview ? 'justify-center' : 'justify-start'} flex-wrap dark:text-gray-500 text-gray-400 hover:text-blue-500 dark:hover:text-blue-400 `}>
<div>
{ post.category && (<>
<Link href={`/category/${post.category}`} passHref>
<a className='cursor-pointer font-light text-sm hover:underline transform'>
<FontAwesomeIcon icon={faFolder} className='mr-1' />{post.category}
<i className='mr-1 fas fa-folder' />{post.category}
</a>
</Link>
<span className='mx-2'>|</span>
</>) }
<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>
</Link>
@@ -63,7 +63,7 @@ const BlogPostCard = ({ post, showSummary }) => {
<Link href={`${BLOG.PATH}/article/${post.slug}`}>
<a className='hover:bg-opacity-100 hover:scale-105 hover:underline pointer-events-auto transform duration-300 p-3 text-white bg-gray-800 cursor-pointer'>
{locale.COMMON.ARTICLE_DETAIL}
<FontAwesomeIcon className='ml-1' icon={faAngleRight} /></a>
<i className='ml-1 fas fa-angle-right' /></a>
</Link>
</div>
</div>

View File

@@ -1,5 +1,3 @@
import { faFolder, faFolderOpen } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Link from 'next/link'
import React from 'react'
@@ -13,7 +11,7 @@ const CategoryGroup = ({ currentCategory, categories }) => {
? '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'}>
<FontAwesomeIcon icon={selected ? faFolderOpen : faFolder} className={`${selected ? 'text-white' : 'text-gray-400'} mr-2`} />{category}({categories[category]})
<i className={`${selected ? 'text-white fa-folder-open ' : 'text-gray-400 fa-folder '} mr-2 fas`} />{category}({categories[category]})
</a>
</Link>
})}

View File

@@ -1,7 +1,5 @@
import Link from 'next/link'
import React from 'react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faFolder, faFolderOpen } from '@fortawesome/free-solid-svg-icons'
import { useGlobal } from '@/lib/global'
const CategoryList = ({ currentCategory, categories }) => {
@@ -24,7 +22,7 @@ const CategoryList = ({ currentCategory, categories }) => {
}`}
>
<a>
<FontAwesomeIcon icon={selected ? faFolderOpen : faFolder} className='mr-1' />
<i className={`${selected ? 'fa-folder-open ' : 'fa-folder '} fas mr-1`}/>
{`${category} `}
</a>
</li>

View File

@@ -1,7 +1,5 @@
import React from 'react'
import Link from 'next/link'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faInfo } from '@fortawesome/free-solid-svg-icons'
/**
* 悬浮在屏幕右下角,联系我的按钮
@@ -14,7 +12,7 @@ const ContactButton = () => {
<a 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'>
<FontAwesomeIcon icon={faInfo} className='dark:text-gray-200 ' title='about' />
<i className='dark:text-gray-200 fas fa-info' title='about' />
</span>
</a>
</Link>

View File

@@ -1,6 +1,4 @@
import { useGlobal } from '@/lib/global'
import { faMoon, faSun } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { loadUserThemeFromCookies, saveTheme } from '@/lib/theme'
const DarkModeButton = () => {
@@ -14,7 +12,7 @@ const DarkModeButton = () => {
changeTheme(newTheme)
}
return <div className='z-10 duration-200 text-xs cursor-pointer py-1.5 px-1'>
<FontAwesomeIcon icon={userTheme === 'dark' ? faSun : faMoon} id='darkModeButton' className='hover:scale-125 transform duration-200'
<i id='darkModeButton' className={`hover:scale-125 transform duration-200 fas ${userTheme === 'dark' ? 'fa-sun' : 'fa-moon'}`}
onClick={handleChangeDarkMode} />
</div>
}

View File

@@ -1,7 +1,5 @@
import { useGlobal } from '@/lib/global'
import { loadUserThemeFromCookies, saveTheme } from '@/lib/theme'
import { faMoon, faSun } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import CONFIG_NEXT from '../config_next'
export default function FloatDarkModeButton () {
@@ -27,10 +25,9 @@ export default function FloatDarkModeButton () {
className={ ' text-black dark:border-gray-500 flex justify-center items-center dark:text-gray-200 py-2 px-3'
}
>
<FontAwesomeIcon
icon={userTheme === 'dark' ? faSun : faMoon}
<i
id="darkModeButton"
className="hover:scale-150 transform duration-200"
className={`${userTheme === 'dark' ? 'fa-sun' : 'fa-moon'} fas hover:scale-150 transform duration-200`}
/>
</div>
)

View File

@@ -1,8 +1,5 @@
import { faCopyright, faEye, faShieldAlt, faUsers, faHeart } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import React from 'react'
import BLOG from '@/blog.config'
import Link from 'next/link'
const Footer = ({ title }) => {
const d = new Date()
@@ -12,16 +9,16 @@ const Footer = ({ title }) => {
<footer
className='dark:bg-gray-900 flex-shrink-0 justify-center text-center m-auto w-full leading-6 text-gray-400 text-sm p-6'
>
<FontAwesomeIcon icon={faCopyright} /> {`${startYear}${currentYear}`} <span><FontAwesomeIcon icon={faHeart} className='mx-1 animate-pulse'/> <Link href='/about'><a className='underline font-bold text-gray-500 dark:text-gray-300 '>{BLOG.AUTHOR}</a></Link>.
<i className='fas fa-copyright' /> {`${startYear}${currentYear}`} <span><i className='mx-1 animate-pulse fas fas-heart'/> <a href={BLOG.LINK} className='underline font-bold text-gray-500 dark:text-gray-300 '>{BLOG.AUTHOR}</a>.
<br/>
<span>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></span>
{BLOG.BEI_AN && <><br /><FontAwesomeIcon icon={faShieldAlt} /> <a href='https://beian.miit.gov.cn/' className='mr-2'>{BLOG.BEI_AN}</a><br/></>}
{BLOG.BEI_AN && <><br /><i className='fas fa-shield-alt' /> <a href='https://beian.miit.gov.cn/' className='mr-2'>{BLOG.BEI_AN}</a><br/></>}
<span className='hidden busuanzi_container_site_pv'>
<FontAwesomeIcon icon={faEye}/><span className='px-1 busuanzi_value_site_pv'> </span> </span>
<i className='fas fa-eye'/><span className='px-1 busuanzi_value_site_pv'> </span> </span>
<span className='pl-2 hidden busuanzi_container_site_uv'>
<FontAwesomeIcon icon={faUsers}/> <span className='px-1 busuanzi_value_site_uv'> </span> </span>
<i className='fas fa-users'/> <span className='px-1 busuanzi_value_site_uv'> </span> </span>
<br/>
<h1>{title}</h1>
</footer>

View File

@@ -1,6 +1,4 @@
import { useGlobal } from '@/lib/global'
import { faAngleDown } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { useEffect, useState } from 'react'
import Typed from 'typed.js'
import CONFIG_NEXT from '../config_next'
@@ -111,7 +109,7 @@ export default function Header () {
}}
className="cursor-pointer w-full text-center py-4 text-5xl absolute bottom-10 text-white"
>
<FontAwesomeIcon icon={faAngleDown} className='animate-bounce'/>
<i className='animate-bounce fas fa-angle-down'/>
</div>
</header>
)

View File

@@ -1,5 +1,3 @@
import { faArrowDown } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import React, { useEffect, useState } from 'react'
import smoothscroll from 'smoothscroll-polyfill'
import CONFIG_NEXT from '../config_next'
@@ -47,7 +45,7 @@ const JumpToBottomButton = ({ showPercent = false }) => {
return (<div className='flex space-x-1 transform hover:scale-105 duration-200 py-2 px-3' onClick={scrollToBottom} >
<div className='dark:text-gray-200' >
<FontAwesomeIcon icon={faArrowDown} />
<i className='fas fa-arrow-down' />
</div>
{showPercent && (<div className='dark:text-gray-200 block lg:hidden'>{percent}%</div>)}
</div>)

View File

@@ -1,6 +1,4 @@
import { useGlobal } from '@/lib/global'
import { faArrowUp } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import React from 'react'
import CONFIG_NEXT from '../config_next'
@@ -19,7 +17,7 @@ const JumpToTopButton = ({ showPercent = true, percent }) => {
const { locale } = useGlobal()
return (<div className='flex space-x-1 items-center transform hover:scale-105 duration-200 py-2 px-3' onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })} >
<div className='dark:text-gray-200' title={locale.POST.TOP} >
<FontAwesomeIcon icon={faArrowUp} />
<i className='fa-arrow-up fas' />
</div>
{showPercent && (<div className='text-xs dark:text-gray-200 block lg:hidden'>{percent}%</div>)}
</div>)

View File

@@ -1,7 +1,5 @@
import BLOG from '@/blog.config'
import { useGlobal } from '@/lib/global'
import { faArchive, faFileAlt } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Link from 'next/link'
import { useRouter } from 'next/router'
@@ -21,7 +19,7 @@ const LatestPostsGroup = ({ posts }) => {
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 className='font-light text-gray-600 dark:text-gray-200'><i className='mr-2 fas fa-archive' />{locale.COMMON.LATEST_POSTS}</div>
</div>
{posts.map(post => {
const selected = currentPath === `${BLOG.PATH}/article/${post.slug}`
@@ -30,7 +28,7 @@ const LatestPostsGroup = ({ posts }) => {
<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'/>
<i className='mr-2 fas fa-file-alt'/>
<div className='truncate'>{post.title}</div>
</div>
</a>

View File

@@ -1,8 +1,6 @@
import React, { useEffect, useState } from 'react'
import throttle from 'lodash.throttle'
import DarkModeButton from './DarkModeButton'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faBars } from '@fortawesome/free-solid-svg-icons'
/**
* 左上角悬浮菜单栏
@@ -32,8 +30,7 @@ const LeftFloatButton = () => {
{/* 菜单折叠 */}
<div className='p-1 border hover:shadow-xl duration-200 dark:border-gray-500 h-12 bg-white dark:bg-gray-600 dark:bg-opacity-70 bg-opacity-70
dark:hover:bg-gray-100 text-xl cursor-pointer mr-2 my-2 dark:text-gray-300 dark:hover:text-black'>
<FontAwesomeIcon icon={faBars} className='p-2.5 hover:scale-125 transform duration-200'
onClick={() => changeCollapse(!collapse)} />
<i className='p-2.5 hover:scale-125 transform duration-200 fas fa-bars' onClick={() => changeCollapse(!collapse)} />
</div>
{/* 夜间模式 */}
<DarkModeButton />

View File

@@ -1,10 +1,7 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faSpinner } from '@fortawesome/free-solid-svg-icons'
export default function LoadingCover () {
return (<div id="loading-cover" className={'md:-mt-20 flex-grow dark:text-white text-black animate__animated animate__fadeIn flex flex-col justify-center z-10 w-full h-screen container mx-auto'}>
<div className="mx-auto">
<FontAwesomeIcon icon={faSpinner} spin size='2x'/>
<i className="fas fa-spinner animate-spin"/>
</div>
</div>
)

View File

@@ -2,31 +2,34 @@ import React from 'react'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useGlobal } from '@/lib/global'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faArchive, faHome, faTag, faTh, faUser } from '@fortawesome/free-solid-svg-icons'
import CONFIG_NEXT from '../config_next'
const MenuButtonGroup = ({ postCount }) => {
const MenuButtonGroup = (props) => {
const { postCount, customNav } = props
const { locale } = useGlobal()
const router = useRouter()
const archiveSlot = <div className='bg-gray-300 dark:bg-gray-500 rounded-md text-gray-50 px-1 text-xs'>{postCount}</div>
const links = [
{ id: 0, icon: faHome, name: locale.NAV.INDEX, to: '/' || '/', show: CONFIG_NEXT.MENU_HOME },
{ id: 1, icon: faTh, name: locale.COMMON.CATEGORY, to: '/category', show: CONFIG_NEXT.MENU_CATEGORY },
{ id: 2, icon: faTag, name: locale.COMMON.TAGS, to: '/tag', show: CONFIG_NEXT.MENU_TAG },
{ id: 3, icon: faArchive, name: locale.NAV.ARCHIVE, to: '/archive', slot: archiveSlot, show: CONFIG_NEXT.MENU_ARCHIVE },
{ id: 4, icon: faUser, name: locale.NAV.ABOUT, to: '/about', show: CONFIG_NEXT.MENU_ABOUT }
let links = [
{ icon: 'fas fa-home', name: locale.NAV.INDEX, to: '/' || '/', show: true },
{ icon: 'fas fa-th', name: locale.COMMON.CATEGORY, to: '/category', show: CONFIG_NEXT.MENU_CATEGORY },
{ icon: 'fas fa-tag', name: locale.COMMON.TAGS, to: '/tag', show: CONFIG_NEXT.MENU_TAG },
{ icon: 'fas fa-archive', name: locale.NAV.ARCHIVE, to: '/archive', slot: archiveSlot, show: CONFIG_NEXT.MENU_ARCHIVE },
{ icon: 'fas fa-user', name: locale.NAV.ABOUT, to: '/about', show: CONFIG_NEXT.MENU_ABOUT }
]
if (customNav) {
links = links.concat(customNav)
}
return <nav id='nav' className='leading-8 text-gray-500 dark:text-gray-400 font-sans'>
{links.map(link => {
if (link.show) {
if (link && 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} >
return <Link key={`${link.to}`} title={link.to} href={link.to} >
<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} />
<i className={`${link.icon} w-4 text-center`} />
<div className={'ml-4'}>{link.name}</div>
</div>
{link.slot}

View File

@@ -1,8 +1,6 @@
import BLOG from '@/blog.config'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faAngleLeft, faAngleRight } from '@fortawesome/free-solid-svg-icons'
/**
* 数字翻页插件
@@ -29,7 +27,7 @@ const PaginationNumber = ({ page, totalPage }) => {
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`}
>
<FontAwesomeIcon icon={faAngleLeft}/>
<i className='fas fa-angle-left'/>
</div>
</Link>
@@ -41,7 +39,7 @@ const PaginationNumber = ({ page, totalPage }) => {
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`}
>
<FontAwesomeIcon icon={faAngleRight}/>
<i className='fas fa-angle-right'/>
</div>
</Link>
</div>

View File

@@ -1,7 +1,5 @@
import React from 'react'
import Image from 'next/image'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faQrcode } from '@fortawesome/free-solid-svg-icons'
/**
* 赞赏按钮
@@ -23,7 +21,7 @@ const RewardButton = () => {
<div className='justify-center'>
<div onMouseEnter={openPopover} onMouseLeave={closePopover}
className='bg-pink-500 py-2 w-36 mx-auto animate__jello text-white hover:bg-green-400 duration-200 transform hover:scale-110 px-3 rounded cursor-pointer'>
<FontAwesomeIcon icon={faQrcode} className='mr-2' />
<i className='mr-2 fas fa-qrcode' />
<span>打赏一杯咖啡</span>
</div>

View File

@@ -1,8 +1,6 @@
import { useRouter } from 'next/router'
import { useGlobal } from '@/lib/global'
import { useImperativeHandle, useRef, useState } from 'react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faSearch, faSpinner, faTimes } from '@fortawesome/free-solid-svg-icons'
const SearchInput = ({ currentTag, currentSearch, cRef }) => {
const { locale } = useGlobal()
@@ -54,11 +52,11 @@ const SearchInput = ({ currentTag, currentSearch, cRef }) => {
onChange={e => updateSearchKey(e.target.value)}
defaultValue={searchKey}
/>
{(searchKey && searchKey.length && <FontAwesomeIcon icon={faTimes} className='text-gray-300 float-right m-3 cursor-pointer' onClick={cleanSearch} />)}
{(searchKey && searchKey.length && <i className='fas fa-times text-gray-300 float-right m-3 cursor-pointer' onClick={cleanSearch} />)}
<div className='p-3 bg-gray-50 flex border-l dark:border-gray-700 dark:hover:bg-gray-800 dark:bg-gray-600 justify-center items-center cursor-pointer'
onClick={() => { handleSearch(searchKey) }}>
<FontAwesomeIcon spin={onLoading} icon={onLoading ? faSpinner : faSearch} className='hover:scale-125 hover:text-black transform duration-200 dark:text-gray-300 dark:hover:text-white text-gray-600 cursor-pointer ' />
<i className={`${onLoading ? 'fa-spinner animate-spin ' : 'fa-search'} fas hover:scale-125 hover:text-black transform duration-200 dark:text-gray-300 dark:hover:text-white text-gray-600 cursor-pointer`} />
</div>
</div>
}

View File

@@ -5,16 +5,6 @@ import { createPopper } from '@popperjs/core'
import copy from 'copy-to-clipboard'
import QRCode from 'qrcode.react'
import { useGlobal } from '@/lib/global'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import {
faFacebookSquare,
faQq,
faTelegram,
faTwitterSquare,
faWeibo,
faWeixin
} from '@fortawesome/free-brands-svg-icons'
import { faLink } from '@fortawesome/free-solid-svg-icons'
import CONFIG_NEXT from '../config_next'
const ShareBar = ({ post }) => {
@@ -51,22 +41,22 @@ const ShareBar = ({ post }) => {
<div className='hidden md:block text-gray-800 dark:text-gray-300 mr-2 my-2 whitespace-nowrap'>{locale.COMMON.SHARE}:</div>
<div className='text-3xl cursor-pointer'>
<a className='text-blue-700' href={`https://www.facebook.com/sharer.php?u=${shareUrl}`} >
<FontAwesomeIcon icon={faFacebookSquare}/>
<i className='fab fa-facebook-square'/>
</a>
</div>
<div className='text-3xl cursor-pointer'>
<a className='text-blue-400' target='_blank' rel='noreferrer' href={`https://twitter.com/intent/tweet?title=${post.title}&url${shareUrl}`} >
<FontAwesomeIcon icon={faTwitterSquare}/>
<i className='fab fa-twitter-square'/>
</a>
</div>
<div className='text-3xl cursor-pointer'>
<a className='text-blue-500' href={`https://telegram.me/share/url?url=${shareUrl}&text=${post.title}`} >
<FontAwesomeIcon icon={faTelegram}/>
<i className='fab fa-telegram'/>
</a>
</div>
<div className='cursor-pointer text-2xl'>
<a className='text-green-600' ref={btnRef} onMouseEnter={openPopover} onMouseLeave={closePopover}>
<FontAwesomeIcon icon={faWeixin}/>
<i className='fab fa-weixin'/>
<div ref={popoverRef} className={(qrCodeShow ? 'animate__animated animate__fadeIn ' : 'hidden') + ' text-center py-2'}>
<div className='p-2 bg-white border-0 duration-200 transform block z-50 font-normal shadow-xl mr-10'>
<QRCode value={shareUrl} fgColor='#000000' />
@@ -79,17 +69,17 @@ const ShareBar = ({ post }) => {
</div>
<div className='cursor-pointer text-2xl'>
<a className='text-red-600' target='_blank' rel='noreferrer' href={`https://service.weibo.com/share/share.php?url=${shareUrl}&title=${post.title}`} >
<FontAwesomeIcon icon={faWeibo}/>
<i className='fab fa-weibo'/>
</a>
</div>
<div className='cursor-pointer text-2xl'>
<a className='text-blue-400' target='_blank' rel='noreferrer' href={`http://connect.qq.com/widget/shareqq/index.html?url=${shareUrl}&sharesource=qzone&title=${post.title}&desc=${post.summary}`} >
<FontAwesomeIcon icon={faQq}/>
<i className='fab fa-qq'/>
</a>
</div>
<div className='cursor-pointer text-2xl'>
<a className='text-yellow-600' onClick={copyUrl} >
<FontAwesomeIcon icon={faLink}/>
<i className='fab fa-link'/>
</a>
</div>
</div>

View File

@@ -1,7 +1,5 @@
import React from 'react'
import ShareBar from './ShareBar'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faShareAltSquare } from '@fortawesome/free-solid-svg-icons'
/**
* 悬浮在屏幕右下角,分享按钮
@@ -27,7 +25,7 @@ const ShareButton = ({ post }) => {
</div>
<div ref={btnRef}
className='z-20 border dark:border-gray-500 dark:bg-gray-600 bg-white cursor-pointer text-md hover:shadow-2xl shadow-lg'>
<FontAwesomeIcon icon={faShareAltSquare} className='transform duration-200 hover:scale-150 dark:text-gray-200 p-4' title='share' />
<i className='fas fa-share-alt-square transform duration-200 hover:scale-150 dark:text-gray-200 p-4' title='share' />
</div>
</div>
)

View File

@@ -18,7 +18,8 @@ import CONFIG_NEXT from '../config_next'
* @returns {JSX.Element}
* @constructor
*/
const SideAreaLeft = ({ currentTag, post, postCount, currentSearch }) => {
const SideAreaLeft = (props) => {
const { currentTag, post, postCount, currentSearch } = props
const { locale } = useGlobal()
const showToc = post && post.toc && post.toc.length > 1
return <aside id='left' className='hidden lg:block flex-col w-60 mr-4'>
@@ -28,7 +29,7 @@ const SideAreaLeft = ({ currentTag, post, postCount, currentSearch }) => {
<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 px-2 font-sans'>
<MenuButtonGroup allowCollapse={true} postCount={postCount} />
<MenuButtonGroup allowCollapse={true} {...props} />
</div>
{CONFIG_NEXT.MENU_SEARCH && <div className='px-2 pt-2 font-sans'>
<SearchInput currentTag={currentTag} currentSearch={currentSearch} />
@@ -47,7 +48,6 @@ const SideAreaLeft = ({ currentTag, post, postCount, currentSearch }) => {
<div key={locale.NAV.ABOUT} className='mb-5 bg-white dark:bg-gray-800 duration-200 py-6'>
<InfoCard />
<>
{/* <div className='px-5 text-sm font-light pb-1 text-gray-600 dark:text-gray-200'><FontAwesomeIcon icon={faChartBar} className='mr-2' />{locale.COMMON.ANALYTICS}</div> */}
<div className='mt-2 text-center dark:text-gray-300 font-light text-xs'>
<span className='px-1 '>
<strong className='font-medium'>{postCount}</strong>{locale.COMMON.POSTS}</span>

View File

@@ -1,6 +1,4 @@
import { useGlobal } from '@/lib/global'
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'
@@ -51,10 +49,10 @@ const SideAreaRight = ({
{CONFIG_NEXT.RIGHT_CATEGORY_LIST && categories && (
<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>
<div className='pb-1 text-gray-600 dark:text-gray-300'><i 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'>
{locale.COMMON.MORE} <FontAwesomeIcon icon={faAngleRight} />
{locale.COMMON.MORE} <i icon={faAngleRight} />
</a>
</Link>
</div>
@@ -68,13 +66,13 @@ const SideAreaRight = ({
<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={faTag} className="mr-2" />
<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}{' '}
<FontAwesomeIcon icon={faAngleDoubleRight} />
<i className='fas fa-angle-double-right' />
</a>
</Link>
</div>

View File

@@ -2,8 +2,6 @@ import CategoryGroup from './CategoryGroup'
import InfoCard from './InfoCard'
import TagGroups from './TagGroups'
import { useGlobal } from '@/lib/global'
import { faAngleDoubleRight, faTag, faThList } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Link from 'next/link'
import React from 'react'
@@ -32,10 +30,10 @@ const SideBar = ({ tags, currentTag, post, slot, categories, currentCategory })
{categories && (
<section className='mt-8'>
<div className='text-sm px-5 flex flex-nowrap justify-between font-light'>
<div className='text-gray-600 dark:text-gray-200'><FontAwesomeIcon icon={faThList} className='mr-2' />{locale.COMMON.CATEGORY}</div>
<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} <FontAwesomeIcon icon={faAngleDoubleRight} />
{locale.COMMON.MORE} <i className='fas fa-angle-double-right'/>
</a>
</Link>
</div>
@@ -47,10 +45,10 @@ const SideBar = ({ tags, currentTag, post, slot, categories, currentCategory })
{tags && (
<section className='mt-4'>
<div className='text-sm py-2 px-5 flex flex-nowrap justify-between font-light dark:text-gray-200'>
<div className='text-gray-600 dark:text-gray-200'><FontAwesomeIcon icon={faTag} className='mr-2'/>{locale.COMMON.TAGS}</div>
<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} <FontAwesomeIcon icon={faAngleDoubleRight} />
{locale.COMMON.MORE} <i className='fas fa-angle-double-right'/>
</a>
</Link>
</div>

View File

@@ -1,7 +1,4 @@
import BLOG from '@/blog.config'
import { faGithub, faTelegram, faTwitter, faWeibo } from '@fortawesome/free-brands-svg-icons'
import { faEnvelope, faRss } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import React from 'react'
/**
@@ -13,22 +10,22 @@ const SocialButton = () => {
return <div className='w-52 justify-center flex-wrap flex'>
<div className='space-x-3 text-xl text-gray-600 dark:text-gray-400 '>
{BLOG.CONTACT_GITHUB && <a target='_blank' rel='noreferrer' title={'github'} href={BLOG.CONTACT_GITHUB} >
<FontAwesomeIcon icon={faGithub} className='transform hover:scale-125 duration-150'/>
<i className='fab fa-github transform hover:scale-125 duration-150'/>
</a>}
{BLOG.CONTACT_TWITTER && <a target='_blank' rel='noreferrer' title={'twitter'} href={BLOG.CONTACT_TWITTER} >
<FontAwesomeIcon icon={faTwitter} className='transform hover:scale-125 duration-150'/>
<i className='fab fa-twitter transform hover:scale-125 duration-150'/>
</a>}
{BLOG.CONTACT_TELEGRAM && <a target='_blank' rel='noreferrer' href={BLOG.CONTACT_TELEGRAM} title={'telegram'} >
<FontAwesomeIcon icon={faTelegram} className='transform hover:scale-125 duration-150'/>
<i className='fab fa-telegram transform hover:scale-125 duration-150'/>
</a>}
{BLOG.CONTACT_WEIBO && <a target='_blank' rel='noreferrer' title={'weibo'} href={BLOG.CONTACT_WEIBO} >
<FontAwesomeIcon icon={faWeibo} className='transform hover:scale-125 duration-150'/>
<i className='fab fa-weibo transform hover:scale-125 duration-150'/>
</a>}
{BLOG.CONTACT_EMAIL && <a target='_blank' rel='noreferrer' title={'email'} href={`mailto:${BLOG.CONTACT_EMAIL}`} >
<FontAwesomeIcon icon={faEnvelope} className='transform hover:scale-125 duration-150'/>
<i className='fas fa-envelope transform hover:scale-125 duration-150'/>
</a>}
<a target='_blank' rel='noreferrer' title={'RSS'} href={'/feed'} >
<FontAwesomeIcon icon={faRss} className='transform hover:scale-125 duration-150'/>
<i className='fas fa-rss transform hover:scale-125 duration-150'/>
</a>
</div>
</div>

View File

@@ -1,5 +1,3 @@
import { faTag } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import Link from 'next/link'
import React from 'react'
import { useGlobal } from '@/lib/global'
@@ -16,7 +14,7 @@ const TagItem = ({ tag, selected }) => {
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 && <FontAwesomeIcon icon={faTag} className='mr-1'/>} {`${tag.name} `} {tag.count ? `(${tag.count})` : ''}
{selected && <i className='fas fa-tag mr-1'/>} {`${tag.name} `} {tag.count ? `(${tag.count})` : ''}
</div>
</li>
</Link>

Some files were not shown because too many files have changed in this diff Show More