mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-14 15:09:22 +00:00
Merge branch 'main' of https://github.com/tangly1024/NotionNext
This commit is contained in:
@@ -37,6 +37,8 @@ const BLOG = {
|
||||
|
||||
BLOG_FAVICON: process.env.NEXT_PUBLIC_FAVICON || '/favicon.ico', // blog favicon 配置, 默认使用 /public/favicon.ico,支持在线图片,如 https://img.imesong.com/favicon.png
|
||||
|
||||
IMAGE_COMPRESS_WIDTH: process.env.NEXT_PUBLIC_IMAGE_COMPRESS_WIDTH || 800, // 图片压缩宽度默认值,作用于博客封面和文章内容 越小加载图片越快
|
||||
IMAGE_ZOOM_IN_WIDTH: process.env.NEXT_PUBLIC_IMAGE_ZOOM_IN_WIDTH || 1200, // 文章图片点击放大后的画质宽度,不代表在网页中的实际展示宽度
|
||||
RANDOM_IMAGE_URL: process.env.NEXT_PUBLIC_RANDOM_IMAGE_URL || '', // 随机图片API,如果未配置下面的关键字,主页封面,头像,文章封面图都会被替换为随机图片
|
||||
RANDOM_IMAGE_REPLACE_TEXT: process.env.NEXT_PUBLIC_RANDOM_IMAGE_NOT_REPLACE_TEXT || 'images.unsplash.com', // 触发替换图片的 url 关键字(多个支持用英文逗号分开),只有图片地址中包含此关键字才会替换为上方随机图片url
|
||||
// eg: images.unsplash.com(notion图床的所有图片都会替换),如果你在 notion 里已经添加了一个随机图片 url,恰巧那个服务跑路或者挂掉,想一键切换所有配图可以将该 url 配置在这里
|
||||
|
||||
@@ -2,7 +2,7 @@ import dynamic from 'next/dynamic'
|
||||
import mediumZoom from '@fisch0920/medium-zoom'
|
||||
import { useEffect, useRef } from 'react'
|
||||
import 'katex/dist/katex.min.css'
|
||||
import { mapImgUrl } from '@/lib/notion/mapImage'
|
||||
import { compressImage, mapImgUrl } from '@/lib/notion/mapImage'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { NotionRenderer } from 'react-notion-x'
|
||||
@@ -61,6 +61,11 @@ const Tweet = ({ id }) => {
|
||||
return <TweetEmbed tweetId={id} />
|
||||
}
|
||||
|
||||
/**
|
||||
* Notin渲染成网页的核心组件
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
const NotionPage = ({ post, className }) => {
|
||||
useEffect(() => {
|
||||
autoScrollToTarget()
|
||||
@@ -74,6 +79,8 @@ const NotionPage = ({ post, className }) => {
|
||||
const zoomRef = useRef(zoom ? zoom.clone() : null)
|
||||
|
||||
useEffect(() => {
|
||||
if (!isBrowser) return;
|
||||
|
||||
// 将相册gallery下的图片加入放大功能
|
||||
if (siteConfig('POST_DISABLE_GALLERY_CLICK')) {
|
||||
setTimeout(() => {
|
||||
@@ -111,6 +118,30 @@ const NotionPage = ({ post, className }) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 放大图片:调整图片质量
|
||||
const observer = new MutationObserver((mutationsList, observer) => {
|
||||
mutationsList.forEach(mutation => {
|
||||
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
|
||||
if (mutation.target.classList.contains('medium-zoom-image--opened')) {
|
||||
// 等待动画完成后替换为更高清的图像
|
||||
setTimeout(() => {
|
||||
// 获取该元素的 src 属性
|
||||
const src = mutation?.target?.getAttribute('src');
|
||||
// 替换为更高清的图像
|
||||
mutation?.target?.setAttribute('src', compressImage(src, siteConfig('IMAGE_ZOOM_IN_WIDTH', 1200)));
|
||||
}, 800);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 监视整个文档中的元素和属性的变化
|
||||
observer.observe(document.body, { attributes: true, subtree: true, attributeFilter: ['class'] });
|
||||
|
||||
return () => {
|
||||
observer.disconnect();
|
||||
};
|
||||
}, [])
|
||||
|
||||
if (!post || !post.blockMap) {
|
||||
|
||||
@@ -25,7 +25,9 @@ const ThemeSwitch = () => {
|
||||
const query = router.query
|
||||
query.theme = newTheme
|
||||
router.push({ pathname: router.pathname, query }).then(() => {
|
||||
setIsLoading(false)
|
||||
setTimeout(() => {
|
||||
setIsLoading(false)
|
||||
}, 500);
|
||||
})
|
||||
}
|
||||
|
||||
@@ -72,8 +74,8 @@ const ThemeSwitch = () => {
|
||||
</Draggable>
|
||||
|
||||
{/* 切换主题加载时的全屏遮罩 */}
|
||||
<div className={`${isLoading ? 'opacity-50 ' : 'opacity-0'}
|
||||
w-screen h-screen bg-black text-white shadow-text flex justify-center items-center
|
||||
<div className={`${isLoading ? 'opacity-90 ' : 'opacity-0'}
|
||||
w-screen h-screen glassmorphism bg-black text-white shadow-text flex justify-center items-center
|
||||
transition-all fixed top-0 left-0 pointer-events-none duration-1000 z-50 shadow-inner`}>
|
||||
<i className='text-3xl mr-5 fas fa-spinner animate-spin' />
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,7 @@ import { getAllCategories } from './getAllCategories'
|
||||
import getAllPageIds from './getAllPageIds'
|
||||
import { getAllTags } from './getAllTags'
|
||||
import getPageProperties from './getPageProperties'
|
||||
import { mapImgUrl, compressImage } from './mapImage'
|
||||
import { compressImage, mapImgUrl } from './mapImage'
|
||||
import { getConfigMapFromConfigPage } from './getNotionConfig'
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import BLOG from '@/blog.config'
|
||||
import { siteConfig } from '../config'
|
||||
|
||||
/**
|
||||
* 图片映射
|
||||
@@ -58,7 +59,7 @@ const mapImgUrl = (img, block, type = 'block', from = 'post') => {
|
||||
|
||||
// 统一压缩图片
|
||||
if (from === 'pageCoverThumbnail' || block.type === 'image' || block.type === 'page') {
|
||||
const width = block?.format?.block_width || 200
|
||||
const width = block?.format?.block_width
|
||||
ret = compressImage(ret, width)
|
||||
}
|
||||
|
||||
@@ -81,19 +82,29 @@ function isEmoji(str) {
|
||||
* 2. UnPlash 图片可以通过api q=50 控制压缩质量 width=400 控制图片尺寸
|
||||
* @param {*} image
|
||||
*/
|
||||
const compressImage = (image, width = 800, quality = 50, fmt = 'webp') => {
|
||||
if (!image) {
|
||||
return null
|
||||
const compressImage = (image, width, quality = 50, fmt = 'webp') => {
|
||||
if (!image || image.indexOf('http') !== 0) {
|
||||
return image
|
||||
}
|
||||
|
||||
if (!width || width === 0) {
|
||||
width = siteConfig('IMAGE_COMPRESS_WIDTH')
|
||||
}
|
||||
|
||||
// 将URL解析为一个对象
|
||||
const urlObj = new URL(image)
|
||||
// 获取URL参数
|
||||
const params = new URLSearchParams(urlObj.search)
|
||||
|
||||
// Notion图床
|
||||
if (image.indexOf(BLOG.NOTION_HOST) === 0 && image.indexOf('amazonaws.com') > 0) {
|
||||
return `${image}&width=${width}&cache=v2`
|
||||
}
|
||||
// 压缩unsplash图片
|
||||
if (image.indexOf('https://images.unsplash.com/') === 0) {
|
||||
// 将URL解析为一个对象
|
||||
const urlObj = new URL(image)
|
||||
// 获取URL参数
|
||||
const params = new URLSearchParams(urlObj.search)
|
||||
params.set('width', width)
|
||||
params.set('cache', 'v2')
|
||||
// 生成新的URL
|
||||
urlObj.search = params.toString()
|
||||
return urlObj.toString()
|
||||
} else if (image.indexOf('https://images.unsplash.com/') === 0) {
|
||||
// 压缩unsplash图片
|
||||
// 将q参数的值替换
|
||||
params.set('q', quality)
|
||||
// 尺寸
|
||||
@@ -104,11 +115,9 @@ const compressImage = (image, width = 800, quality = 50, fmt = 'webp') => {
|
||||
// 生成新的URL
|
||||
urlObj.search = params.toString()
|
||||
return urlObj.toString()
|
||||
}
|
||||
|
||||
// 此处还可以添加您的自定义图传的封面图压缩参数。
|
||||
} else if (image.indexOf('https://your_picture_bed') === 0) {
|
||||
// 此处还可以添加您的自定义图传的封面图压缩参数。
|
||||
// .e.g
|
||||
if (image.indexOf('https://your_picture_bed') === 0) {
|
||||
return 'do_somethin_here'
|
||||
}
|
||||
|
||||
|
||||
27
lib/utils.js
27
lib/utils.js
@@ -30,6 +30,33 @@ export const memorize = (Component) => {
|
||||
}
|
||||
return memo(MemoizedComponent)
|
||||
}
|
||||
|
||||
// 转换外链
|
||||
export function sliceUrlFromHttp(str) {
|
||||
// 检查字符串是否包含http
|
||||
if (str.includes('http')) {
|
||||
// 如果包含,找到http的位置
|
||||
const index = str.indexOf('http');
|
||||
// 返回http之后的部分
|
||||
return str.slice(index, str.length);
|
||||
} else {
|
||||
// 如果不包含,返回原字符串
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否外链
|
||||
export function checkContainHttp(str) {
|
||||
// 检查字符串是否包含http
|
||||
if (str.includes('http')) {
|
||||
// 如果包含,找到http的位置
|
||||
return str.indexOf('http') > -1
|
||||
} else {
|
||||
// 不包含
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载外部资源
|
||||
* @param url 地址 例如 https://xx.com/xx.js
|
||||
|
||||
@@ -28,7 +28,7 @@ class MyDocument extends Document {
|
||||
})}
|
||||
</Head>
|
||||
|
||||
<body className={`${BLOG.FONT_STYLE} font-light scroll-smooth`}>
|
||||
<body className={`${BLOG.FONT_STYLE} dark:bg-black font-light scroll-smooth`}>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
|
||||
@@ -950,6 +950,7 @@ code[class*='language-'] {
|
||||
margin-left: 8px;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.notion-toggle {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
import Link from 'next/link'
|
||||
|
||||
/**
|
||||
@@ -14,8 +15,10 @@ export default function BlogListGroupByDate({ archiveTitle, archivePosts }) {
|
||||
</div>
|
||||
|
||||
<ul>
|
||||
{archivePosts[archiveTitle].map(post => (
|
||||
<li
|
||||
{archivePosts[archiveTitle].map(post => {
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
return <li
|
||||
key={post.id}
|
||||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
||||
>
|
||||
@@ -24,12 +27,12 @@ export default function BlogListGroupByDate({ archiveTitle, archivePosts }) {
|
||||
{post?.publishDay}
|
||||
</span>{' '}
|
||||
|
||||
<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`} className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||
<Link href={url} className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||
{post.title}
|
||||
</Link>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -3,9 +3,11 @@ import CONFIG from '../config'
|
||||
import Link from 'next/link'
|
||||
import TwikooCommentCount from '@/components/TwikooCommentCount'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
const BlogPostCard = ({ post }) => {
|
||||
const showPageCover = siteConfig('EXAMPLE_POST_LIST_COVER', null, CONFIG) && post?.pageCoverThumbnail
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
return <article className={`${showPageCover ? 'flex md:flex-row flex-col-reverse' : ''} replace mb-12 `}>
|
||||
<div className={`${showPageCover ? 'md:w-7/12' : ''}`}>
|
||||
@@ -41,7 +43,7 @@ const BlogPostCard = ({ post }) => {
|
||||
{/* 图片封面 */}
|
||||
{showPageCover && (
|
||||
<div className="md:w-5/12 w-full h-44 overflow-hidden p-1">
|
||||
<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`} passHref legacyBehavior>
|
||||
<Link href={url} passHref legacyBehavior>
|
||||
<LazyImage src={post?.pageCoverThumbnail} className='w-full bg-cover hover:scale-110 duration-200' />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@@ -9,11 +9,14 @@ import Announcement from './Announcement'
|
||||
import { useRouter } from 'next/router'
|
||||
import DarkModeButton from '@/components/DarkModeButton'
|
||||
import SocialButton from './SocialButton'
|
||||
import { useFukasawaGlobal } from '..'
|
||||
import CONFIG from '@/themes/fukasawa/config'
|
||||
import { AdSlot } from '@/components/GoogleAdsense'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import MailChimpForm from './MailChimpForm'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
import { debounce } from 'lodash'
|
||||
|
||||
/**
|
||||
* 侧边栏
|
||||
@@ -23,39 +26,59 @@ import MailChimpForm from './MailChimpForm'
|
||||
function AsideLeft(props) {
|
||||
const { tagOptions, currentTag, categoryOptions, currentCategory, post, slot, notice } = props
|
||||
const router = useRouter()
|
||||
const { isCollapsed, setIsCollapse } = useFukasawaGlobal()
|
||||
const { fullWidth } = useGlobal()
|
||||
|
||||
const FUKASAWA_SIDEBAR_COLLAPSE_SATUS_DEFAULT = fullWidth || siteConfig('FUKASAWA_SIDEBAR_COLLAPSE_SATUS_DEFAULT', null, CONFIG)
|
||||
|
||||
// 侧边栏折叠从 本地存储中获取 open 状态的初始值
|
||||
const [isCollapsed, setIsCollapse] = useState(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
return localStorage.getItem('fukasawa-sidebar-collapse') === 'true' || FUKASAWA_SIDEBAR_COLLAPSE_SATUS_DEFAULT
|
||||
}
|
||||
return FUKASAWA_SIDEBAR_COLLAPSE_SATUS_DEFAULT
|
||||
})
|
||||
|
||||
// 在组件卸载时保存 open 状态到本地存储中
|
||||
useEffect(() => {
|
||||
if (isBrowser) {
|
||||
localStorage.setItem('fukasawa-sidebar-collapse', isCollapsed)
|
||||
}
|
||||
}, [isCollapsed])
|
||||
|
||||
// 折叠侧边栏
|
||||
const toggleOpen = () => {
|
||||
setIsCollapse(!isCollapsed)
|
||||
}
|
||||
|
||||
// 自动折叠侧边栏 onResize 窗口宽度小于1366 || 滚动条滚动至页面的300px时 ; 将open设置为false
|
||||
// useEffect(() => {
|
||||
// const handleResize = debounce(() => {
|
||||
// if (window.innerWidth < 1366 || window.scrollY >= 100) {
|
||||
// setIsCollapse(true)
|
||||
// } else {
|
||||
// setIsCollapse(false)
|
||||
// }
|
||||
// }, 100)
|
||||
useEffect(() => {
|
||||
if (!siteConfig('FUKASAWA_SIDEBAR_COLLAPSE_ON_SCROLL', false, CONFIG)) {
|
||||
return
|
||||
}
|
||||
const handleResize = debounce(() => {
|
||||
if (window.innerWidth < 1366 || window.scrollY >= 1366) {
|
||||
setIsCollapse(true)
|
||||
} else {
|
||||
setIsCollapse(false)
|
||||
}
|
||||
}, 100)
|
||||
|
||||
// console.log('router', router)
|
||||
// if (router.pathname === '/[...slug]') {
|
||||
// window.addEventListener('resize', handleResize)
|
||||
// window.addEventListener('scroll', handleResize, { passive: true })
|
||||
// }
|
||||
if (post) {
|
||||
window.addEventListener('resize', handleResize)
|
||||
window.addEventListener('scroll', handleResize, { passive: true })
|
||||
}
|
||||
|
||||
// return () => {
|
||||
// if (router.pathname === '/[...slug]') {
|
||||
// window.removeEventListener('resize', handleResize)
|
||||
// window.removeEventListener('scroll', handleResize, { passive: true })
|
||||
// }
|
||||
// }
|
||||
// }, [])
|
||||
return () => {
|
||||
if (post) {
|
||||
window.removeEventListener('resize', handleResize)
|
||||
window.removeEventListener('scroll', handleResize, { passive: true })
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
|
||||
return <div className={`sideLeft relative ${isCollapsed ? 'w-0' : 'w-80'} duration-150 transition-all bg-white dark:bg-hexo-black-gray min-h-screen hidden lg:block z-20`}>
|
||||
return <div className={`sideLeft relative ${isCollapsed ? 'w-0' : 'w-80'} duration-300 transition-all bg-white dark:bg-hexo-black-gray min-h-screen hidden lg:block z-20`}>
|
||||
{/* 折叠按钮 */}
|
||||
{siteConfig('FUKASAWA_SIDEBAR_COLLAPSE_BUTTON', null, CONFIG) && <div className={`${isCollapsed ? '' : 'ml-80'} hidden lg:block sticky top-0 mx-2 cursor-pointer hover:scale-110 duration-150 px-3 py-2`} onClick={toggleOpen}>
|
||||
{siteConfig('FUKASAWA_SIDEBAR_COLLAPSE_BUTTON', null, CONFIG) && <div className={`${isCollapsed ? '' : 'ml-80'} hidden lg:block sticky top-0 mx-2 cursor-pointer hover:scale-110 duration-300 px-3 py-2`} onClick={toggleOpen}>
|
||||
{isCollapsed ? <i className="fa-solid fa-indent text-xl"></i> : <i className='fas fa-bars text-xl'></i>}
|
||||
</div>}
|
||||
|
||||
|
||||
@@ -3,7 +3,13 @@ import Link from 'next/link'
|
||||
import TagItemMini from './TagItemMini'
|
||||
import CONFIG from '../config'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 文章列表卡片
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
const BlogCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
const showPreview = siteConfig('FUKASAWA_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
||||
// fukasawa 强制显示图片
|
||||
@@ -11,22 +17,29 @@ const BlogCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
post.pageCoverThumbnail = siteInfo?.pageCover
|
||||
}
|
||||
const showPageCover = siteConfig('FUKASAWA_POST_LIST_COVER', null, CONFIG) && post?.pageCoverThumbnail
|
||||
const SUB_PATH = siteConfig('SUB_PATH', '')
|
||||
const FUKASAWA_POST_LIST_ANIMATION = siteConfig('FUKASAWA_POST_LIST_ANIMATION', null, CONFIG)
|
||||
|
||||
// 动画样式 首屏卡片不用,后面翻出来的加动画
|
||||
const aosProps = FUKASAWA_POST_LIST_ANIMATION
|
||||
? {
|
||||
'data-aos': 'fade-up',
|
||||
'data-aos-duration': '300',
|
||||
'data-aos-once': 'true',
|
||||
'data-aos-anchor-placement': 'top-bottom'
|
||||
}
|
||||
: {}
|
||||
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
return (
|
||||
<div
|
||||
data-aos="fade-up"
|
||||
data-aos-duration="600"
|
||||
data-aos-once="true"
|
||||
data-aos-anchor-placement="top-bottom"
|
||||
style={{ maxHeight: '60rem' }}
|
||||
<div {...aosProps} style={{ maxHeight: '60rem' }}
|
||||
className="w-full lg:max-w-sm p-3 shadow mb-4 mx-2 bg-white dark:bg-hexo-black-gray hover:shadow-lg duration-200"
|
||||
>
|
||||
<div className="flex flex-col justify-between h-full">
|
||||
{/* 封面图 */}
|
||||
{showPageCover && (
|
||||
<div className="flex-grow mb-3 w-full duration-200 cursor-pointer transform overflow-hidden">
|
||||
<Link href={`${SUB_PATH}/${post.slug}`} passHref legacyBehavior>
|
||||
<Link href={url} passHref legacyBehavior>
|
||||
<LazyImage
|
||||
src={post?.pageCoverThumbnail}
|
||||
alt={post?.title || siteConfig('TITLE')}
|
||||
@@ -38,7 +51,7 @@ const BlogCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
|
||||
{/* 文字部分 */}
|
||||
<div className="flex flex-col w-full">
|
||||
<Link passHref href={`${SUB_PATH}/${post.slug}`}
|
||||
<Link passHref href={url}
|
||||
className={`break-words cursor-pointer font-bold hover:underline text-xl ${showPreview ? 'justify-center' : 'justify-start'} leading-tight text-gray-700 dark:text-gray-100 hover:text-blue-500 dark:hover:text-blue-400`}
|
||||
>
|
||||
{post.title}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Link from 'next/link'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 博客归档
|
||||
@@ -21,8 +22,9 @@ const BlogArchiveItem = ({ posts = [], archiveTitle }) => {
|
||||
{archiveTitle}
|
||||
</div>
|
||||
<ul>
|
||||
{posts?.map(post => (
|
||||
<li
|
||||
{posts?.map(post => {
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
return <li
|
||||
key={post.id}
|
||||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
||||
>
|
||||
@@ -30,7 +32,7 @@ const BlogArchiveItem = ({ posts = [], archiveTitle }) => {
|
||||
<span className="text-gray-400">{post.date?.start_date}</span>{' '}
|
||||
|
||||
<Link
|
||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
href={url}
|
||||
passHref
|
||||
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||
|
||||
@@ -39,7 +41,7 @@ const BlogArchiveItem = ({ posts = [], archiveTitle }) => {
|
||||
</Link>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -44,7 +44,7 @@ export const MenuItemCollapse = (props) => {
|
||||
<div><div className={`${link.icon} text-center w-4 mr-4`} />{link.name}</div>
|
||||
<div className='inline-flex items-center '><i className={`px-2 fas fa-chevron-right transition-all duration-200 ${isOpen ? 'rotate-90' : ''}`}></i></div>
|
||||
</div>}
|
||||
</div>
|
||||
</div>f
|
||||
|
||||
{/* 折叠子菜单 */}
|
||||
{hasSubMenu && <Collapse isOpen={isOpen} onHeightChange={props.onHeightChange}>
|
||||
|
||||
@@ -4,6 +4,7 @@ const CONFIG = {
|
||||
FUKASAWA_POST_LIST_COVER: true, // 文章列表显示图片封面
|
||||
FUKASAWA_POST_LIST_COVER_FORCE: false, // 即使没有封面也将站点背景图设置为封面
|
||||
FUKASAWA_POST_LIST_PREVIEW: false, // 显示文章预览
|
||||
FUKASAWA_POST_LIST_ANIMATION: false, // 博客列表淡入动画
|
||||
|
||||
// 菜单
|
||||
FUKASAWA_MENU_CATEGORY: true, // 显示分类
|
||||
@@ -12,7 +13,8 @@ const CONFIG = {
|
||||
FUKASAWA_MENU_SEARCH: false, // 显示搜索
|
||||
|
||||
FUKASAWA_SIDEBAR_COLLAPSE_BUTTON: true, // 侧边栏折叠按钮
|
||||
FUKASAWA_SIDEBAR_COLLAPSE_SATUS_DEFAULT: false // 侧边栏默认折叠收起
|
||||
FUKASAWA_SIDEBAR_COLLAPSE_SATUS_DEFAULT: false, // 侧边栏默认折叠收起
|
||||
FUKASAWA_SIDEBAR_COLLAPSE_ON_SCROLL: false // 侧边栏滚动时折叠 仅文章阅读页有效
|
||||
|
||||
}
|
||||
export default CONFIG
|
||||
|
||||
@@ -12,7 +12,7 @@ import ArticleDetail from './components/ArticleDetail'
|
||||
import ArticleLock from './components/ArticleLock'
|
||||
import TagItemMini from './components/TagItemMini'
|
||||
import { useRouter } from 'next/router'
|
||||
import { createContext, useContext, useEffect, useState } from 'react'
|
||||
import { createContext, useContext, useEffect } from 'react'
|
||||
import Link from 'next/link'
|
||||
import { Transition } from '@headlessui/react'
|
||||
import dynamic from 'next/dynamic'
|
||||
@@ -48,25 +48,8 @@ const LayoutBase = (props) => {
|
||||
const leftAreaSlot = <Live2D />
|
||||
const { onLoading, fullWidth } = useGlobal()
|
||||
|
||||
const FUKASAWA_SIDEBAR_COLLAPSE_SATUS_DEFAULT = fullWidth || siteConfig('FUKASAWA_SIDEBAR_COLLAPSE_SATUS_DEFAULT', null, CONFIG)
|
||||
|
||||
// 侧边栏折叠从 本地存储中获取 open 状态的初始值
|
||||
const [isCollapsed, setIsCollapse] = useState(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
return localStorage.getItem('fukasawa-sidebar-collapse') === 'true' || FUKASAWA_SIDEBAR_COLLAPSE_SATUS_DEFAULT
|
||||
}
|
||||
return FUKASAWA_SIDEBAR_COLLAPSE_SATUS_DEFAULT
|
||||
})
|
||||
|
||||
// 在组件卸载时保存 open 状态到本地存储中
|
||||
useEffect(() => {
|
||||
if (isBrowser) {
|
||||
localStorage.setItem('fukasawa-sidebar-collapse', isCollapsed)
|
||||
}
|
||||
}, [isCollapsed])
|
||||
|
||||
return (
|
||||
<ThemeGlobalFukasawa.Provider value={{ isCollapsed, setIsCollapse }}>
|
||||
<ThemeGlobalFukasawa.Provider value={{}}>
|
||||
|
||||
<div id='theme-fukasawa'>
|
||||
{/* SEO信息 */}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import Link from 'next/link'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 归档分组
|
||||
@@ -13,8 +14,10 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
||||
{archiveTitle}
|
||||
</div>
|
||||
<ul>
|
||||
{archivePosts[archiveTitle]?.map(post => (
|
||||
<li key={post.id}
|
||||
{archivePosts[archiveTitle]?.map(post => {
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
return <li key={post.id}
|
||||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
||||
>
|
||||
<div id={post?.publishDay}>
|
||||
@@ -23,13 +26,13 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
||||
</span>{' '}
|
||||
|
||||
|
||||
<Link passHref href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
<Link passHref href={url}
|
||||
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||
{post.title}
|
||||
</Link>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
const BlogPostCard = ({ post, className }) => {
|
||||
const router = useRouter()
|
||||
const currentSelected = router.asPath.split('?')[0] === '/' + post.slug
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
return (
|
||||
<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`} passHref> <div key={post.id} className={`${className} py-1.5 cursor-pointer px-1.5 hover:bg-gray-50 rounded-md dark:hover:bg-gray-600 ${currentSelected ? 'bg-green-50 text-green-500' : ''}`}>
|
||||
<Link href={url} passHref> <div key={post.id} className={`${className} py-1.5 cursor-pointer px-1.5 hover:bg-gray-50 rounded-md dark:hover:bg-gray-600 ${currentSelected ? 'bg-green-50 text-green-500' : ''}`}>
|
||||
<div className="flex flex-col w-full select-none">
|
||||
{post.title}
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,7 @@ import CONFIG from '../config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 关联推荐文章
|
||||
@@ -38,12 +39,13 @@ export default function ArticleRecommend({ recommendPosts, siteInfo }) {
|
||||
const headerImage = post?.pageCoverThumbnail
|
||||
? post.pageCoverThumbnail
|
||||
: siteInfo?.pageCover
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
return (
|
||||
(<Link
|
||||
key={post.id}
|
||||
title={post.title}
|
||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
href={url}
|
||||
passHref
|
||||
className="flex h-40 cursor-pointer overflow-hidden rounded-2xl">
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ import CONFIG from '../config'
|
||||
import TagItemMini from './TagItemMini'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 博客归档列表
|
||||
* @param posts 所有文章
|
||||
@@ -24,6 +26,8 @@ const BlogPostArchive = ({ posts = [], archiveTitle, siteInfo }) => {
|
||||
</div>
|
||||
<ul>
|
||||
{posts?.map(post => {
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
const showPreview = siteConfig('HEO_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
||||
if (post && !post.pageCoverThumbnail && siteConfig('HEO_POST_LIST_COVER_DEFAULT', null, CONFIG)) {
|
||||
post.pageCoverThumbnail = siteInfo?.pageCover
|
||||
@@ -34,7 +38,7 @@ const BlogPostArchive = ({ posts = [], archiveTitle, siteInfo }) => {
|
||||
{/* 图片封面 */}
|
||||
{showPageCover && (
|
||||
<div>
|
||||
<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`} passHref legacyBehavior>
|
||||
<Link href={url} passHref legacyBehavior>
|
||||
<LazyImage className={'rounded-xl bg-center bg-cover w-40 h-24'} src={post?.pageCoverThumbnail}/>
|
||||
</Link>
|
||||
</div>
|
||||
@@ -53,7 +57,7 @@ const BlogPostArchive = ({ posts = [], archiveTitle, siteInfo }) => {
|
||||
|
||||
{/* 标题 */}
|
||||
<Link
|
||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
href={url}
|
||||
passHref
|
||||
className={' group-hover:text-indigo-700 group-hover:dark:text-indigo-400 text-black dark:text-gray-100 dark:group-hover:text-yellow-600 line-clamp-2 replace cursor-pointer text-xl font-extrabold leading-tight'}>
|
||||
<span className='menu-link '>{post.title}</span>
|
||||
|
||||
@@ -3,6 +3,7 @@ import CONFIG from '../config'
|
||||
import TagItemMini from './TagItemMini'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
const showPreview = siteConfig('HEO_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
||||
@@ -10,6 +11,7 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
post.pageCoverThumbnail = siteInfo?.pageCover
|
||||
}
|
||||
const showPageCover = siteConfig('HEO_POST_LIST_COVER', null, CONFIG) && post?.pageCoverThumbnail && !showPreview
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
return (
|
||||
<div className={` ${siteConfig('HEO_POST_LIST_COVER_HOVER_ENLARGE', null, CONFIG) ? ' hover:scale-110 transition-all duration-150' : ''}`} >
|
||||
|
||||
@@ -22,7 +24,7 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
|
||||
{/* 图片封面 */}
|
||||
{showPageCover && (
|
||||
<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`} passHref legacyBehavior>
|
||||
<Link href={url} passHref legacyBehavior>
|
||||
<div className="w-full md:w-5/12 2xl:w-full overflow-hidden">
|
||||
<LazyImage priority={index === 0} src={post?.pageCoverThumbnail} alt={post?.title} className='h-60 w-full object-cover group-hover:scale-105 group-hover:brightness-75 transition-all duration-300' />
|
||||
</div>
|
||||
@@ -42,7 +44,7 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
|
||||
{/* 标题 */}
|
||||
<Link
|
||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
href={url}
|
||||
passHref
|
||||
className={' group-hover:text-indigo-700 dark:hover:text-yellow-700 dark:group-hover:text-yellow-600 text-black dark:text-gray-100 line-clamp-2 replace cursor-pointer text-xl font-extrabold leading-tight'}>
|
||||
<span className='menu-link '>{post.title}</span>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import Link from 'next/link'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 最新文章列表
|
||||
@@ -18,11 +19,12 @@ const LatestPostsGroup = ({ latestPosts, siteInfo }) => {
|
||||
return <div className='grid grid-cols-2 gap-4'>
|
||||
{latestPosts.map(post => {
|
||||
const headerImage = post?.pageCoverThumbnail ? post.pageCoverThumbnail : siteInfo?.pageCover
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
return (
|
||||
(<Link key={post.id} passHref
|
||||
title={post.title}
|
||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
href={url}
|
||||
|
||||
className={'my-3 flex flex-col w-full'}>
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useGlobal } from '@/lib/global'
|
||||
// import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 最新文章列表
|
||||
@@ -29,14 +30,14 @@ export default function LatestPostsGroupMini ({ latestPosts, siteInfo }) {
|
||||
</div>
|
||||
{latestPosts.map(post => {
|
||||
const selected = currentPath === `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
const headerImage = post?.pageCoverThumbnail ? post.pageCoverThumbnail : siteInfo?.pageCover
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
return (
|
||||
(<Link
|
||||
key={post.id}
|
||||
title={post.title}
|
||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
href={url}
|
||||
passHref
|
||||
className={'my-3 flex'}>
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import CONFIG from '../config'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 关联推荐文章
|
||||
@@ -33,12 +34,13 @@ export default function ArticleRecommend({ recommendPosts, siteInfo }) {
|
||||
const headerImage = post?.pageCoverThumbnail
|
||||
? post.pageCoverThumbnail
|
||||
: siteInfo?.pageCover
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
return (
|
||||
(<Link
|
||||
key={post.id}
|
||||
title={post.title}
|
||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
href={url}
|
||||
passHref
|
||||
className="flex h-40 cursor-pointer overflow-hidden">
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Link from 'next/link'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 博客归档列表
|
||||
@@ -21,8 +22,9 @@ const BlogPostArchive = ({ posts = [], archiveTitle }) => {
|
||||
{archiveTitle}
|
||||
</div>
|
||||
<ul>
|
||||
{posts?.map(post => (
|
||||
<li
|
||||
{posts?.map(post => {
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
return <li
|
||||
key={post.id}
|
||||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-indigo-500 dark:hover:border-indigo-300 dark:border-indigo-400 transform duration-500"
|
||||
>
|
||||
@@ -30,7 +32,7 @@ const BlogPostArchive = ({ posts = [], archiveTitle }) => {
|
||||
<span className="text-gray-400">{post.date?.start_date}</span>{' '}
|
||||
|
||||
<Link
|
||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
href={url}
|
||||
passHref
|
||||
className="dark:text-gray-400 dark:hover:text-indigo-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||
|
||||
@@ -39,7 +41,7 @@ const BlogPostArchive = ({ posts = [], archiveTitle }) => {
|
||||
</Link>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -3,7 +3,7 @@ import CONFIG from '../config'
|
||||
import { BlogPostCardInfo } from './BlogPostCardInfo'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
// import Image from 'next/image'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
const showPreview = siteConfig('HEXO_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
||||
@@ -12,6 +12,7 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
}
|
||||
const showPageCover = siteConfig('HEXO_POST_LIST_COVER', null, CONFIG) && post?.pageCoverThumbnail && !showPreview
|
||||
// const delay = (index % 2) * 200
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
return (
|
||||
|
||||
@@ -32,7 +33,7 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
{/* 图片封面 */}
|
||||
{showPageCover && (
|
||||
<div className="md:w-5/12 overflow-hidden">
|
||||
<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`} passHref legacyBehavior>
|
||||
<Link href={url} passHref legacyBehavior>
|
||||
<LazyImage priority={index === 1} src={post?.pageCoverThumbnail} className='h-56 w-full object-cover object-center group-hover:scale-110 duration-500' />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@@ -4,6 +4,7 @@ import TagItemMini from './TagItemMini'
|
||||
import TwikooCommentCount from '@/components/TwikooCommentCount'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { formatDateFmt } from '@/lib/formatDate'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 博客列表的文字内容
|
||||
@@ -11,11 +12,12 @@ import { formatDateFmt } from '@/lib/formatDate'
|
||||
* @returns
|
||||
*/
|
||||
export const BlogPostCardInfo = ({ post, showPreview, showPageCover, showSummary }) => {
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
return <div className={`flex flex-col justify-between lg:p-6 p-4 ${showPageCover && !showPreview ? 'md:w-7/12 w-full md:max-h-60' : 'w-full'}`}>
|
||||
<div>
|
||||
{/* 标题 */}
|
||||
<Link
|
||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
href={url}
|
||||
passHref
|
||||
className={`line-clamp-2 replace cursor-pointer text-2xl ${showPreview ? 'text-center' : ''
|
||||
} leading-tight font-normal text-gray-600 dark:text-gray-100 hover:text-indigo-700 dark:hover:text-indigo-400`}>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useGlobal } from '@/lib/global'
|
||||
// import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 最新文章列表
|
||||
@@ -28,15 +29,15 @@ const LatestPostsGroup = ({ latestPosts, siteInfo }) => {
|
||||
</div>
|
||||
</div>
|
||||
{latestPosts.map(post => {
|
||||
const selected = currentPath === `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
const headerImage = post?.pageCoverThumbnail ? post.pageCoverThumbnail : siteInfo?.pageCover
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
const selected = currentPath === url
|
||||
|
||||
return (
|
||||
(<Link
|
||||
key={post.id}
|
||||
title={post.title}
|
||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
href={url}
|
||||
passHref
|
||||
className={'my-3 flex'}>
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import CONFIG from '../config'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 关联推荐文章
|
||||
@@ -33,12 +34,13 @@ export default function ArticleRecommend({ recommendPosts, siteInfo }) {
|
||||
const headerImage = post?.pageCoverThumbnail
|
||||
? post.pageCoverThumbnail
|
||||
: siteInfo?.pageCover
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
return (
|
||||
(<Link
|
||||
key={post.id}
|
||||
title={post.title}
|
||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
href={url}
|
||||
passHref
|
||||
className="flex h-40 cursor-pointer overflow-hidden">
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Link from 'next/link'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 博客归档列表
|
||||
@@ -21,17 +22,17 @@ const BlogPostArchive = ({ posts = [], archiveTitle }) => {
|
||||
{archiveTitle}
|
||||
</div>
|
||||
<ul>
|
||||
{posts?.map(post => (
|
||||
<li
|
||||
{posts?.map(post => {
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
return <li
|
||||
key={post.id}
|
||||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-indigo-500 dark:hover:border-indigo-300 dark:border-indigo-400 transform duration-500"
|
||||
>
|
||||
<div id={post?.publishDay}>
|
||||
<span className="text-gray-400">{post.date?.start_date}</span>{' '}
|
||||
|
||||
<Link
|
||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
passHref
|
||||
<Link href={url} passHref
|
||||
className="dark:text-gray-400 dark:hover:text-indigo-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||
|
||||
{post.title}
|
||||
@@ -39,7 +40,7 @@ const BlogPostArchive = ({ posts = [], archiveTitle }) => {
|
||||
</Link>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -5,7 +5,7 @@ import CONFIG from '../config'
|
||||
import TwikooCommentCount from '@/components/TwikooCommentCount'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import { formatDateFmt } from '@/lib/formatDate'
|
||||
// import Image from 'next/image'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
const showPreview = siteConfig('MATERY_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
||||
@@ -15,6 +15,8 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
}
|
||||
const showPageCover = siteConfig('MATERY_POST_LIST_COVER', null, CONFIG) && post?.pageCoverThumbnail
|
||||
const delay = (index % 3) * 300
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
return (
|
||||
<div
|
||||
data-aos="zoom-in"
|
||||
@@ -29,7 +31,7 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
|
||||
{/* 头部图片 填充卡片 */}
|
||||
{showPageCover && (
|
||||
<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`} passHref legacyBehavior>
|
||||
<Link href={url} passHref legacyBehavior>
|
||||
<div className="flex flex-grow w-full relative duration-200 = rounded-t-md cursor-pointer transform overflow-hidden">
|
||||
<LazyImage
|
||||
src={post?.pageCoverThumbnail}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import Link from 'next/link'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 归档分组
|
||||
@@ -13,23 +14,25 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
||||
{archiveTitle}
|
||||
</div>
|
||||
<ul>
|
||||
{archivePosts[archiveTitle]?.map(post => (
|
||||
<li key={post.id}
|
||||
{archivePosts[archiveTitle]?.map(post => {
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
return <li key={post.id}
|
||||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
||||
>
|
||||
>
|
||||
<div id={post?.publishDay}>
|
||||
<span className="text-gray-400">
|
||||
{post.date?.start_date}
|
||||
</span>{' '}
|
||||
|
||||
|
||||
<Link passHref href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
<Link passHref href={url}
|
||||
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||
{post.title}
|
||||
</Link>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</li>
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -7,10 +7,12 @@ import CategoryItem from './CategoryItem'
|
||||
import TagItemMini from './TagItemMini'
|
||||
import TwikooCommentCount from '@/components/TwikooCommentCount'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
const BlogPostCard = ({ post, showSummary }) => {
|
||||
const showPreview = siteConfig('MEDIUM_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
||||
const { locale } = useGlobal()
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
return (
|
||||
<div
|
||||
key={post.id}
|
||||
@@ -23,7 +25,7 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
|
||||
<div className="lg:py-8 py-4 flex flex-col w-full">
|
||||
<Link
|
||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
href={url}
|
||||
passHref
|
||||
className={
|
||||
'cursor-pointer font-bold hover:underline text-3xl leading-tight text-gray-700 dark:text-gray-300 hover:text-green-500 dark:hover:text-green-400'
|
||||
@@ -62,7 +64,7 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
<div className="pointer-events-none border-t pt-8 border-dashed">
|
||||
<div className="w-full justify-start flex">
|
||||
<Link
|
||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
href={url}
|
||||
passHref
|
||||
className="hover:bg-opacity-100 hover:scale-105 duration-200 pointer-events-auto transform font-bold text-green-500 cursor-pointer">
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import Link from 'next/link'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 归档分组
|
||||
@@ -13,8 +14,10 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
||||
{archiveTitle}
|
||||
</div>
|
||||
<ul>
|
||||
{archivePosts[archiveTitle]?.map(post => (
|
||||
<li key={post.id}
|
||||
{archivePosts[archiveTitle]?.map(post => {
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
return <li key={post.id}
|
||||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
||||
>
|
||||
<div id={post?.publishDay}>
|
||||
@@ -23,13 +26,13 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
||||
</span>{' '}
|
||||
|
||||
|
||||
<Link passHref href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
<Link passHref href={url}
|
||||
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||
{post.title}
|
||||
</Link>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -2,14 +2,16 @@ import Link from 'next/link'
|
||||
import NotionIcon from './NotionIcon'
|
||||
import { useRouter } from 'next/router'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
const BlogPostCard = ({ post, className }) => {
|
||||
const router = useRouter()
|
||||
const currentSelected = router.asPath.split('?')[0] === '/' + post.slug
|
||||
let pageIcon = post.pageIcon !== '' ? post.pageIcon : siteConfig('IMG_LAZY_LOAD_PLACEHOLDER')
|
||||
pageIcon = post.pageIcon.indexOf('amazonaws.com') !== -1 ? post.pageIcon + '&width=88' : post.pageIcon
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
return (
|
||||
<Link href={`${siteConfig('SUB_PATH', '')}/${removeHttp(post.slug)}`} target={(checkRemoveHttp(post.slug) ? '_blank' : '_self')} passHref>
|
||||
<Link href={`${url}`} target={(checkContainHttp(post.slug) ? '_blank' : '_self')} passHref>
|
||||
<div key={post.id} className={`${className} h-full rounded-2xl p-4 dark:bg-neutral-800 cursor-pointer bg-white hover:bg-white dark:hover:bg-gray-800 ${currentSelected ? 'bg-green-50 text-green-500' : ''}`}>
|
||||
<div className="stack-entry w-full flex space-x-3 select-none dark:text-neutral-200">
|
||||
<NotionIcon icon={pageIcon} size='10' className='text-6xl w-11 h-11 mx-1 my-0 flex-none' />
|
||||
@@ -21,28 +23,6 @@ const BlogPostCard = ({ post, className }) => {
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
function removeHttp(str) {
|
||||
// 检查字符串是否包含http
|
||||
if (str.includes('http')) {
|
||||
// 如果包含,找到http的位置
|
||||
const index = str.indexOf('http');
|
||||
// 返回http之后的部分
|
||||
return str.slice(index, str.length);
|
||||
} else {
|
||||
// 如果不包含,返回原字符串
|
||||
return str;
|
||||
}
|
||||
}
|
||||
function checkRemoveHttp(str) {
|
||||
// 检查字符串是否包含http
|
||||
if (str.includes('http')) {
|
||||
// 如果包含,找到http的位置
|
||||
return str.indexOf('http') > -1
|
||||
} else {
|
||||
// 不包含
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default BlogPostCard
|
||||
|
||||
@@ -13,15 +13,9 @@ import { siteConfig } from '@/lib/config'
|
||||
* @constructor
|
||||
*/
|
||||
const BlogPostListAll = (props) => {
|
||||
// const { customMenu, posts, category, tag, allNavPages, categoryOptions } = props
|
||||
// const [filteredNavPages, setFilteredNavPages] = useState(allNavPages)
|
||||
const { customMenu } = props
|
||||
|
||||
// const [filteredNavPages, setFilteredNavPages] = useState(allNavPages)
|
||||
const { filteredNavPages, setFilteredNavPages, allNavPages } = useNavGlobal()
|
||||
// const [filteredNavPages] = useState(allNavPages)
|
||||
|
||||
// const router = useRouter()
|
||||
// 对自定义分类格式化,方便后续使用分类名称做索引,检索同步图标信息
|
||||
// 目前只支持二级分类
|
||||
const links = customMenu
|
||||
@@ -29,9 +23,6 @@ const BlogPostListAll = (props) => {
|
||||
// for循环遍历数组
|
||||
links?.map((link, i) => {
|
||||
const linkTitle = link.title + ''
|
||||
// console.log('####### link')
|
||||
// console.log(link)
|
||||
// filterLinks[linkTitle] = link
|
||||
filterLinks[linkTitle] = { title: link.title, icon: link.icon, pageIcon: link.pageIcon }
|
||||
if (link?.subMenus) {
|
||||
link.subMenus?.map((group, index) => {
|
||||
@@ -44,22 +35,10 @@ const BlogPostListAll = (props) => {
|
||||
}
|
||||
})
|
||||
|
||||
console.log('####### filterLinks')
|
||||
console.log(filterLinks)
|
||||
|
||||
// console.log('####### filterLinks')
|
||||
// console.log(filterLinks)
|
||||
|
||||
const selectedSth = false
|
||||
const groupedArray = filteredNavPages?.reduce((groups, item) => {
|
||||
const categoryName = item?.category ? item?.category : '' // 将category转换为字符串
|
||||
const categoryIcon = filterLinks[categoryName]?.icon ? filterLinks[categoryName]?.icon : '' // 将pageIcon转换为字符串
|
||||
|
||||
// console.log('####### categoryName')
|
||||
// console.log(categoryName)
|
||||
// console.log('####### categoryIcon')
|
||||
// console.log(categoryIcon)
|
||||
|
||||
let existingGroup = null
|
||||
// 开启自动分组排序
|
||||
if (JSON.parse(siteConfig('NAV_AUTO_SORT', null, CONFIG))) {
|
||||
@@ -81,17 +60,9 @@ const BlogPostListAll = (props) => {
|
||||
groupedArray?.map((group) => {
|
||||
// 自定义分类图标与post的category共用
|
||||
// 判断自定义分类与Post中category同名的项,将icon的值传递给post
|
||||
// let groupTitle = group?.category
|
||||
// item.icon = filterLinks[categoryName]?.icon ? filterLinks[categoryName]?.icon : ''
|
||||
// console.log('####### item')
|
||||
// console.log(item)
|
||||
|
||||
const groupSelected = false
|
||||
// for (const post of group?.items) {
|
||||
// if (router.asPath.split('?')[0] === '/' + post.slug) {
|
||||
// groupSelected = true
|
||||
// selectedSth = true
|
||||
// }
|
||||
// }
|
||||
|
||||
group.selected = groupSelected
|
||||
return null
|
||||
})
|
||||
@@ -110,27 +81,6 @@ const BlogPostListAll = (props) => {
|
||||
</div>
|
||||
}
|
||||
|
||||
// 处理自定义导航菜单项
|
||||
// let keyword = searchInputRef.current.value
|
||||
// if (keyword) {
|
||||
// keyword = keyword.trim()
|
||||
// } else {
|
||||
// setFilteredNavPages(allNavPages)
|
||||
// }
|
||||
// for (const filterGroup of filterAllNavPages) {
|
||||
// for (let i = filterGroup.items.length - 1; i >= 0; i--) {
|
||||
// const post = filterGroup.items[i]
|
||||
// const articleInfo = post.title + ''
|
||||
// const hit = articleInfo.toLowerCase().indexOf(keyword.toLowerCase()) > -1
|
||||
// if (!hit) {
|
||||
// // 删除
|
||||
// filterGroup.items.splice(i, 1)
|
||||
// }
|
||||
// }
|
||||
// if (filterGroup.items && filterGroup.items.length > 0) {
|
||||
// filterPosts.push(filterGroup)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
export default BlogPostListAll
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import Link from 'next/link'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 博客归档列表
|
||||
@@ -21,8 +22,10 @@ const BlogPostArchive = ({ posts = [], archiveTitle }) => {
|
||||
{archiveTitle}
|
||||
</div>
|
||||
<ul>
|
||||
{posts?.map(post => (
|
||||
<li
|
||||
{posts?.map(post => {
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
return <li
|
||||
key={post.id}
|
||||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
||||
>
|
||||
@@ -30,7 +33,7 @@ const BlogPostArchive = ({ posts = [], archiveTitle }) => {
|
||||
<span className="text-gray-500">{post.date?.start_date}</span>{' '}
|
||||
|
||||
<Link
|
||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
href={url}
|
||||
passHref
|
||||
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||
|
||||
@@ -39,7 +42,7 @@ const BlogPostArchive = ({ posts = [], archiveTitle }) => {
|
||||
</Link>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -9,6 +9,7 @@ import NotionIcon from '@/components/NotionIcon'
|
||||
import TwikooCommentCount from '@/components/TwikooCommentCount'
|
||||
import { formatDateFmt } from '@/lib/formatDate'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
const BlogPostCard = ({ post, index, showSummary }) => {
|
||||
const { locale } = useGlobal()
|
||||
@@ -22,6 +23,7 @@ const BlogPostCard = ({ post, index, showSummary }) => {
|
||||
'data-aos-anchor-placement': 'top-bottom'
|
||||
}
|
||||
: {}
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
return (
|
||||
<Card className="w-full">
|
||||
@@ -34,7 +36,7 @@ const BlogPostCard = ({ post, index, showSummary }) => {
|
||||
{/* 文章标题 */}
|
||||
<Link
|
||||
{...aosProps}
|
||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
href={url}
|
||||
passHref
|
||||
className={`cursor-pointer text-3xl ${showPreview ? 'text-center' : ''} leading-tight text-gray-700 dark:text-gray-100 hover:text-blue-500 dark:hover:text-blue-400`}>
|
||||
|
||||
@@ -99,7 +101,7 @@ const BlogPostCard = ({ post, index, showSummary }) => {
|
||||
|
||||
<div className="text-right border-t pt-8 border-dashed">
|
||||
<Link
|
||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
href={url}
|
||||
className="hover:bg-opacity-100 hover:underline transform duration-300 p-3 text-white bg-gray-800 cursor-pointer">
|
||||
|
||||
{locale.COMMON.ARTICLE_DETAIL}
|
||||
@@ -110,7 +112,7 @@ const BlogPostCard = ({ post, index, showSummary }) => {
|
||||
</div>
|
||||
|
||||
{siteConfig('NEXT_POST_LIST_COVER', null, CONFIG) && post?.pageCoverThumbnail && (
|
||||
<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`} passHref legacyBehavior>
|
||||
<Link href={url} passHref legacyBehavior>
|
||||
<div className="h-72 w-full relative duration-200 cursor-pointer transform overflow-hidden">
|
||||
<Image
|
||||
className="hover:scale-105 transform duration-500"
|
||||
|
||||
@@ -2,6 +2,7 @@ import { siteConfig } from '@/lib/config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 最新文章列表
|
||||
@@ -27,11 +28,12 @@ const LatestPostsGroup = ({ latestPosts }) => {
|
||||
</div>
|
||||
{latestPosts.map(post => {
|
||||
const selected = currentPath === `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
return (
|
||||
(<Link
|
||||
key={post.id}
|
||||
title={post.title}
|
||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
href={url}
|
||||
passHref
|
||||
className={'my-1 flex font-light'}>
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import Link from 'next/link'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 归档分组文章
|
||||
@@ -14,8 +15,10 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
||||
</div>
|
||||
|
||||
<ul>
|
||||
{archivePosts[archiveTitle].map(post => (
|
||||
<li
|
||||
{archivePosts[archiveTitle].map(post => {
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
return <li
|
||||
key={post.id}
|
||||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
||||
>
|
||||
@@ -25,7 +28,7 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
||||
</span>{' '}
|
||||
|
||||
<Link
|
||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
href={url}
|
||||
passHref
|
||||
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||
|
||||
@@ -34,7 +37,7 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
||||
</Link>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import Link from 'next/link'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
const BlogPost = ({ post }) => {
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
return (
|
||||
(<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}>
|
||||
(<Link href={url}>
|
||||
|
||||
<article key={post.id} className="mb-6 md:mb-8">
|
||||
<header className="flex flex-col justify-between md:flex-row md:items-baseline">
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Link from 'next/link'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 归档分组文章
|
||||
@@ -14,8 +15,10 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
||||
</div>
|
||||
|
||||
<ul>
|
||||
{archivePosts[archiveTitle].map(post => (
|
||||
<li
|
||||
{archivePosts[archiveTitle].map(post => {
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
return <li
|
||||
key={post.id}
|
||||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
||||
>
|
||||
@@ -25,7 +28,7 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
||||
</span>{' '}
|
||||
|
||||
<Link
|
||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
href={url}
|
||||
passHref
|
||||
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||
|
||||
@@ -34,7 +37,7 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
||||
</Link>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -11,7 +11,7 @@ import LazyImage from '@/components/LazyImage'
|
||||
*/
|
||||
const BlogPost = (props) => {
|
||||
const { post, index, siteInfo } = props
|
||||
const pageThumbnail = compressImage(post?.pageCoverThumbnail || siteInfo?.pageCover, 800, 80)
|
||||
const pageThumbnail = compressImage(post?.pageCoverThumbnail || siteInfo?.pageCover)
|
||||
const { setModalContent, setShowModal } = usePlogGlobal()
|
||||
const handleClick = () => {
|
||||
setShowModal(true)
|
||||
|
||||
@@ -41,7 +41,7 @@ const LayoutBase = props => {
|
||||
|
||||
// 页面切换关闭遮罩
|
||||
const router = useRouter()
|
||||
const closeModal = ()=>{
|
||||
const closeModal = () => {
|
||||
setShowModal(false)
|
||||
}
|
||||
|
||||
@@ -52,7 +52,6 @@ const LayoutBase = props => {
|
||||
}
|
||||
}, [router.events])
|
||||
|
||||
|
||||
return (
|
||||
<ThemeGlobalPlog.Provider value={{ showModal, setShowModal, modalContent, setModalContent }}>
|
||||
<div id='theme-plog' className='plog relative dark:text-gray-300 w-full dark:bg-black min-h-screen'>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import Link from 'next/link'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 归档分组文章
|
||||
@@ -14,8 +15,9 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
||||
</div>
|
||||
|
||||
<ul>
|
||||
{archivePosts[archiveTitle].map(post => (
|
||||
<li
|
||||
{archivePosts[archiveTitle].map(post => {
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
return <li
|
||||
key={post.id}
|
||||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500"
|
||||
>
|
||||
@@ -25,7 +27,7 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
||||
</span>{' '}
|
||||
|
||||
<Link
|
||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
href={url}
|
||||
passHref
|
||||
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600">
|
||||
|
||||
@@ -34,7 +36,7 @@ export default function BlogArchiveItem({ archiveTitle, archivePosts }) {
|
||||
</Link>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -4,10 +4,12 @@ import TwikooCommentCount from '@/components/TwikooCommentCount'
|
||||
import { formatDateFmt } from '@/lib/formatDate'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
|
||||
export const BlogItem = props => {
|
||||
const { post } = props
|
||||
const showPageCover = siteConfig('SIMPLE_POST_COVER_ENABLE', false, CONFIG)
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
return <div key={post.id} className="h-42 my-6 pb-12 border-b dark:border-gray-800" >
|
||||
{/* 文章标题 */}
|
||||
@@ -17,7 +19,7 @@ export const BlogItem = props => {
|
||||
{/* 图片封面 */}
|
||||
{showPageCover && (
|
||||
<div className="overflow-hidden mr-2 w-56 h-full">
|
||||
<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`} passHref legacyBehavior>
|
||||
<Link href={url} passHref legacyBehavior>
|
||||
<LazyImage src={post?.pageCoverThumbnail} className='w-56 h-full object-cover object-center group-hover:scale-110 duration-500' />
|
||||
</Link>
|
||||
</div>
|
||||
@@ -27,7 +29,7 @@ export const BlogItem = props => {
|
||||
<div className='article-info'>
|
||||
<h2 className="mb-2">
|
||||
<Link
|
||||
href={`${siteConfig('SUB_PATH', '')}/${post.slug}`}
|
||||
href={url}
|
||||
className="blog-item-title font-bold text-black text-2xl menu-link">
|
||||
{post.title}
|
||||
</Link>
|
||||
@@ -60,7 +62,7 @@ export const BlogItem = props => {
|
||||
</div>
|
||||
|
||||
<div className='block'>
|
||||
<Link href={`${siteConfig('SUB_PATH', '')}/${post.slug}`} className='inline-block rounded-sm text-blue-600 text-xs dark:border-gray-800 border hover:text-red-400 transition-all duration-200 hover:border-red-300 h-9 leading-8 px-5'>
|
||||
<Link href={url} className='inline-block rounded-sm text-blue-600 text-xs dark:border-gray-800 border hover:text-red-400 transition-all duration-200 hover:border-red-300 h-9 leading-8 px-5'>
|
||||
Continue Reading <i className="fa-solid fa-angle-right align-middle"></i>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,6 @@ import Link from 'next/link'
|
||||
import CONFIG from '../config'
|
||||
import SocialButton from './SocialButton'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { compressImage } from '@/lib/notion/mapImage'
|
||||
|
||||
/**
|
||||
* 网站顶部
|
||||
@@ -11,7 +10,6 @@ import { compressImage } from '@/lib/notion/mapImage'
|
||||
*/
|
||||
export default function Header (props) {
|
||||
const { siteInfo } = props
|
||||
const avatar = compressImage(siteInfo?.icon || siteConfig('AVATAR'), 200)
|
||||
|
||||
return (
|
||||
<header className="text-center justify-between items-center px-6 bg-white h-80 dark:bg-black relative z-10">
|
||||
@@ -20,7 +18,7 @@ export default function Header (props) {
|
||||
{/* 可使用一张单图作为logo */}
|
||||
<div className='flex space-x-6'>
|
||||
<div className='hover:rotate-45 hover:scale-125 transform duration-200 cursor-pointer justify-center items-center flex'>
|
||||
<LazyImage priority={true} src={avatar} className='rounded-full' width={100} height={100} alt={siteConfig('AUTHOR')} />
|
||||
<LazyImage priority={true} src={siteInfo?.icon} className='rounded-full' width={100} height={100} alt={siteConfig('AUTHOR')} />
|
||||
</div>
|
||||
|
||||
<div className='flex-col flex justify-center'>
|
||||
|
||||
Reference in New Issue
Block a user