diff --git a/.env.local b/.env.local index c1efd7f1..6a70781b 100644 --- a/.env.local +++ b/.env.local @@ -1,2 +1,2 @@ # 环境变量 @see https://www.nextjs.cn/docs/basic-features/environment-variables -NEXT_PUBLIC_VERSION=3.3.6 \ No newline at end of file +NEXT_PUBLIC_VERSION=3.3.7 \ No newline at end of file diff --git a/blog.config.js b/blog.config.js index 460d7268..920c12e0 100644 --- a/blog.config.js +++ b/blog.config.js @@ -102,7 +102,12 @@ const BLOG = { COMMENT_DAO_VOICE_ID: process.env.NEXT_PUBLIC_COMMENT_DAO_VOICE_ID || '', // DaoVoice http://dashboard.daovoice.io/get-started COMMENT_TIDIO_ID: process.env.NEXT_PUBLIC_COMMENT_TIDIO_ID || '', // [tidio_id] -> //code.tidio.co/[tidio_id].js - // 站点统计 + COMMENT_VALINE_APP_ID: process.env.NEXT_PUBLIC_VALINE_ID || '', // Valine @see https://valine.js.org/quickstart.html 或 https://github.com/stonehank/react-valine#%E8%8E%B7%E5%8F%96app-id-%E5%92%8C-app-key + COMMENT_VALINE_APP_KEY: process.env.NEXT_PUBLIC_VALINE_KEY || '', + COMMENT_VALINE_SERVER_URLS: process.env.NEXT_PUBLIC_VALINE_SERVER_URLS || '', // 该配置适用于国内自定义域名用户, 海外版本会自动检测(无需手动填写) @see https://valine.js.org/configuration.html#serverURLs + COMMENT_VALINE_PLACEHOLDER: process.env.NEXT_PUBLIC_VALINE_PLACEHOLDER || '抢个沙发吧~', // 可以搭配后台管理评论 https://github.com/DesertsP/Valine-Admin 便于查看评论,以及邮件通知,垃圾评论过滤等功能 + + // 站点统计 ANALYTICS_BUSUANZI_ENABLE: true, // 展示网站阅读量、访问数 see http://busuanzi.ibruce.info/ ANALYTICS_BAIDU_ID: process.env.NEXT_PUBLIC_ANALYTICS_BAIDU_ID || '', // e.g 只需要填写百度统计的id,[baidu_id] -> https://hm.baidu.com/hm.js?[baidu_id] ANALYTICS_CNZZ_ID: process.env.NEXT_PUBLIC_ANALYTICS_CNZZ_ID || '', // 只需要填写站长统计的id, [cnzz_id] -> https://s9.cnzz.com/z_stat.php?id=[cnzz_id]&web_id=[cnzz_id] diff --git a/components/Comment.js b/components/Comment.js index 915b96ee..890a92d1 100644 --- a/components/Comment.js +++ b/components/Comment.js @@ -24,12 +24,18 @@ const GiscusComponent = dynamic( { ssr: false } ) +const ValineComponent = dynamic(() => import('@/components/ValineComponent'), { + ssr: false +}) + const Comment = ({ frontMatter }) => { if (!frontMatter) { return <>Loading... } const router = useRouter() const { locale, isDarkMode } = useGlobal() + // const theme = isDarkMode ? 'dark' : 'light' + return (
@@ -40,19 +46,8 @@ const Comment = ({ frontMatter }) => {
)} - {BLOG.COMMENT_GITALK_CLIENT_ID && (
- + {BLOG.COMMENT_VALINE_APP_ID && (
+
)} {BLOG.COMMENT_UTTERRANCES_REPO && (
@@ -71,6 +66,21 @@ const Comment = ({ frontMatter }) => { }} />
)} + + {BLOG.COMMENT_GITALK_CLIENT_ID && (
+ +
)}
) diff --git a/components/CommonHead.js b/components/CommonHead.js index f4fe840a..d8aea1fc 100644 --- a/components/CommonHead.js +++ b/components/CommonHead.js @@ -43,9 +43,7 @@ const CommonHead = ({ meta, children }) => { - {JSON.parse(BLOG.ANALYTICS_BUSUANZI_ENABLE) && ( - - )} + {JSON.parse(BLOG.ANALYTICS_BUSUANZI_ENABLE) && } {meta?.type === 'article' && ( <> import('react-notion-x/build/third-party/code').then((m) => m.Code), { ssr: false } @@ -27,7 +28,7 @@ const NotionPage = ({ post }) => { return <>{post?.summary || ''} } - const zoom = typeof window !== 'undefined' && mediumZoom({ + const zoom = isBrowser() && mediumZoom({ container: '.notion-viewport', background: 'rgba(0, 0, 0, 0.2)', margin: getMediumZoomMargin() @@ -39,7 +40,7 @@ const NotionPage = ({ post }) => { addWatch4Dom() }, []) setTimeout(() => { - if (typeof document !== 'undefined') { + if (isBrowser()) { // 将相册gallery下的图片加入放大功能 const imgList = document.querySelectorAll('.notion-collection-card-cover img') if (imgList && zoomRef.current) { diff --git a/components/SideBarDrawer.js b/components/SideBarDrawer.js index b6c33530..ad988503 100644 --- a/components/SideBarDrawer.js +++ b/components/SideBarDrawer.js @@ -24,22 +24,20 @@ const SideBarDrawer = ({ children, isOpen, onOpen, onClose, className }) => { // 点击按钮更改侧边抽屉状态 const switchSideDrawerVisible = (showStatus) => { - if (window) { - if (showStatus) { - onOpen() - } else { - onClose() - } - const sideBarDrawer = window.document.getElementById('sidebar-drawer') - const sideBarDrawerBackground = window.document.getElementById('sidebar-drawer-background') + if (showStatus) { + onOpen() + } else { + onClose() + } + const sideBarDrawer = window.document.getElementById('sidebar-drawer') + const sideBarDrawerBackground = window.document.getElementById('sidebar-drawer-background') - if (showStatus) { - sideBarDrawer.classList.replace('-ml-80', 'ml-0') - sideBarDrawerBackground.classList.replace('hidden', 'block') - } else { - sideBarDrawer.classList.replace('ml-0', '-ml-80') - sideBarDrawerBackground.classList.replace('block', 'hidden') - } + if (showStatus) { + sideBarDrawer.classList.replace('-ml-80', 'ml-0') + sideBarDrawerBackground.classList.replace('hidden', 'block') + } else { + sideBarDrawer.classList.replace('ml-0', '-ml-80') + sideBarDrawerBackground.classList.replace('block', 'hidden') } } diff --git a/components/Valine.js b/components/Valine.js new file mode 100644 index 00000000..c1e915db --- /dev/null +++ b/components/Valine.js @@ -0,0 +1,3 @@ +import { Valine } from 'react-valine' + +export default Valine diff --git a/components/ValineComponent.js b/components/ValineComponent.js new file mode 100644 index 00000000..2829ace7 --- /dev/null +++ b/components/ValineComponent.js @@ -0,0 +1,26 @@ +import BLOG from '@/blog.config' +import React from 'react' +import Valine from 'valine' + +const ValineComponent = (props) => { + const { path } = props + React.useEffect(() => { + const valine = Valine({ + el: '#vcomments', + appId: BLOG.COMMENT_VALINE_APP_ID, + appKey: BLOG.COMMENT_VALINE_APP_KEY, + avatar: '', + path: path, + recordIP: false, + placeholder: BLOG.COMMENT_VALINE_PLACEHOLDER, + serverURLs: BLOG.COMMENT_VALINE_SERVER_URLS, + visitor: true + }) + if (!valine) { + console.error('valine插件加载失败') + } + }) + return
+} + +export default ValineComponent diff --git a/components/ValineCount.js b/components/ValineCount.js new file mode 100644 index 00000000..e07602f8 --- /dev/null +++ b/components/ValineCount.js @@ -0,0 +1,6 @@ +import { ValineCount } from 'react-valine' + +/** + * 显示评论数 + */ +export default ValineCount diff --git a/components/ValinePanel.js b/components/ValinePanel.js new file mode 100644 index 00000000..7755c1fd --- /dev/null +++ b/components/ValinePanel.js @@ -0,0 +1,3 @@ +import { ValinePanel } from 'react-valine' + +export default ValinePanel diff --git a/lib/lang.js b/lib/lang.js index 7c6594f9..8531761b 100644 --- a/lib/lang.js +++ b/lib/lang.js @@ -2,7 +2,7 @@ import zhCN from './lang/zh-CN' import enUS from './lang/en-US' import zhHK from './lang/zh-HK' import zhTW from './lang/zh-TW' -import { mergeDeep } from './utils' +import { isBrowser, mergeDeep } from './utils' const lang = { 'en-US': enUS, 'zh-CN': zhCN, @@ -45,7 +45,7 @@ export function generateLocaleDict (langString) { * 根据用户当前浏览器语言进行切换 */ export function initLocale (locale, changeLocale) { - if (typeof window !== 'undefined') { + if (isBrowser()) { const targetLocale = generateLocaleDict(window.navigator.language) if (JSON.stringify(locale) !== JSON.stringify(targetLocale)) { changeLocale(targetLocale) diff --git a/lib/notion/getPostBlocks.js b/lib/notion/getPostBlocks.js index 50e80032..dfd3988e 100644 --- a/lib/notion/getPostBlocks.js +++ b/lib/notion/getPostBlocks.js @@ -38,6 +38,7 @@ async function getPageWithRetry(id, from, retryAttempts = 3) { console.info('[响应成功]:', `from:${from}`, `id:${id}`) return pageData } catch (e) { + console.warn('[响应异常]:', e) await delay(1000) const cacheKey = 'page_block_' + id const pageBlock = await getDataFromCache(cacheKey) diff --git a/lib/utils.js b/lib/utils.js index e4b854a7..1119bdf9 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -32,7 +32,7 @@ export function loadExternalResource(url, type) { * @returns */ export function getQueryVariable(variable) { - const query = typeof window !== 'undefined' ? window.location.search.substring(1) : '' + const query = isBrowser() ? window.location.search.substring(1) : '' const vars = query.split('&') for (let i = 0; i < vars.length; i++) { const pair = vars[i].split('=') @@ -99,3 +99,9 @@ export function deepClone(obj) { * @returns */ export const delay = ms => new Promise(resolve => setTimeout(resolve, ms)) + +/** + * 判断是否客户端 + * @returns {boolean} + */ +export const isBrowser = () => typeof window !== 'undefined' diff --git a/package.json b/package.json index f6b327a4..ceae6563 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "notion-next", - "version": "3.3.6", + "version": "3.3.7", "homepage": "https://github.com/tangly1024/NotionNext.git", "license": "MIT", "repository": { @@ -47,7 +47,8 @@ "react-share": "^4.4.0", "smoothscroll-polyfill": "^0.4.4", "typed.js": "^2.0.12", - "use-ackee": "^3.0.0" + "use-ackee": "^3.0.0", + "valine": "^1.4.18" }, "devDependencies": { "autoprefixer": "^10.2.5", diff --git a/pages/[slug].js b/pages/[slug].js index 16f67e6c..64b949e9 100644 --- a/pages/[slug].js +++ b/pages/[slug].js @@ -5,6 +5,7 @@ import { useGlobal } from '@/lib/global' import * as ThemeMap from '@/themes' import React from 'react' import { useRouter } from 'next/router' +import { isBrowser } from '@/lib/utils' /** * 根据notion的slug访问页面,针对类型为Page的页面 @@ -20,7 +21,7 @@ const Slug = props => { changeLoadingState(true) const router = useRouter() setTimeout(() => { - if (typeof document !== 'undefined') { + if (isBrowser()) { const article = document.getElementById('container') if (!article) { router.push('/404').then(() => { diff --git a/pages/article/[slug].js b/pages/article/[slug].js index 89a42833..e654ee64 100644 --- a/pages/article/[slug].js +++ b/pages/article/[slug].js @@ -6,6 +6,7 @@ import * as ThemeMap from '@/themes' import React from 'react' import { idToUuid } from 'notion-utils' import { useRouter } from 'next/router' +import { isBrowser } from '@/lib/utils' /** * 根据notion的slug访问页面 @@ -21,7 +22,7 @@ const Slug = props => { changeLoadingState(true) const router = useRouter() setTimeout(() => { - if (typeof document !== 'undefined') { + if (isBrowser()) { const article = document.getElementById('container') if (!article) { router.push('/404').then(() => { diff --git a/pages/index.js b/pages/index.js index 1eb1f070..bc519e2c 100644 --- a/pages/index.js +++ b/pages/index.js @@ -27,7 +27,7 @@ export async function getStaticProps() { if (BLOG.POST_LIST_STYLE !== 'page') { postsToShow = Array.from(allPosts) } else { - postsToShow = allPosts.slice( + postsToShow = allPosts?.slice( BLOG.POSTS_PER_PAGE * (page - 1), BLOG.POSTS_PER_PAGE * page ) diff --git a/themes/example/LayoutSearch.js b/themes/example/LayoutSearch.js index c79c3ed0..29a07f99 100644 --- a/themes/example/LayoutSearch.js +++ b/themes/example/LayoutSearch.js @@ -5,6 +5,7 @@ import { useRouter } from 'next/router' import { useEffect, useState } from 'react' import SearchInput from './components/SearchInput' import LayoutBase from './LayoutBase' +import { isBrowser } from '@/lib/utils' export const LayoutSearch = props => { const { keyword, posts } = props @@ -12,7 +13,7 @@ export const LayoutSearch = props => { useEffect(() => { setTimeout(() => { - const container = typeof document !== 'undefined' && document.getElementById('container') + const container = isBrowser() && document.getElementById('container') if (container && container.innerHTML) { const re = new RegExp(`${keyword}`, 'gim') container.innerHTML = container.innerHTML.replace(re, `${keyword}`) diff --git a/themes/fukasawa/LayoutArchive.js b/themes/fukasawa/LayoutArchive.js index 79f6ea85..62128ec6 100644 --- a/themes/fukasawa/LayoutArchive.js +++ b/themes/fukasawa/LayoutArchive.js @@ -25,16 +25,14 @@ export const LayoutArchive = (props) => { }) useEffect(() => { - if (window) { - const anchor = window.location.hash - if (anchor) { - setTimeout(() => { - const anchorElement = document.getElementById(anchor.substring(1)) - if (anchorElement) { - anchorElement.scrollIntoView({ block: 'start', behavior: 'smooth' }) - } - }, 300) - } + const anchor = window.location.hash + if (anchor) { + setTimeout(() => { + const anchorElement = document.getElementById(anchor.substring(1)) + if (anchorElement) { + anchorElement.scrollIntoView({ block: 'start', behavior: 'smooth' }) + } + }, 300) } }, []) return diff --git a/themes/fukasawa/LayoutSearch.js b/themes/fukasawa/LayoutSearch.js index f3e8da7d..e4723c41 100644 --- a/themes/fukasawa/LayoutSearch.js +++ b/themes/fukasawa/LayoutSearch.js @@ -2,6 +2,7 @@ import LayoutBase from './LayoutBase' import BlogListPage from './components/BlogListPage' import { useRouter } from 'next/router' import { useEffect } from 'react' +import { isBrowser } from '@/lib/utils' export const LayoutSearch = (props) => { const { keyword } = props @@ -9,7 +10,7 @@ export const LayoutSearch = (props) => { const currentSearch = keyword || router?.query?.s useEffect(() => { setTimeout(() => { - const container = typeof document !== 'undefined' && document.getElementById('container') + const container = isBrowser() && document.getElementById('container') if (container && container.innerHTML) { const re = new RegExp(`${currentSearch}`, 'gim') container.innerHTML = container.innerHTML.replace(re, `${currentSearch}`) diff --git a/themes/hexo/Layout404.js b/themes/hexo/Layout404.js index 4ed0ebea..609b6e7c 100644 --- a/themes/hexo/Layout404.js +++ b/themes/hexo/Layout404.js @@ -7,13 +7,11 @@ export const Layout404 = props => { useEffect(() => { // 延时3秒如果加载失败就返回首页 setTimeout(() => { - if (window) { - const article = typeof document !== 'undefined' && document.getElementById('container') - if (!article) { - router.push('/').then(() => { - // console.log('找不到页面', router.asPath) - }) - } + const article = typeof document !== 'undefined' && document.getElementById('container') + if (!article) { + router.push('/').then(() => { + // console.log('找不到页面', router.asPath) + }) } }, 3000) }) diff --git a/themes/hexo/LayoutArchive.js b/themes/hexo/LayoutArchive.js index d2f86b3b..ed0e97fe 100644 --- a/themes/hexo/LayoutArchive.js +++ b/themes/hexo/LayoutArchive.js @@ -27,16 +27,14 @@ export const LayoutArchive = (props) => { }) useEffect(() => { - if (window) { - const anchor = window.location.hash - if (anchor) { - setTimeout(() => { - const anchorElement = document.getElementById(anchor.substring(1)) - if (anchorElement) { - anchorElement.scrollIntoView({ block: 'start', behavior: 'smooth' }) - } - }, 300) - } + const anchor = window.location.hash + if (anchor) { + setTimeout(() => { + const anchorElement = document.getElementById(anchor.substring(1)) + if (anchorElement) { + anchorElement.scrollIntoView({ block: 'start', behavior: 'smooth' }) + } + }, 300) } }, []) return diff --git a/themes/hexo/LayoutIndex.js b/themes/hexo/LayoutIndex.js index 18219cd4..1361c1e6 100644 --- a/themes/hexo/LayoutIndex.js +++ b/themes/hexo/LayoutIndex.js @@ -4,9 +4,11 @@ import BlogPostListScroll from './components/BlogPostListScroll' import Header from './components/Header' import CONFIG_HEXO from './config_hexo' import LayoutBase from './LayoutBase' +import React from 'react' export const LayoutIndex = (props) => { return }> + {BLOG.POST_LIST_STYLE === 'page' ? : } } diff --git a/themes/hexo/LayoutSlug.js b/themes/hexo/LayoutSlug.js index ce832a68..12697b01 100644 --- a/themes/hexo/LayoutSlug.js +++ b/themes/hexo/LayoutSlug.js @@ -11,6 +11,7 @@ import NotionPage from '@/components/NotionPage' import ArticleAdjacent from './components/ArticleAdjacent' import ArticleCopyright from './components/ArticleCopyright' import ArticleRecommend from './components/ArticleRecommend' +import { isBrowser } from '@/lib/utils' export const LayoutSlug = props => { const { post, lock, validPassword } = props @@ -30,7 +31,7 @@ export const LayoutSlug = props => { } const drawerRight = useRef(null) - const targetRef = typeof window !== 'undefined' ? document.getElementById('container') : null + const targetRef = isBrowser() ? document.getElementById('container') : null const floatSlot = <> {post?.toc?.length > 1 &&
diff --git a/themes/hexo/components/Header.js b/themes/hexo/components/Header.js index 9430c1db..eb811550 100644 --- a/themes/hexo/components/Header.js +++ b/themes/hexo/components/Header.js @@ -90,10 +90,8 @@ const Header = props => { function updateHeaderHeight () { setTimeout(() => { - if (window) { - const wrapperElement = document.getElementById('wrapper') - wrapperTop = wrapperElement?.offsetTop - } + const wrapperElement = document.getElementById('wrapper') + wrapperTop = wrapperElement?.offsetTop }, 500) } diff --git a/themes/hexo/components/Progress.js b/themes/hexo/components/Progress.js index b31ae16e..938f42f1 100644 --- a/themes/hexo/components/Progress.js +++ b/themes/hexo/components/Progress.js @@ -1,4 +1,5 @@ import React, { useEffect, useState } from 'react' +import { isBrowser } from '@/lib/utils' /** * 顶部页面阅读进度条 @@ -9,7 +10,7 @@ const Progress = ({ targetRef, showPercent = true }) => { const currentRef = targetRef?.current || targetRef const [percent, changePercent] = useState(0) const scrollListener = () => { - const target = currentRef || (typeof document !== 'undefined' && document.getElementById('container')) + const target = currentRef || (isBrowser() && document.getElementById('container')) if (target) { const clientHeight = target.clientHeight const scrollY = window.pageYOffset diff --git a/themes/medium/LayoutSearch.js b/themes/medium/LayoutSearch.js index 1b329b1c..6aa2ec5a 100644 --- a/themes/medium/LayoutSearch.js +++ b/themes/medium/LayoutSearch.js @@ -5,13 +5,14 @@ import TagGroups from './components/TagGroups' import CategoryGroup from './components/CategoryGroup' import BlogPostListScroll from './components/BlogPostListScroll' import { useEffect } from 'react' +import { isBrowser } from '@/lib/utils' export const LayoutSearch = (props) => { const { locale } = useGlobal() const { keyword } = props useEffect(() => { setTimeout(() => { - const container = typeof document !== 'undefined' && document.getElementById('container') + const container = isBrowser() && document.getElementById('container') if (container && container.innerHTML) { const re = new RegExp(`${keyword}`, 'gim') container.innerHTML = container.innerHTML.replace(re, `${keyword}`) diff --git a/themes/medium/components/Progress.js b/themes/medium/components/Progress.js index 50d2bc92..9a7cc7e0 100644 --- a/themes/medium/components/Progress.js +++ b/themes/medium/components/Progress.js @@ -1,4 +1,5 @@ import React, { useEffect, useState } from 'react' +import { isBrowser } from '@/lib/utils' /** * 顶部页面阅读进度条 @@ -9,7 +10,7 @@ const Progress = ({ targetRef, showPercent = true }) => { const currentRef = targetRef?.current || targetRef const [percent, changePercent] = useState(0) const scrollListener = () => { - const target = currentRef || (typeof document !== 'undefined' && document.getElementById('container')) + const target = currentRef || (isBrowser() && document.getElementById('container')) if (target) { const clientHeight = target.clientHeight const scrollY = window.pageYOffset diff --git a/themes/next/Layout404.js b/themes/next/Layout404.js index a9d18559..8c1bc421 100644 --- a/themes/next/Layout404.js +++ b/themes/next/Layout404.js @@ -1,19 +1,18 @@ import { useRouter } from 'next/router' import LayoutBase from './LayoutBase' import { useEffect } from 'react' +import { isBrowser } from '@/lib/utils' export const Layout404 = props => { const router = useRouter() useEffect(() => { // 延时3秒如果加载失败就返回首页 setTimeout(() => { - if (window) { - const article = typeof document !== 'undefined' && document.getElementById('container') - if (!article) { - router.push('/').then(() => { - // console.log('找不到页面', router.asPath) - }) - } + const article = isBrowser() && document.getElementById('container') + if (!article) { + router.push('/').then(() => { + // console.log('找不到页面', router.asPath) + }) } }, 3000) }, []) diff --git a/themes/next/LayoutArchive.js b/themes/next/LayoutArchive.js index f4f6ed3e..1b322fd0 100644 --- a/themes/next/LayoutArchive.js +++ b/themes/next/LayoutArchive.js @@ -26,16 +26,14 @@ export const LayoutArchive = (props) => { }) useEffect(() => { - if (window) { - const anchor = window.location.hash - if (anchor) { - setTimeout(() => { - const anchorElement = document.getElementById(anchor.substring(1)) - if (anchorElement) { - anchorElement.scrollIntoView({ block: 'start', behavior: 'smooth' }) - } - }, 300) - } + const anchor = window.location.hash + if (anchor) { + setTimeout(() => { + const anchorElement = document.getElementById(anchor.substring(1)) + if (anchorElement) { + anchorElement.scrollIntoView({ block: 'start', behavior: 'smooth' }) + } + }, 300) } }, []) diff --git a/themes/next/LayoutSearch.js b/themes/next/LayoutSearch.js index e3e58025..b1e0be2f 100644 --- a/themes/next/LayoutSearch.js +++ b/themes/next/LayoutSearch.js @@ -2,12 +2,13 @@ import LayoutBase from './LayoutBase' import StickyBar from './components/StickyBar' import BlogPostListScroll from './components/BlogPostListScroll' import { useGlobal } from '@/lib/global' +import { isBrowser } from '@/lib/utils' export const LayoutSearch = (props) => { const { locale } = useGlobal() const { posts, keyword } = props setTimeout(() => { - const container = typeof document !== 'undefined' && document.getElementById('container') + const container = isBrowser() && document.getElementById('container') if (container && container.innerHTML) { const re = new RegExp(`${keyword}`, 'gim') container.innerHTML = container.innerHTML.replace(re, `${keyword}`) diff --git a/themes/next/LayoutSlug.js b/themes/next/LayoutSlug.js index 8e7ddd72..9e1b0341 100644 --- a/themes/next/LayoutSlug.js +++ b/themes/next/LayoutSlug.js @@ -8,6 +8,7 @@ import TocDrawer from './components/TocDrawer' import { useRef } from 'react' import CONFIG_NEXT from './config_next' import { ArticleLock } from './components/ArticleLock' +import { isBrowser } from '@/lib/utils' export const LayoutSlug = (props) => { const { post, latestPosts, lock, validPassword } = props @@ -26,7 +27,7 @@ export const LayoutSlug = (props) => { } const drawerRight = useRef(null) - const targetRef = typeof window !== 'undefined' ? document.getElementById('container') : null + const targetRef = isBrowser() ? document.getElementById('container') : null const floatSlot = post?.toc?.length > 1 ?
{ drawerRight?.current?.handleSwitchVisible() diff --git a/themes/next/components/Header.js b/themes/next/components/Header.js index df6db180..77c6ce61 100644 --- a/themes/next/components/Header.js +++ b/themes/next/components/Header.js @@ -74,10 +74,8 @@ export default function Header(props) { function updateHeaderHeight() { setTimeout(() => { - if (window) { - const wrapperElement = document.getElementById('wrapper') - wrapperTop = wrapperElement.offsetTop - } + const wrapperElement = document.getElementById('wrapper') + wrapperTop = wrapperElement.offsetTop }, 500) } diff --git a/themes/next/components/Live2DWaifu.js b/themes/next/components/Live2DWaifu.js index f6d383f4..c21fc79a 100644 --- a/themes/next/components/Live2DWaifu.js +++ b/themes/next/components/Live2DWaifu.js @@ -4,9 +4,7 @@ import { loadExternalResource } from '@/lib/utils' export default function Live2DWife() { useEffect(() => { - if (window) { - initLive2DWife() - } + initLive2DWife() }, []) return <> diff --git a/themes/next/components/Progress.js b/themes/next/components/Progress.js index 19ca0ffa..91dfecc5 100644 --- a/themes/next/components/Progress.js +++ b/themes/next/components/Progress.js @@ -1,4 +1,5 @@ import React, { useEffect, useState } from 'react' +import { isBrowser } from '@/lib/utils' /** * 顶部页面阅读进度条 @@ -9,7 +10,7 @@ const Progress = ({ targetRef, showPercent = true }) => { const currentRef = targetRef?.current || targetRef const [percent, changePercent] = useState(0) const scrollListener = () => { - const target = currentRef || (typeof document !== 'undefined' && document.getElementById('container')) + const target = currentRef || (isBrowser() && document.getElementById('container')) if (target) { const clientHeight = target.clientHeight const scrollY = window.pageYOffset diff --git a/themes/next/components/RewardButton.js b/themes/next/components/RewardButton.js index 6de4f449..44733d6d 100644 --- a/themes/next/components/RewardButton.js +++ b/themes/next/components/RewardButton.js @@ -8,14 +8,10 @@ import Image from 'next/image' */ const RewardButton = () => { const openPopover = () => { - if (window) { - document.getElementById('reward-qrcode').classList.remove('hidden') - } + document.getElementById('reward-qrcode').classList.remove('hidden') } const closePopover = () => { - if (window) { - document.getElementById('reward-qrcode').classList.add('hidden') - } + document.getElementById('reward-qrcode').classList.add('hidden') } return (
diff --git a/themes/next/components/SideBarDrawer.js b/themes/next/components/SideBarDrawer.js index 8a22505d..213269f4 100644 --- a/themes/next/components/SideBarDrawer.js +++ b/themes/next/components/SideBarDrawer.js @@ -33,17 +33,15 @@ const SideBarDrawer = ({ post, cRef, tags, slot, categories, currentCategory }) // 点击按钮更改侧边抽屉状态 const switchSideDrawerVisible = (showStatus) => { - if (window) { - const sideBarDrawer = window.document.getElementById('sidebar-drawer') - const sideBarDrawerBackground = window.document.getElementById('sidebar-drawer-background') + const sideBarDrawer = window.document.getElementById('sidebar-drawer') + const sideBarDrawerBackground = window.document.getElementById('sidebar-drawer-background') - if (showStatus) { - sideBarDrawer.classList.replace('-ml-80', 'ml-0') - sideBarDrawerBackground.classList.replace('hidden', 'block') - } else { - sideBarDrawer.classList.replace('ml-0', '-ml-80') - sideBarDrawerBackground.classList.replace('block', 'hidden') - } + if (showStatus) { + sideBarDrawer.classList.replace('-ml-80', 'ml-0') + sideBarDrawerBackground.classList.replace('hidden', 'block') + } else { + sideBarDrawer.classList.replace('ml-0', '-ml-80') + sideBarDrawerBackground.classList.replace('block', 'hidden') } } diff --git a/themes/next/components/WordCount.js b/themes/next/components/WordCount.js index 37cd9efc..7188d90c 100644 --- a/themes/next/components/WordCount.js +++ b/themes/next/components/WordCount.js @@ -18,17 +18,15 @@ export default function WordCount() { * 更新字数统计和阅读时间 */ function countWords() { - if (window) { - const articleElement = document.getElementById('notion-article') - if (articleElement) { - const articleText = deleteHtmlTag(articleElement.innerHTML) - const wordCount = fnGetCpmisWords(articleText) - // 阅读速度 300-500每分钟 - document.getElementById('wordCount').innerHTML = wordCount - document.getElementById('readTime').innerHTML = Math.floor(wordCount / 400) + 1 - const wordCountWrapper = document.getElementById('wordCountWrapper') - wordCountWrapper.classList.remove('hidden') - } + const articleElement = document.getElementById('notion-article') + if (articleElement) { + const articleText = deleteHtmlTag(articleElement.innerHTML) + const wordCount = fnGetCpmisWords(articleText) + // 阅读速度 300-500每分钟 + document.getElementById('wordCount').innerHTML = wordCount + document.getElementById('readTime').innerHTML = Math.floor(wordCount / 400) + 1 + const wordCountWrapper = document.getElementById('wordCountWrapper') + wordCountWrapper.classList.remove('hidden') } }