mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-13 15:09:13 +00:00
- Rename isUrl function to isUrlLikePath for better clarity - Simplify function logic and add type checking - Update all references to use the new function name - Improve function documentation and parameter typing
191 lines
5.0 KiB
JavaScript
191 lines
5.0 KiB
JavaScript
'use client'
|
||
|
||
import BLOG from '@/blog.config'
|
||
import { useGlobal } from './global'
|
||
import { deepClone, isUrlLikePath } from './utils'
|
||
|
||
/**
|
||
* 读取配置顺序
|
||
* 1. 优先读取NotionConfig表
|
||
* 2. 其次读取环境变量
|
||
* 3. 再读取blog.config.js / 或各个主题的CONFIG文件
|
||
* @param {*} key ; 参数名
|
||
* @param {*} defaultVal ; 参数不存在默认返回值
|
||
* @param {*} extendConfig ; 参考配置对象{key:val},如果notion中找不到优先尝试在这里面查找
|
||
* @returns
|
||
*/
|
||
export const siteConfig = (key, defaultVal = null, extendConfig = {}) => {
|
||
if (!key) {
|
||
return null
|
||
}
|
||
const getValue = (value, fallback) => (hasVal(value) ? value : fallback)
|
||
const hasVal = value => value !== undefined && value !== null
|
||
|
||
// 特殊配置处理;以下配置只在服务端生效;而Global的NOTION_CONFIG仅限前端组件使用,因此需要从extendConfig中读取
|
||
switch (key) {
|
||
case 'NEXT_REVALIDATE_SECOND':
|
||
case 'POST_RECOMMEND_COUNT':
|
||
case 'IMAGE_COMPRESS_WIDTH':
|
||
case 'PSEUDO_STATIC':
|
||
case 'POSTS_SORT_BY':
|
||
case 'POSTS_PER_PAGE':
|
||
case 'POST_PREVIEW_LINES':
|
||
case 'POST_URL_PREFIX':
|
||
case 'POST_LIST_STYLE':
|
||
case 'POST_LIST_PREVIEW':
|
||
case 'POST_URL_PREFIX_MAPPING_CATEGORY':
|
||
case 'POST_SCHEDULE_PUBLISH':
|
||
case 'IS_TAG_COLOR_DISTINGUISHED':
|
||
case 'TAG_SORT_BY_COUNT':
|
||
case 'THEME':
|
||
case 'LINK':
|
||
case 'AI_SUMMARY_API':
|
||
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) {
|
||
break
|
||
}
|
||
}
|
||
return convertVal(
|
||
getValue(extendConfig[key], getValue(defaultVal, BLOG[key]))
|
||
)
|
||
default:
|
||
}
|
||
|
||
let global = {}
|
||
try {
|
||
// const isClient = typeof window !== 'undefined'
|
||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||
global = useGlobal()
|
||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||
// global = useGlobal()
|
||
} catch (error) {
|
||
// 本地调试用
|
||
// console.warn('SiteConfig警告', key, error)
|
||
}
|
||
|
||
// 配置最优先读取NOTION中的表格配置
|
||
let val = null
|
||
let siteInfo = null
|
||
|
||
if (global) {
|
||
siteInfo = global.siteInfo
|
||
val = global.NOTION_CONFIG?.[key] || global.THEME_CONFIG?.[key]
|
||
}
|
||
|
||
if (!val) {
|
||
// 这里针对部分key做一些兼容处理
|
||
switch (key) {
|
||
case 'HOME_BANNER_IMAGE':
|
||
val = siteInfo?.pageCover // 封面图取Notion的封面
|
||
break
|
||
case 'AVATAR':
|
||
val = siteInfo?.icon // 封面图取Notion的头像
|
||
break
|
||
case 'TITLE':
|
||
val = siteInfo?.title // 标题取Notion中的标题
|
||
break
|
||
case 'DESCRIPTION':
|
||
val = siteInfo?.description // 标题取Notion中的标题
|
||
break
|
||
}
|
||
}
|
||
|
||
// 其次 有传入的extendConfig,则尝试读取
|
||
if (!hasVal(val) && extendConfig) {
|
||
val = extendConfig[key]
|
||
}
|
||
|
||
// 其次 NOTION没有找到配置,则会读取blog.config.js文件
|
||
if (!hasVal(val)) {
|
||
val = BLOG[key]
|
||
}
|
||
|
||
if (!hasVal(val)) {
|
||
return defaultVal
|
||
}
|
||
|
||
return convertVal(val)
|
||
}
|
||
|
||
export const cleanJsonString = val => {
|
||
// 使用正则表达式去掉不必要的空格、换行符和制表符
|
||
return val.replace(/\s+/g, ' ').trim()
|
||
}
|
||
|
||
/**
|
||
* 从环境变量和NotionConfig读取的配置都是string类型;
|
||
* 这里识别出配置的字符值若为否 数字、布尔、[]数组,{}对象,若是则转成对应类型
|
||
* 使用JSON和eval两个函数
|
||
* @param {*} val
|
||
* @returns
|
||
*/
|
||
export const convertVal = val => {
|
||
// 如果传入参数本身就是 obj、数组、boolean,就无需处理
|
||
if (typeof val !== 'string' || !val) {
|
||
return val
|
||
}
|
||
|
||
// 检测是否数字并避免数值溢出
|
||
if (/^\d+$/.test(val)) {
|
||
const parsedNum = Number(val)
|
||
// 如果数值大于 JavaScript 最大安全整数,则作为字符串返回
|
||
if (parsedNum > Number.MAX_SAFE_INTEGER) {
|
||
return val + ''
|
||
}
|
||
return parsedNum
|
||
}
|
||
|
||
// 检测是否为布尔值
|
||
if (val === 'true' || val === 'false') {
|
||
return JSON.parse(val)
|
||
}
|
||
|
||
// 检测是否为 URL
|
||
if (isUrlLikePath(val)) {
|
||
return val
|
||
}
|
||
|
||
// 配置值前可能有污染的空格
|
||
// 如果字符串中没有 '[' 或 '{',则直接返回
|
||
if (!val.trim().startsWith('{') && !val.trim().startsWith('[')) {
|
||
return val
|
||
}
|
||
|
||
// 转换 [] , {} 这类字符串为对象
|
||
try {
|
||
val = cleanJsonString(val)
|
||
const parsedJson = JSON.parse(val)
|
||
// 检查解析后的结果是否为对象
|
||
if (parsedJson !== null) {
|
||
return parsedJson
|
||
}
|
||
} catch (error) {
|
||
// 解析失败,返回原始字符串
|
||
return val
|
||
}
|
||
|
||
return val
|
||
}
|
||
|
||
/**
|
||
* 读取所有配置
|
||
* 1. 优先读取NotionConfig表
|
||
* 2. 其次读取环境变量
|
||
* 3. 再读取blog.config.js文件
|
||
* @param {*} key
|
||
* @returns
|
||
*/
|
||
export const siteConfigMap = () => {
|
||
const val = deepClone(BLOG)
|
||
for (const key in val) {
|
||
val[key] = siteConfig(key)
|
||
// console.log('site', key, val[key], siteConfig(key))
|
||
}
|
||
return val
|
||
}
|