mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-14 07:26:52 +00:00
NEXT主题-fontawesome改成引用CDN
This commit is contained in:
@@ -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,11 +31,12 @@ 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 ?? []
|
||||
properties.icon = pageBlock[id].value?.icon ?? null
|
||||
properties.tagItems = properties?.tags?.map(tag => {
|
||||
return { name: tag, color: tagOptions.find(t => t.value === tag)?.color || 'gray' }
|
||||
}) || []
|
||||
@@ -45,19 +46,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 +54,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) => {
|
||||
|
||||
@@ -12,27 +12,30 @@ 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?.filter(post =>
|
||||
post.title && post.slug &&
|
||||
post?.status?.[0] === 'Published' &&
|
||||
(post?.type?.[0] === 'Post')
|
||||
const allPosts = await getAllPosts({ notionPageData, from, pageType })
|
||||
const postCount = allPosts?.filter(post => post?.status?.[0] === 'Published' && (post?.type?.[0] === 'Post')
|
||||
)?.length
|
||||
const customNav = await getCustomNav({ notionPageData })
|
||||
const categories = await getAllCategories(allPosts)
|
||||
const tags = await getAllTags({ allPosts, tagOptions, sliceCount: tagsCount })
|
||||
// 深拷贝
|
||||
@@ -51,6 +54,7 @@ export async function getGlobalNotionData ({
|
||||
latestPosts,
|
||||
categories,
|
||||
postCount,
|
||||
customNav,
|
||||
tags
|
||||
}
|
||||
}
|
||||
@@ -77,6 +81,18 @@ 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'] })
|
||||
console.log(allPage)
|
||||
return [{ icon: 'fas fa-file-alt', name: '简历', to: '/' + 'resume', show: true }]
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取标签选项
|
||||
* @param schema
|
||||
|
||||
@@ -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",
|
||||
|
||||
59
pages/[slug].js
Normal file
59
pages/[slug].js
Normal file
@@ -0,0 +1,59 @@
|
||||
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
|
||||
@@ -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>
|
||||
)
|
||||
|
||||
@@ -26,7 +26,7 @@ export async function getStaticProps () {
|
||||
latestPosts
|
||||
} = await getGlobalNotionData({
|
||||
from,
|
||||
includePage: true
|
||||
pageType: ['Page']
|
||||
})
|
||||
const post = allPosts.find(p => p.slug === 'about')
|
||||
|
||||
|
||||
@@ -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 })
|
||||
|
||||
const post = allPosts.find(p => p.slug === slug)
|
||||
|
||||
@@ -61,7 +61,8 @@ export async function getStaticProps ({ params: { slug } }) {
|
||||
recommendPosts,
|
||||
categories,
|
||||
postCount,
|
||||
latestPosts
|
||||
latestPosts,
|
||||
customNav
|
||||
},
|
||||
revalidate: 1
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
{/* 右下角悬浮 */}
|
||||
|
||||
@@ -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>
|
||||
})}
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
|
||||
{/* 悬浮目录按钮 */}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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'/>
|
||||
|
||||
<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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
})}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
|
||||
@@ -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 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>
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
|
||||
@@ -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>)
|
||||
|
||||
@@ -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>)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
|
||||
@@ -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: true },
|
||||
{ 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} />
|
||||
<div className={'ml-4'}>{link.name}</div>
|
||||
</div>
|
||||
{link.slot}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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} />
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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='fas fa-tag mr-1'/>} {tag.name + (tag.count ? `(${tag.count})` : '')} </div>
|
||||
</a>
|
||||
</Link>
|
||||
}
|
||||
|
||||
@@ -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_NEXT from '../config_next'
|
||||
|
||||
@@ -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>)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { faAngleDoubleRight, faBars, faSearch, 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 { useCallback, useEffect, useRef, useState } from 'react'
|
||||
@@ -19,7 +17,8 @@ let windowTop = 0
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
const TopNav = ({ tags, currentTag, categories, currentCategory, postCount }) => {
|
||||
const TopNav = (props) => {
|
||||
const { tags, currentTag, categories, currentCategory } = props
|
||||
const { locale } = useGlobal()
|
||||
const searchDrawer = useRef()
|
||||
|
||||
@@ -57,10 +56,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>
|
||||
@@ -71,10 +70,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>
|
||||
@@ -94,7 +93,7 @@ const TopNav = ({ tags, currentTag, categories, currentCategory, postCount }) =>
|
||||
{/* 左侧LOGO 标题 */}
|
||||
<div className='flex flex-none flex-grow-0'>
|
||||
<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>
|
||||
|
||||
@@ -105,14 +104,14 @@ const TopNav = ({ tags, currentTag, categories, currentCategory, postCount }) =>
|
||||
{/* 右侧功能 */}
|
||||
<div className='mr-1 flex justify-end items-center text-sm space-x-4 font-serif dark:text-gray-200'>
|
||||
<div className="cursor-pointer block lg:hidden" onClick={() => { searchDrawer?.current?.show() }}>
|
||||
<FontAwesomeIcon icon={faSearch} className="mr-2" />{locale.NAV.SEARCH}
|
||||
<i className="mr-2 fas fa-search" />{locale.NAV.SEARCH}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Collapse isOpen={isOpen}>
|
||||
<div className='bg-white py-1 px-5'>
|
||||
<MenuButtonGroup postCount={postCount}/>
|
||||
<MenuButtonGroup {...props} from='top'/>
|
||||
</div>
|
||||
</Collapse>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { faClock, faFileWord } from '@fortawesome/free-solid-svg-icons'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
/**
|
||||
@@ -12,7 +10,7 @@ export default function WordCount () {
|
||||
})
|
||||
|
||||
return <div id='wordCountWrapper' className='hidden'>
|
||||
<FontAwesomeIcon icon={faFileWord} className='mr-1'/> 本文字数 <strong id='wordCount'>0</strong> | <FontAwesomeIcon className='mr-1' icon={faClock}/> 阅读时长 ≈ <strong id='readTime'>0</strong> 分钟
|
||||
<i className='mr-1 fas fa-file-word'/> 本文字数 <strong id='wordCount'>0</strong> | <i className='mr-1 fas fa-clock' /> 阅读时长 ≈ <strong id='readTime'>0</strong> 分钟
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user