diff --git a/.env.local b/.env.local index dac45ac8..a597737c 100644 --- a/.env.local +++ b/.env.local @@ -1,2 +1,2 @@ # 环境变量 @see https://www.nextjs.cn/docs/basic-features/environment-variables -NEXT_PUBLIC_VERSION=3.5.0 \ No newline at end of file +NEXT_PUBLIC_VERSION=3.5.1 \ No newline at end of file diff --git a/README.md b/README.md index fffcc637..0562ac6b 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,8 @@ yarn run start # 本地启动NextJS服务 mouyase
mouyase

🔧 🐛 - + qfdk
qfdk

🔧 🐛 + diff --git a/blog.config.js b/blog.config.js index 23d02168..136e8e7b 100644 --- a/blog.config.js +++ b/blog.config.js @@ -31,8 +31,8 @@ const BLOG = { CUSTOM_FONT_SANS: ['LXGW WenKai Screen'], // 自定义无衬线字体 CUSTOM_FONT_SERIF: ['LXGW WenKai Screen'], // 自定义衬线字体 - // 图标字体 - FONT_AWESOME_PATH: 'https://cdn.bootcdn.net/ajax/libs/font-awesome/5.15.4/css/all.min.css', // 图标库CDN ,国内推荐BootCDN,国外推荐 CloudFlare https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css + // 图标库CDN(可以直接改版本号) + FONT_AWESOME_PATH: 'https://cdn.bootcdn.net/ajax/libs/font-awesome/6.2.0/css/all.min.css', BACKGROUND_LIGHT: '#eeeeee', // use hex value, don't forget '#' e.g #fffefc BACKGROUND_DARK: '#000000', // use hex value, don't forget '#' @@ -59,7 +59,7 @@ const BLOG = { CONTACT_TELEGRAM: '', // 鼠标点击烟花特效 - FIREWORKS: process.env.NEXT_PUBLIC_FIREWORKS || true, // 鼠标点击烟花特效 + FIREWORKS: process.env.NEXT_PUBLIC_FIREWORKS || false, // 鼠标点击烟花特效 // 悬浮挂件 WIDGET_PET: process.env.NEXT_PUBLIC_WIDGET_PET || true, // 是否显示宠物挂件 diff --git a/components/Busuanzi.js b/components/Busuanzi.js index a2456a75..12e592d8 100644 --- a/components/Busuanzi.js +++ b/components/Busuanzi.js @@ -1,10 +1,15 @@ import busuanzi from '@/lib/busuanzi' import { useRouter } from 'next/router' -import { useEffect } from 'react' +import { useGlobal } from '@/lib/global' +// import { useRouter } from 'next/router' +import React from 'react' export default function Busuanzi () { + const { theme } = useGlobal() const router = useRouter() - useEffect(() => { + + // 切换文章时更新 + React.useEffect(() => { const busuanziRouteChange = url => { busuanzi.fetch() } @@ -13,5 +18,12 @@ export default function Busuanzi () { router.events.off('routeChangeComplete', busuanziRouteChange) } }, [router.events]) + + // 更换主题时更新 + React.useEffect(() => { + if (theme) { + busuanzi.fetch() + } + }) return null } diff --git a/components/NotionPage.js b/components/NotionPage.js index a6f0a8ce..863069a3 100644 --- a/components/NotionPage.js +++ b/components/NotionPage.js @@ -1,27 +1,51 @@ import { NotionRenderer } from 'react-notion-x' import dynamic from 'next/dynamic' -import mediumZoom from 'medium-zoom' +// import mediumZoom from 'medium-zoom' +import mediumZoom from '@fisch0920/medium-zoom' import React from 'react' import { isBrowser } from '@/lib/utils' import Image from 'next/image' import Link from 'next/link' import { Code } from 'react-notion-x/build/third-party/code' - -// 支持更多的自定义语言 +import { Pdf } from 'react-notion-x/build/third-party/pdf' +import { Equation } from 'react-notion-x/build/third-party/equation' +import 'prismjs/components/prism-bash.js' +import 'prismjs/components/prism-markup-templating.js' +import 'prismjs/components/prism-markup.js' +import 'prismjs/components/prism-c.js' +import 'prismjs/components/prism-cpp.js' +import 'prismjs/components/prism-csharp.js' +import 'prismjs/components/prism-docker.js' +import 'prismjs/components/prism-java.js' +import 'prismjs/components/prism-js-templates.js' +import 'prismjs/components/prism-coffeescript.js' +import 'prismjs/components/prism-diff.js' +import 'prismjs/components/prism-git.js' +import 'prismjs/components/prism-go.js' +import 'prismjs/components/prism-graphql.js' +import 'prismjs/components/prism-handlebars.js' +import 'prismjs/components/prism-less.js' +import 'prismjs/components/prism-makefile.js' +import 'prismjs/components/prism-markdown.js' +import 'prismjs/components/prism-objectivec.js' +import 'prismjs/components/prism-ocaml.js' +import 'prismjs/components/prism-python.js' +import 'prismjs/components/prism-reason.js' +import 'prismjs/components/prism-rust.js' +import 'prismjs/components/prism-sass.js' +import 'prismjs/components/prism-scss.js' +import 'prismjs/components/prism-solidity.js' +import 'prismjs/components/prism-sql.js' +import 'prismjs/components/prism-stylus.js' +import 'prismjs/components/prism-swift.js' +import 'prismjs/components/prism-wasm.js' +import 'prismjs/components/prism-yaml.js' import 'prismjs/components/prism-r.js' const Collection = dynamic(() => import('react-notion-x/build/third-party/collection').then((m) => m.Collection), { ssr: true } ) -const Equation = dynamic(() => - import('react-notion-x/build/third-party/equation').then((m) => m.Equation), { ssr: true } -) - -const Pdf = dynamic( - () => import('react-notion-x/build/third-party/pdf').then((m) => m.Pdf), { ssr: false } -) - const Modal = dynamic( () => import('react-notion-x/build/third-party/modal').then((m) => m.Modal), { ssr: false } ) @@ -140,7 +164,9 @@ function addWatch4Dom(element) { const observer = new MutationObserver(mutationCallback) // console.log(observer) // 以上述配置开始观察目标节点 - observer.observe(targetNode, config) + if (targetNode) { + observer.observe(targetNode, config) + } // observer.disconnect(); } diff --git a/lib/lang.js b/lib/lang.js index 8531761b..a3a2a65d 100644 --- a/lib/lang.js +++ b/lib/lang.js @@ -2,12 +2,15 @@ import zhCN from './lang/zh-CN' import enUS from './lang/en-US' import zhHK from './lang/zh-HK' import zhTW from './lang/zh-TW' -import { isBrowser, mergeDeep } from './utils' +import frFR from '@/lib/lang/fr-FR' +import { getQueryVariable, isBrowser, mergeDeep } from './utils' + const lang = { 'en-US': enUS, 'zh-CN': zhCN, 'zh-HK': zhHK, - 'zh-TW': zhTW + 'zh-TW': zhTW, + 'fr-FR': frFR } export default lang @@ -16,26 +19,25 @@ export default lang * 获取当前语言字典 * @returns 不同语言对应字典 */ -export function generateLocaleDict (langString) { +export function generateLocaleDict(langString) { let userLocale = lang['en-US'] - if (!langString) { - return userLocale - } - if (langString.slice(0, 2).toLowerCase() === 'zh') { - switch (langString.toLowerCase()) { - case 'zh-cn': - case 'zh-sg': - userLocale = lang['zh-CN'] - break - case 'zh-hk': - userLocale = lang['zh-HK'] - break - case 'zh-tw': - userLocale = lang['zh-TW'] - break - default: - userLocale = lang['zh-CN'] - } + + switch (langString.toLowerCase()) { + case 'zh-cn': + case 'zh-sg': + userLocale = lang['zh-CN'] + break + case 'zh-hk': + userLocale = lang['zh-HK'] + break + case 'zh-tw': + userLocale = lang['zh-TW'] + break + case 'fr-fr': + userLocale = lang['fr-FR'] + break + default: + userLocale = lang['en-US'] } return mergeDeep({}, lang['en-US'], userLocale) } @@ -44,9 +46,11 @@ export function generateLocaleDict (langString) { * 初始化语言 * 根据用户当前浏览器语言进行切换 */ -export function initLocale (locale, changeLocale) { +export function initLocale(locale, changeLocale) { if (isBrowser()) { - const targetLocale = generateLocaleDict(window.navigator.language) + const browserLocale = window.navigator.language + const queryLocale = getQueryVariable('lang') + const targetLocale = generateLocaleDict(queryLocale || browserLocale) if (JSON.stringify(locale) !== JSON.stringify(targetLocale)) { changeLocale(targetLocale) } diff --git a/lib/lang/fr-FR.js b/lib/lang/fr-FR.js new file mode 100644 index 00000000..30089a70 --- /dev/null +++ b/lib/lang/fr-FR.js @@ -0,0 +1,54 @@ +export default { + LOCALE: 'fr-FR', + NAV: { + INDEX: 'Accueil', + RSS: 'RSS', + SEARCH: 'Recherche', + ABOUT: 'À propos', + NAVIGATOR: 'Navigation', + MAIL: 'E-mail', + ARCHIVE: 'Archive' + }, + COMMON: { + MORE: 'Plus', + NO_MORE: 'Aucune donnée', + LATEST_POSTS: 'Nouveaux articles', + TAGS: 'Tags', + NO_TAG: 'Non tag', + CATEGORY: 'Catégorie(s)', + SHARE: 'Partager', + SCAN_QR_CODE: 'Scan QRCode', + URL_COPIED: "L'URL est copé!", + TABLE_OF_CONTENTS: 'Sommaire', + RELATE_POSTS: 'Article similaire', + COPYRIGHT: 'Droit d\'auteur', + AUTHOR: 'Auteur', + URL: 'Link', + ANALYTICS: 'Analytique', + POSTS: 'Articles', + ARTICLE: 'Article(s)', + VISITORS: 'Visiteurs', + VIEWS: 'Views', + COPYRIGHT_NOTICE: 'Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International (CC BY-NC-SA 4.0)', + RESULT_OF_SEARCH: 'Résultats', + ARTICLE_DETAIL: 'Plus de détails', + PASSWORD_ERROR: 'Mot de passe est incorrect!', + ARTICLE_LOCK_TIPS: 'Saisir le mot de passe pour accéder au contenu', + SUBMIT: 'Valider', + POST_TIME: 'Date de publication', + LAST_EDITED_TIME: 'Date de modification', + RECENT_COMMENTS: 'Nouveau commentaire' + }, + PAGINATION: { + PREV: 'PREV', + NEXT: 'NEXT' + }, + SEARCH: { + ARTICLES: 'Recherche les articles', + TAGS: 'Recherche les tags' + }, + POST: { + BACK: 'Page precedente', + TOP: 'Haut' + } +} diff --git a/lib/notion/getAllCategories.js b/lib/notion/getAllCategories.js new file mode 100644 index 00000000..2225b965 --- /dev/null +++ b/lib/notion/getAllCategories.js @@ -0,0 +1,49 @@ +import { isIterable } from '../utils' + +/** + * 获取所有文章的标签 + * @param allPosts + * @param sliceCount 默认截取数量为12,若为0则返回全部 + * @param tagOptions tags的下拉选项 + * @returns {Promise<{}|*[]>} + */ + +/** + * 获取所有文章的分类 + * @param allPosts + * @returns {Promise<{}|*[]>} + */ +export function getAllCategories({ allPages, categoryOptions, sliceCount = 0 }) { + const allPosts = allPages.filter(page => page.type === 'Post') + if (!allPosts || !categoryOptions) { + return [] + } + // 计数 + let categories = allPosts.map(p => p.category) + categories = [...categories.flat()] + const categoryObj = {} + categories.forEach(category => { + if (category in categoryObj) { + categoryObj[category]++ + } else { + categoryObj[category] = 1 + } + }) + const list = [] + if (isIterable(categoryOptions)) { + for (const c of categoryOptions) { + const count = categoryObj[c.value] + if (count) { + list.push({ id: c.id, name: c.value, color: c.color, count }) + } + } + } + + // 按照数量排序 + // list.sort((a, b) => b.count - a.count) + if (sliceCount && sliceCount > 0) { + return list.slice(0, sliceCount) + } else { + return list + } +} diff --git a/lib/notion/getNotionData.js b/lib/notion/getNotionData.js index c74552cb..3da64da3 100644 --- a/lib/notion/getNotionData.js +++ b/lib/notion/getNotionData.js @@ -3,7 +3,8 @@ import { getDataFromCache, setDataToCache } from '@/lib/cache/cache_manager' import { getPostBlocks } from '@/lib/notion/getPostBlocks' import { idToUuid } from 'notion-utils' import { defaultMapImageUrl } from 'react-notion-x' -import { deepClone, isIterable } from '../utils' +import { deepClone } from '../utils' +import { getAllCategories } from './getAllCategories' import getAllPageIds from './getAllPageIds' import { getAllTags } from './getAllTags' import getPageProperties from './getPageProperties' @@ -31,8 +32,6 @@ export async function getGlobalNotionData({ delete notionPageData.schema delete notionPageData.rawMetadata delete notionPageData.pageIds - delete notionPageData.tagOptions - delete notionPageData.categoryOptions return notionPageData } @@ -42,7 +41,7 @@ export async function getGlobalNotionData({ * @returns */ function getLatestPosts({ allPages, from, latestPostCount }) { - const allPosts = allPages.filter(page => page.type === 'Post') + const allPosts = allPages.filter(page => page.type === 'Post' && page.status === 'Published') const latestPosts = Object.create(allPosts).sort((a, b) => { const dateA = new Date(a?.lastEditedTime || a?.createdTime || a?.date?.start_date) @@ -117,46 +116,6 @@ function getCategoryOptions(schema) { return categorySchema?.options || [] } -/** - * 获取所有文章的分类 - * @param allPosts - * @returns {Promise<{}|*[]>} - */ -function getAllCategories({ allPages, categoryOptions, sliceCount = 0 }) { - const allPosts = allPages.filter(page => page.type === 'Post') - if (!allPosts || !categoryOptions) { - return [] - } - // 计数 - let categories = allPosts.map(p => p.category) - categories = [...categories.flat()] - const categoryObj = {} - categories.forEach(category => { - if (category in categoryObj) { - categoryObj[category]++ - } else { - categoryObj[category] = 1 - } - }) - const list = [] - if (isIterable(categoryOptions)) { - for (const c of categoryOptions) { - const count = categoryObj[c.value] - if (count) { - list.push({ id: c.id, name: c.value, color: c.color, count }) - } - } - } - - // 按照数量排序 - // list.sort((a, b) => b.count - a.count) - if (sliceCount && sliceCount > 0) { - return list.slice(0, sliceCount) - } else { - return list - } -} - /** * 站点信息 * @param notionPageData @@ -279,7 +238,7 @@ async function getPageRecordMapByNotionAPI({ pageId, from }) { const customNav = getCustomNav({ allPages }) const categories = getAllCategories({ allPages, categoryOptions, sliceCount: BLOG.PREVIEW_CATEGORY_COUNT }) - const tags = getAllTags({ allPages, tagOptions, sliceCount: BLOG.PREVIEW_TAG_COUNT }) + const tags = getAllTags({ allPages, sliceCount: BLOG.PREVIEW_TAG_COUNT, tagOptions }) const latestPosts = getLatestPosts({ allPages, from, latestPostCount: 5 }) return { diff --git a/lib/notion/getPageProperties.js b/lib/notion/getPageProperties.js index 4061632c..47cb9dae 100644 --- a/lib/notion/getPageProperties.js +++ b/lib/notion/getPageProperties.js @@ -67,11 +67,11 @@ async function getPageProperties(id, block, schema, authToken, tagOptions, siteI }) } - properties.type = properties.type[0] - properties.status = properties.status[0] + properties.type = properties.type?.[0] + properties.status = properties.status?.[0] if (properties.type === 'Post') { - properties.slug = BLOG.POST_URL_PREFIX + '/' + (properties.slug ?? properties.id) + properties.slug = BLOG.POST_URL_PREFIX ? (BLOG.POST_URL_PREFIX + '/' + (properties.slug ?? properties.id)) : (properties.slug ?? properties.id) } else { properties.slug = (properties.slug ?? properties.id) } diff --git a/lib/utils.js b/lib/utils.js index 1119bdf9..9df42aaf 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -105,3 +105,17 @@ export const delay = ms => new Promise(resolve => setTimeout(resolve, ms)) * @returns {boolean} */ export const isBrowser = () => typeof window !== 'undefined' + +/** + * 获取从第1页到指定页码的文章 + * @param pageIndex 第几页 + * @param list 所有文章 + * @param pageSize 每页文章数量 + * @returns {*} + */ +export const getListByPage = function (list, pageIndex, pageSize) { + return list.slice( + 0, + pageIndex * pageSize + ) +} diff --git a/package.json b/package.json index e1f17edf..e9277d2a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "notion-next", - "version": "3.5.0", + "version": "3.5.1", "homepage": "https://github.com/tangly1024/NotionNext.git", "license": "MIT", "repository": { @@ -34,8 +34,8 @@ "memory-cache": "^0.2.0", "mongodb": "^4.6.0", "next": "12.1.6", - "notion-client": "6.12.9", - "notion-utils": "6.10.0", + "notion-client": "6.15.6", + "notion-utils": "6.15.6", "preact": "^10.5.15", "qrcode.react": "^1.0.1", "react": "17.0.2", @@ -44,7 +44,7 @@ "react-dom": "17.0.2", "react-facebook": "^8.1.4", "react-messenger-customer-chat": "^0.8.0", - "react-notion-x": "6.6.2", + "react-notion-x": "6.15.6", "react-share": "^4.4.0", "smoothscroll-polyfill": "^0.4.4", "typed.js": "^2.0.12", diff --git a/pages/_app.js b/pages/_app.js index e4205758..2099f722 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -9,7 +9,8 @@ import '@/styles/notion.css' // 重写部分样式 // used for collection views (optional) // import 'rc-dropdown/assets/index.css' import 'prismjs/themes/prism-tomorrow.min.css' -import 'react-notion-x/build/third-party/equation.css' +// import 'react-notion-x/build/third-party/equation.css' +import 'katex/dist/katex.min.css' // waline 评论插件 import '@waline/client/dist/waline.css' diff --git a/pages/archive/index.js b/pages/archive/index.js index ed40b48a..6e8f115a 100644 --- a/pages/archive/index.js +++ b/pages/archive/index.js @@ -20,10 +20,10 @@ const ArchiveIndex = props => { export async function getStaticProps() { const props = await getGlobalNotionData({ from: 'archive-index' }) - const { allPages } = props - const allPosts = allPages.filter(page => page.type === 'Post' && page.status === 'Published') // 处理分页 - props.posts = allPosts + props.posts = props.allPages.filter(page => page.type === 'Post' && page.status === 'Published') + delete props.allPages + return { props, revalidate: 1 diff --git a/pages/category/[category].js b/pages/category/[category]/index.js similarity index 64% rename from pages/category/[category].js rename to pages/category/[category]/index.js index 6082c336..a6c4f1af 100644 --- a/pages/category/[category].js +++ b/pages/category/[category]/index.js @@ -2,7 +2,13 @@ import { getGlobalNotionData } from '@/lib/notion/getNotionData' import React from 'react' import { useGlobal } from '@/lib/global' import * as ThemeMap from '@/themes' +import BLOG from '@/blog.config' +/** + * 分类页 + * @param {*} props + * @returns + */ export default function Category(props) { const { theme } = useGlobal() const ThemeComponents = ThemeMap[theme] @@ -26,12 +32,23 @@ export default function Category(props) { export async function getStaticProps({ params: { category } }) { const from = 'category-props' let props = await getGlobalNotionData({ from }) - const { allPages } = props - const allPosts = allPages.filter(page => page.type === 'Post' && page.status === 'Published') - const posts = allPosts.filter( - post => post && post.category && post.category.includes(category) - ) - props = { ...props, posts, category } + + // 过滤状态 + props.posts = props.allPages.filter(page => page.type === 'Post' && page.status === 'Published') + // 处理过滤 + props.posts = props.posts.filter(post => post && post.category && post.category.includes(category)) + // 处理文章页数 + props.postCount = props.posts.length + // 处理分页 + if (BLOG.POST_LIST_STYLE === 'scroll') { + // 滚动列表 给前端返回所有数据 + } else if (BLOG.POST_LIST_STYLE === 'page') { + props.posts = props.posts?.slice(0, BLOG.POSTS_PER_PAGE - 1) + } + + delete props.allPages + + props = { ...props, category } return { props, diff --git a/pages/category/[category]/page/[page].js b/pages/category/[category]/page/[page].js new file mode 100644 index 00000000..122d48f5 --- /dev/null +++ b/pages/category/[category]/page/[page].js @@ -0,0 +1,76 @@ +import { getGlobalNotionData } from '@/lib/notion/getNotionData' +import React from 'react' +import { useGlobal } from '@/lib/global' +import * as ThemeMap from '@/themes' +import BLOG from '@/blog.config' + +/** + * 分类页 + * @param {*} props + * @returns + */ +export default function Category(props) { + const { theme } = useGlobal() + const ThemeComponents = ThemeMap[theme] + const { siteInfo, posts } = props + const { locale } = useGlobal() + if (!posts) { + return + } + const meta = { + title: `${props.category} | ${locale.COMMON.CATEGORY} | ${ + siteInfo?.title || '' + }`, + description: siteInfo?.description, + slug: 'category/' + props.category, + image: siteInfo?.pageCover, + type: 'website' + } + return +} + +export async function getStaticProps({ params: { category, page } }) { + const from = 'category-page-props' + let props = await getGlobalNotionData({ from }) + + // 过滤状态类型 + props.posts = props.allPages.filter(page => page.type === 'Post' && page.status === 'Published').filter(post => post && post.category && post.category.includes(category)) + // 处理文章页数 + props.postCount = props.posts.length + // 处理分页 + props.posts = props.posts.slice(BLOG.POSTS_PER_PAGE * (page - 1), BLOG.POSTS_PER_PAGE * page - 1) + + delete props.allPages + props.page = page + + props = { ...props, category, page } + + return { + props, + revalidate: 1 + } +} + +export async function getStaticPaths() { + const from = 'category-paths' + const { categories, allPages } = await getGlobalNotionData({ from }) + const paths = [] + + categories?.forEach(category => { + // 过滤状态类型 + const categoryPosts = allPages.filter(page => page.type === 'Post' && page.status === 'Published').filter(post => post && post.category && post.category.includes(category.name)) + // 处理文章页数 + const postCount = categoryPosts.length + const totalPages = Math.ceil(postCount / BLOG.POSTS_PER_PAGE) + if (totalPages > 1) { + for (let i = 1; i <= totalPages; i++) { + paths.push({ params: { category: category.name, page: '' + i } }) + } + } + }) + + return { + paths, + fallback: true + } +} diff --git a/pages/category/index.js b/pages/category/index.js index 13f95eee..bb219bb5 100644 --- a/pages/category/index.js +++ b/pages/category/index.js @@ -2,7 +2,13 @@ import { getGlobalNotionData } from '@/lib/notion/getNotionData' import React from 'react' import { useGlobal } from '@/lib/global' import * as ThemeMap from '@/themes' +import { getAllCategories } from '@/lib/notion/getAllCategories' +/** + * 分类首页 + * @param {*} props + * @returns + */ export default function Category(props) { const { theme } = useGlobal() const ThemeComponents = ThemeMap[theme] @@ -19,10 +25,9 @@ export default function Category(props) { } export async function getStaticProps() { - const props = await getGlobalNotionData({ - from: 'category-index-props', - categoryCount: 0 - }) + const props = await getGlobalNotionData({ from: 'category-index-props' }) + props.categories = getAllCategories({ allPages: props.allPages, categoryOptions: props.categoryOptions, sliceCount: 0 }) + delete props.categoryOptions return { props, revalidate: 1 diff --git a/pages/feed.js b/pages/feed/index.js similarity index 100% rename from pages/feed.js rename to pages/feed/index.js diff --git a/pages/index.js b/pages/index.js index 92a70474..067b9a32 100644 --- a/pages/index.js +++ b/pages/index.js @@ -12,8 +12,8 @@ const Index = props => { export async function getStaticProps() { const from = 'index' const props = await getGlobalNotionData({ from }) - const { allPages, siteInfo } = props - const allPosts = allPages.filter(page => page.type === 'Post' && page.status === 'Published') + const { siteInfo } = props + props.posts = props.allPages.filter(page => page.type === 'Post' && page.status === 'Published') const meta = { title: `${siteInfo?.title} | ${siteInfo?.description}`, description: siteInfo?.description, @@ -21,35 +21,23 @@ export async function getStaticProps() { slug: '', type: 'website' } - // 处理分页 - const page = 1 - let postsToShow - if (BLOG.POST_LIST_STYLE !== 'page') { - postsToShow = Array.from(allPosts) - } else { - postsToShow = allPosts?.slice( - BLOG.POSTS_PER_PAGE * (page - 1), - BLOG.POSTS_PER_PAGE * page - ) - if (BLOG.POST_LIST_PREVIEW === 'true') { - for (const i in postsToShow) { - const post = postsToShow[i] - if (post.password && post.password !== '') { - continue - } - const blockMap = await getPostBlocks( - post.id, - 'slug', - BLOG.POST_PREVIEW_LINES - ) - if (blockMap) { - post.blockMap = blockMap - } + if (BLOG.POST_LIST_STYLE === 'scroll') { + // 滚动列表默认给前端返回所有数据 + } else if (BLOG.POST_LIST_STYLE === 'page') { + props.posts = props.posts?.slice(0, BLOG.POSTS_PER_PAGE) + } + + // 预览文章内容 + if (BLOG.POST_LIST_PREVIEW === 'true') { + for (const i in props.posts) { + const post = props.posts[i] + if (post.password && post.password !== '') { + continue } + post.blockMap = await getPostBlocks(post.id, 'slug', BLOG.POST_PREVIEW_LINES) } } - props.posts = postsToShow return { props: { diff --git a/pages/page/[page].js b/pages/page/[page].js index a09f08d1..3162250b 100644 --- a/pages/page/[page].js +++ b/pages/page/[page].js @@ -37,28 +37,20 @@ export async function getStaticPaths() { export async function getStaticProps({ params: { page } }) { const from = `page-${page}` const props = await getGlobalNotionData({ from }) - props.page = page const { allPages } = props const allPosts = allPages.filter(page => page.type === 'Post' && page.status === 'Published') // 处理分页 - props.posts = allPosts.slice( - BLOG.POSTS_PER_PAGE * (page - 1), - BLOG.POSTS_PER_PAGE * page - ) + props.posts = allPosts.slice(BLOG.POSTS_PER_PAGE * (page - 1), BLOG.POSTS_PER_PAGE * page) + props.page = page + + // 处理预览 if (BLOG.POST_LIST_PREVIEW === 'true') { for (const i in props.posts) { const post = props.posts[i] if (post.password && post.password !== '') { continue } - const blockMap = await getPostBlocks( - post.id, - 'slug', - BLOG.POST_PREVIEW_LINES - ) - if (blockMap) { - post.blockMap = blockMap - } + post.blockMap = await getPostBlocks(post.id, 'slug', BLOG.POST_PREVIEW_LINES) } } diff --git a/pages/tag/[tag].js b/pages/tag/[tag]/index.js similarity index 68% rename from pages/tag/[tag].js rename to pages/tag/[tag]/index.js index 875a8768..ca52f8f1 100644 --- a/pages/tag/[tag].js +++ b/pages/tag/[tag]/index.js @@ -1,6 +1,7 @@ import { useGlobal } from '@/lib/global' import { getGlobalNotionData } from '@/lib/notion/getNotionData' import * as ThemeMap from '@/themes' +import BLOG from '@/blog.config' const Tag = props => { const { theme } = useGlobal() @@ -23,16 +24,22 @@ const Tag = props => { } export async function getStaticProps({ params: { tag } }) { - const props = await getGlobalNotionData({ - from: 'tag-props', - includePage: false, - tagsCount: 0 - }) - const { allPages } = props - const allPosts = allPages.filter(page => page.type === 'Post' && page.status === 'Published') - props.posts = allPosts.filter( - post => post && post.tags && post.tags.includes(tag) - ) + const from = 'tag-props' + const props = await getGlobalNotionData({ from }) + + // 过滤状态 + props.posts = props.allPages.filter(page => page.type === 'Post' && page.status === 'Published').filter(post => post && post.tags && post.tags.includes(tag)) + + // 处理文章页数 + props.postCount = props.posts.length + + // 处理分页 + if (BLOG.POST_LIST_STYLE === 'scroll') { + // 滚动列表 给前端返回所有数据 + } else if (BLOG.POST_LIST_STYLE === 'page') { + props.posts = props.posts?.slice(0, BLOG.POSTS_PER_PAGE - 1) + } + props.tag = tag return { props, diff --git a/pages/tag/[tag]/page/[page].js b/pages/tag/[tag]/page/[page].js new file mode 100644 index 00000000..ffd2efb0 --- /dev/null +++ b/pages/tag/[tag]/page/[page].js @@ -0,0 +1,67 @@ +import { useGlobal } from '@/lib/global' +import { getGlobalNotionData } from '@/lib/notion/getNotionData' +import * as ThemeMap from '@/themes' +import BLOG from '@/blog.config' + +const Tag = props => { + const { theme } = useGlobal() + const ThemeComponents = ThemeMap[theme] + const { locale } = useGlobal() + const { tag, siteInfo, posts } = props + + if (!posts) { + return + } + + const meta = { + title: `${tag} | ${locale.COMMON.TAGS} | ${siteInfo?.title}`, + description: siteInfo?.description, + image: siteInfo?.pageCover, + slug: 'tag/' + tag, + type: 'website' + } + return +} + +export async function getStaticProps({ params: { tag, page } }) { + const from = 'tag-page-props' + const props = await getGlobalNotionData({ from }) + // 过滤状态、标签 + props.posts = props.allPages.filter(page => page.type === 'Post' && page.status === 'Published').filter(post => post && post.tags && post.tags.includes(tag)) + // 处理文章数 + props.postCount = props.posts.length + // 处理分页 + props.posts = props.posts.slice(BLOG.POSTS_PER_PAGE * (page - 1), BLOG.POSTS_PER_PAGE * page - 1) + + props.tag = tag + props.page = page + delete props.allPages + return { + props, + revalidate: 1 + } +} + +export async function getStaticPaths() { + const from = 'tag-page-static-path' + const { tags, allPages } = await getGlobalNotionData({ from }) + const paths = [] + tags?.forEach(tag => { + // 过滤状态类型 + const tagPosts = allPages.filter(page => page.type === 'Post' && page.status === 'Published').filter(post => post && post.tags && post.tags.includes(tag.name)) + // 处理文章页数 + const postCount = tagPosts.length + const totalPages = Math.ceil(postCount / BLOG.POSTS_PER_PAGE) + if (totalPages > 1) { + for (let i = 1; i <= totalPages; i++) { + paths.push({ params: { tag: tag.name, page: '' + i } }) + } + } + }) + return { + paths: paths, + fallback: true + } +} + +export default Tag diff --git a/pages/tag/index.js b/pages/tag/index.js index 1ceb0f07..93965586 100644 --- a/pages/tag/index.js +++ b/pages/tag/index.js @@ -2,7 +2,13 @@ import { getGlobalNotionData } from '@/lib/notion/getNotionData' import React from 'react' import { useGlobal } from '@/lib/global' import * as ThemeMap from '@/themes' +import { getAllTags } from '@/lib/notion' +/** + * 标签首页 + * @param {*} props + * @returns + */ const TagIndex = props => { const { theme } = useGlobal() const ThemeComponents = ThemeMap[theme] @@ -21,6 +27,8 @@ const TagIndex = props => { export async function getStaticProps() { const from = 'tag-index-props' const props = await getGlobalNotionData({ from }) + props.tags = getAllTags({ allPages: props.allPages, sliceCount: 0, tagOptions: props.tagOptions }) + delete props.tagOptions return { props, revalidate: 1 diff --git a/styles/globals.css b/styles/globals.css index 4382cd6c..6035eed9 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -178,3 +178,17 @@ nav { height: 1.25em; margin: -0.125em 0.25em; } + + +/* waline评论插件夜间适配 */ +.wl-panel{ + @apply dark:bg-black dark:border-gray-800 +} + +.wl-input,.wl-editor{ + @apply dark:focus-within:bg-gray-900 dark:text-gray-200 +} + +.wl-meta > span { + @apply dark:bg-gray-800 !important +} \ No newline at end of file diff --git a/styles/notion.css b/styles/notion.css index 4dc32e95..f4bcd76e 100644 --- a/styles/notion.css +++ b/styles/notion.css @@ -1902,3 +1902,11 @@ pre[class*='language-'] { .notion-table-cell-multi_select { padding: 7px 8px 0; } + +.notion-simple-table { + width: 100% !important; +} + +.notion-simple-table td { + white-space: nowrap; +} \ No newline at end of file diff --git a/themes/example/LayoutCategory.js b/themes/example/LayoutCategory.js index a9c99d90..6d819185 100644 --- a/themes/example/LayoutCategory.js +++ b/themes/example/LayoutCategory.js @@ -1,61 +1,10 @@ import BLOG from '@/blog.config' -import { useGlobal } from '@/lib/global' -import Link from 'next/link' -import { useState } from 'react' +import { BlogListPage } from './components/BlogListPage' +import { BlogListScroll } from './components/BlogListScroll' import LayoutBase from './LayoutBase' export const LayoutCategory = props => { - const { category, posts } = props - const { locale } = useGlobal() - - const [page, updatePage] = useState(1) - let hasMore = false - const postsToShow = posts - ? Object.assign(posts).slice(0, BLOG.POSTS_PER_PAGE * page) - : [] - - if (posts) { - const totalCount = posts.length - hasMore = page * BLOG.POSTS_PER_PAGE < totalCount - } - const handleGetMore = () => { - if (!hasMore) return - updatePage(page + 1) - } - return -
-
{category}
- - {postsToShow.map(p => ( - - ))} - -
- {' '} - {hasMore ? locale.COMMON.MORE : `${locale.COMMON.NO_MORE} 😰`}{' '} -
-
+ {BLOG.POST_LIST_STYLE === 'page' ? : }
} diff --git a/themes/example/LayoutCategoryIndex.js b/themes/example/LayoutCategoryIndex.js index 7690b316..28b98b6e 100644 --- a/themes/example/LayoutCategoryIndex.js +++ b/themes/example/LayoutCategoryIndex.js @@ -5,7 +5,6 @@ export const LayoutCategoryIndex = (props) => { const { categories } = props return -
{categories && categories.map(category => { return @@ -16,6 +15,5 @@ export const LayoutCategoryIndex = (props) => { })}
-
} diff --git a/themes/example/LayoutIndex.js b/themes/example/LayoutIndex.js index 7d6a17a6..17b77b4a 100644 --- a/themes/example/LayoutIndex.js +++ b/themes/example/LayoutIndex.js @@ -1,11 +1,11 @@ -import { BlogList } from './components/BlogList' +import { BlogListPage } from './components/BlogListPage' import LayoutBase from './LayoutBase' export const LayoutIndex = props => { return ( - + ) } diff --git a/themes/example/LayoutPage.js b/themes/example/LayoutPage.js index fc19035f..15355018 100644 --- a/themes/example/LayoutPage.js +++ b/themes/example/LayoutPage.js @@ -1,10 +1,10 @@ -import { BlogList } from './components/BlogList' +import { BlogListPage } from './components/BlogListPage' import LayoutBase from './LayoutBase' export const LayoutPage = props => { return ( - + ) } diff --git a/themes/example/LayoutTag.js b/themes/example/LayoutTag.js index f60653e3..06a6d778 100644 --- a/themes/example/LayoutTag.js +++ b/themes/example/LayoutTag.js @@ -1,59 +1,10 @@ import BLOG from '@/blog.config' -import { useGlobal } from '@/lib/global' -import Link from 'next/link' -import { useState } from 'react' +import { BlogListPage } from './components/BlogListPage' +import { BlogListScroll } from './components/BlogListScroll' import LayoutBase from './LayoutBase' export const LayoutTag = props => { - const { posts } = props - const { locale } = useGlobal() - - const [page, updatePage] = useState(1) - - let hasMore = false - const postsToShow = posts - ? Object.assign(posts).slice(0, BLOG.POSTS_PER_PAGE * page) - : [] - - if (posts) { - const totalCount = posts.length - hasMore = page * BLOG.POSTS_PER_PAGE < totalCount - } - const handleGetMore = () => { - if (!hasMore) return - updatePage(page + 1) - } - - return - {postsToShow.map(p => ( - - ))} - -
- {' '} - {hasMore ? locale.COMMON.MORE : `${locale.COMMON.NO_MORE} 😰`}{' '} -
- + return + {BLOG.POST_LIST_STYLE === 'page' ? : } } diff --git a/themes/example/components/BlogList.js b/themes/example/components/BlogListPage.js similarity index 76% rename from themes/example/components/BlogList.js rename to themes/example/components/BlogListPage.js index 1a45d6f7..5eb89ece 100644 --- a/themes/example/components/BlogList.js +++ b/themes/example/components/BlogListPage.js @@ -4,20 +4,17 @@ import { useGlobal } from '@/lib/global' import { useRouter } from 'next/router' import Link from 'next/link' -export const BlogList = (props) => { - const { page, posts, postCount } = props - +export const BlogListPage = props => { + const { page = 1, posts, postCount } = props const { locale } = useGlobal() const router = useRouter() const totalPage = Math.ceil(postCount / BLOG.POSTS_PER_PAGE) - - const showNext = - page < totalPage && - posts.length === BLOG.POSTS_PER_PAGE && - posts.length < postCount - const currentPage = +page + const showPrev = currentPage > 1 + const showNext = page < totalPage + const pagePrefix = router.asPath.replace(/\/page\/[1-9]\d*/, '').replace(/\/$/, '') + return
{posts.map(p => ( @@ -51,10 +48,10 @@ export const BlogList = (props) => { ))} diff --git a/themes/example/components/BlogListScroll.js b/themes/example/components/BlogListScroll.js new file mode 100644 index 00000000..07da67d3 --- /dev/null +++ b/themes/example/components/BlogListScroll.js @@ -0,0 +1,78 @@ +import BLOG from '@/blog.config' +import { useGlobal } from '@/lib/global' +import Link from 'next/link' +import React from 'react' +import throttle from 'lodash.throttle' + +export const BlogListScroll = props => { + const { posts } = props + const { locale } = useGlobal() + + const [page, updatePage] = React.useState(1) + + let hasMore = false + const postsToShow = posts + ? Object.assign(posts).slice(0, BLOG.POSTS_PER_PAGE * page) + : [] + + if (posts) { + const totalCount = posts.length + hasMore = page * BLOG.POSTS_PER_PAGE < totalCount + } + const handleGetMore = () => { + if (!hasMore) return + updatePage(page + 1) + } + + const targetRef = React.useRef(null) + + // 监听滚动自动分页加载 + const scrollTrigger = React.useCallback(throttle(() => { + const scrollS = window.scrollY + window.outerHeight + const clientHeight = targetRef ? (targetRef.current ? (targetRef.current.clientHeight) : 0) : 0 + if (scrollS > clientHeight + 100) { + handleGetMore() + } + }, 500)) + + React.useEffect(() => { + window.addEventListener('scroll', scrollTrigger) + + return () => { + window.removeEventListener('scroll', scrollTrigger) + } + }) + + return
+ {postsToShow.map(p => ( + + ))} + +
+ {' '} + {hasMore ? locale.COMMON.MORE : `${locale.COMMON.NO_MORE} 😰`}{' '} +
+ +
+} diff --git a/themes/fukasawa/LayoutCategory.js b/themes/fukasawa/LayoutCategory.js index 8b3f3b04..fa6c8c0d 100644 --- a/themes/fukasawa/LayoutCategory.js +++ b/themes/fukasawa/LayoutCategory.js @@ -1,8 +1,10 @@ +import BLOG from '@/blog.config' import BlogListPage from './components/BlogListPage' +import BlogListScroll from './components/BlogListScroll' import LayoutBase from './LayoutBase' export const LayoutCategory = props => { return - + {BLOG.POST_LIST_STYLE === 'page' ? : } } diff --git a/themes/fukasawa/LayoutIndex.js b/themes/fukasawa/LayoutIndex.js index 7559d65b..47ae1bce 100644 --- a/themes/fukasawa/LayoutIndex.js +++ b/themes/fukasawa/LayoutIndex.js @@ -1,8 +1,10 @@ +import BLOG from '@/blog.config' import BlogListPage from './components/BlogListPage' +import BlogListScroll from './components/BlogListScroll' import LayoutBase from './LayoutBase' export const LayoutIndex = (props) => { return - + {BLOG.POST_LIST_STYLE === 'page' ? : } } diff --git a/themes/fukasawa/components/ArticleDetail.js b/themes/fukasawa/components/ArticleDetail.js index 78957330..50da0ee2 100644 --- a/themes/fukasawa/components/ArticleDetail.js +++ b/themes/fukasawa/components/ArticleDetail.js @@ -92,7 +92,7 @@ export default function ArticleDetail(props) { - + {post.type === 'Post' && } {/* 评论互动 */}
diff --git a/themes/fukasawa/components/BlogListPage.js b/themes/fukasawa/components/BlogListPage.js index 04ef2b47..47650b5b 100644 --- a/themes/fukasawa/components/BlogListPage.js +++ b/themes/fukasawa/components/BlogListPage.js @@ -14,7 +14,7 @@ import PaginationSimple from './PaginationSimple' */ const BlogListPage = ({ page = 1, posts = [], postCount }) => { const totalPage = Math.ceil(postCount / BLOG.POSTS_PER_PAGE) - const showNext = page < totalPage && posts.length === BLOG.POSTS_PER_PAGE && posts.length < postCount + const showNext = page < totalPage const [colCount, changeCol] = useState(1) function updateCol() { diff --git a/themes/fukasawa/components/BlogListScroll.js b/themes/fukasawa/components/BlogListScroll.js new file mode 100644 index 00000000..522d3f0e --- /dev/null +++ b/themes/fukasawa/components/BlogListScroll.js @@ -0,0 +1,93 @@ +import BLOG from '@/blog.config' +import React from 'react' +import BlogCard from './BlogCard' +import BlogPostListEmpty from './BlogListEmpty' +import { useGlobal } from '@/lib/global' +import throttle from 'lodash.throttle' +/** + * 文章列表分页表格 + * @param page 当前页 + * @param posts 所有文章 + * @param tags 所有标签 + * @returns {JSX.Element} + * @constructor + */ +const BlogListScroll = props => { + const { posts = [] } = props + const [colCount, changeCol] = React.useState(1) + const { locale } = useGlobal() + + function updateCol() { + if (window.outerWidth > 1200) { + changeCol(3) + } else if (window.outerWidth > 900) { + changeCol(2) + } else { + changeCol(1) + } + } + const targetRef = React.useRef(null) + + const [page, updatePage] = React.useState(1) + + let hasMore = false + const postsToShow = posts + ? Object.assign(posts).slice(0, BLOG.POSTS_PER_PAGE * page) + : [] + + if (posts) { + const totalCount = posts.length + hasMore = page * BLOG.POSTS_PER_PAGE < totalCount + } + const handleGetMore = () => { + if (!hasMore) return + updatePage(page + 1) + } + + // 监听滚动自动分页加载 + const scrollTrigger = React.useCallback(throttle(() => { + const scrollS = window.scrollY + window.outerHeight + const clientHeight = targetRef ? (targetRef.current ? (targetRef.current.clientHeight) : 0) : 0 + if (scrollS > clientHeight + 100) { + handleGetMore() + } + }, 500)) + + React.useEffect(() => { + updateCol() + window.addEventListener('scroll', scrollTrigger) + + window.addEventListener('resize', updateCol) + return () => { + window.removeEventListener('resize', updateCol) + window.removeEventListener('scroll', scrollTrigger) + } + }) + + if (!posts || posts.length === 0) { + return + } else { + return ( +
+ {/* 文章列表 */} +
+ {postsToShow?.map(post => ( +
+ +
+ ))} +
+ +
+ {' '} + {hasMore ? locale.COMMON.MORE : `${locale.COMMON.NO_MORE} 😰`}{' '} +
+
+ ) + } +} + +export default BlogListScroll diff --git a/themes/fukasawa/components/PaginationSimple.js b/themes/fukasawa/components/PaginationSimple.js index 11eb837d..71ba8b8f 100644 --- a/themes/fukasawa/components/PaginationSimple.js +++ b/themes/fukasawa/components/PaginationSimple.js @@ -1,4 +1,3 @@ -import BLOG from '@/blog.config' import Link from 'next/link' import { useRouter } from 'next/router' import { useGlobal } from '@/lib/global' @@ -14,14 +13,16 @@ const PaginationSimple = ({ page, showNext }) => { const { locale } = useGlobal() const router = useRouter() const currentPage = +page + const pagePrefix = router.asPath.replace(/\/page\/[1-9]\d*/, '').replace(/\/$/, '') + return (
{ { - const { tags, posts, category } = props + const { category } = props return
{category}
- + {BLOG.POST_LIST_STYLE === 'page' ? : }
} diff --git a/themes/hexo/LayoutSlug.js b/themes/hexo/LayoutSlug.js index 36bb3449..7875c990 100644 --- a/themes/hexo/LayoutSlug.js +++ b/themes/hexo/LayoutSlug.js @@ -74,9 +74,10 @@ export const LayoutSlug = props => { data-ad-slot="3806269138" /> - - - + {post.type === 'Post' && } + {post.type === 'Post' && } + {post.type === 'Post' && } +
diff --git a/themes/hexo/LayoutTag.js b/themes/hexo/LayoutTag.js index 7380aef0..75c308e5 100644 --- a/themes/hexo/LayoutTag.js +++ b/themes/hexo/LayoutTag.js @@ -1,10 +1,21 @@ +import BLOG from '@/blog.config' import BlogPostListScroll from './components/BlogPostListScroll' +import BlogPostListPage from './components/BlogPostListPage' import LayoutBase from './LayoutBase' +import TagItemMini from '../next/components/TagItemMini' +import React from 'react' export const LayoutTag = (props) => { - const { tags, posts, tag } = props + const currentTag = props.tags.find((t) => { + return t.name === props.tag + }) return - - + {currentTag && ( +
+ +
+ )} + {BLOG.POST_LIST_STYLE === 'page' ? : } + } diff --git a/themes/hexo/components/BlogPostListPage.js b/themes/hexo/components/BlogPostListPage.js index 4964f024..3662aee9 100644 --- a/themes/hexo/components/BlogPostListPage.js +++ b/themes/hexo/components/BlogPostListPage.js @@ -14,8 +14,7 @@ import BlogPostListEmpty from './BlogPostListEmpty' const BlogPostListPage = ({ page = 1, posts = [], postCount }) => { const totalPage = Math.ceil(postCount / BLOG.POSTS_PER_PAGE) const showPagination = postCount >= BLOG.POSTS_PER_PAGE - - if (!posts || posts.length === 0) { + if (!posts || posts.length === 0 || page > totalPage) { return } else { return ( diff --git a/themes/hexo/components/BlogPostListScroll.js b/themes/hexo/components/BlogPostListScroll.js index 4c56ff8e..ca6f705d 100644 --- a/themes/hexo/components/BlogPostListScroll.js +++ b/themes/hexo/components/BlogPostListScroll.js @@ -3,8 +3,9 @@ import BlogPostCard from './BlogPostCard' import BlogPostListEmpty from './BlogPostListEmpty' import { useGlobal } from '@/lib/global' import throttle from 'lodash.throttle' -import React, { useCallback, useEffect, useRef, useState } from 'react' +import React from 'react' import CONFIG_HEXO from '../config_hexo' +import { getListByPage } from '@/lib/utils' /** * 博客列表滚动分页 @@ -15,8 +16,8 @@ import CONFIG_HEXO from '../config_hexo' */ const BlogPostListScroll = ({ posts = [], currentSearch, showSummary = CONFIG_HEXO.POST_LIST_SUMMARY }) => { const postsPerPage = BLOG.POSTS_PER_PAGE - const [page, updatePage] = useState(1) - const postsToShow = getPostByPage(page, posts, postsPerPage) + const [page, updatePage] = React.useState(1) + const postsToShow = getListByPage(posts, page, postsPerPage) let hasMore = false if (posts) { @@ -30,7 +31,7 @@ const BlogPostListScroll = ({ posts = [], currentSearch, showSummary = CONFIG_HE } // 监听滚动自动分页加载 - const scrollTrigger = useCallback(throttle(() => { + const scrollTrigger = React.useCallback(throttle(() => { const scrollS = window.scrollY + window.outerHeight const clientHeight = targetRef ? (targetRef.current ? (targetRef.current.clientHeight) : 0) : 0 if (scrollS > clientHeight + 100) { @@ -39,14 +40,14 @@ const BlogPostListScroll = ({ posts = [], currentSearch, showSummary = CONFIG_HE }, 500)) // 监听滚动 - useEffect(() => { + React.useEffect(() => { window.addEventListener('scroll', scrollTrigger) return () => { window.removeEventListener('scroll', scrollTrigger) } }) - const targetRef = useRef(null) + const targetRef = React.useRef(null) const { locale } = useGlobal() if (!postsToShow || postsToShow.length === 0) { @@ -62,9 +63,7 @@ const BlogPostListScroll = ({ posts = [], currentSearch, showSummary = CONFIG_HE
-
{ - handleGetMore() - }} +
{ handleGetMore() }} className='w-full my-4 py-4 text-center cursor-pointer rounded-xl dark:text-gray-200' > {hasMore ? locale.COMMON.MORE : `${locale.COMMON.NO_MORE}`}
@@ -72,17 +71,4 @@ const BlogPostListScroll = ({ posts = [], currentSearch, showSummary = CONFIG_HE } } -/** - * 获取从第1页到指定页码的文章 - * @param page 第几页 - * @param totalPosts 所有文章 - * @param postsPerPage 每页文章数量 - * @returns {*} - */ -const getPostByPage = function (page, totalPosts, postsPerPage) { - return totalPosts.slice( - 0, - postsPerPage * page - ) -} export default BlogPostListScroll diff --git a/themes/hexo/components/HeaderArticle.js b/themes/hexo/components/HeaderArticle.js index b11d7cfc..64636717 100644 --- a/themes/hexo/components/HeaderArticle.js +++ b/themes/hexo/components/HeaderArticle.js @@ -58,7 +58,7 @@ export default function HeaderArticle({ post, siteInfo }) {
{BLOG.ANALYTICS_BUSUANZI_ENABLE &&
- 次访问 + {locale.COMMON.VIEWS}
}
diff --git a/themes/hexo/components/PaginationNumber.js b/themes/hexo/components/PaginationNumber.js index a2b446a8..96207d43 100644 --- a/themes/hexo/components/PaginationNumber.js +++ b/themes/hexo/components/PaginationNumber.js @@ -1,4 +1,3 @@ -import BLOG from '@/blog.config' import Link from 'next/link' import { useRouter } from 'next/router' @@ -13,78 +12,66 @@ const PaginationNumber = ({ page, totalPage }) => { const router = useRouter() const currentPage = +page const showNext = page < totalPage - const pages = generatePages(page, currentPage, totalPage) + const pagePrefix = router.asPath.replace(/\/page\/[1-9]\d*/, '').replace(/\/$/, '') + const pages = generatePages(pagePrefix, page, currentPage, totalPage) return ( -
- {/* 上一页 */} - - - +
+ {/* 上一页 */} + + + - {pages} + {pages} - {/* 下一页 */} - - - -
) } -function getPageElement(page, currentPage) { +function getPageElement(page, currentPage, pagePrefix) { return ( - - - {page} - - + + + {page} + + ) } -function generatePages(page, currentPage, totalPage) { +function generatePages(pagePrefix, page, currentPage, totalPage) { const pages = [] const groupCount = 7 // 最多显示页签数 if (totalPage <= groupCount) { for (let i = 1; i <= totalPage; i++) { - pages.push(getPageElement(i, page)) + pages.push(getPageElement(i, page, pagePrefix)) } } else { - pages.push(getPageElement(1, page)) + pages.push(getPageElement(1, page, pagePrefix)) const dynamicGroupCount = groupCount - 2 let startPage = currentPage - 2 if (startPage <= 1) { @@ -99,7 +86,7 @@ function generatePages(page, currentPage, totalPage) { for (let i = 0; i < dynamicGroupCount; i++) { if (startPage + i < totalPage) { - pages.push(getPageElement(startPage + i, page)) + pages.push(getPageElement(startPage + i, page, pagePrefix)) } } @@ -107,7 +94,7 @@ function generatePages(page, currentPage, totalPage) { pages.push(
...
) } - pages.push(getPageElement(totalPage, page)) + pages.push(getPageElement(totalPage, page, pagePrefix)) } return pages } diff --git a/themes/medium/LayoutCategory.js b/themes/medium/LayoutCategory.js index 0cd835da..a3018144 100644 --- a/themes/medium/LayoutCategory.js +++ b/themes/medium/LayoutCategory.js @@ -1,11 +1,13 @@ import LayoutBase from './LayoutBase' import BlogPostListScroll from './components/BlogPostListScroll' +import BlogPostListPage from './components/BlogPostListPage' +import BLOG from '@/blog.config' export const LayoutCategory = props => { const { category } = props - const slotTop =
分类:
{category}
+ const slotTop =
分类:
{category}
return - - + {BLOG.POST_LIST_STYLE === 'page' ? : } + } diff --git a/themes/medium/LayoutTag.js b/themes/medium/LayoutTag.js index 0e6bd79b..dda44141 100644 --- a/themes/medium/LayoutTag.js +++ b/themes/medium/LayoutTag.js @@ -1,11 +1,13 @@ import LayoutBase from './LayoutBase' import BlogPostListScroll from './components/BlogPostListScroll' +import BLOG from '@/blog.config' +import BlogPostListPage from './components/BlogPostListPage' export const LayoutTag = (props) => { const { tag } = props const slotTop =
标签:
{tag}
return - + {BLOG.POST_LIST_STYLE === 'page' ? : } } diff --git a/themes/medium/components/ArticleDetail.js b/themes/medium/components/ArticleDetail.js index c9eabe73..48630d47 100644 --- a/themes/medium/components/ArticleDetail.js +++ b/themes/medium/components/ArticleDetail.js @@ -66,7 +66,7 @@ export const ArticleDetail = props => { {CONFIG_MEDIUM.POST_DETAIL_TAG && post?.tagItems?.map(tag => )}
- + {post.type === 'Post' && } diff --git a/themes/medium/components/PaginationSimple.js b/themes/medium/components/PaginationSimple.js index 080a899f..a8f685d8 100644 --- a/themes/medium/components/PaginationSimple.js +++ b/themes/medium/components/PaginationSimple.js @@ -1,4 +1,3 @@ -import BLOG from '@/blog.config' import Link from 'next/link' import { useRouter } from 'next/router' import { useGlobal } from '@/lib/global' @@ -15,14 +14,16 @@ const PaginationSimple = ({ page, totalPage }) => { const router = useRouter() const currentPage = +page const showNext = currentPage < totalPage + const pagePrefix = router.asPath.replace(/\/page\/[1-9]\d*/, '').replace(/\/$/, '') + return (
{ { - const { tags, posts, category, categories } = props + const { category, categories } = props return
- + {BLOG.POST_LIST_STYLE !== 'page' + ? + : + }
} diff --git a/themes/next/LayoutTag.js b/themes/next/LayoutTag.js index b50f801a..7594ba8c 100644 --- a/themes/next/LayoutTag.js +++ b/themes/next/LayoutTag.js @@ -2,16 +2,21 @@ import LayoutBase from './LayoutBase' import StickyBar from './components/StickyBar' import TagList from './components/TagList' import BlogPostListScroll from './components/BlogPostListScroll' +import BlogPostListPage from './components/BlogPostListPage' +import BLOG from '@/blog.config' export const LayoutTag = (props) => { - const { tags, posts, tag } = props + const { tags, tag } = props return
- + {BLOG.POST_LIST_STYLE !== 'page' + ? + : + }
} diff --git a/themes/next/components/ArticleDetail.js b/themes/next/components/ArticleDetail.js index ab7f9608..340f0f5a 100644 --- a/themes/next/components/ArticleDetail.js +++ b/themes/next/components/ArticleDetail.js @@ -100,29 +100,31 @@ export default function ArticleDetail(props) { {showArticleInfo && <> {/* 版权声明 */} - + {post.type === 'Post' && } {/* 推荐文章 */} - + {post.type === 'Post' && } {/* 标签列表 */} -
- {post.tagItems && ( -
-
- {locale.COMMON.TAGS}: -
- {post.tagItems.map(tag => ( - - ))} + {post.type === 'Post' && ( +
+ {post.tagItems && ( +
+
+ {locale.COMMON.TAGS}: +
+ {post.tagItems.map(tag => ( + + ))} +
+ )} +
+
- )} -
- -
-
+
+ )} - + {post.type === 'Post' && } } {/* 评论互动 */} diff --git a/themes/next/components/InfoCard.js b/themes/next/components/InfoCard.js index 6ddde9c4..5bbed271 100644 --- a/themes/next/components/InfoCard.js +++ b/themes/next/components/InfoCard.js @@ -12,7 +12,7 @@ const InfoCard = (props) => {
{BLOG.AUTHOR}
-
{BLOG.BIO}
+
{BLOG.BIO}
diff --git a/themes/next/components/Logo.js b/themes/next/components/Logo.js index 8169b624..46cb814e 100644 --- a/themes/next/components/Logo.js +++ b/themes/next/components/Logo.js @@ -6,7 +6,7 @@ const Logo = props => { return
{siteInfo?.title}
-
{siteInfo?.description}
+
{siteInfo?.description}
} diff --git a/themes/next/components/StickyBar.js b/themes/next/components/StickyBar.js index fdcba64d..2f56dc4a 100644 --- a/themes/next/components/StickyBar.js +++ b/themes/next/components/StickyBar.js @@ -39,7 +39,7 @@ const StickyBar = ({ children }) => { return (