diff --git a/.env.local b/.env.local
index c7c37481..f7d7ec09 100644
--- a/.env.local
+++ b/.env.local
@@ -1,2 +1,2 @@
# 环境变量 @see https://www.nextjs.cn/docs/basic-features/environment-variables
-NEXT_PUBLIC_VERSION=4.0.8
\ No newline at end of file
+NEXT_PUBLIC_VERSION=4.0.9
\ No newline at end of file
diff --git a/blog.config.js b/blog.config.js
index d1a0d961..32e80f10 100644
--- a/blog.config.js
+++ b/blog.config.js
@@ -119,6 +119,8 @@ const BLOG = {
// Mermaid 图表CDN
MERMAID_CDN: process.env.NEXT_PUBLIC_MERMAID_CDN || 'https://cdnjs.cloudflare.com/ajax/libs/mermaid/10.2.4/mermaid.min.js', // CDN
+ // QRCodeCDN
+ QR_CODE_CDN: process.env.NEXT_PUBLIC_QR_CODE_CDN || 'https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js',
BACKGROUND_LIGHT: '#eeeeee', // use hex value, don't forget '#' e.g #fffefc
BACKGROUND_DARK: '#000000', // use hex value, don't forget '#'
@@ -307,12 +309,10 @@ const BLOG = {
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]
ANALYTICS_GOOGLE_ID: process.env.NEXT_PUBLIC_ANALYTICS_GOOGLE_ID || '', // 谷歌Analytics的id e.g: G-XXXXXXXXXX
- ANALYTICS_ACKEE_TRACKER:
- process.env.NEXT_PUBLIC_ANALYTICS_ACKEE_TRACKER || '', // e.g 'https://ackee.tangly1024.net/tracker.js'
- ANALYTICS_ACKEE_DATA_SERVER:
- process.env.NEXT_PUBLIC_ANALYTICS_ACKEE_DATA_SERVER || '', // e.g https://ackee.tangly1024.net , don't end with a slash
- ANALYTICS_ACKEE_DOMAIN_ID:
- process.env.NEXT_PUBLIC_ANALYTICS_ACKEE_DOMAIN_ID || '', // e.g '0e2257a8-54d4-4847-91a1-0311ea48cc7b'
+ // ACKEE网站访客统计工具
+ ANALYTICS_ACKEE_TRACKER: process.env.NEXT_PUBLIC_ANALYTICS_ACKEE_TRACKER || '', // e.g 'https://ackee.tangly1024.com/tracker.js'
+ ANALYTICS_ACKEE_DATA_SERVER: process.env.NEXT_PUBLIC_ANALYTICS_ACKEE_DATA_SERVER || '', // e.g https://ackee.tangly1024.com , don't end with a slash
+ ANALYTICS_ACKEE_DOMAIN_ID: process.env.NEXT_PUBLIC_ANALYTICS_ACKEE_DOMAIN_ID || '', // e.g '82e51db6-dec2-423a-b7c9-b4ff7ebb3302'
SEO_GOOGLE_SITE_VERIFICATION:
process.env.NEXT_PUBLIC_SEO_GOOGLE_SITE_VERIFICATION || '', // Remove the value or replace it with your own google site verification code
diff --git a/components/Ackee.js b/components/Ackee.js
index ab22c969..dd9467f0 100644
--- a/components/Ackee.js
+++ b/components/Ackee.js
@@ -1,21 +1,83 @@
-import { useRouter } from 'next/router'
-import useAckee from 'use-ackee'
-import BLOG from '@/blog.config'
+'use strict'
+import { useEffect } from 'react'
+import BLOG from '@/blog.config'
+import { loadExternalResource } from '@/lib/utils'
+import { useRouter } from 'next/router'
const Ackee = () => {
const router = useRouter()
- useAckee(
- router.asPath,
- {
- server: BLOG.ANALYTICS_ACKEE_DATA_SERVER,
- domainId: BLOG.ANALYTICS_ACKEE_DOMAIN_ID
- },
- {
- detailed: false,
- ignoreLocalhost: true
- }
- )
+
+ // handleAckee 函数
+ const handleAckeeCallback = () => {
+ handleAckee(
+ router.asPath,
+ {
+ server: BLOG.ANALYTICS_ACKEE_DATA_SERVER,
+ domainId: BLOG.ANALYTICS_ACKEE_DOMAIN_ID
+ },
+ {
+ /*
+ * Enable or disable tracking of personal data.
+ * We recommend to ask the user for permission before turning this option on.
+ */
+ detailed: true,
+ /*
+ * Enable or disable tracking when on localhost.
+ */
+ ignoreLocalhost: false,
+ /*
+ * Enable or disable the tracking of your own visits.
+ * This is enabled by default, but should be turned off when using a wildcard Access-Control-Allow-Origin header.
+ * Some browsers strictly block third-party cookies. The option won't have an impact when this is the case.
+ */
+ ignoreOwnVisits: false
+ }
+ )
+ }
+
+ // 或者使用其他依赖数组,根据需要执行 handleAckee
+ useEffect(() => {
+ handleAckeeCallback()
+ }, [router])
+
return null
}
export default Ackee
+
+/**
+ * Function to use Ackee.
+ * Creates an instance once and a new record every time the pathname changes.
+ * Safely no-ops during server-side rendering.
+ * @param {?String} pathname - Current path.
+ * @param {Object} environment - Object containing the URL of the Ackee server and the domain id.
+ * @param {?Object} options - Ackee options.
+ */
+const handleAckee = async function(pathname, environment, options = {}) {
+ await loadExternalResource(BLOG.ANALYTICS_ACKEE_TRACKER, 'js')
+ const ackeeTracker = window.ackeeTracker
+
+ const instance = ackeeTracker.create(environment.server, options)
+
+ if (instance == null) {
+ console.warn('Skipped record creation because useAckee has been called in a non-browser environment')
+ return
+ }
+
+ const hasPathname = (
+ pathname != null && pathname !== ''
+ )
+
+ if (hasPathname === false) {
+ console.warn('Skipped record creation because useAckee has been called without pathname')
+ return
+ }
+
+ const attributes = ackeeTracker.attributes(options.detailed)
+ const url = new URL(pathname, location)
+
+ return instance.record(environment.domainId, {
+ ...attributes,
+ siteLocation: url.href
+ }).stop
+}
diff --git a/components/Comment.js b/components/Comment.js
index 2baebfbb..1b335fe7 100644
--- a/components/Comment.js
+++ b/components/Comment.js
@@ -62,7 +62,7 @@ const ValineComponent = dynamic(() => import('@/components/ValineComponent'), {
const Comment = ({ frontMatter, className }) => {
const router = useRouter()
- if (isBrowser() && ('giscus' in router.query || router.query.target === 'comment')) {
+ if (isBrowser && ('giscus' in router.query || router.query.target === 'comment')) {
setTimeout(() => {
const url = router.asPath.replace('?target=comment', '')
history.replaceState({}, '', url)
diff --git a/components/CommonScript.js b/components/CommonScript.js
index 6912c3cc..4bef4da0 100644
--- a/components/CommonScript.js
+++ b/components/CommonScript.js
@@ -56,12 +56,12 @@ const CommonScript = () => {
{/* 代码统计 */}
{/* ackee统计脚本 */}
- {BLOG.ANALYTICS_ACKEE_TRACKER && (
+ {/* {BLOG.ANALYTICS_ACKEE_TRACKER && (
- )}
+ )} */}
{/* 百度统计 */}
{BLOG.ANALYTICS_BAIDU_ID && (
diff --git a/components/CusdisComponent.js b/components/CusdisComponent.js
index 83b962b5..b3fa0bda 100644
--- a/components/CusdisComponent.js
+++ b/components/CusdisComponent.js
@@ -1,8 +1,8 @@
import { useGlobal } from '@/lib/global'
-import { ReactCusdis } from 'react-cusdis'
import BLOG from '@/blog.config'
import { useRouter } from 'next/router'
import { useEffect } from 'react'
+import { loadExternalResource } from '@/lib/utils'
const CusdisComponent = ({ frontMatter }) => {
const { locale } = useGlobal()
@@ -11,33 +11,21 @@ const CusdisComponent = ({ frontMatter }) => {
// 处理cusdis主题
useEffect(() => {
- const cusdisThread = document?.getElementById('cusdis_thread')
- const cusdisIframe = cusdisThread?.getElementsByTagName('iframe')
- if (cusdisIframe) {
- const cusdisWrapper = cusdisIframe[0]?.contentDocument?.getElementById('root')
- if (isDarkMode) {
- cusdisWrapper?.classList?.remove('light')
- cusdisWrapper?.classList?.add('dark')
- } else {
- cusdisWrapper?.classList?.remove('dark')
- cusdisWrapper?.classList?.add('light')
- }
- if (!cusdisWrapper?.firstElementChild?.classList?.contains('dark:text-gray-100')) {
- cusdisWrapper?.firstElementChild?.classList?.add('dark:text-gray-100')
- }
- }
- })
+ loadExternalResource(BLOG.COMMENT_CUSDIS_SCRIPT_SRC, 'js').then(url => {
+ const CUSDIS = window.CUSDIS
+ CUSDIS.initial()
+ })
+ }, [isDarkMode])
- return
+ return
}
export default CusdisComponent
diff --git a/components/ExternalScript.js b/components/ExternalScript.js
index 62b6e95c..7f5d015d 100644
--- a/components/ExternalScript.js
+++ b/components/ExternalScript.js
@@ -8,7 +8,7 @@ import { isBrowser, loadExternalResource } from '@/lib/utils'
* @returns
*/
const ExternalScript = () => {
- if (isBrowser()) {
+ if (isBrowser) {
// 静态导入本地自定义样式
loadExternalResource('/css/custom.css', 'css')
loadExternalResource('/js/custom.js', 'js')
diff --git a/components/FacebookMessenger.js b/components/FacebookMessenger.js
index 0948996a..7487002b 100644
--- a/components/FacebookMessenger.js
+++ b/components/FacebookMessenger.js
@@ -1,11 +1,255 @@
import BLOG from '@/blog.config'
-import MessengerCustomerChat from 'react-messenger-customer-chat'
+import { Component } from 'react'
+import PropTypes from 'prop-types'
-const Messenger = () => (
-
-)
-export default Messenger
+}
+
+/**
+ * @see https://github.com/Yoctol/react-messenger-customer-chat
+ */
+class MessengerCustomerChat extends Component {
+ constructor(props) {
+ super(props)
+ this.state = {
+ fbLoaded: false,
+ shouldShowDialog: undefined
+ }
+ }
+
+ /**
+ * 初始化
+ */
+ componentDidMount() {
+ this.setFbAsyncInit()
+ this.reloadSDKAsynchronously()
+ }
+
+ componentDidUpdate(prevProps) {
+ if (
+ prevProps.pageId !== this.props.pageId ||
+ prevProps.appId !== this.props.appId ||
+ prevProps.shouldShowDialog !== this.props.shouldShowDialog ||
+ prevProps.htmlRef !== this.props.htmlRef ||
+ prevProps.minimized !== this.props.minimized ||
+ prevProps.themeColor !== this.props.themeColor ||
+ prevProps.loggedInGreeting !== this.props.loggedInGreeting ||
+ prevProps.loggedOutGreeting !== this.props.loggedOutGreeting ||
+ prevProps.greetingDialogDisplay !== this.props.greetingDialogDisplay ||
+ prevProps.greetingDialogDelay !== this.props.greetingDialogDelay ||
+ prevProps.autoLogAppEvents !== this.props.autoLogAppEvents ||
+ prevProps.xfbml !== this.props.xfbml ||
+ prevProps.version !== this.props.version ||
+ prevProps.language !== this.props.language
+ ) {
+ this.setFbAsyncInit()
+ this.reloadSDKAsynchronously()
+ }
+ }
+
+ componentWillUnmount() {
+ if (window.FB !== undefined) {
+ window.FB.CustomerChat.hide()
+ }
+ }
+
+ /**
+ * 初始化
+ */
+ setFbAsyncInit() {
+ const { appId, autoLogAppEvents, xfbml, version } = this.props
+
+ window.fbAsyncInit = () => {
+ window.FB.init({
+ appId,
+ autoLogAppEvents,
+ xfbml,
+ version: `v${version}`
+ })
+
+ this.setState({ fbLoaded: true })
+ }
+ }
+
+ loadSDKAsynchronously() {
+ const { language } = this.props;
+ /* eslint-disable */
+ (function (d, s, id) {
+ var js,
+ fjs = d.getElementsByTagName(s)[0];
+ if (d.getElementById(id)) {
+ return;
+ }
+ js = d.createElement(s);
+ js.id = id;
+ js.src = `https://connect.facebook.net/${language}/sdk/xfbml.customerchat.js`;
+ fjs.parentNode.insertBefore(js, fjs);
+ })(document, 'script', 'facebook-jssdk');
+ /* eslint-enable */
+ }
+
+ removeFacebookSDK() {
+ removeElementByIds(['facebook-jssdk', 'fb-root'])
+
+ delete window.FB
+ }
+
+ reloadSDKAsynchronously() {
+ this.removeFacebookSDK()
+ this.loadSDKAsynchronously()
+ }
+
+ controlPlugin() {
+ const { shouldShowDialog } = this.props
+
+ if (shouldShowDialog) {
+ window.FB.CustomerChat.showDialog()
+ } else {
+ window.FB.CustomerChat.hideDialog()
+ }
+ }
+
+ subscribeEvents() {
+ const { onCustomerChatDialogShow, onCustomerChatDialogHide } = this.props
+
+ if (onCustomerChatDialogShow) {
+ window.FB.Event.subscribe(
+ 'customerchat.dialogShow',
+ onCustomerChatDialogShow
+ )
+ }
+
+ if (onCustomerChatDialogHide) {
+ window.FB.Event.subscribe(
+ 'customerchat.dialogHide',
+ onCustomerChatDialogHide
+ )
+ }
+ }
+
+ createMarkup() {
+ const {
+ pageId,
+ htmlRef,
+ minimized,
+ themeColor,
+ loggedInGreeting,
+ loggedOutGreeting,
+ greetingDialogDisplay,
+ greetingDialogDelay
+ } = this.props
+
+ const refAttribute = htmlRef !== undefined ? `ref="${htmlRef}"` : ''
+ const minimizedAttribute =
+ minimized !== undefined ? `minimized="${minimized}"` : ''
+ const themeColorAttribute =
+ themeColor !== undefined ? `theme_color="${themeColor}"` : ''
+ const loggedInGreetingAttribute =
+ loggedInGreeting !== undefined
+ ? `logged_in_greeting="${loggedInGreeting}"`
+ : ''
+ const loggedOutGreetingAttribute =
+ loggedOutGreeting !== undefined
+ ? `logged_out_greeting="${loggedOutGreeting}"`
+ : ''
+ const greetingDialogDisplayAttribute =
+ greetingDialogDisplay !== undefined
+ ? `greeting_dialog_display="${greetingDialogDisplay}"`
+ : ''
+ const greetingDialogDelayAttribute =
+ greetingDialogDelay !== undefined
+ ? `greeting_dialog_delay="${greetingDialogDelay}"`
+ : ''
+
+ return {
+ __html: ``
+ }
+ }
+
+ render() {
+ const { fbLoaded, shouldShowDialog } = this.state
+
+ if (fbLoaded && shouldShowDialog !== this.props.shouldShowDialog) {
+ document.addEventListener(
+ 'DOMNodeInserted',
+ (event) => {
+ const element = event.target
+ if (
+ element.className &&
+ typeof element.className === 'string' &&
+ element.className.includes('fb_dialog')
+ ) {
+ this.controlPlugin()
+ }
+ },
+ false
+ )
+ this.subscribeEvents()
+ }
+ // Add a random key to rerender. Reference:
+ // https://stackoverflow.com/questions/30242530/dangerouslysetinnerhtml-doesnt-update-during-render
+ return
+ }
+}
+
+const removeElementByIds = (ids) => {
+ ids.forEach((id) => {
+ const element = document.getElementById(id)
+ if (element && element.parentNode) {
+ element.parentNode.removeChild(element)
+ }
+ })
+}
+
+MessengerCustomerChat.propTypes = {
+ pageId: PropTypes.string.isRequired,
+ appId: PropTypes.string,
+ shouldShowDialog: PropTypes.bool,
+ htmlRef: PropTypes.string,
+ minimized: PropTypes.bool,
+ themeColor: PropTypes.string,
+ loggedInGreeting: PropTypes.string,
+ loggedOutGreeting: PropTypes.string,
+ greetingDialogDisplay: PropTypes.oneOf(['show', 'hide', 'fade']),
+ greetingDialogDelay: PropTypes.number,
+ autoLogAppEvents: PropTypes.bool,
+ xfbml: PropTypes.bool,
+ version: PropTypes.string,
+ language: PropTypes.string,
+ onCustomerChatDialogShow: PropTypes.func,
+ onCustomerChatDialogHide: PropTypes.func
+}
+
+MessengerCustomerChat.defaultProps = {
+ appId: null,
+ shouldShowDialog: false,
+ htmlRef: undefined,
+ minimized: undefined,
+ themeColor: undefined,
+ loggedInGreeting: undefined,
+ loggedOutGreeting: undefined,
+ greetingDialogDisplay: undefined,
+ greetingDialogDelay: undefined,
+ autoLogAppEvents: true,
+ xfbml: true,
+ version: '11.0',
+ language: 'en_US',
+ onCustomerChatDialogShow: undefined,
+ onCustomerChatDialogHide: undefined
+}
diff --git a/components/FacebookPage.js b/components/FacebookPage.js
index e4e52c93..95f77fc1 100644
--- a/components/FacebookPage.js
+++ b/components/FacebookPage.js
@@ -2,13 +2,17 @@ import BLOG from '@/blog.config'
import { FacebookProvider, Page } from 'react-facebook'
import { FacebookIcon } from 'react-share'
+/**
+ * facebook个人主页
+ * @returns
+ */
const FacebookPage = () => {
- if (!BLOG.FACEBOOK_APP_ID && !BLOG.FACEBOOK_PAGE) {
+ if (!BLOG.FACEBOOK_APP_ID || !BLOG.FACEBOOK_PAGE) {
return <>>
}
return
{BLOG.FACEBOOK_PAGE && (
-
+
{
const [isFullScreen, setIsFullScreen] = useState(false)
const handleFullScreenClick = () => {
- if (!isBrowser()) {
+ if (!isBrowser) {
return
}
const element = document.documentElement
diff --git a/components/GoogleAdsense.js b/components/GoogleAdsense.js
index 22fca879..420dc993 100644
--- a/components/GoogleAdsense.js
+++ b/components/GoogleAdsense.js
@@ -21,7 +21,7 @@ export default function GoogleAdsense() {
for (let i = 0; i <= ads.length; i++) {
try {
adsbygoogle.push(ads[i])
- console.log('adsbygoogle', i, ads[i], adsbygoogle)
+ // console.log('adsbygoogle', i, ads[i], adsbygoogle)
} catch (e) {
}
diff --git a/components/NotionPage.js b/components/NotionPage.js
index 0ff61e11..16e8716e 100644
--- a/components/NotionPage.js
+++ b/components/NotionPage.js
@@ -65,7 +65,7 @@ const NotionPage = ({ post, className }) => {
// 将相册gallery下的图片加入放大功能
if (JSON.parse(BLOG.POST_DISABLE_GALLERY_CLICK)) {
setTimeout(() => {
- if (isBrowser()) {
+ if (isBrowser) {
const imgList = document?.querySelectorAll('.notion-collection-card-cover img')
if (imgList && zoomRef.current) {
for (let i = 0; i < imgList.length; i++) {
@@ -80,6 +80,25 @@ const NotionPage = ({ post, className }) => {
}
}, 800)
}
+
+ /**
+ * 处理页面内连接跳转
+ * 如果链接就是当前网站,则不打开新窗口访问
+ */
+ if (isBrowser) {
+ const currentURL = window.location.origin + window.location.pathname
+ const allAnchorTags = document.getElementsByTagName('a') // 或者使用 document.querySelectorAll('a') 获取 NodeList
+ for (const anchorTag of allAnchorTags) {
+ if (anchorTag?.target === '_blank') {
+ const hrefWithoutQueryHash = anchorTag.href.split('?')[0].split('#')[0]
+ const hrefWithRelativeHash = currentURL.split('#')[0] + anchorTag.href.split('#')[1]
+
+ if (currentURL === hrefWithoutQueryHash || currentURL === hrefWithRelativeHash) {
+ anchorTag.target = '_self'
+ }
+ }
+ }
+ }
}, [])
if (!post || !post.blockMap) {
diff --git a/components/PrismMac.js b/components/PrismMac.js
index 172c6ceb..38742281 100644
--- a/components/PrismMac.js
+++ b/components/PrismMac.js
@@ -141,7 +141,6 @@ const renderMermaid = async() => {
if (needLoad) {
loadExternalResource(BLOG.MERMAID_CDN, 'js').then(url => {
const mermaid = window.mermaid
- console.log('mermaid加载成功', url, mermaid)
mermaid.contentLoaded()
})
}
diff --git a/components/QrCode.js b/components/QrCode.js
new file mode 100644
index 00000000..ca78c881
--- /dev/null
+++ b/components/QrCode.js
@@ -0,0 +1,34 @@
+import BLOG from '@/blog.config'
+import { loadExternalResource } from '@/lib/utils'
+import { useEffect } from 'react'
+
+/**
+ * 二维码生成
+ */
+export default function QrCode({ value }) {
+ useEffect(() => {
+ let qrcode
+ if (!value) {
+ return
+ }
+ loadExternalResource(BLOG.QR_CODE_CDN, 'js').then(url => {
+ const QRCode = window.QRCode
+ qrcode = new QRCode(document.getElementById('qrcode'), {
+ text: value,
+ width: 256,
+ height: 256,
+ colorDark: '#000000',
+ colorLight: '#ffffff',
+ correctLevel: QRCode.CorrectLevel.H
+ })
+ console.log('二维码', qrcode, value)
+ })
+ return () => {
+ if (qrcode) {
+ qrcode.clear() // clear the code.
+ }
+ }
+ }, [])
+
+ return
+}
diff --git a/components/ShareButtons.js b/components/ShareButtons.js
index ca860d22..efd3ab87 100644
--- a/components/ShareButtons.js
+++ b/components/ShareButtons.js
@@ -49,12 +49,7 @@ import {
HatenaIcon
} from 'react-share'
-const QRCode = dynamic(
- () => {
- return import('qrcode.react')
- },
- { ssr: false }
-)
+const QrCode = dynamic(() => import('@/components/QrCode'), { ssr: false })
/**
* @author https://github.com/txs
@@ -353,8 +348,8 @@ const ShareButtons = ({ shareUrl, title, body, image }) => {
-
-
+
+
{locale.COMMON.SCAN_QR_CODE}
diff --git a/components/Twikoo.js b/components/Twikoo.js
index 7b6080b6..233e77ad 100644
--- a/components/Twikoo.js
+++ b/components/Twikoo.js
@@ -13,8 +13,7 @@ import { useEffect } from 'react'
const Twikoo = ({ isDarkMode }) => {
const loadTwikoo = async () => {
try {
- const url = await loadExternalResource(BLOG.COMMENT_TWIKOO_CDN_URL, 'js')
- console.log('twikoo 加载成功', url)
+ await loadExternalResource(BLOG.COMMENT_TWIKOO_CDN_URL, 'js')
const twikoo = window.twikoo
twikoo.init({
envId: BLOG.COMMENT_TWIKOO_ENV_ID, // 腾讯云环境填 envId;Vercel 环境填地址(https://xxx.vercel.app)
diff --git a/components/ValineComponent.js b/components/ValineComponent.js
index 3a7464b3..0a7ab6cb 100644
--- a/components/ValineComponent.js
+++ b/components/ValineComponent.js
@@ -6,7 +6,6 @@ const ValineComponent = ({ path }) => {
const loadValine = async () => {
try {
await loadExternalResource(BLOG.COMMENT_VALINE_CDN, 'js')
- // console.log('valine 加载成功', url)
const Valine = window.Valine
// eslint-disable-next-line no-unused-vars
const valine = new Valine({
diff --git a/lib/global.js b/lib/global.js
index 04d0176e..c290a9e0 100644
--- a/lib/global.js
+++ b/lib/global.js
@@ -91,7 +91,7 @@ export function GlobalContextProvider(props) {
* @param {*} setTheme
*/
const initTheme = () => {
- if (isBrowser()) {
+ if (isBrowser) {
setTimeout(() => {
const elements = document.querySelectorAll('[id^="theme-"]')
if (elements?.length > 1) {
diff --git a/lib/lang.js b/lib/lang.js
index 83f867b3..abc51354 100644
--- a/lib/lang.js
+++ b/lib/lang.js
@@ -64,7 +64,7 @@ export function generateLocaleDict(langString) {
* 根据用户当前浏览器语言进行切换
*/
export function initLocale(lang, locale, changeLang, changeLocale) {
- if (isBrowser()) {
+ if (isBrowser) {
const queryLang = getQueryVariable('lang') || loadLangFromCookies() || window.navigator.language
let currentLang = lang
if (queryLang !== lang) {
diff --git a/lib/utils.js b/lib/utils.js
index dc7cbeb6..af2d5da8 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -1,6 +1,12 @@
// 封装异步加载资源的方法
import { memo } from 'react'
+/**
+ * 判断是否客户端
+ * @returns {boolean}
+ */
+export const isBrowser = typeof window !== 'undefined'
+
/**
* 组件持久化
*/
@@ -39,8 +45,14 @@ export function loadExternalResource(url, type) {
tag.src = url
}
if (tag) {
- tag.onload = () => resolve(url)
- tag.onerror = () => reject(url)
+ tag.onload = () => {
+ console.log('Load Success', url)
+ resolve(url)
+ }
+ tag.onerror = () => {
+ console.log('Load Error', url)
+ reject(url)
+ }
document.head.appendChild(tag)
}
})
@@ -52,7 +64,7 @@ export function loadExternalResource(url, type) {
* @returns
*/
export function getQueryVariable(key) {
- const query = isBrowser() ? 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('=')
@@ -145,12 +157,6 @@ export function deepClone(obj) {
*/
export const delay = ms => new Promise(resolve => setTimeout(resolve, ms))
-/**
- * 判断是否客户端
- * @returns {boolean}
- */
-export const isBrowser = () => typeof window !== 'undefined'
-
/**
* 获取从第1页到指定页码的文章
* @param pageIndex 第几页
@@ -170,7 +176,7 @@ export const getListByPage = function (list, pageIndex, pageSize) {
*/
export const isMobile = () => {
let isMobile = false
- if (!isBrowser()) {
+ if (!isBrowser) {
return isMobile
}
diff --git a/package.json b/package.json
index c1baace5..63168f1c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "notion-next",
- "version": "4.0.8",
+ "version": "4.0.9",
"homepage": "https://github.com/tangly1024/NotionNext.git",
"license": "MIT",
"repository": {
@@ -43,18 +43,14 @@
"nprogress": "^0.2.0",
"preact": "^10.5.15",
"prism-themes": "1.9.0",
- "qrcode.react": "^1.0.1",
"react": "^18.2.0",
"react-cookies": "^0.1.1",
- "react-cusdis": "^2.1.3",
"react-dom": "^18.2.0",
"react-facebook": "^8.1.4",
- "react-messenger-customer-chat": "^0.8.0",
"react-notion-x": "6.16.0",
"react-share": "^4.4.1",
"react-tweet-embed": "~2.0.0",
- "typed.js": "^2.0.12",
- "use-ackee": "^3.0.0"
+ "typed.js": "^2.0.12"
},
"devDependencies": {
"@waline/client": "^2.5.1",
diff --git a/pages/[prefix]/index.js b/pages/[prefix]/index.js
index 5f6ac5c8..079f1a83 100644
--- a/pages/[prefix]/index.js
+++ b/pages/[prefix]/index.js
@@ -41,7 +41,7 @@ const Slug = props => {
// 404
if (!post) {
setTimeout(() => {
- if (isBrowser()) {
+ if (isBrowser) {
const article = document.getElementById('notion-article')
if (!article) {
router.push('/404').then(() => {
diff --git a/pages/archive/index.js b/pages/archive/index.js
index 1ef1f216..106ad7d2 100644
--- a/pages/archive/index.js
+++ b/pages/archive/index.js
@@ -15,7 +15,7 @@ const ArchiveIndex = props => {
const Layout = getLayoutByTheme(useRouter())
useEffect(() => {
- if (isBrowser()) {
+ if (isBrowser) {
const anchor = window.location.hash
if (anchor) {
setTimeout(() => {
diff --git a/themes/example/index.js b/themes/example/index.js
index 0772f7fd..36ec9108 100644
--- a/themes/example/index.js
+++ b/themes/example/index.js
@@ -177,7 +177,7 @@ const LayoutSearch = props => {
const slotTop =
const router = useRouter()
useEffect(() => {
- if (isBrowser()) {
+ if (isBrowser) {
// 高亮搜索到的结果
const container = document.getElementById('posts-wrapper')
if (keyword && container) {
diff --git a/themes/fukasawa/components/BlogListPage.js b/themes/fukasawa/components/BlogListPage.js
index b48655f2..30f0c38b 100644
--- a/themes/fukasawa/components/BlogListPage.js
+++ b/themes/fukasawa/components/BlogListPage.js
@@ -77,7 +77,7 @@ const BlogListPage = ({ page = 1, posts = [], postCount, siteInfo }) => {
* @returns
*/
const calculateColumns = () => {
- if (!isBrowser()) {
+ if (!isBrowser) {
return 3
} else {
if (window.innerWidth >= 1024) {
diff --git a/themes/fukasawa/index.js b/themes/fukasawa/index.js
index 6b5eb94b..2e867cde 100644
--- a/themes/fukasawa/index.js
+++ b/themes/fukasawa/index.js
@@ -57,7 +57,7 @@ const LayoutBase = (props) => {
// 在组件卸载时保存 open 状态到本地存储中
useEffect(() => {
- if (isBrowser()) {
+ if (isBrowser) {
localStorage.setItem('fukasawa-sidebar-collapse', isCollapsed)
}
}, [isCollapsed])
@@ -149,7 +149,7 @@ const LayoutSearch = props => {
const { keyword } = props
const router = useRouter()
useEffect(() => {
- if (isBrowser()) {
+ if (isBrowser) {
replaceSearchResult({
doms: document.getElementById('posts-wrapper'),
search: keyword,
diff --git a/themes/gitbook/components/Catalog.js b/themes/gitbook/components/Catalog.js
index 5a51bee6..f6722511 100644
--- a/themes/gitbook/components/Catalog.js
+++ b/themes/gitbook/components/Catalog.js
@@ -49,7 +49,7 @@ const Catalog = ({ post }) => {
}
setActiveSection(currentSectionId)
const index = tocIds.indexOf(currentSectionId) || 0
- if (isBrowser() && tocIds?.length > 0) {
+ if (isBrowser && tocIds?.length > 0) {
for (const tocWrapper of document?.getElementsByClassName('toc-wrapper')) {
tocWrapper?.scrollTo({ top: 28 * index, behavior: 'smooth' })
}
diff --git a/themes/gitbook/components/Progress.js b/themes/gitbook/components/Progress.js
index bca7a17d..669d09a8 100644
--- a/themes/gitbook/components/Progress.js
+++ b/themes/gitbook/components/Progress.js
@@ -10,7 +10,7 @@ const Progress = ({ targetRef, showPercent = true }) => {
const currentRef = targetRef?.current || targetRef
const [percent, changePercent] = useState(0)
const scrollListener = () => {
- const target = currentRef || (isBrowser() && document.getElementById('posts-wrapper'))
+ const target = currentRef || (isBrowser && document.getElementById('posts-wrapper'))
if (target) {
const clientHeight = target.clientHeight
const scrollY = window.pageYOffset
diff --git a/themes/gitbook/index.js b/themes/gitbook/index.js
index 72056e66..0884e761 100644
--- a/themes/gitbook/index.js
+++ b/themes/gitbook/index.js
@@ -56,7 +56,6 @@ const LayoutBase = (props) => {
const showTocButton = post?.toc?.length > 1
useEffect(() => {
- console.log('更新导航', allNavPages)
setFilteredNavPages(allNavPages)
}, [post])
@@ -174,7 +173,7 @@ const LayoutIndex = (props) => {
router.push(CONFIG.INDEX_PAGE).then(() => {
// console.log('跳转到指定首页', CONFIG.INDEX_PAGE)
setTimeout(() => {
- if (isBrowser()) {
+ if (isBrowser) {
const article = document.getElementById('notion-article')
if (!article) {
console.log('请检查您的Notion数据库中是否包含此slug页面: ', CONFIG.INDEX_PAGE)
diff --git a/themes/heo/components/NavBar.js b/themes/heo/components/NavBar.js
index cd1c205b..eff61f68 100644
--- a/themes/heo/components/NavBar.js
+++ b/themes/heo/components/NavBar.js
@@ -84,12 +84,12 @@ const NavBar = props => {
}
}
- if (isBrowser()) {
+ if (isBrowser) {
window.addEventListener('scroll', handleScroll)
}
return () => {
- if (isBrowser()) {
+ if (isBrowser) {
window.removeEventListener('scroll', handleScroll)
}
}
diff --git a/themes/heo/components/Swipe.js b/themes/heo/components/Swipe.js
index f8d4be3e..6afc5f27 100644
--- a/themes/heo/components/Swipe.js
+++ b/themes/heo/components/Swipe.js
@@ -11,7 +11,7 @@ export function Swipe({ items }) {
const [activeIndex, setActiveIndex] = useState(0)
const handleClick = (item) => {
- if (isBrowser()) {
+ if (isBrowser) {
window.open(item?.url)
}
}
diff --git a/themes/hexo/components/Progress.js b/themes/hexo/components/Progress.js
index 5b4f9b20..59ee1697 100644
--- a/themes/hexo/components/Progress.js
+++ b/themes/hexo/components/Progress.js
@@ -10,7 +10,7 @@ const Progress = ({ targetRef, showPercent = true }) => {
const currentRef = targetRef?.current || targetRef
const [percent, changePercent] = useState(0)
const scrollListener = () => {
- const target = currentRef || (isBrowser() && document.getElementById('article-wrapper'))
+ const target = currentRef || (isBrowser && document.getElementById('article-wrapper'))
if (target) {
const clientHeight = target.clientHeight
const scrollY = window.pageYOffset
diff --git a/themes/hexo/index.js b/themes/hexo/index.js
index c07e70a0..e550c7b2 100644
--- a/themes/hexo/index.js
+++ b/themes/hexo/index.js
@@ -191,7 +191,7 @@ const LayoutSlug = props => {
const { post, lock, validPassword } = props
const drawerRight = useRef(null)
- const targetRef = isBrowser() ? document.getElementById('article-wrapper') : null
+ const targetRef = isBrowser ? document.getElementById('article-wrapper') : null
const floatSlot = <>
{post?.toc?.length > 1 &&
@@ -254,7 +254,7 @@ const Layout404 = props => {
useEffect(() => {
// 延时3秒如果加载失败就返回首页
setTimeout(() => {
- if (isBrowser()) {
+ if (isBrowser) {
const article = document.getElementById('notion-article')
if (!article) {
router.push('/').then(() => {
diff --git a/themes/matery/components/Progress.js b/themes/matery/components/Progress.js
index d6a68fe8..dcdea5ba 100644
--- a/themes/matery/components/Progress.js
+++ b/themes/matery/components/Progress.js
@@ -11,7 +11,7 @@ const Progress = ({ targetRef, showPercent = true }) => {
const [percent, changePercent] = useState(0)
const scrollListener = () => {
requestAnimationFrame(() => {
- const target = currentRef || (isBrowser() && document.getElementById('article-wrapper'))
+ const target = currentRef || (isBrowser && document.getElementById('article-wrapper'))
if (target) {
const clientHeight = target.clientHeight
const scrollY = window.pageYOffset
diff --git a/themes/medium/components/Progress.js b/themes/medium/components/Progress.js
index b57a3bb5..62e1cc87 100644
--- a/themes/medium/components/Progress.js
+++ b/themes/medium/components/Progress.js
@@ -10,7 +10,7 @@ const Progress = ({ targetRef, showPercent = true }) => {
const currentRef = targetRef?.current || targetRef
const [percent, changePercent] = useState(0)
const scrollListener = () => {
- const target = currentRef || (isBrowser() && document.getElementById('article-wrapper'))
+ const target = currentRef || (isBrowser && document.getElementById('article-wrapper'))
if (target) {
const clientHeight = target.clientHeight
const scrollY = window.pageYOffset
diff --git a/themes/medium/index.js b/themes/medium/index.js
index 01d3f904..82811e46 100644
--- a/themes/medium/index.js
+++ b/themes/medium/index.js
@@ -206,7 +206,7 @@ const LayoutSearch = (props) => {
const currentSearch = keyword || router?.query?.s
useEffect(() => {
- if (isBrowser()) {
+ if (isBrowser) {
replaceSearchResult({
doms: document.getElementById('posts-wrapper'),
search: keyword,
diff --git a/themes/next/components/Progress.js b/themes/next/components/Progress.js
index 2f29064d..8eab47e9 100644
--- a/themes/next/components/Progress.js
+++ b/themes/next/components/Progress.js
@@ -10,7 +10,7 @@ const Progress = ({ targetRef, showPercent = true }) => {
const currentRef = targetRef?.current || targetRef
const [percent, changePercent] = useState(0)
const scrollListener = () => {
- const target = currentRef || (isBrowser() && document.getElementById('article-wrapper'))
+ const target = currentRef || (isBrowser && document.getElementById('article-wrapper'))
if (target) {
const clientHeight = target.clientHeight
const scrollY = window.pageYOffset
diff --git a/themes/next/index.js b/themes/next/index.js
index e3b079a0..93590525 100644
--- a/themes/next/index.js
+++ b/themes/next/index.js
@@ -161,7 +161,7 @@ const LayoutSearch = (props) => {
const { posts, keyword } = props
useEffect(() => {
- if (isBrowser()) {
+ if (isBrowser) {
replaceSearchResult({
doms: document.getElementById('posts-wrapper'),
search: keyword,
@@ -201,7 +201,7 @@ const Layout404 = props => {
useEffect(() => {
// 延时3秒如果加载失败就返回首页
setTimeout(() => {
- const article = isBrowser() && document.getElementById('article-wrapper')
+ const article = isBrowser && document.getElementById('article-wrapper')
if (!article) {
router.push('/').then(() => {
// console.log('找不到页面', router.asPath)
@@ -253,7 +253,7 @@ const LayoutArchive = (props) => {
const LayoutSlug = (props) => {
const { post, lock, validPassword } = props
const drawerRight = useRef(null)
- const targetRef = isBrowser() ? document.getElementById('article-wrapper') : null
+ const targetRef = isBrowser ? document.getElementById('article-wrapper') : null
const floatSlot =
{
drawerRight?.current?.handleSwitchVisible()
diff --git a/themes/nobelium/index.js b/themes/nobelium/index.js
index d9a930e0..d175e2c9 100644
--- a/themes/nobelium/index.js
+++ b/themes/nobelium/index.js
@@ -134,7 +134,7 @@ const LayoutPostList = props => {
const LayoutSearch = props => {
const { keyword } = props
useEffect(() => {
- if (isBrowser()) {
+ if (isBrowser) {
replaceSearchResult({
doms: document.getElementById('posts-wrapper'),
search: keyword,
diff --git a/themes/plog/index.js b/themes/plog/index.js
index 55895df4..0f44c2a4 100644
--- a/themes/plog/index.js
+++ b/themes/plog/index.js
@@ -132,7 +132,7 @@ const LayoutSearch = props => {
const { keyword } = props
useEffect(() => {
- if (isBrowser()) {
+ if (isBrowser) {
replaceSearchResult({
doms: document.getElementById('posts-wrapper'),
search: keyword,
diff --git a/themes/simple/index.js b/themes/simple/index.js
index b0c9f95c..13d38a87 100644
--- a/themes/simple/index.js
+++ b/themes/simple/index.js
@@ -36,7 +36,7 @@ const LayoutBase = props => {
const { children, slotTop, meta } = props
const { onLoading } = useGlobal()
- if (isBrowser()) {
+ if (isBrowser) {
loadExternalResource('/css/theme-simple.css', 'css')
}
return (
@@ -122,7 +122,7 @@ const LayoutSearch = props => {
const { keyword } = props
useEffect(() => {
- if (isBrowser()) {
+ if (isBrowser) {
replaceSearchResult({
doms: document.getElementById('posts-wrapper'),
search: keyword,