From ebc5bd15bb79ca8cebec8ca7eeb8d84a384e52bf Mon Sep 17 00:00:00 2001 From: anime Date: Fri, 3 Jan 2025 00:34:25 +0800 Subject: [PATCH 1/6] =?UTF-8?q?feat(=E5=88=9D=E6=AD=A5=E5=AE=9E=E7=8E=B0UU?= =?UTF-8?q?ID=E5=8F=8A=E5=85=B6=E5=8E=BB=E9=99=A4-=E5=BD=A2=E5=BC=8F?= =?UTF-8?q?=E9=87=8D=E5=AE=9A=E5=90=91=E5=88=B0slug):?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/redirect.js | 15 +++++++++++++++ middleware.ts | 27 +++++++++++++++++++++++++-- pages/index.js | 3 +++ 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 lib/redirect.js diff --git a/lib/redirect.js b/lib/redirect.js new file mode 100644 index 00000000..7a05dfee --- /dev/null +++ b/lib/redirect.js @@ -0,0 +1,15 @@ +import fs from 'fs' + +export function generateRedirectJson({ allPages }) { + let uuidSlugMap = {} + allPages.forEach(page => { + if (page.type === 'Post' && page.status === 'Published') { + uuidSlugMap[page.id] = page.slug + } + }) + try { + fs.writeFileSync('./public/redirect.json', JSON.stringify(uuidSlugMap)) + } catch (error) { + console.warn('无法写入文件', error) + } +} diff --git a/middleware.ts b/middleware.ts index dc623d08..c60ee9cd 100644 --- a/middleware.ts +++ b/middleware.ts @@ -1,5 +1,7 @@ import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server' -import { NextResponse } from 'next/server' +import { NextRequest, NextResponse } from 'next/server' +import { checkStrIsNotionId, getLastPartOfUrl } from '@/lib/utils' +import { idToUuid } from 'notion-utils' /** * Clerk 身份验证中间件 @@ -30,8 +32,29 @@ const isTenantAdminRoute = createRouteMatcher([ * @returns */ // eslint-disable-next-line @typescript-eslint/require-await, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars -const noAuthMiddleware = async (req: any, ev: any) => { +const noAuthMiddleware = async (req: NextRequest, ev: any) => { // 如果没有配置 Clerk 相关环境变量,返回一个默认响应或者继续处理请求 + let redirectJson: Record = {} + try { + const response = await fetch(`${req.nextUrl.origin}/redirect.json`) + if (response.ok) { + redirectJson = (await response.json()) as Record + } + } catch (err) { + console.error('Error fetching static file:', err) + } + let lastPart = getLastPartOfUrl(req.nextUrl.pathname) as string + if (checkStrIsNotionId(lastPart)) { + lastPart = idToUuid(lastPart) + } + if (lastPart && redirectJson[lastPart]) { + const redirectToUrl = req.nextUrl.clone() + redirectToUrl.pathname = '/' + redirectJson[lastPart] + console.log( + `redirect from ${req.nextUrl.pathname} to ${redirectToUrl.pathname}` + ) + return NextResponse.redirect(redirectToUrl) + } return NextResponse.next() } /** diff --git a/pages/index.js b/pages/index.js index 31e2610b..a83d42c8 100644 --- a/pages/index.js +++ b/pages/index.js @@ -5,6 +5,7 @@ import { generateRobotsTxt } from '@/lib/robots.txt' import { generateRss } from '@/lib/rss' import { generateSitemapXml } from '@/lib/sitemap.xml' import { DynamicLayout } from '@/themes/theme' +import { generateRedirectJson } from '@/lib/redirect' /** * 首页布局 @@ -60,6 +61,8 @@ export async function getStaticProps(req) { generateRss(props) // 生成 generateSitemapXml(props) + // 生成重定向 JSON + generateRedirectJson(props) // 生成全文索引 - 仅在 yarn build 时执行 && process.env.npm_lifecycle_event === 'build' From e405ab9dd70c913c4097ab312b83e2cadc048598 Mon Sep 17 00:00:00 2001 From: anime Date: Fri, 3 Jan 2025 00:41:12 +0800 Subject: [PATCH 2/6] =?UTF-8?q?fix(=E4=BF=AE=E5=A4=8D=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=88=B0=E5=80=BC=E7=9A=84=E9=94=99=E8=AF=AF?= =?UTF-8?q?):?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- themes/theme.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes/theme.js b/themes/theme.js index 97fcd64a..3d89f878 100644 --- a/themes/theme.js +++ b/themes/theme.js @@ -6,7 +6,7 @@ import { useRouter } from 'next/router' import { getQueryParam, getQueryVariable, isBrowser } from '../lib/utils' // 在next.config.js中扫描所有主题 -export const { THEMES = [] } = getConfig().publicRuntimeConfig +export const { THEMES = [] } = getConfig()?.publicRuntimeConfig || {} /** * 获取主题配置 From daa47e520321d1471ca445cc686bf73ee77bf0a7 Mon Sep 17 00:00:00 2001 From: anime Date: Fri, 3 Jan 2025 00:48:53 +0800 Subject: [PATCH 3/6] =?UTF-8?q?feat(=E6=94=AF=E6=8C=81=E9=85=8D=E7=BD=AEUU?= =?UTF-8?q?ID=E5=8F=8A=E5=85=B6=E5=8E=BB=E9=99=A4-=E5=BD=A2=E5=BC=8F?= =?UTF-8?q?=E9=87=8D=E5=AE=9A=E5=90=91=E5=88=B0slug=E5=8A=9F=E8=83=BD):?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blog.config.js | 12 +++++------- middleware.ts | 41 ++++++++++++++++++++++------------------- pages/index.js | 6 ++++-- 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/blog.config.js b/blog.config.js index 24cf06ae..379e15d3 100644 --- a/blog.config.js +++ b/blog.config.js @@ -271,16 +271,11 @@ const BLOG = { STARRY_SKY: process.env.NEXT_PUBLIC_STARRY_SKY || false, // 开关 // AI 文章摘要生成 - AI_SUMMARY_API: - process.env.AI_SUMMARY_API|| - '', - AI_SUMMARY_KEY: - process.env.AI_SUMMARY_KEY || - '', + AI_SUMMARY_API: process.env.AI_SUMMARY_API || '', + AI_SUMMARY_KEY: process.env.AI_SUMMARY_KEY || '', AI_SUMMARY_CACHE_TIME: process.env.AI_SUMMARY_CACHE_TIME || 1800, // 缓存时间,单位秒 AI_SUMMARY_WORD_LIMIT: process.env.AI_SUMMARY_WORD_LIMIT || 1000, - // ********挂件组件相关******** // AI 文章摘要生成 @see https://docs_s.tianli0.top/ TianliGPT_CSS: @@ -532,6 +527,9 @@ const BLOG = { MAILCHIMP_LIST_ID: process.env.MAILCHIMP_LIST_ID || null, // 开启mailichimp邮件订阅 客户列表ID ,具体使用方法参阅文档 MAILCHIMP_API_KEY: process.env.MAILCHIMP_API_KEY || null, // 开启mailichimp邮件订阅 APIkey + // uuid重定向至 slug + UUID_REDIRECT: process.env.UUID_REDIRECT || false, + // ANIMATE.css 动画 ANIMATE_CSS_URL: process.env.NEXT_PUBLIC_ANIMATE_CSS_URL || diff --git a/middleware.ts b/middleware.ts index c60ee9cd..6c622069 100644 --- a/middleware.ts +++ b/middleware.ts @@ -2,6 +2,7 @@ import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server' import { NextRequest, NextResponse } from 'next/server' import { checkStrIsNotionId, getLastPartOfUrl } from '@/lib/utils' import { idToUuid } from 'notion-utils' +import { siteConfig } from '@/lib/config' /** * Clerk 身份验证中间件 @@ -34,26 +35,28 @@ const isTenantAdminRoute = createRouteMatcher([ // eslint-disable-next-line @typescript-eslint/require-await, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars const noAuthMiddleware = async (req: NextRequest, ev: any) => { // 如果没有配置 Clerk 相关环境变量,返回一个默认响应或者继续处理请求 - let redirectJson: Record = {} - try { - const response = await fetch(`${req.nextUrl.origin}/redirect.json`) - if (response.ok) { - redirectJson = (await response.json()) as Record + if (siteConfig('UUID_REDIRECT')) { + let redirectJson: Record = {} + try { + const response = await fetch(`${req.nextUrl.origin}/redirect.json`) + if (response.ok) { + redirectJson = (await response.json()) as Record + } + } catch (err) { + console.error('Error fetching static file:', err) + } + let lastPart = getLastPartOfUrl(req.nextUrl.pathname) as string + if (checkStrIsNotionId(lastPart)) { + lastPart = idToUuid(lastPart) + } + if (lastPart && redirectJson[lastPart]) { + const redirectToUrl = req.nextUrl.clone() + redirectToUrl.pathname = '/' + redirectJson[lastPart] + console.log( + `redirect from ${req.nextUrl.pathname} to ${redirectToUrl.pathname}` + ) + return NextResponse.redirect(redirectToUrl) } - } catch (err) { - console.error('Error fetching static file:', err) - } - let lastPart = getLastPartOfUrl(req.nextUrl.pathname) as string - if (checkStrIsNotionId(lastPart)) { - lastPart = idToUuid(lastPart) - } - if (lastPart && redirectJson[lastPart]) { - const redirectToUrl = req.nextUrl.clone() - redirectToUrl.pathname = '/' + redirectJson[lastPart] - console.log( - `redirect from ${req.nextUrl.pathname} to ${redirectToUrl.pathname}` - ) - return NextResponse.redirect(redirectToUrl) } return NextResponse.next() } diff --git a/pages/index.js b/pages/index.js index a83d42c8..b66b5610 100644 --- a/pages/index.js +++ b/pages/index.js @@ -61,8 +61,10 @@ export async function getStaticProps(req) { generateRss(props) // 生成 generateSitemapXml(props) - // 生成重定向 JSON - generateRedirectJson(props) + if (siteConfig('UUID_REDIRECT', false, props?.NOTION_CONFIG)) { + // 生成重定向 JSON + generateRedirectJson(props) + } // 生成全文索引 - 仅在 yarn build 时执行 && process.env.npm_lifecycle_event === 'build' From 6e85af112ddfaa7a06e7003f419aae269a388104 Mon Sep 17 00:00:00 2001 From: anime Date: Fri, 3 Jan 2025 00:52:36 +0800 Subject: [PATCH 4/6] =?UTF-8?q?fix(=E4=BF=AE=E5=A4=8DUUID=5FREDIRECT=20Sit?= =?UTF-8?q?eConfig=E4=BD=BF=E7=94=A8Context=E9=97=AE=E9=A2=98):?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/config.js b/lib/config.js index 314e8318..3712d877 100644 --- a/lib/config.js +++ b/lib/config.js @@ -42,6 +42,7 @@ export const siteConfig = (key, defaultVal = null, extendConfig = {}) => { case 'AI_SUMMARY_KEY': case 'AI_SUMMARY_CACHE_TIME': case 'AI_SUMMARY_WORD_LIMIT': + case 'UUID_REDIRECT': // LINK比较特殊, if (key === 'LINK') { if (!extendConfig || Object.keys(extendConfig).length === 0) { From 8a2ec282d8d952fdc748c46a665070efb26fec49 Mon Sep 17 00:00:00 2001 From: anime Date: Fri, 3 Jan 2025 01:08:14 +0800 Subject: [PATCH 5/6] =?UTF-8?q?feat(=E4=B8=BA=E4=BA=86SEO=E9=87=8D?= =?UTF-8?q?=E5=AE=9A=E5=90=91=E7=B1=BB=E5=9E=8B=E8=AE=BE=E7=BD=AE=E4=B8=BA?= =?UTF-8?q?308=E6=B0=B8=E4=B9=85=E9=87=8D=E5=AE=9A=E5=90=91):?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- middleware.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/middleware.ts b/middleware.ts index 6c622069..c099e62a 100644 --- a/middleware.ts +++ b/middleware.ts @@ -55,7 +55,7 @@ const noAuthMiddleware = async (req: NextRequest, ev: any) => { console.log( `redirect from ${req.nextUrl.pathname} to ${redirectToUrl.pathname}` ) - return NextResponse.redirect(redirectToUrl) + return NextResponse.redirect(redirectToUrl, 308) } } return NextResponse.next() From 704a4ebeb1b25ec2725909564d435ad4fac5bbf4 Mon Sep 17 00:00:00 2001 From: anime Date: Fri, 3 Jan 2025 02:40:40 +0800 Subject: [PATCH 6/6] =?UTF-8?q?fix(=E6=97=A0=E6=B3=95=E4=BD=BF=E7=94=A8sit?= =?UTF-8?q?econfig=E6=94=B9=E4=B8=BA=E4=BD=BF=E7=94=A8Blog=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1):?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- middleware.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/middleware.ts b/middleware.ts index c099e62a..550c6f8b 100644 --- a/middleware.ts +++ b/middleware.ts @@ -2,7 +2,7 @@ import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server' import { NextRequest, NextResponse } from 'next/server' import { checkStrIsNotionId, getLastPartOfUrl } from '@/lib/utils' import { idToUuid } from 'notion-utils' -import { siteConfig } from '@/lib/config' +import BLOG from './blog.config' /** * Clerk 身份验证中间件 @@ -35,7 +35,7 @@ const isTenantAdminRoute = createRouteMatcher([ // eslint-disable-next-line @typescript-eslint/require-await, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars const noAuthMiddleware = async (req: NextRequest, ev: any) => { // 如果没有配置 Clerk 相关环境变量,返回一个默认响应或者继续处理请求 - if (siteConfig('UUID_REDIRECT')) { + if (BLOG['UUID_REDIRECT']) { let redirectJson: Record = {} try { const response = await fetch(`${req.nextUrl.origin}/redirect.json`)