Skip to content

Commit f4d54c8

Browse files
committed
theme-heo
1 parent 1d81886 commit f4d54c8

37 files changed

+739
-283
lines changed

components/Comment.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const ValineComponent = dynamic(() => import('@/components/ValineComponent'), {
5454
ssr: false
5555
})
5656

57-
const Comment = ({ frontMatter }) => {
57+
const Comment = ({ frontMatter, className }) => {
5858
const router = useRouter()
5959

6060
if (isBrowser() && ('giscus' in router.query || router.query.target === 'comment')) {
@@ -70,7 +70,7 @@ const Comment = ({ frontMatter }) => {
7070
}
7171

7272
return (
73-
<div id='comment' className='comment mt-5 text-gray-800 dark:text-gray-300'>
73+
<div id='comment' className={`comment mt-5 text-gray-800 dark:text-gray-300 ${className || ''}`}>
7474
<Tabs>
7575

7676
{BLOG.COMMENT_TWIKOO_ENV_ID && (<div key='Twikoo'>

components/FlipCard.js

+3-5
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ export default function FlipCard(props) {
1717
<div className={`flip-card-front ${props.className || ''}`} onMouseEnter={handleCardFlip}>
1818
{props.frontContent}
1919
</div>
20-
<div className={`flip-card-back ${props.className || ''}`} onMouseOut={handleCardFlip}>
20+
<div className={`flip-card-back ${props.className || ''}`} onMouseLeave={handleCardFlip}>
2121
{props.backContent}
2222
</div>
2323
<style jsx>{`
2424
.flip-card {
25-
width: auto;
26-
height: auto;
25+
width: 100%;
26+
height: 100%;
2727
display: inline-block;
2828
position: relative;
2929
transform-style: preserve-3d;
@@ -41,12 +41,10 @@ export default function FlipCard(props) {
4141
.flip-card-front {
4242
z-index: 2;
4343
transform: rotateY(0);
44-
background-color: #f1f1f1;
4544
}
4645
4746
.flip-card-back {
4847
transform: rotateY(180deg);
49-
background-color: #888;
5048
}
5149
5250
.flip-card.flipped {

components/ThemeSwitch.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@ const ThemeSwitch = () => {
2323

2424
return (<>
2525
<Draggable>
26-
<div id="draggableBox" style={{ left: '10px', top: '85vh' }} className="fixed dark:text-white bg-gray-50 dark:bg-black z-50 border dark:border-gray-800 rounded-xl shadow-card">
27-
<div className="py-2 flex items-center text-sm px-2">
28-
<DarkModeButton className='mr-1'/>
29-
<select value={theme} onChange={onSelectChange} name="cars" className=' outline-none dark:text-white bg-gray-50 dark:bg-black uppercase cursor-pointer'>
26+
<div id="draggableBox" style={{ left: '10px', top: '85vh' }} className="fixed dark:text-white bg-gray-50 dark:bg-black z-50 border dark:border-gray-800 rounded-2xl shadow-card">
27+
<div className="p-3 flex items-center text-sm">
28+
<DarkModeButton className='mr-2'/>
29+
<select value={theme} onChange={onSelectChange} name="cars" className='appearance-none outline-none dark:text-white bg-gray-50 dark:bg-black uppercase cursor-pointer'>
3030
{THEMES?.map(t => {
3131
return <option key={t} value={t}>{t}</option>
3232
})}
3333
</select>
34-
<i className='fas fa-palette pl-1' />
34+
<i class="fa-solid fa-paintbrush pl-2"></i>
3535
</div>
3636
</div>
3737
</Draggable>

components/WordCount.js

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { useGlobal } from '@/lib/global'
2+
import { useEffect } from 'react'
3+
4+
/**
5+
* 字数统计
6+
* @returns
7+
*/
8+
export default function WordCount() {
9+
const { locale } = useGlobal()
10+
useEffect(() => {
11+
countWords()
12+
})
13+
14+
return <span id='wordCountWrapper' className='flex gap-3 font-light'>
15+
<span className='flex whitespace-nowrap items-center'>
16+
<i className='pl-1 pr-2 fas fa-file-word' />
17+
<span id='wordCount'>0</span>
18+
</span>
19+
<span className='flex whitespace-nowrap items-center'>
20+
<i className='mr-1 fas fa-clock' />
21+
<span></span>
22+
<span id='readTime'>0</span>&nbsp;{locale.COMMON.MINUTE}
23+
</span>
24+
</span>
25+
}
26+
27+
/**
28+
* 更新字数统计和阅读时间
29+
*/
30+
function countWords() {
31+
const articleText = deleteHtmlTag(document.getElementById('notion-article')?.innerHTML)
32+
const wordCount = fnGetCpmisWords(articleText)
33+
// 阅读速度 300-500每分钟
34+
document.getElementById('wordCount').innerHTML = wordCount
35+
document.getElementById('readTime').innerHTML = Math.floor(wordCount / 400) + 1
36+
const wordCountWrapper = document.getElementById('wordCountWrapper')
37+
wordCountWrapper.classList.remove('hidden')
38+
}
39+
40+
// 去除html标签
41+
function deleteHtmlTag(str) {
42+
if (!str) {
43+
return ''
44+
}
45+
str = str.replace(/<[^>]+>|&[^>]+;/g, '').trim()// 去掉所有的html标签和&nbsp;之类的特殊符合
46+
return str
47+
}
48+
49+
// 用word方式计算正文字数
50+
function fnGetCpmisWords(str) {
51+
if (!str) {
52+
return 0
53+
}
54+
let sLen = 0
55+
try {
56+
// eslint-disable-next-line no-irregular-whitespace
57+
str = str.replace(/(\r\n+|\s+| +)/g, '龘')
58+
// eslint-disable-next-line no-control-regex
59+
str = str.replace(/[\x00-\xff]/g, 'm')
60+
str = str.replace(/m+/g, '*')
61+
str = str.replace(/+/g, '')
62+
sLen = str.length
63+
} catch (e) {
64+
65+
}
66+
return sLen
67+
}

lib/lang/en-US.js

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export default {
3535
SUBMIT: 'Submit',
3636
POST_TIME: 'Post on',
3737
LAST_EDITED_TIME: 'Last edited',
38+
COMMENTS: 'Comments',
3839
RECENT_COMMENTS: 'Recent Comments',
3940
DEBUG_OPEN: 'Debug',
4041
DEBUG_CLOSE: 'Close',

lib/lang/zh-CN.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export default {
1212
COMMON: {
1313
MORE: '更多',
1414
NO_MORE: '没有更多了',
15-
LATEST_POSTS: '最新文章',
15+
LATEST_POSTS: '最新发布',
1616
TAGS: '标签',
1717
NO_TAG: 'NoTag',
1818
CATEGORY: '分类',
@@ -37,6 +37,7 @@ export default {
3737
SUBMIT: '提交',
3838
POST_TIME: '发布于',
3939
LAST_EDITED_TIME: '最后更新',
40+
COMMENTS: '评论',
4041
RECENT_COMMENTS: '最新评论',
4142
DEBUG_OPEN: '开启调试',
4243
DEBUG_CLOSE: '关闭调试',

styles/notion.css

+1
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,7 @@ summary > .notion-h {
443443

444444
.notion-h:hover .notion-hash-link {
445445
opacity: 1;
446+
@apply dark:fill-gray-200
446447
}
447448

448449
.notion-hash-link {
+69-19
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,83 @@
11
import Link from 'next/link'
2+
import { useEffect, useState } from 'react'
23
import CONFIG from '../config'
34

45
/**
56
* 上一篇,下一篇文章
67
* @param {prev,next} param0
78
* @returns
89
*/
9-
export default function ArticleAdjacent ({ prev, next }) {
10+
export default function ArticleAdjacent({ prev, next }) {
11+
const [isScrollEnd, setIsScrollEnd] = useState(false)
12+
13+
useEffect(() => {
14+
// 文章是否已经到了底部
15+
const targetElement = document.getElementById('article-end')
16+
17+
const handleIntersect = (entries) => {
18+
entries.forEach((entry) => {
19+
console.log(entry.isIntersecting)
20+
if (entry.isIntersecting) {
21+
setIsScrollEnd(true)
22+
} else {
23+
// setIsScrollEnd(false)
24+
}
25+
})
26+
}
27+
28+
const options = {
29+
root: null,
30+
rootMargin: '0px',
31+
threshold: 0.1
32+
}
33+
34+
const observer = new IntersectionObserver(handleIntersect, options)
35+
observer.observe(targetElement)
36+
37+
return () => {
38+
observer.disconnect()
39+
}
40+
}, [])
41+
1042
if (!prev || !next || !CONFIG.ARTICLE_ADJACENT) {
1143
return <></>
1244
}
45+
1346
return (
14-
<section className='pt-8 text-gray-800 items-center text-xs md:text-sm flex justify-between m-1 '>
15-
<Link
16-
href={`/${prev.slug}`}
17-
passHref
18-
className='py-1 cursor-pointer hover:underline justify-start items-center dark:text-white flex w-full h-full duration-200'>
19-
20-
<i className='mr-1 fas fa-angle-left' />{prev.title}
21-
22-
</Link>
23-
<Link
24-
href={`/${next.slug}`}
25-
passHref
26-
className='py-1 cursor-pointer hover:underline justify-end items-center dark:text-white flex w-full h-full duration-200'>
27-
{next.title}
28-
<i className='ml-1 my-1 fas fa-angle-right' />
29-
30-
</Link>
31-
</section>
47+
<div id='article-end'>
48+
{/* 移动端 */}
49+
<section className='lg:hidden pt-8 text-gray-800 items-center text-xs md:text-sm flex flex-col m-1 '>
50+
<Link
51+
href={`/${prev.slug}`}
52+
passHref
53+
className='cursor-pointer justify-between space-y-1 px-5 py-6 rounded-t-xl dark:bg-[#1e1e1e] border dark:border-gray-600 border-b-0 items-center dark:text-white flex flex-col w-full h-18 duration-200'
54+
>
55+
<div className='flex justify-start items-center w-full'>上一篇</div>
56+
<div className='flex justify-center items-center text-lg font-bold'>{prev.title}</div>
57+
</Link>
58+
<Link
59+
href={`/${next.slug}`}
60+
passHref
61+
className='cursor-pointer justify-between space-y-1 px-5 py-6 rounded-b-xl dark:bg-[#1e1e1e] border dark:border-gray-600 items-center dark:text-white flex flex-col w-full h-18 duration-200'
62+
>
63+
<div className='flex justify-start items-center w-full'>下一篇</div>
64+
<div className='flex justify-center items-center text-lg font-bold'>{next.title}</div>
65+
</Link>
66+
</section>
67+
68+
{/* 桌面端 */}
69+
70+
<div id='pc-next-post' className={`hidden md:block fixed right-4 bottom-4 duration-200 transition-all ${isScrollEnd ? 'mb-0 opacity-100' : '-mb-24 opacity-0'}`}>
71+
<Link
72+
href={`/${next.slug}`}
73+
className='cursor-pointer duration transition-all w-52 h-24 dark:bg-[#1e1e1e] border dark:border-gray-600 p-3 bg-white hover:text-white hover:bg-gray-400 rounded-lg flex flex-col justify-between'
74+
>
75+
<div className='text-xs'>下一篇</div>
76+
<hr />
77+
<div>{next?.title}</div>
78+
</Link>
79+
</div>
80+
81+
</div>
3282
)
3383
}

themes/heo/components/ArticleRecommend.js

+45-40
Original file line numberDiff line numberDiff line change
@@ -13,53 +13,58 @@ export default function ArticleRecommend({ recommendPosts, siteInfo }) {
1313

1414
if (
1515
!CONFIG.ARTICLE_RECOMMEND ||
16-
!recommendPosts ||
17-
recommendPosts.length === 0
16+
!recommendPosts ||
17+
recommendPosts.length === 0
1818
) {
1919
return <></>
2020
}
2121

2222
return (
23-
<div className="pt-8">
24-
<div className=" mb-2 px-1 flex flex-nowrap justify-between">
25-
<div className='dark:text-gray-300'>
26-
<i className="mr-2 fas fa-thumbs-up" />
27-
{locale.COMMON.RELATE_POSTS}
28-
</div>
29-
</div>
30-
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
31-
{recommendPosts.map(post => {
32-
const headerImage = post?.pageCoverThumbnail
33-
? `url("${post.pageCoverThumbnail}")`
34-
: `url("${siteInfo?.pageCover}")`
35-
36-
return (
37-
(<Link
38-
key={post.id}
39-
title={post.title}
40-
href={`${BLOG.SUB_PATH}/${post.slug}`}
41-
passHref
42-
className="flex h-40 cursor-pointer overflow-hidden">
23+
<div className="pt-8 hidden md:block">
4324

44-
<div
45-
className="h-full w-full bg-cover bg-center bg-no-repeat hover:scale-110 transform duration-200"
46-
style={{ backgroundImage: headerImage }}
47-
>
48-
<div className="flex items-center justify-center bg-black bg-opacity-60 hover:bg-opacity-10 w-full h-full duration-300 ">
49-
<div className=" text-sm text-white text-center shadow-text">
50-
<div>
51-
<i className="fas fa-calendar-alt mr-1" />
52-
{post.date?.start_date}
53-
</div>
54-
<div className="">{post.title}</div>
55-
</div>
25+
{/* 推荐文章 */}
26+
<div className=" mb-2 px-1 flex flex-nowrap justify-between">
27+
<div className='dark:text-gray-300'>
28+
<i className="mr-2 fas fa-thumbs-up" />
29+
{locale.COMMON.RELATE_POSTS}
5630
</div>
57-
</div>
31+
</div>
32+
33+
{/* 文章列表 */}
34+
35+
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
36+
{recommendPosts.map(post => {
37+
const headerImage = post?.pageCoverThumbnail
38+
? `url("${post.pageCoverThumbnail}")`
39+
: `url("${siteInfo?.pageCover}")`
5840

59-
</Link>)
60-
)
61-
})}
62-
</div>
63-
</div>
41+
return (
42+
(<Link
43+
key={post.id}
44+
title={post.title}
45+
href={`${BLOG.SUB_PATH}/${post.slug}`}
46+
passHref
47+
className="flex h-40 cursor-pointer overflow-hidden rounded-2xl">
48+
49+
<div
50+
className="h-full w-full bg-cover bg-center bg-no-repeat hover:scale-110 transform duration-200"
51+
style={{ backgroundImage: headerImage }}
52+
>
53+
<div className="flex items-center justify-center bg-black bg-opacity-60 hover:bg-opacity-10 w-full h-full duration-300 ">
54+
<div className=" text-sm text-white text-center shadow-text">
55+
<div>
56+
<i className="fas fa-calendar-alt mr-1" />
57+
{post.date?.start_date}
58+
</div>
59+
<div className="">{post.title}</div>
60+
</div>
61+
</div>
62+
</div>
63+
64+
</Link>)
65+
)
66+
})}
67+
</div>
68+
</div>
6469
)
6570
}

0 commit comments

Comments
 (0)