mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-14 07:26:52 +00:00
Merge branch 'main' into main
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# 环境变量 @see https://www.nextjs.cn/docs/basic-features/environment-variables
|
||||
NEXT_PUBLIC_VERSION=4.2.3
|
||||
NEXT_PUBLIC_VERSION=4.2.4
|
||||
|
||||
|
||||
# 可在此添加环境变量,去掉最左边的(# )注释即可
|
||||
|
||||
@@ -45,8 +45,9 @@ const BLOG = {
|
||||
// 默认下会将你上传到 notion的主页封面图和头像也给替换,建议将主页封面图和头像放在其他图床,在 notion 里配置 link 即可。
|
||||
|
||||
// START ************网站字体*****************
|
||||
|
||||
FONT_STYLE: process.env.NEXT_PUBLIC_FONT_STYLE || 'font-sans', // ['font-serif','font-sans'] 两种可选,分别是衬线和无衬线: 参考 https://www.jianshu.com/p/55e410bd2115
|
||||
// ['font-serif','font-sans'] 两种可选,分别是衬线和无衬线: 参考 https://www.jianshu.com/p/55e410bd2115
|
||||
// 后面空格隔开的font-light的字体粗细,留空是默认粗细;参考 https://www.tailwindcss.cn/docs/font-weight
|
||||
FONT_STYLE: process.env.NEXT_PUBLIC_FONT_STYLE || 'font-sans font-light',
|
||||
// 字体CSS 例如 https://npm.elemecdn.com/lxgw-wenkai-webfont@1.6.0/style.css
|
||||
FONT_URL: [
|
||||
// 'https://npm.elemecdn.com/lxgw-wenkai-webfont@1.6.0/style.css',
|
||||
|
||||
@@ -119,6 +119,7 @@ export async function getNotionPageData({ pageId, from }) {
|
||||
|
||||
/**
|
||||
* 获取用户自定义单页菜单
|
||||
* 旧版本,不读取Menu菜单,而是读取type=Page生成菜单
|
||||
* @param notionPageData
|
||||
* @returns {Promise<[]|*[]>}
|
||||
*/
|
||||
@@ -126,11 +127,16 @@ function getCustomNav({ allPages }) {
|
||||
const customNav = []
|
||||
if (allPages && allPages.length > 0) {
|
||||
allPages.forEach(p => {
|
||||
p.to = p.slug
|
||||
if (p?.slug?.indexOf('http') === 0) {
|
||||
customNav.push({ icon: p.icon || null, name: p.title, to: p.slug, target: '_blank', show: true })
|
||||
p.target = '_blank'
|
||||
} else {
|
||||
customNav.push({ icon: p.icon || null, name: p.title, to: '/' + p.slug, target: '_self', show: true })
|
||||
p.target = '_self'
|
||||
if (p?.slug?.indexOf('/') !== 0) {
|
||||
p.to = '/' + p.slug
|
||||
}
|
||||
}
|
||||
customNav.push({ icon: p.icon || null, name: p.title, to: p.slug, target: '_blank', show: true })
|
||||
})
|
||||
}
|
||||
return customNav
|
||||
@@ -142,13 +148,19 @@ function getCustomNav({ allPages }) {
|
||||
* @returns
|
||||
*/
|
||||
function getCustomMenu({ collectionData }) {
|
||||
const menuPages = collectionData.filter(post => (post?.type === BLOG.NOTION_PROPERTY_NAME.type_menu || post?.type === BLOG.NOTION_PROPERTY_NAME.type_sub_menu) && post.status === 'Published')
|
||||
const menuPages = collectionData.filter(post => post.status === 'Published' && (post?.type === BLOG.NOTION_PROPERTY_NAME.type_menu || post?.type === BLOG.NOTION_PROPERTY_NAME.type_sub_menu))
|
||||
const menus = []
|
||||
if (menuPages && menuPages.length > 0) {
|
||||
menuPages.forEach(e => {
|
||||
e.show = true
|
||||
if (e?.slug?.indexOf('http') === 0) {
|
||||
e.target = '_blank'
|
||||
e.to = e.slug
|
||||
} else {
|
||||
e.target = '_self'
|
||||
if (e?.slug?.indexOf('/') !== 0) {
|
||||
e.to = '/' + e.slug
|
||||
}
|
||||
}
|
||||
if (e.type === BLOG.NOTION_PROPERTY_NAME.type_menu) {
|
||||
menus.push(e)
|
||||
|
||||
@@ -18,10 +18,7 @@ export async function getPostBlocks(id, from, slice) {
|
||||
return filterPostBlocks(id, pageBlock, slice)
|
||||
}
|
||||
|
||||
const start = new Date().getTime()
|
||||
pageBlock = await getPageWithRetry(id, from)
|
||||
const end = new Date().getTime()
|
||||
console.log('[API耗时]', `${end - start}ms`)
|
||||
|
||||
if (pageBlock) {
|
||||
await setDataToCache(cacheKey, pageBlock)
|
||||
@@ -38,10 +35,7 @@ export async function getSingleBlock(id, from) {
|
||||
return pageBlock
|
||||
}
|
||||
|
||||
const start = new Date().getTime()
|
||||
pageBlock = await getPageWithRetry(id, from)
|
||||
const end = new Date().getTime()
|
||||
console.log('[API耗时]', `${end - start}ms`)
|
||||
|
||||
if (pageBlock) {
|
||||
await setDataToCache(cacheKey, pageBlock)
|
||||
@@ -56,16 +50,17 @@ export async function getSingleBlock(id, from) {
|
||||
*/
|
||||
export async function getPageWithRetry(id, from, retryAttempts = 3) {
|
||||
if (retryAttempts && retryAttempts > 0) {
|
||||
console.log('[请求API]', `from:${from}`, `id:${id}`, retryAttempts < 3 ? `剩余重试次数:${retryAttempts}` : '')
|
||||
console.log('[API-->>请求]', `from:${from}`, `id:${id}`, retryAttempts < 3 ? `剩余重试次数:${retryAttempts}` : '')
|
||||
try {
|
||||
const authToken = BLOG.NOTION_ACCESS_TOKEN || null
|
||||
const api = new NotionAPI({ authToken, userTimeZone: Intl.DateTimeFormat().resolvedOptions().timeZone })
|
||||
const start = new Date().getTime()
|
||||
const pageData = await api.getPage(id)
|
||||
// console.log('stringfy', JSON.stringify(pageData))
|
||||
console.info('[响应成功]:', `from:${from}`)
|
||||
const end = new Date().getTime()
|
||||
console.log('[API<<--响应]', `耗时:${end - start}ms - from:${from}`)
|
||||
return pageData
|
||||
} catch (e) {
|
||||
console.warn('[响应异常]:', e)
|
||||
console.warn('[API<<--异常]:', e)
|
||||
await delay(1000)
|
||||
const cacheKey = 'page_block_' + id
|
||||
const pageBlock = await getDataFromCache(cacheKey)
|
||||
|
||||
@@ -16,13 +16,16 @@ function scanSubdirectories(directory) {
|
||||
const subdirectories = []
|
||||
|
||||
fs.readdirSync(directory).forEach(file => {
|
||||
const fullPath = path.join(directory, file)
|
||||
const stats = fs.statSync(fullPath)
|
||||
// 这段代码会将landing排除在可选主题中
|
||||
|
||||
// landing主题比较特殊,不在可切换的主题中显示
|
||||
if (stats.isDirectory() && file !== 'landing') {
|
||||
subdirectories.push(file)
|
||||
}
|
||||
// const fullPath = path.join(directory, file)
|
||||
// const stats = fs.statSync(fullPath)
|
||||
// landing主题默认隐藏掉,一般网站不会用到
|
||||
// if (stats.isDirectory() && file !== 'landing') {
|
||||
// subdirectories.push(file)
|
||||
// }
|
||||
|
||||
subdirectories.push(file)
|
||||
})
|
||||
|
||||
return subdirectories
|
||||
@@ -94,7 +97,7 @@ module.exports = withBundleAnalyzer({
|
||||
// }
|
||||
// 动态主题:添加 resolve.alias 配置,将动态路径映射到实际路径
|
||||
if (!isServer) {
|
||||
console.log('加载默认主题', path.resolve(__dirname, 'themes', THEME))
|
||||
console.log('[加载主题]', path.resolve(__dirname, 'themes', THEME))
|
||||
}
|
||||
config.resolve.alias['@theme-components'] = path.resolve(__dirname, 'themes', THEME)
|
||||
return config
|
||||
|
||||
153
package.json
153
package.json
@@ -1,77 +1,78 @@
|
||||
{
|
||||
"name": "notion-next",
|
||||
"version": "4.2.3",
|
||||
"homepage": "https://github.com/tangly1024/NotionNext.git",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/tangly1024/NotionNext.git"
|
||||
},
|
||||
"author": {
|
||||
"name": "tangly",
|
||||
"email": "mail@tangly1024.com",
|
||||
"url": "http://tangly1024.com"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"post-build": "next-sitemap --config next-sitemap.config.js",
|
||||
"export": "next build && next-sitemap --config next-sitemap.config.js && next export",
|
||||
"bundle-report": "ANALYZE=true yarn build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@giscus/react": "^2.2.6",
|
||||
"@headlessui/react": "^1.7.15",
|
||||
"@next/bundle-analyzer": "^12.1.1",
|
||||
"@vercel/analytics": "^1.0.0",
|
||||
"algoliasearch": "^4.18.0",
|
||||
"animejs": "^3.2.1",
|
||||
"aos": "^3.0.0-beta.6",
|
||||
"axios": ">=0.21.1",
|
||||
"copy-to-clipboard": "^3.3.1",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"feed": "^4.2.2",
|
||||
"js-md5": "^0.7.3",
|
||||
"localStorage": "^1.0.4",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"memory-cache": "^0.2.0",
|
||||
"mongodb": "^4.6.0",
|
||||
"next": "13.3.1",
|
||||
"notion-client": "6.15.6",
|
||||
"notion-utils": "6.15.6",
|
||||
"nprogress": "^0.2.0",
|
||||
"preact": "^10.5.15",
|
||||
"prism-themes": "1.9.0",
|
||||
"react": "^18.2.0",
|
||||
"react-cookies": "^0.1.1",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-facebook": "^8.1.4",
|
||||
"react-notion-x": "6.16.0",
|
||||
"react-share": "^4.4.1",
|
||||
"react-tweet-embed": "~2.0.0",
|
||||
"typed.js": "^2.0.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@waline/client": "^2.5.1",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"eslint": "^7.26.0",
|
||||
"eslint-config-next": "^13.1.1",
|
||||
"eslint-config-standard": "^16.0.2",
|
||||
"eslint-plugin-import": "^2.23.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^5.1.0",
|
||||
"eslint-plugin-react": "^7.23.2",
|
||||
"next-sitemap": "^1.6.203",
|
||||
"postcss": "^8.4.31",
|
||||
"tailwindcss": "^3.3.2",
|
||||
"webpack-bundle-analyzer": "^4.5.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"axios": ">=0.21.1"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/tangly/NotionNext/issues",
|
||||
"email": "tlyong1992@hotmail.com"
|
||||
}
|
||||
}
|
||||
"name": "notion-next",
|
||||
"version": "4.2.4",
|
||||
"homepage": "https://github.com/tangly1024/NotionNext.git",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/tangly1024/NotionNext.git"
|
||||
},
|
||||
"author": {
|
||||
"name": "tangly",
|
||||
"email": "mail@tangly1024.com",
|
||||
"url": "http://tangly1024.com"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"post-build": "next-sitemap --config next-sitemap.config.js",
|
||||
"export": "next build && next-sitemap --config next-sitemap.config.js && next export",
|
||||
"bundle-report": "ANALYZE=true yarn build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@giscus/react": "^2.2.6",
|
||||
"@headlessui/react": "^1.7.15",
|
||||
"@next/bundle-analyzer": "^12.1.1",
|
||||
"@vercel/analytics": "^1.0.0",
|
||||
"algoliasearch": "^4.18.0",
|
||||
"animejs": "^3.2.1",
|
||||
"aos": "^3.0.0-beta.6",
|
||||
"axios": ">=0.21.1",
|
||||
"copy-to-clipboard": "^3.3.1",
|
||||
"feed": "^4.2.2",
|
||||
"js-md5": "^0.7.3",
|
||||
"localStorage": "^1.0.4",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"memory-cache": "^0.2.0",
|
||||
"mongodb": "^4.6.0",
|
||||
"next": "13.3.1",
|
||||
"notion-client": "6.15.6",
|
||||
"notion-utils": "6.15.6",
|
||||
"nprogress": "^0.2.0",
|
||||
"preact": "^10.5.15",
|
||||
"prism-themes": "1.9.0",
|
||||
"react": "^18.2.0",
|
||||
"react-cookies": "^0.1.1",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-facebook": "^8.1.4",
|
||||
"react-notion-x": "6.16.0",
|
||||
"react-share": "^4.4.1",
|
||||
"react-tweet-embed": "~2.0.0",
|
||||
"typed.js": "^2.0.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@waline/client": "^2.5.1",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"eslint": "^7.26.0",
|
||||
"eslint-config-next": "^13.1.1",
|
||||
"eslint-config-standard": "^16.0.2",
|
||||
"eslint-plugin-import": "^2.23.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^5.1.0",
|
||||
"eslint-plugin-react": "^7.23.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"next-sitemap": "^1.6.203",
|
||||
"postcss": "^8.4.31",
|
||||
"prettier": "3.2.5",
|
||||
"tailwindcss": "^3.3.2",
|
||||
"webpack-bundle-analyzer": "^4.5.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"axios": ">=0.21.1"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/tangly/NotionNext/issues",
|
||||
"email": "tlyong1992@hotmail.com"
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ class MyDocument extends Document {
|
||||
})}
|
||||
</Head>
|
||||
|
||||
<body className={`${BLOG.FONT_STYLE} dark:bg-black font-light scroll-smooth`}>
|
||||
<body className={`${BLOG.FONT_STYLE} dark:bg-black scroll-smooth`}>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
|
||||
@@ -4,6 +4,7 @@ import Link from 'next/link'
|
||||
import TwikooCommentCount from '@/components/TwikooCommentCount'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
|
||||
const BlogPostCard = ({ post }) => {
|
||||
const showPageCover = siteConfig('EXAMPLE_POST_LIST_COVER', null, CONFIG) && post?.pageCoverThumbnail
|
||||
@@ -15,16 +16,18 @@ const BlogPostCard = ({ post }) => {
|
||||
<Link
|
||||
href={`/${post.slug}`}
|
||||
className="text-black dark:text-gray-100 text-xl md:text-2xl no-underline hover:underline">
|
||||
{post?.title}
|
||||
<NotionIcon icon={post.pageIcon} />{post?.title}
|
||||
</Link>
|
||||
</h2>
|
||||
|
||||
<div className="mb-4 text-sm text-gray-700 dark:text-gray-300">
|
||||
by <a href="#" className="text-gray-700 dark:text-gray-300">{siteConfig('AUTHOR')}</a> on {post.date?.start_date || post.createdTime}
|
||||
<TwikooCommentCount post={post} className='pl-1'/>
|
||||
{post.category && <>
|
||||
<span className="font-bold mx-1"> | </span>
|
||||
<Link href={`/category/${post.category}`} className="text-gray-700 dark:text-gray-300 hover:underline">{post.category}</Link>
|
||||
{/* <span className="font-bold mx-1"> | </span> */}
|
||||
</>}
|
||||
{/* <span className="font-bold mx-1"> | </span> */}
|
||||
{/* <a href="#" className="text-gray-700">2 Comments</a> */}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
|
||||
/**
|
||||
@@ -11,7 +12,7 @@ export const Title = (props) => {
|
||||
const description = post?.description || siteConfig('AUTHOR')
|
||||
|
||||
return <div className="text-center px-6 py-12 mb-6 bg-gray-100 dark:bg-hexo-black-gray dark:border-hexo-black-gray border-b">
|
||||
<h1 className=" text-xl md:text-4xl pb-4">{title}</h1>
|
||||
<h1 className="text-xl md:text-4xl pb-4"><NotionIcon icon={post?.pageIcon} />{title}</h1>
|
||||
<p className="leading-loose text-gray-dark">
|
||||
{description}
|
||||
</p>
|
||||
|
||||
@@ -9,6 +9,7 @@ import { AdSlot } from '@/components/GoogleAdsense'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import { formatDateFmt } from '@/lib/formatDate'
|
||||
import WWAds from '@/components/WWAds'
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -36,7 +37,7 @@ export default function ArticleDetail(props) {
|
||||
|
||||
{/* 文章Title */}
|
||||
<div className="font-bold text-4xl text-black dark:text-white">
|
||||
{post.title}
|
||||
<NotionIcon icon={post?.pageIcon} />{post.title}
|
||||
</div>
|
||||
|
||||
<section className="flex-wrap flex mt-2 text-gray-400 dark:text-gray-400 font-light leading-8">
|
||||
|
||||
@@ -4,6 +4,7 @@ import TagItemMini from './TagItemMini'
|
||||
import CONFIG from '../config'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
|
||||
/**
|
||||
* 文章列表卡片
|
||||
@@ -32,7 +33,7 @@ const BlogCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
|
||||
return (
|
||||
<div {...aosProps} style={{ maxHeight: '60rem' }}
|
||||
<article {...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">
|
||||
@@ -51,16 +52,18 @@ const BlogCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
|
||||
{/* 文字部分 */}
|
||||
<div className="flex flex-col w-full">
|
||||
<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}
|
||||
</Link>
|
||||
<h2>
|
||||
<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`}
|
||||
>
|
||||
<NotionIcon icon={post.pageIcon} /> {post.title}
|
||||
</Link>
|
||||
</h2>
|
||||
|
||||
{(!showPreview || showSummary) && (
|
||||
<p className="my-2 tracking-wide line-clamp-3 text-gray-800 dark:text-gray-300 text-md font-light leading-6">
|
||||
<main className="my-2 tracking-wide line-clamp-3 text-gray-800 dark:text-gray-300 text-md font-light leading-6">
|
||||
{post.summary}
|
||||
</p>
|
||||
</main>
|
||||
)}
|
||||
|
||||
{/* 分类标签 */}
|
||||
@@ -83,7 +86,7 @@ const BlogCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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>f
|
||||
</div>
|
||||
|
||||
{/* 折叠子菜单 */}
|
||||
{hasSubMenu && <Collapse isOpen={isOpen} onHeightChange={props.onHeightChange}>
|
||||
|
||||
@@ -2,6 +2,7 @@ import { siteConfig } from '@/lib/config'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
|
||||
const BlogPostCard = ({ post, className }) => {
|
||||
const router = useRouter()
|
||||
@@ -9,8 +10,8 @@ const BlogPostCard = ({ post, className }) => {
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
return (
|
||||
<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 className="w-full select-none">
|
||||
<NotionIcon icon={post?.pageIcon}/> {post.title}
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
@@ -4,8 +4,6 @@ import { useRouter } from 'next/router'
|
||||
|
||||
export const MenuItemDrop = ({ link }) => {
|
||||
const [show, changeShow] = useState(false)
|
||||
// const show = true
|
||||
// const changeShow = () => {}
|
||||
const router = useRouter()
|
||||
|
||||
if (!link || !link.show) {
|
||||
@@ -13,7 +11,6 @@ export const MenuItemDrop = ({ link }) => {
|
||||
}
|
||||
const hasSubMenu = link?.subMenus?.length > 0
|
||||
const selected = (router.pathname === link.to) || (router.asPath === link.to)
|
||||
|
||||
return <li className='cursor-pointer list-none items-center flex mx-2' onMouseOver={() => changeShow(true)} onMouseOut={() => changeShow(false)} >
|
||||
|
||||
{hasSubMenu &&
|
||||
|
||||
@@ -33,6 +33,7 @@ import BlogArchiveItem from './components/BlogArchiveItem'
|
||||
import Link from 'next/link'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
const WWAds = dynamic(() => import('@/components/WWAds'), { ssr: false })
|
||||
|
||||
// 主题全局变量
|
||||
@@ -219,7 +220,7 @@ const LayoutSlug = (props) => {
|
||||
{!lock && <div id='container'>
|
||||
|
||||
{/* title */}
|
||||
<h1 className="text-3xl pt-12 dark:text-gray-300">{post?.title}</h1>
|
||||
<h1 className="text-3xl pt-12 dark:text-gray-300"><NotionIcon icon={post?.pageIcon} />{post?.title}</h1>
|
||||
|
||||
{/* Notion文章主体 */}
|
||||
{post && (<section id="article-wrapper" className="px-1">
|
||||
|
||||
@@ -4,6 +4,7 @@ import TagItemMini from './TagItemMini'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
|
||||
const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
const showPreview = siteConfig('HEO_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
||||
@@ -13,7 +14,7 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
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' : ''}`} >
|
||||
<article className={` ${siteConfig('HEO_POST_LIST_COVER_HOVER_ENLARGE', null, CONFIG) ? ' hover:scale-110 transition-all duration-150' : ''}`} >
|
||||
|
||||
<div
|
||||
data-aos="fade-up"
|
||||
@@ -33,7 +34,7 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
|
||||
{/* 文字区块 */}
|
||||
<div className={'flex p-6 2xl:p-4 flex-col justify-between h-48 md:h-full 2xl:h-48 w-full md:w-7/12 2xl:w-full'}>
|
||||
<div>
|
||||
<header>
|
||||
{/* 分类 */}
|
||||
{post?.category && <div className={`flex mb-1 items-center ${showPreview ? 'justify-center' : 'justify-start'} hidden md:block flex-wrap dark:text-gray-500 text-gray-600 `}>
|
||||
<Link passHref href={`/category/${post.category}`}
|
||||
@@ -47,15 +48,15 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
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>
|
||||
<NotionIcon icon={post.pageIcon} /><span className='menu-link '>{post.title}</span>
|
||||
</Link>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{/* 摘要 */}
|
||||
{(!showPreview || showSummary) && (
|
||||
<p className="line-clamp-2 replace my-3 2xl:my-1 text-gray-700 dark:text-gray-300 text-sm font-light leading-tight">
|
||||
<main className="line-clamp-2 replace my-3 2xl:my-1 text-gray-700 dark:text-gray-300 text-sm font-light leading-tight">
|
||||
{post.summary}
|
||||
</p>
|
||||
</main>
|
||||
)}
|
||||
|
||||
<div className="md:flex-nowrap flex-wrap md:justify-start inline-block">
|
||||
@@ -70,7 +71,7 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</article>
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
/**
|
||||
* 标签组
|
||||
@@ -8,22 +9,34 @@ import Link from 'next/link'
|
||||
* @constructor
|
||||
*/
|
||||
const TagGroups = ({ tags, className }) => {
|
||||
const router = useRouter()
|
||||
const { tag: currentTag } = router.query
|
||||
if (!tags) return <></>
|
||||
return (
|
||||
<div id='tags-group' className='dark:border-gray-700 space-y-2'>
|
||||
{
|
||||
tags.map((tag, index) => {
|
||||
return <Link passHref
|
||||
key={index}
|
||||
href={`/tag/${encodeURIComponent(tag.name)}`}
|
||||
className={'cursor-pointer inline-block whitespace-nowrap'}>
|
||||
<div className={`${className || ''} flex items-center hover:bg-blue-600 dark:hover:bg-yellow-600 hover:scale-110 hover:text-white rounded-lg px-2 py-0.5 duration-150 transition-all`}>
|
||||
<div className='text-lg'>{tag.name} </div>{tag.count ? <sup className='relative ml-1'>{tag.count}</sup> : <></>}
|
||||
</div>
|
||||
|
||||
return (
|
||||
<div id="tags-group" className="dark:border-gray-700 space-y-2">
|
||||
{tags.map((tag, index) => {
|
||||
const selected = currentTag === tag.name
|
||||
return (
|
||||
<Link passHref key={index} href={`/tag/${encodeURIComponent(tag.name)}`}
|
||||
className={'cursor-pointer inline-block whitespace-nowrap'}
|
||||
>
|
||||
<div className={`${className || ''}
|
||||
${selected ? 'text-white bg-blue-600 dark:bg-yellow-600' : ''}
|
||||
flex items-center hover:bg-blue-600 dark:hover:bg-yellow-600 hover:scale-110 hover:text-white rounded-lg px-2 py-0.5 duration-150 transition-all`}
|
||||
>
|
||||
<div className="text-lg">{tag.name} </div>
|
||||
{tag.count
|
||||
? (
|
||||
<sup className="relative ml-1">{tag.count}</sup>
|
||||
)
|
||||
: (
|
||||
<></>
|
||||
)}
|
||||
</div>
|
||||
</Link>
|
||||
})
|
||||
}
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import TwikooCommentCount from '@/components/TwikooCommentCount'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { formatDateFmt } from '@/lib/formatDate'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
|
||||
/**
|
||||
* 博客列表的文字内容
|
||||
@@ -13,58 +14,63 @@ import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
*/
|
||||
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'}`}>
|
||||
return <article 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={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`}>
|
||||
<header>
|
||||
<h2>
|
||||
{/* 标题 */}
|
||||
<Link
|
||||
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`}>
|
||||
|
||||
<span className='menu-link '>{post.title}</span>
|
||||
<NotionIcon icon={post.pageIcon} /><span className='menu-link '>{post.title}</span>
|
||||
|
||||
</Link>
|
||||
</Link>
|
||||
</h2>
|
||||
|
||||
{/* 分类 */}
|
||||
{ post?.category && <div
|
||||
className={`flex mt-2 items-center ${showPreview ? 'justify-center' : 'justify-start'
|
||||
} flex-wrap dark:text-gray-500 text-gray-400 `}
|
||||
>
|
||||
<Link
|
||||
href={`/category/${post.category}`}
|
||||
passHref
|
||||
className="cursor-pointer font-light text-sm menu-link hover:text-indigo-700 dark:hover:text-indigo-400 transform">
|
||||
{/* 分类 */}
|
||||
{ post?.category && <div
|
||||
className={`flex mt-2 items-center ${showPreview ? 'justify-center' : 'justify-start'
|
||||
} flex-wrap dark:text-gray-500 text-gray-400 `}
|
||||
>
|
||||
<Link
|
||||
href={`/category/${post.category}`}
|
||||
passHref
|
||||
className="cursor-pointer font-light text-sm menu-link hover:text-indigo-700 dark:hover:text-indigo-400 transform">
|
||||
|
||||
<i className="mr-1 far fa-folder" />
|
||||
{post.category}
|
||||
<i className="mr-1 far fa-folder" />
|
||||
{post.category}
|
||||
|
||||
</Link>
|
||||
</Link>
|
||||
|
||||
<TwikooCommentCount className='text-sm hover:text-indigo-700 dark:hover:text-indigo-400' post={post}/>
|
||||
</div>}
|
||||
<TwikooCommentCount className='text-sm hover:text-indigo-700 dark:hover:text-indigo-400' post={post}/>
|
||||
</div>}
|
||||
</header>
|
||||
|
||||
{/* 摘要 */}
|
||||
{(!showPreview || showSummary) && !post.results && (
|
||||
<p className="line-clamp-2 replace my-3 text-gray-700 dark:text-gray-300 text-sm font-light leading-7">
|
||||
{/* 摘要 */}
|
||||
{(!showPreview || showSummary) && !post.results && (
|
||||
<main className="line-clamp-2 replace my-3 text-gray-700 dark:text-gray-300 text-sm font-light leading-7">
|
||||
{post.summary}
|
||||
</p>
|
||||
)}
|
||||
</main>
|
||||
)}
|
||||
|
||||
{/* 搜索结果 */}
|
||||
{post.results && (
|
||||
<p className="line-clamp-2 mt-4 text-gray-700 dark:text-gray-300 text-sm font-light leading-7">
|
||||
{post.results.map((r, index) => (
|
||||
<span key={index}>{r}</span>
|
||||
))}
|
||||
</p>
|
||||
)}
|
||||
{/* 预览 */}
|
||||
{showPreview && (
|
||||
<div className="overflow-ellipsis truncate">
|
||||
<NotionPage post={post} />
|
||||
</div>
|
||||
)}
|
||||
{/* 搜索结果 */}
|
||||
{post.results && (
|
||||
<p className="line-clamp-2 mt-4 text-gray-700 dark:text-gray-300 text-sm font-light leading-7">
|
||||
{post.results.map((r, index) => (
|
||||
<span key={index}>{r}</span>
|
||||
))}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* 预览 */}
|
||||
{showPreview && (
|
||||
<div className="overflow-ellipsis truncate">
|
||||
<NotionPage post={post} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
</div>
|
||||
|
||||
@@ -92,5 +98,5 @@ export const BlogPostCardInfo = ({ post, showPreview, showPageCover, showSummary
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ export default function Features() {
|
||||
<section className="relative">
|
||||
|
||||
{/* Section background (needs .relative class on parent and next sibling elements) */}
|
||||
<div className="absolute inset-0 bg-gray-100 pointer-events-none mb-16" aria-hidden="true"></div>
|
||||
<div className="absolute inset-0 bg-gray-100 dark:bg-black pointer-events-none mb-16" aria-hidden="true"></div>
|
||||
<div className="absolute left-0 right-0 m-auto w-px p-px h-20 bg-gray-200 transform -translate-y-1/2"></div>
|
||||
|
||||
<div className="relative max-w-6xl mx-auto px-4 sm:px-6">
|
||||
@@ -33,8 +33,8 @@ export default function Features() {
|
||||
|
||||
{/* Section header */}
|
||||
<div className="max-w-3xl mx-auto text-center pb-12 md:pb-16">
|
||||
<h1 className="h2 mb-4">{siteConfig('LANDING_FEATURES_HEADER_1', null, CONFIG)}</h1>
|
||||
<p className="text-xl text-gray-600 leading-relaxed" dangerouslySetInnerHTML={{ __html: siteConfig('LANDING_FEATURES_HEADER_1_P', null, CONFIG) }}></p>
|
||||
<h1 className="h2 mb-4 dark:text-white">{siteConfig('LANDING_FEATURES_HEADER_1', null, CONFIG)}</h1>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-400 leading-relaxed" dangerouslySetInnerHTML={{ __html: siteConfig('LANDING_FEATURES_HEADER_1_P', null, CONFIG) }}></p>
|
||||
</div>
|
||||
|
||||
{/* Section content */}
|
||||
@@ -43,8 +43,8 @@ export default function Features() {
|
||||
{/* Content */}
|
||||
<div className="max-w-xl md:max-w-none md:w-full mx-auto md:col-span-7 lg:col-span-6 md:mt-6" data-aos="fade-right">
|
||||
<div className="md:pr-4 lg:pr-12 xl:pr-16 mb-8">
|
||||
<h3 className="h3 mb-3">{siteConfig('LANDING_FEATURES_HEADER_2', null, CONFIG)}</h3>
|
||||
<p className="text-xl text-gray-600">{siteConfig('LANDING_FEATURES_HEADER_2_P', null, CONFIG)}</p>
|
||||
<h3 className="h3 mb-3 dark:text-white">{siteConfig('LANDING_FEATURES_HEADER_2', null, CONFIG)}</h3>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-400">{siteConfig('LANDING_FEATURES_HEADER_2_P', null, CONFIG)}</p>
|
||||
</div>
|
||||
{/* Tabs buttons */}
|
||||
<div className="mb-8 md:mb-0">
|
||||
|
||||
@@ -6,7 +6,7 @@ export default function FeaturesBlocks() {
|
||||
<section className="relative">
|
||||
|
||||
{/* Section background (needs .relative class on parent and next sibling elements) */}
|
||||
<div className="absolute inset-0 top-1/2 md:mt-24 lg:mt-0 bg-gray-900 pointer-events-none" aria-hidden="true"></div>
|
||||
<div className="absolute inset-0 top-1/2 md:mt-24 lg:mt-0 bg-gray-900 dark:bg-black pointer-events-none" aria-hidden="true"></div>
|
||||
<div className="absolute left-0 right-0 bottom-0 m-auto w-px p-px h-20 bg-gray-200 transform translate-y-1/2"></div>
|
||||
|
||||
<div className="relative max-w-6xl mx-auto px-4 sm:px-6">
|
||||
@@ -14,15 +14,15 @@ export default function FeaturesBlocks() {
|
||||
|
||||
{/* Section header */}
|
||||
<div className="max-w-3xl mx-auto text-center pb-12 md:pb-20">
|
||||
<h2 className="h2 mb-4">{siteConfig('LANDING_FEATURES_BLOCK_HEADER', null, CONFIG)}</h2>
|
||||
<p className="text-xl text-gray-600" dangerouslySetInnerHTML={{ __html: siteConfig('LANDING_FEATURES_BLOCK_P', null, CONFIG) }}></p>
|
||||
<h2 className="h2 mb-4 dark:text-white">{siteConfig('LANDING_FEATURES_BLOCK_HEADER', null, CONFIG)}</h2>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-400" dangerouslySetInnerHTML={{ __html: siteConfig('LANDING_FEATURES_BLOCK_P', null, CONFIG) }}></p>
|
||||
</div>
|
||||
|
||||
{/* Items */}
|
||||
<div className="max-w-sm mx-auto grid gap-6 md:grid-cols-2 lg:grid-cols-3 items-start md:max-w-2xl lg:max-w-none">
|
||||
|
||||
{/* 1st item */}
|
||||
<div className="relative flex flex-col items-center p-6 bg-white rounded shadow-xl">
|
||||
<div className="relative flex flex-col items-center p-6 bg-white rounded-md shadow-xl border">
|
||||
<svg className="w-16 h-16 p-1 -mt-1 mb-2" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" fillRule="evenodd">
|
||||
<rect className="fill-current text-blue-600" width="64" height="64" rx="32" />
|
||||
@@ -39,7 +39,7 @@ export default function FeaturesBlocks() {
|
||||
</div>
|
||||
|
||||
{/* 2nd item */}
|
||||
<div className="relative flex flex-col items-center p-6 bg-white rounded shadow-xl">
|
||||
<div className="relative flex flex-col items-center p-6 bg-white rounded-md shadow-xl border">
|
||||
<svg className="w-16 h-16 p-1 -mt-1 mb-2" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" fillRule="evenodd">
|
||||
<rect className="fill-current text-blue-600" width="64" height="64" rx="32" />
|
||||
@@ -55,7 +55,7 @@ export default function FeaturesBlocks() {
|
||||
</div>
|
||||
|
||||
{/* 3rd item */}
|
||||
<div className="relative flex flex-col items-center p-6 bg-white rounded shadow-xl">
|
||||
<div className="relative flex flex-col items-center p-6 bg-white rounded-md shadow-xl border">
|
||||
<svg className="w-16 h-16 p-1 -mt-1 mb-2" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" fillRule="evenodd">
|
||||
<rect className="fill-current text-blue-600" width="64" height="64" rx="32" />
|
||||
@@ -72,7 +72,7 @@ export default function FeaturesBlocks() {
|
||||
</div>
|
||||
|
||||
{/* 4th item */}
|
||||
<div className="relative flex flex-col items-center p-6 bg-white rounded shadow-xl">
|
||||
<div className="relative flex flex-col items-center p-6 bg-white rounded-md shadow-xl border">
|
||||
<svg className="w-16 h-16 p-1 -mt-1 mb-2" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" fillRule="evenodd">
|
||||
<rect className="fill-current text-blue-600" width="64" height="64" rx="32" />
|
||||
@@ -89,7 +89,7 @@ export default function FeaturesBlocks() {
|
||||
</div>
|
||||
|
||||
{/* 5th item */}
|
||||
<div className="relative flex flex-col items-center p-6 bg-white rounded shadow-xl">
|
||||
<div className="relative flex flex-col items-center p-6 bg-white rounded-md shadow-xl border">
|
||||
<svg className="w-16 h-16 p-1 -mt-1 mb-2" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" fillRule="evenodd">
|
||||
<rect className="fill-current text-blue-600" width="64" height="64" rx="32" />
|
||||
@@ -105,7 +105,7 @@ export default function FeaturesBlocks() {
|
||||
</div>
|
||||
|
||||
{/* 6th item */}
|
||||
<div className="relative flex flex-col items-center p-6 bg-white rounded shadow-xl">
|
||||
<div className="relative flex flex-col items-center p-6 bg-white rounded-md shadow-xl border">
|
||||
<svg className="w-16 h-16 p-1 -mt-1 mb-2" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" fillRule="evenodd">
|
||||
<rect className="fill-current text-blue-600" width="64" height="64" rx="32" />
|
||||
|
||||
@@ -149,6 +149,11 @@ export default function Footer() {
|
||||
|
||||
{/* Social as */}
|
||||
<ul className="flex mb-4 md:order-1 md:ml-4 md:mb-0">
|
||||
<li>
|
||||
<div className='h-full flex justify-center items-center text-gray-600 hover:text-gray-900 bg-white hover:bg-white-100'>
|
||||
Powered by<a href='https://github.com/tangly1024/NotionNext' className='mx-1 hover:underline font-semibold'>NotionNext {siteConfig('VERSION')}</a>
|
||||
</div>
|
||||
</li>
|
||||
{/* <li>
|
||||
<a href="#0" className="flex justify-center items-center text-gray-600 hover:text-gray-900 bg-white hover:bg-white-100 rounded-full shadow transition duration-150 ease-in-out" aria-label="Twitter">
|
||||
<svg className="w-8 h-8 fill-current" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
|
||||
|
||||
@@ -22,7 +22,7 @@ export default function Header() {
|
||||
}, [top])
|
||||
|
||||
return (
|
||||
<header className={`fixed w-full z-30 md:bg-opacity-90 transition duration-300 ease-in-out ${!top ? 'bg-white backdrop-blur-sm shadow-lg' : ''}`}>
|
||||
<header className={`fixed w-full z-50 md:bg-opacity-90 transition duration-300 ease-in-out ${!top ? 'bg-white dark:bg-hexo-black-gray backdrop-blur-sm shadow-lg' : ''}`}>
|
||||
<div className="max-w-6xl mx-auto px-5 sm:px-6">
|
||||
<div className="flex items-center justify-between h-16 md:h-20">
|
||||
|
||||
@@ -36,7 +36,7 @@ export default function Header() {
|
||||
{/* Desktop sign in links */}
|
||||
<ul className="flex grow justify-end flex-wrap items-center">
|
||||
<li>
|
||||
<Link href={siteConfig('LANDING_HEADER_BUTTON_1_URL', null, CONFIG)} target='_blank' className="font-medium hover:font-bold text-gray-600 hover:text-gray-900 px-5 py-3 flex items-center transition duration-150 ease-in-out">
|
||||
<Link href={siteConfig('LANDING_HEADER_BUTTON_1_URL', null, CONFIG)} target='_blank' className="font-medium hover:font-bold text-gray-600 hover:text-gray-900 dark:text-gray-400 px-5 py-3 flex items-center transition duration-150 ease-in-out">
|
||||
<div>{siteConfig('LANDING_HEADER_BUTTON_1_TITLE', null, CONFIG)}</div>
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
@@ -34,7 +34,7 @@ export default function Hero() {
|
||||
<span className="bg-clip-text text-transparent bg-gradient-to-r from-blue-500 to-teal-400">{siteConfig('LANDING_HERO_TITLE_1', null, CONFIG)}</span>
|
||||
</h1>
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<p className="text-xl text-gray-600 mb-8" data-aos="zoom-y-out" data-aos-delay="150">{siteConfig('LANDING_HERO_P_1', null, CONFIG)}</p>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-400 mb-8" data-aos="zoom-y-out" data-aos-delay="150">{siteConfig('LANDING_HERO_P_1', null, CONFIG)}</p>
|
||||
<div className="max-w-xs mx-auto sm:max-w-none sm:flex sm:justify-center" data-aos="zoom-y-out" data-aos-delay="300">
|
||||
<div>
|
||||
<a target='_blank' className="btn text-white bg-blue-600 hover:bg-blue-700 w-full mb-4 sm:w-auto sm:mb-0"
|
||||
|
||||
56
themes/landing/components/Pricing.js
Normal file
56
themes/landing/components/Pricing.js
Normal file
@@ -0,0 +1,56 @@
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import CONFIG from '../config'
|
||||
import Link from 'next/link'
|
||||
|
||||
/**
|
||||
* 价格收费表
|
||||
*/
|
||||
export const Pricing = (props) => {
|
||||
return <div className="w-full mx-auto bg-white dark:bg-black px-5 py-10 text-gray-800 mb-10">
|
||||
<div className="text-center max-w-xl mx-auto">
|
||||
<h1 className="text-5xl md:text-5xl font-bold mb-5 dark:text-white">{siteConfig('LANDING_PRICING_TITLE', null, CONFIG)}</h1>
|
||||
<h3 className="text-xl font-medium mb-10 dark:text-gray-400">{siteConfig('LANDING_PRICING_P', null, CONFIG)}</h3>
|
||||
</div>
|
||||
<div className="max-w-4xl mx-auto md:flex">
|
||||
<div className="w-full md:w-1/3 md:max-w-none bg-white dark:bg-hexo-black-gray px-8 md:px-10 py-8 md:py-10 mb-3 mx-auto md:my-6 rounded-md shadow-lg shadow-gray-600 md:flex md:flex-col">
|
||||
<div className="w-full flex-grow dark:text-gray-400">
|
||||
<h2 className="text-center font-bold uppercase mb-4">{siteConfig('LANDING_PRICING_1_TITLE', null, CONFIG)}</h2>
|
||||
<h3 className="text-center font-bold text-4xl mb-5">{siteConfig('LANDING_PRICING_1_PRICE', null, CONFIG)}</h3>
|
||||
<ul className="text-sm px-5 mb-8">
|
||||
{siteConfig('LANDING_PRICING_1_CONTENT', null, CONFIG)?.split(',').map((item, index) => <li key={index} className="leading-tight"><i className="mdi-check-bold text-lg"></i>{item}</li>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
<Link className="w-full" href={siteConfig('LANDING_PRICING_1_URL', null, CONFIG)}>
|
||||
<button className="font-bold bg-blue-600 hover:bg-blue-700 text-white rounded-md px-10 py-2 transition-colors w-full">{siteConfig('LANDING_PRICING_1_BUTTON', null, CONFIG)}</button>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="w-full md:w-1/3 md:max-w-none bg-white dark:bg-hexo-black-gray px-8 md:px-10 py-8 md:py-10 mb-3 mx-auto md:-mx-3 md:mb-0 rounded-md shadow-lg shadow-gray-600 md:relative md:z-20 md:flex md:flex-col">
|
||||
<div className="w-full flex-grow dark:text-gray-400">
|
||||
<h2 className="text-center font-bold uppercase mb-4">{siteConfig('LANDING_PRICING_2_TITLE', null, CONFIG)}</h2>
|
||||
<h3 className="text-center font-bold text-4xl md:text-5xl mb-5">{siteConfig('LANDING_PRICING_2_PRICE', null, CONFIG)}</h3>
|
||||
<ul className="text-sm px-5 mb-8">
|
||||
{siteConfig('LANDING_PRICING_2_CONTENT', null, CONFIG)?.split(',').map((item, index) => <li key={index} className="leading-tight"><i className="mdi-check-bold text-lg"></i>{item}</li>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
<Link className="w-full" target='_blank' href={siteConfig('LANDING_PRICING_2_URL', null, CONFIG)}>
|
||||
<button className="font-bold bg-blue-600 hover:bg-blue-700 text-white rounded-md px-10 py-2 transition-colors w-full">{siteConfig('LANDING_PRICING_2_BUTTON', null, CONFIG)}</button>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="w-full md:w-1/3 md:max-w-none bg-white dark:bg-hexo-black-gray px-8 md:px-10 py-8 md:py-10 mb-3 mx-auto md:my-6 rounded-md shadow-lg shadow-gray-600 md:flex md:flex-col">
|
||||
<div className="w-full flex-grow dark:text-gray-400">
|
||||
<h2 className="text-center font-bold uppercase mb-4">{siteConfig('LANDING_PRICING_3_TITLE', null, CONFIG)}</h2>
|
||||
<h3 className="text-center font-bold text-4xl mb-5">{siteConfig('LANDING_PRICING_3_PRICE', null, CONFIG)}</h3>
|
||||
<ul className="text-sm px-5 mb-8">
|
||||
{siteConfig('LANDING_PRICING_3_CONTENT', null, CONFIG)?.split(',').map((item, index) => <li key={index} className="leading-tight"><i className="mdi-check-bold text-lg"></i>{item}</li>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
<Link className="w-full" target='_blank' href={siteConfig('LANDING_PRICING_3_URL', null, CONFIG)}>
|
||||
<button className="font-bold bg-blue-600 hover:bg-blue-700 text-white rounded-md px-10 py-2 transition-colors w-full">{siteConfig('LANDING_PRICING_3_BUTTON', null, CONFIG)}</button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -31,8 +31,8 @@ export default function Testimonials() {
|
||||
|
||||
{/* Section header */}
|
||||
<div className="max-w-3xl mx-auto text-center pb-12 md:pb-16">
|
||||
<h2 className="h2 mb-4">{siteConfig('LANDING_TESTIMONIALS_HEADER', null, CONFIG)}</h2>
|
||||
<p className="text-xl text-gray-600" data-aos="zoom-y-out">{siteConfig('LANDING_TESTIMONIALS_P', null, CONFIG)}</p>
|
||||
<h2 className="h2 mb-4 dark:text-white">{siteConfig('LANDING_TESTIMONIALS_HEADER', null, CONFIG)}</h2>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-400" data-aos="zoom-y-out">{siteConfig('LANDING_TESTIMONIALS_P', null, CONFIG)}</p>
|
||||
</div>
|
||||
|
||||
{/* Testimonials */}
|
||||
|
||||
@@ -47,7 +47,7 @@ const CONFIG = {
|
||||
LANDING_FEATURES_BLOCK_6_P: 'NotionNext,助您轻松开始写作',
|
||||
|
||||
// 感言
|
||||
LANDING_TESTIMONIALS_HEADER: '已搭建超5300个网站、总浏览量突破100,000,000+',
|
||||
LANDING_TESTIMONIALS_HEADER: '已搭建超7000个网站、总浏览量突破100,000,000+',
|
||||
LANDING_TESTIMONIALS_P: '网站内容涵盖地产、教育、建筑、医学、机械、IT、电子、软件、自媒体、数位游民、短视频、电商、学生、摄影爱好者、旅行爱好者等等各行各业',
|
||||
|
||||
LANDING_TESTIMONIALS_AVATAR: 'https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F22de3fcb-d90d-4271-bc01-f815f476122b%2F4FE0A0C0-E487-4C74-BF8E-6F01A27461B8-14186-000008094BC289A6.jpg?table=collection&id=a320a2cc-6ebe-4a8d-95cc-ea94e63bced9&width=200',
|
||||
@@ -60,6 +60,27 @@ const CONFIG = {
|
||||
LANDING_POST_REDIRECT_ENABLE: process.env.NEXT_PUBLIC_POST_REDIRECT_ENABLE || false, // 是否开启文章地址重定向 ; 用于迁移旧网站域名
|
||||
LANDING_POST_REDIRECT_URL: process.env.NEXT_PUBLIC_POST_REDIRECT_URL || 'https://blog.tangly1024.com', // 重定向网站地址
|
||||
|
||||
LANDING_PRICING_TITLE: '价格表',
|
||||
LANDING_PRICING_P: 'NotionNext开源免费,此处仅演示订阅付费功能!请勿购买!',
|
||||
|
||||
LANDING_PRICING_1_TITLE: '个人版',
|
||||
LANDING_PRICING_1_PRICE: '免费',
|
||||
LANDING_PRICING_1_CONTENT: '项目源代码,部署教程,不定时技术答疑',
|
||||
LANDING_PRICING_1_BUTTON: '开始体验',
|
||||
LANDING_PRICING_1_URL: 'https://docs.tangly1024.com/about',
|
||||
|
||||
LANDING_PRICING_2_TITLE: '捐赠版',
|
||||
LANDING_PRICING_2_PRICE: '$9.9/月',
|
||||
LANDING_PRICING_2_CONTENT: '项目源代码,部署教程,长期技术答疑,代码升级合并,内部社群',
|
||||
LANDING_PRICING_2_BUTTON: '立即购买',
|
||||
LANDING_PRICING_2_URL: 'https://tangly1024.lemonsqueezy.com/checkout/buy/0adb9153-0799-4f51-91aa-1f06391ea4e0',
|
||||
|
||||
LANDING_PRICING_3_TITLE: '企业版',
|
||||
LANDING_PRICING_3_PRICE: '$59/月',
|
||||
LANDING_PRICING_3_CONTENT: '项目源代码,部署教程,VIP技术咨询,代码升级合并,内部社群,定制功能开发,SEO优化',
|
||||
LANDING_PRICING_3_BUTTON: '立即购买',
|
||||
LANDING_PRICING_3_URL: 'https://tangly1024.lemonsqueezy.com/checkout/buy/df924d66-09dc-42a4-a632-a6b0c5cc4f28',
|
||||
|
||||
LANDING_NEWSLETTER: process.env.NEXT_PUBLIC_THEME_LANDING_NEWSLETTER || false // 是否开启邮件订阅 请先配置mailchimp功能 https://docs.tangly1024.com/article/notion-next-mailchimp
|
||||
}
|
||||
export default CONFIG
|
||||
|
||||
@@ -20,18 +20,19 @@ import CONFIG from './config'
|
||||
import Loading from '@/components/Loading'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { Pricing } from './components/Pricing'
|
||||
|
||||
/**
|
||||
* 布局框架
|
||||
* 作为一个基础框架使用,定义了整个主题每个页面必备的顶部导航栏和页脚
|
||||
* 其它页面都嵌入到此框架中使用
|
||||
* Landing 主题用作产品落地页展示
|
||||
* 结合Stripe或者lemonsqueezy插件可以成为saas支付订阅
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutBase = (props) => {
|
||||
const { children } = props
|
||||
|
||||
return <div id='theme-landing' className="overflow-hidden flex flex-col justify-between bg-white">
|
||||
return <div id='theme-landing' className="overflow-hidden flex flex-col justify-between bg-white dark:bg-black">
|
||||
|
||||
{/* 顶部导航栏 */}
|
||||
<Header />
|
||||
@@ -58,6 +59,7 @@ const LayoutIndex = (props) => {
|
||||
<Features />
|
||||
<FeaturesBlocks />
|
||||
<Testimonials />
|
||||
<Pricing/>
|
||||
<Newsletter />
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -6,6 +6,7 @@ import TwikooCommentCount from '@/components/TwikooCommentCount'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import { formatDateFmt } from '@/lib/formatDate'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
|
||||
const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
const showPreview = siteConfig('MATERY_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
||||
@@ -27,7 +28,7 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
className="w-full mb-4 overflow-hidden shadow-md border dark:border-black rounded-xl bg-white dark:bg-hexo-black-gray">
|
||||
|
||||
{/* 固定高度 ,空白用图片拉升填充 */}
|
||||
<div className="group flex flex-col h-80 justify-between">
|
||||
<header className="group flex flex-col h-80 justify-between">
|
||||
|
||||
{/* 头部图片 填充卡片 */}
|
||||
{showPageCover && (
|
||||
@@ -38,13 +39,15 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
alt={post.title}
|
||||
className="h-full w-full group-hover:scale-125 group-hover:brightness-50 brightness-90 rounded-t-md transform object-cover duration-500"
|
||||
/>
|
||||
<div className='absolute bottom-0 left-0 text-white p-6 text-2xl replace break-words w-full shadow-text'>{post.title}</div>
|
||||
<h2 className='absolute bottom-0 left-0 text-white p-6 text-2xl replace break-words w-full shadow-text'>
|
||||
<NotionIcon icon={post.pageIcon} />{post.title}
|
||||
</h2>
|
||||
</div>
|
||||
</Link>
|
||||
)}
|
||||
|
||||
{/* 文字描述 */}
|
||||
<div >
|
||||
<main >
|
||||
{/* 描述 */}
|
||||
<div className="px-4 flex flex-col w-full text-gray-700 dark:text-gray-300">
|
||||
|
||||
@@ -93,8 +96,8 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
</div>
|
||||
</div>
|
||||
</>)}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</header>
|
||||
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
|
||||
/**
|
||||
* 文章背景图
|
||||
@@ -9,7 +10,7 @@ export default function PostHeader({ post, siteInfo }) {
|
||||
return (
|
||||
<div id='header' className="flex h-96 justify-center align-middle items-center w-full relative bg-black">
|
||||
<div className="z-10 leading-snug font-bold xs:text-4xl sm:text-4xl md:text-5xl md:leading-snug text-4xl shadow-text-md flex justify-center text-center text-white">
|
||||
{title}
|
||||
<NotionIcon icon={post?.pageIcon} />{title}
|
||||
</div>
|
||||
<LazyImage alt={title} src={headerImage} className='pointer-events-none select-none w-full h-full object-cover opacity-30 absolute'
|
||||
placeholder='blur' blurDataURL='/bg_image.jpg' />
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import Link from 'next/link'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
|
||||
/**
|
||||
* 文章详情页介绍
|
||||
@@ -12,7 +13,7 @@ export default function ArticleInfo(props) {
|
||||
|
||||
return (<>
|
||||
{/* title */}
|
||||
<h1 className="text-3xl pt-12 dark:text-gray-300">{post?.title}</h1>
|
||||
<h1 className="text-3xl pt-12 dark:text-gray-300"><NotionIcon icon={post?.pageIcon} />{post?.title}</h1>
|
||||
|
||||
{/* meta */}
|
||||
<section className="py-2 items-center text-sm px-1">
|
||||
|
||||
@@ -8,6 +8,7 @@ import TagItemMini from './TagItemMini'
|
||||
import TwikooCommentCount from '@/components/TwikooCommentCount'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
|
||||
const BlogPostCard = ({ post, showSummary }) => {
|
||||
const showPreview = siteConfig('MEDIUM_POST_LIST_PREVIEW', null, CONFIG) && post.blockMap
|
||||
@@ -23,19 +24,19 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
className="mb-6 max-w-7xl border-b dark:border-gray-800 "
|
||||
>
|
||||
|
||||
<div className="lg:py-8 py-4 flex flex-col w-full">
|
||||
<header className="lg:py-8 py-4 flex flex-col w-full">
|
||||
<Link
|
||||
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'
|
||||
}>
|
||||
<div>
|
||||
<h2>
|
||||
{siteConfig('MEDIUM_POST_LIST_COVER', null, CONFIG) && <div className='w-full max-h-96 object-cover overflow-hidden mb-2'>
|
||||
<LazyImage src={post.pageCoverThumbnail} style={post.pageCoverThumbnail ? {} : { height: '0px' }} className='w-full max-h-96 object-cover hover:scale-125 duration-150' />
|
||||
</div>}
|
||||
{post.title}
|
||||
</div>
|
||||
<NotionIcon icon={post.pageIcon} />{post.title}
|
||||
</h2>
|
||||
|
||||
</Link>
|
||||
|
||||
@@ -53,9 +54,9 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
<div className="flex"></div>
|
||||
|
||||
{(!showPreview || showSummary) && (
|
||||
<p className="my-4 text-gray-700 dark:text-gray-300 text-sm font-light leading-7">
|
||||
<main className="my-4 text-gray-700 dark:text-gray-300 text-sm font-light leading-7">
|
||||
{post.summary}
|
||||
</p>
|
||||
</main>
|
||||
)}
|
||||
|
||||
{showPreview && (
|
||||
@@ -76,7 +77,7 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</header>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ export const MenuItem = ({ link }) => {
|
||||
|
||||
// #号加标题 快速跳转到指定锚点
|
||||
const isAnchor = link?.to === '#'
|
||||
const url = isAnchor ? link.to : `#${link.name}`
|
||||
const url = isAnchor ? `#${link.name}` : link.to
|
||||
|
||||
return <>
|
||||
{/* 菜单 */}
|
||||
@@ -33,7 +33,7 @@ export const MenuItem = ({ link }) => {
|
||||
{link?.subMenus
|
||||
? (<>
|
||||
<span className='dark:text-neutral-400 dark:hover:text-white font-bold w-full display-block'>
|
||||
<i className={`text-base ${link?.icon ? link?.icon : (isAnchor ? 'fas fa-hashtag' : '')} mr-1`} />{link?.title}
|
||||
<i className={`text-base ${link?.icon ? link?.icon : ''} mr-1`} />{link?.title}
|
||||
</span>
|
||||
<div className='inline-flex items-center select-none pointer-events-none '>
|
||||
<i className={`${isOpen ? '-rotate-90' : ''} text-xs dark:text-neutral-500 text-gray-300 hover:text-black dark:hover:text-white-400 px-2 fas fa-chevron-left transition-all duration-200`}></i>
|
||||
|
||||
@@ -33,6 +33,7 @@ import LogoBar from './components/LogoBar'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import Live2D from '@/components/Live2D'
|
||||
import BlogArchiveItem from './components/BlogArchiveItem'
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
|
||||
const WWAds = dynamic(() => import('@/components/WWAds'), { ssr: false })
|
||||
|
||||
@@ -213,7 +214,6 @@ const LayoutPostList = props => {
|
||||
*/
|
||||
const LayoutSlug = (props) => {
|
||||
const { post, lock, validPassword } = props
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* 文章锁 */}
|
||||
@@ -222,7 +222,7 @@ const LayoutSlug = (props) => {
|
||||
{!lock && <div id='container'>
|
||||
|
||||
{/* title */}
|
||||
<h1 className="text-3xl pt-4 md:pt-12 dark:text-gray-300">{post?.title}</h1>
|
||||
<h1 className="text-3xl pt-4 md:pt-12 dark:text-gray-300"><NotionIcon icon={post?.pageIcon} />{post?.title}</h1>
|
||||
|
||||
{/* Notion文章主体 */}
|
||||
{post && (<section id="article-wrapper" className="px-1">
|
||||
|
||||
@@ -3,6 +3,7 @@ import Image from 'next/image'
|
||||
import TagItem from './TagItem'
|
||||
import md5 from 'js-md5'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
|
||||
export const ArticleInfo = (props) => {
|
||||
const { post } = props
|
||||
@@ -12,9 +13,9 @@ export const ArticleInfo = (props) => {
|
||||
return <section className="flex-wrap flex mt-2 text-gray--600 dark:text-gray-400 font-light leading-8">
|
||||
<div>
|
||||
|
||||
<div className="font-bold text-3xl text-black dark:text-white">
|
||||
{post?.title}
|
||||
</div>
|
||||
<h1 className="font-bold text-3xl text-black dark:text-white">
|
||||
<NotionIcon icon={post?.pageIcon} />{post?.title}
|
||||
</h1>
|
||||
|
||||
{post?.type !== 'Page' && <>
|
||||
<nav className="flex mt-7 items-start text-gray-500 dark:text-gray-400">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Link from 'next/link'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
|
||||
const BlogPost = ({ post }) => {
|
||||
const url = checkContainHttp(post.slug) ? sliceUrlFromHttp(post.slug) : `${siteConfig('SUB_PATH', '')}/${post.slug}`
|
||||
@@ -11,7 +12,7 @@ const BlogPost = ({ post }) => {
|
||||
<article key={post.id} className="mb-6 md:mb-8">
|
||||
<header className="flex flex-col justify-between md:flex-row md:items-baseline">
|
||||
<h2 className="text-lg md:text-xl font-medium mb-2 cursor-pointer text-black dark:text-gray-100">
|
||||
{post.title}
|
||||
<NotionIcon icon={post.pageIcon} />{post.title}
|
||||
</h2>
|
||||
<time className="flex-shrink-0 text-gray-600 dark:text-gray-400">
|
||||
{post?.publishDay}
|
||||
|
||||
@@ -3,6 +3,7 @@ import Image from 'next/image'
|
||||
import TagItem from './TagItem'
|
||||
import md5 from 'js-md5'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
|
||||
export const ArticleInfo = (props) => {
|
||||
const { post } = props
|
||||
@@ -12,9 +13,9 @@ export const ArticleInfo = (props) => {
|
||||
return <section className="flex-wrap flex mt-2 text-gray--600 dark:text-gray-400 font-light leading-8">
|
||||
<div>
|
||||
|
||||
<div className="font-bold text-3xl text-black dark:text-white">
|
||||
{post?.title}
|
||||
</div>
|
||||
<h1 className="font-bold text-3xl text-black dark:text-white">
|
||||
<NotionIcon icon={post?.pageIcon} />{post?.title}
|
||||
</h1>
|
||||
|
||||
{post?.type !== 'Page' && <>
|
||||
<nav className="flex mt-7 items-start text-gray-500 dark:text-gray-400">
|
||||
|
||||
@@ -3,6 +3,7 @@ import Link from 'next/link'
|
||||
import { usePlogGlobal } from '..'
|
||||
import { isMobile } from '@/lib/utils'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
|
||||
/**
|
||||
* 博客照片卡牌
|
||||
@@ -37,7 +38,7 @@ const BlogPost = (props) => {
|
||||
<LazyImage src={pageThumbnail} className='aspect-[16/9] w-full h-full object-cover filter contrast-120' />
|
||||
|
||||
<h2 className="text-md absolute left-0 bottom-0 m-4 text-gray-100 shadow-text">
|
||||
{post?.title}
|
||||
<NotionIcon icon={post.pageIcon} /> {post?.title}
|
||||
</h2>
|
||||
{post?.category && <div className='text-xs rounded-lg absolute left-0 top-0 m-4 px-2 py-1 bg-gray-200 dark:bg-black dark:bg-opacity-25 hover:bg-blue-700 hover:text-white duration-200'>
|
||||
<Link href={`/category/${post?.category}`}>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useGlobal } from '@/lib/global'
|
||||
import CONFIG from '../config'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { formatDateFmt } from '@/lib/formatDate'
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
|
||||
/**
|
||||
* 文章描述
|
||||
@@ -18,7 +19,7 @@ export default function ArticleInfo (props) {
|
||||
<section className="mt-2 text-gray-600 dark:text-gray-400 leading-8">
|
||||
<h2
|
||||
className="blog-item-title mb-5 font-bold text-black text-xl md:text-2xl no-underline">
|
||||
{post?.title}
|
||||
<NotionIcon icon={post?.pageIcon} />{post?.title}
|
||||
</h2>
|
||||
|
||||
<div className='flex flex-wrap text-gray-700 dark:text-gray-300'>
|
||||
@@ -27,7 +28,7 @@ export default function ArticleInfo (props) {
|
||||
<span> <i className="fa-regular fa-user"></i> <a href={siteConfig('SIMPLE_AUTHOR_LINK', null, CONFIG)}>{siteConfig('AUTHOR')}</a></span>
|
||||
<span> <i className="fa-regular fa-clock"></i> {post?.publishDay}</span>
|
||||
{post?.category && <span> <i className="fa-regular fa-folder"></i> <a href={`/category/${post?.category}`} className="hover:text-red-400 transition-all duration-200">{post?.category}</a></span>}
|
||||
{post?.tags && post?.tags?.length > 0 && post?.tags.map(t => <span key={t}> / <Link href={`/tag/${t}`}><a className=' hover:text-red-400 transition-all duration-200'>{t}</a></Link></span>)}
|
||||
{post?.tags && post?.tags?.length > 0 && post?.tags.map(t => <span key={t}> / <Link href={`/tag/${t}`}><span className=' hover:text-red-400 transition-all duration-200'>{t}</span></Link></span>)}
|
||||
</div>)}
|
||||
|
||||
{post?.type !== 'Page' && (<div className=''>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { formatDateFmt } from '@/lib/formatDate'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import { checkContainHttp, sliceUrlFromHttp } from '@/lib/utils'
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
|
||||
export const BlogItem = props => {
|
||||
const { post } = props
|
||||
@@ -26,18 +27,18 @@ export const BlogItem = props => {
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className='article-info'>
|
||||
<article className='article-info'>
|
||||
|
||||
<h2 className="mb-2">
|
||||
<Link
|
||||
href={url}
|
||||
className="blog-item-title font-bold text-black text-2xl menu-link">
|
||||
{post.title}
|
||||
<NotionIcon icon={post.pageIcon} />{post.title}
|
||||
</Link>
|
||||
</h2>
|
||||
|
||||
{/* 文章信息 */}
|
||||
|
||||
<div className="mb-5 text-md text-gray-700 dark:text-gray-300 flex-wrap flex leading-6">
|
||||
<header className="mb-5 text-md text-gray-700 dark:text-gray-300 flex-wrap flex leading-6">
|
||||
<div className='space-x-2'>
|
||||
<span> <a href={siteConfig('SIMPLE_AUTHOR_LINK', null, CONFIG)} className='p-1 hover:text-red-400 transition-all duration-200'><i className="fa-regular fa-user"></i> {siteConfig('AUTHOR')}</a></span>
|
||||
<span>
|
||||
@@ -52,13 +53,13 @@ export const BlogItem = props => {
|
||||
{post.category && <Link href={`/category/${post.category}`} className='p-1'> <span className="hover:text-red-400 transition-all duration-200"><i className="fa-regular fa-folder mr-0.5" />{post.category}</span></Link>}
|
||||
{post?.tags && post?.tags?.length > 0 && post?.tags.map(t => <Link key={t} href={`/tag/${t}`} className=' hover:text-red-400 transition-all duration-200'><span > /{t}</span></Link>)}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div className="text-gray-700 dark:text-gray-300 leading-normal mb-6">
|
||||
<main className="text-gray-700 dark:text-gray-300 leading-normal mb-6">
|
||||
{post.summary}
|
||||
{post.summary && <span>...</span>}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div className='block'>
|
||||
|
||||
@@ -4131,6 +4131,11 @@ prelude-ls@^1.2.1:
|
||||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
|
||||
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
|
||||
|
||||
prettier@3.2.5:
|
||||
version "3.2.5"
|
||||
resolved "https://r.cnpmjs.org/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368"
|
||||
integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==
|
||||
|
||||
prism-themes@1.9.0:
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/prism-themes/-/prism-themes-1.9.0.tgz#19c034f3205f1e28d75d89728e54ccd745f7e3dd"
|
||||
|
||||
Reference in New Issue
Block a user