diff --git a/README.md b/README.md index a1e7eaf74b9..baa24be2968 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ here is the website->[ImagineBlog](https://forimagine.eu.org 'ImagineBlog') 访问帮助:[NotionNext帮助手册](https://docs.tangly1024.com/) -> 本项目教程为免费、公开资源,仅限个人学习使用。严禁任何个人或组织将本教程用于商业用途,包括但不限于直接售卖、间接收费、或其他变相盈利行为。转载、复制或介绍本教程内容时,须保留作者信息并明确注明来源。 +> 本项目教程为免费、公开资源,仅限个人学习使用,禁止利用本教程建立的博客发布非法内容、进行违法犯罪活动。严禁任何个人或组织将本教程用于商业用途,包括但不限于直接售卖、间接收费、或其他变相盈利行为。转载、复制或介绍本教程内容时,须保留作者信息并明确注明来源。 > 本项目仅提供由作者团队授权的付费咨询服务,请注意辨别,谨防诈骗行为。任何未经授权的收费服务均可能存在法律风险。 Notion是一个能让效率暴涨的生产力引擎,可以帮你书写文档、管理笔记,搭建知识库,甚至可以为你规划项目、时间管理、组织团队、提高生产力、还有当前最强大的AI技术加持。 @@ -63,20 +63,11 @@ A static blog system built with NextJS and Notion API, deployed on Vercel. Desig ## Contributors - - - - - - - +感谢所有为 NotionNext 做出贡献的人! +<<<<<<< HEAD +[![Contributors](https://contrib.rocks/image?repo=tangly1024/NotionNext)](https://github.com/tangly1024/NotionNext/graphs/contributors) +======= @@ -179,6 +170,7 @@ A static blog system built with NextJS and Notion API, deployed on Vercel. Desig
- tangly1024
tangly1024

🎫 🔧 🐛 -
- uWayLu
uWayLu

🔧 🐛 -
- txs
txs

🔧 🐛 -
yuzhanglong
yuzhanglong

🔧 🐛
+>>>>>>> d371156ad7ec1c8348365a5c983b2e04780a8180 ## 引用技术 diff --git a/README_CN.md b/README_CN.md index ecc2b6413b9..a45d91b3b01 100644 --- a/README_CN.md +++ b/README_CN.md @@ -52,6 +52,9 @@ You can set up your personal website in just a few minutes. Here is the link to ## 贡献者 +<<<<<<< HEAD:README_EN.md +This project exists thanks to all the people who contribute. +=======
@@ -188,7 +191,9 @@ You can set up your personal website in just a few minutes. Here is the link to
+>>>>>>> d371156ad7ec1c8348365a5c983b2e04780a8180:README_CN.md +[![Contributors](https://contrib.rocks/image?repo=tangly1024/NotionNext)](https://github.com/tangly1024/NotionNext/graphs/contributors) ## 引用技术 diff --git a/components/CursorDot.js b/components/CursorDot.js new file mode 100644 index 00000000000..7fb36603c2c --- /dev/null +++ b/components/CursorDot.js @@ -0,0 +1,107 @@ +import { useRouter } from 'next/router'; +import { useEffect } from 'react'; +/** + * 白点鼠标跟随 + * @returns + */ +const CursorDot = () => { + const router = useRouter(); + useEffect(() => { + // 创建小白点元素 + const dot = document.createElement('div'); + dot.classList.add('cursor-dot'); + document.body.appendChild(dot); + + // 鼠标坐标和缓动目标坐标 + let mouse = { x: -100, y: -100 }; // 初始位置在屏幕外 + let dotPos = { x: mouse.x, y: mouse.y }; + + // 监听鼠标移动 + const handleMouseMove = (e) => { + mouse.x = e.clientX; + mouse.y = e.clientY; + }; + document.addEventListener('mousemove', handleMouseMove); + + // 监听鼠标悬停在可点击对象上的事件 + const handleMouseEnter = () => { + dot.classList.add('cursor-dot-hover'); // 添加放大样式 + }; + const handleMouseLeave = () => { + dot.classList.remove('cursor-dot-hover'); // 移除放大样式 + }; + + + // 为所有可点击元素和包含 hover 或 group-hover 类名的元素添加事件监听 + setTimeout(() => { + const clickableElements = document.querySelectorAll( + 'a, button, [role="button"], [onclick], [cursor="pointer"], [class*="hover"], [class*="group-hover"], [class*="cursor-pointer"]' + ); + clickableElements.forEach((el) => { + el.addEventListener('mouseenter', handleMouseEnter); + el.addEventListener('mouseleave', handleMouseLeave); + }); + }, 200); // 延时 200ms 执行 + + // 动画循环:延迟更新小白点位置 + const updateDotPosition = () => { + const damping = 0.2; // 阻尼系数,值越小延迟越明显 + dotPos.x += (mouse.x - dotPos.x) * damping; + dotPos.y += (mouse.y - dotPos.y) * damping; + + // 更新DOM + dot.style.left = `${dotPos.x}px`; + dot.style.top = `${dotPos.y}px`; + + requestAnimationFrame(updateDotPosition); + }; + + // 启动动画 + updateDotPosition(); + + // 清理函数 + return () => { + document.removeEventListener('mousemove', handleMouseMove); + const clickableElements = document.querySelectorAll( + 'a, button, [role="button"], [onclick], [cursor="pointer"], [class*="hover"], [class*="group-hover"], [class*="cursor-pointer"]' + ); + clickableElements.forEach((el) => { + el.removeEventListener('mouseenter', handleMouseEnter); + el.removeEventListener('mouseleave', handleMouseLeave); + }); + document.body.removeChild(dot); + }; + }, [router]); + + return ( + + ); +}; + +export default CursorDot; \ No newline at end of file diff --git a/components/ExternalPlugins.js b/components/ExternalPlugins.js index 4e1f7072a03..fd92820ec81 100644 --- a/components/ExternalPlugins.js +++ b/components/ExternalPlugins.js @@ -10,6 +10,9 @@ import { initGoogleAdsense } from './GoogleAdsense' import Head from 'next/head' import ExternalScript from './ExternalScript' import WebWhiz from './Webwhiz' +import { useGlobal } from '@/lib/global' +import IconFont from './IconFont' + /** * 各种插件脚本 @@ -19,6 +22,7 @@ import WebWhiz from './Webwhiz' const ExternalPlugin = props => { // 读取自Notion的配置 const { NOTION_CONFIG } = props + const {lang} = useGlobal() const DISABLE_PLUGIN = siteConfig('DISABLE_PLUGIN', null, NOTION_CONFIG) const THEME_SWITCH = siteConfig('THEME_SWITCH', null, NOTION_CONFIG) const DEBUG = siteConfig('DEBUG', null, NOTION_CONFIG) @@ -124,6 +128,8 @@ const ExternalPlugin = props => { NOTION_CONFIG ) + const ENABLE_ICON_FONT = siteConfig('ENABLE_ICON_FONT', false) + // 自定义样式css和js引入 if (isBrowser) { // 初始化AOS动画 @@ -165,8 +171,8 @@ const ExternalPlugin = props => { } setTimeout(() => { - // 将notion-id格式的url转成自定义slug - convertInnerUrl(props?.allNavPages) + // 映射url + convertInnerUrl({ allPages:props?.allNavPages, lang:lang }) }, 500) }, [router]) @@ -184,6 +190,7 @@ const ExternalPlugin = props => { <> {/* 全局样式嵌入 */} + {ENABLE_ICON_FONT && } {MOUSE_FOLLOW && } {THEME_SWITCH && } {DEBUG && } diff --git a/components/IconFont.js b/components/IconFont.js new file mode 100644 index 00000000000..72b8349b40f --- /dev/null +++ b/components/IconFont.js @@ -0,0 +1,56 @@ +import { siteConfig } from '@/lib/config' +import { loadExternalResource } from '@/lib/utils' +import { useRouter } from 'next/router' +import { useEffect } from 'react' + +/** + * iconfont + */ +export default function IconFont() { + const router = useRouter() + + useEffect(() => { + loadExternalResource('/webfonts/iconfont.js') + .then(u => { + console.log('iconfont loaded:', u); + + // 查找所有 标签且 class 包含 'icon-' + const iElements = document.querySelectorAll('i[class*="icon-"]'); + iElements.forEach(element => { + const className = Array.from(element.classList).find(cls => cls.startsWith('icon-')); + if (className) { + // 创建新的 元素 + const svgElement = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svgElement.setAttribute('class', 'icon'); + svgElement.setAttribute('aria-hidden', 'true'); + + const useElement = document.createElementNS('http://www.w3.org/2000/svg', 'use'); + useElement.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', `#${className}`); + svgElement.appendChild(useElement); + + // 替换原来的 元素 + element.replaceWith(svgElement); + // console.log(`Replaced with class "${className}" to `); + } + }); + }) + .catch(error => { + console.warn('Failed to load iconfont.js:', error); + }); + }, [router]); + + return +} diff --git a/components/LazyImage.js b/components/LazyImage.js index 8f0645461ee..8190d1b14be 100644 --- a/components/LazyImage.js +++ b/components/LazyImage.js @@ -129,20 +129,6 @@ export default function LazyImage({ )} - ) } diff --git a/components/Lenis.js b/components/Lenis.js new file mode 100644 index 00000000000..43b1c062738 --- /dev/null +++ b/components/Lenis.js @@ -0,0 +1,69 @@ +import { useEffect, useRef } from 'react' +import { loadExternalResource } from '@/lib/utils' + +/** + * 滚动阻尼特效 + * 目前只用在proxio主题 + * @returns + */ +const Lenis = () => { + const lenisRef = useRef(null) // 用于存储 Lenis 实例 + + useEffect(() => { + // 异步加载 + async function loadLenis() { + loadExternalResource('/js/lenis.js', 'js').then(() => { + // console.log('Lenis', window.Lenis) + if (!window.Lenis) { + console.error('Lenis not loaded') + return + } + const Lenis = window.Lenis + + // 创建 Lenis 实例 + const lenis = new Lenis({ + duration: 1.2, + easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)), // https://www.desmos.com/calculator/brs54l4xou + direction: 'vertical', // vertical, horizontal + gestureDirection: 'vertical', // vertical, horizontal, both + smooth: true, + mouseMultiplier: 1, + smoothTouch: false, + touchMultiplier: 2, + infinite: false, + }) + + // 存储实例到 ref + lenisRef.current = lenis + + // 监听滚动事件 + // lenis.on('scroll', ({ scroll, limit, velocity, direction, progress }) => { + // // console.log({ scroll, limit, velocity, direction, progress }) + // }) + + // 动画帧循环 + function raf(time) { + lenis.raf(time) + requestAnimationFrame(raf) + } + + requestAnimationFrame(raf) + }) + } + + loadLenis() + + return () => { + // 在组件卸载时清理资源 + if (lenisRef.current) { + lenisRef.current.destroy() // 销毁 Lenis 实例 + lenisRef.current = null + // console.log('Lenis instance destroyed') + } + } + }, []) + + return <> +} + +export default Lenis diff --git a/components/ShareButtons.js b/components/ShareButtons.js index 29fd37b496f..47c32d82034 100644 --- a/components/ShareButtons.js +++ b/components/ShareButtons.js @@ -37,6 +37,8 @@ import { TumblrShareButton, TwitterIcon, TwitterShareButton, + ThreadsIcon, + ThreadsShareButton, ViberIcon, ViberShareButton, VKIcon, @@ -312,6 +314,16 @@ const ShareButtons = ({ post }) => { ) + case 'threads': + return ( + + + + ) case 'qq': return ( - + {siteConfig('BEI_AN')}
diff --git a/themes/gitbook/components/Footer.js b/themes/gitbook/components/Footer.js index b9929d64d04..cbf6df1403f 100644 --- a/themes/gitbook/components/Footer.js +++ b/themes/gitbook/components/Footer.js @@ -33,7 +33,7 @@ const Footer = ({ siteInfo }) => { {siteConfig('BEI_AN') && ( <> {' '} - + {siteConfig('BEI_AN')} diff --git a/themes/heo/components/Footer.js b/themes/heo/components/Footer.js index 2bd1bf64bb5..1a7e6fb8415 100644 --- a/themes/heo/components/Footer.js +++ b/themes/heo/components/Footer.js @@ -9,6 +9,7 @@ import SocialButton from './SocialButton' */ const Footer = () => { const BEI_AN = siteConfig('BEI_AN') + const BEI_AN_LINK = siteConfig('BEI_AN_LINK') const BIO = siteConfig('BIO') return (