diff --git a/lib/notion/getNotionConfig.js b/lib/notion/getNotionConfig.js new file mode 100644 index 00000000..7a475ed3 --- /dev/null +++ b/lib/notion/getNotionConfig.js @@ -0,0 +1,137 @@ +/** + * 从Notion中读取站点配置; + * 在Notion模板中创建一个类型为CONFIG的页面,再添加一个数据库表格,即可用于填写配置 + * Notion数据库配置优先级最高,将覆盖vercel环境变量以及blog.config.js中的配置 + * --注意-- + * 数据库请从模板复制 https://www.notion.so/tanghh/287869a92e3d4d598cf366bd6994755e + * + */ +import { getDateValue, getTextContent } from 'notion-utils' +import { getPostBlocks } from './getPostBlocks' +import getAllPageIds from './getAllPageIds' +import BLOG from '@/blog.config' + +/** + * 从Notion中读取Config配置表 + * @param {*} allPages + * @returns + */ +export async function getConfigMapFromConfigPage(allPages) { + // 默认返回配置文件 + const notionConfig = BLOG + + if (!allPages || !Array.isArray(allPages) || allPages.length === 0) { + console.warn('[Notion配置] 忽略的配置', allPages, typeof allPages) + return null + } + const configPage = allPages?.find(post => { + return post && post?.type && post?.type === 'CONFIG' + }) + + if (!configPage) { + console.warn('[Notion配置]未找到配置页面', allPages, typeof allPages) + return null + } + const configPageId = configPage.id + + console.log('[Notion配置]请求配置数据 ', configPage.id) + const pageRecordMap = await getPostBlocks(configPageId, 'config-table') + // console.log('配置中心Page', configPageId, pageRecordMap) + const content = pageRecordMap.block[configPageId].value.content + + if (!content) { + console.warn('[Notion配置]未找到配置表格', pageRecordMap.block[configPageId], pageRecordMap.block[configPageId].value) + return null + } + + // 找到配置文件中的database + // for (const contentId of content) { + // console.log('内容', contentId, configPageRecordMap.block[contentId].value.type === 'collection_view') + // } + const configTableId = content?.find(contentId => { + return pageRecordMap.block[contentId].value.type === 'collection_view' + }) + + // eslint-disable-next-line no-constant-condition, no-self-compare + if (!configTableId) { + console.warn('[Notion配置]未找到配置表格数据', pageRecordMap.block[configPageId], pageRecordMap.block[configPageId].value) + return null + } + + // 页面查找 + const databaseRecordMap = pageRecordMap.block[configTableId] + const block = pageRecordMap.block || {} + const rawMetadata = databaseRecordMap.value + // Check Type Page-Database和Inline-Database + if ( + rawMetadata?.type !== 'collection_view_page' && rawMetadata?.type !== 'collection_view' + ) { + console.error(`pageId "${configTableId}" is not a database`) + return null + } + console.log('表格', databaseRecordMap, block, rawMetadata) + const collectionId = rawMetadata?.collection_id + const collection = pageRecordMap.collection[collectionId].value + const collectionQuery = pageRecordMap.collection_query + const collectionView = pageRecordMap.collection_view + const schema = collection?.schema + const viewIds = rawMetadata?.view_ids + const pageIds = getAllPageIds(collectionQuery, collectionId, collectionView, viewIds) + if (pageIds?.length === 0) { + console.error('[Notion配置]获取到的文章列表为空,请检查notion模板', collectionQuery, collection, collectionView, viewIds, databaseRecordMap) + } + // 遍历用户的表格 + for (let i = 0; i < pageIds.length; i++) { + const id = pageIds[i] + const value = block[id]?.value + if (!value) { + continue + } + const rawProperties = Object.entries(block?.[id]?.value?.properties || []) + const excludeProperties = ['date', 'select', 'multi_select', 'person'] + const properties = {} + for (let i = 0; i < rawProperties.length; i++) { + const [key, val] = rawProperties[i] + properties.id = id + if (schema[key]?.type && !excludeProperties.includes(schema[key].type)) { + properties[schema[key].name] = getTextContent(val) + } else { + switch (schema[key]?.type) { + case 'date': { + const dateProperty = getDateValue(val) + delete dateProperty.type + properties[schema[key].name] = dateProperty + break + } + case 'select': + case 'multi_select': { + const selects = getTextContent(val) + if (selects[0]?.length) { + properties[schema[key].name] = selects.split(',') + } + break + } + default: + break + } + } + } + + if (properties) { + // 将表格中的字段映射成 英文 + const config = { + enable: properties['启用'] === 'Yes', + key: properties['配置名'], + value: properties['配置值'] + } + + // 只导入生效的配置 + if (config.enable) { + console.log('[覆盖代码配置]', config.key) + notionConfig[config.key] = config.value + } + } + } + + return notionConfig +} diff --git a/lib/notion/getNotionData.js b/lib/notion/getNotionData.js index 6c01c294..3d063bcf 100755 --- a/lib/notion/getNotionData.js +++ b/lib/notion/getNotionData.js @@ -8,6 +8,7 @@ import getAllPageIds from './getAllPageIds' import { getAllTags } from './getAllTags' import getPageProperties from './getPageProperties' import { mapImgUrl, compressImage } from './mapImage' +import { getConfigMapFromConfigPage } from './getNotionConfig' /** * 获取博客数据 @@ -283,15 +284,8 @@ async function getDataBaseInfoByNotionAPI({ pageId, from }) { (post?.status === 'Invisible' || post?.status === 'Published') }) - // 从notion中读取配置 - const configPage = collectionData.find(post => { - return post && post?.type && post?.type === 'CONFIG' - }) - - if (configPage) { - const config = await getPostBlocks(configPage.id, 'config-table') - console.log('配置中心', configPage, config) - } + // 站点配置优先读取配置表格,否则读取blog.config.js 文件 + const CONFIG = await getConfigMapFromConfigPage(collectionData) || BLOG // Sort by date if (BLOG.POSTS_SORT_BY === 'date') { @@ -311,6 +305,7 @@ async function getDataBaseInfoByNotionAPI({ pageId, from }) { const allNavPages = getNavPages({ allPages }) return { + CONFIG, notice, siteInfo, allPages, diff --git a/lib/notion/getPageProperties.js b/lib/notion/getPageProperties.js index ddf47f3e..3ea1ce28 100644 --- a/lib/notion/getPageProperties.js +++ b/lib/notion/getPageProperties.js @@ -6,6 +6,15 @@ import formatDate from '../formatDate' import md5 from 'js-md5' import { mapImgUrl } from './mapImage' +/** + * 获取页面元素成员属性 + * @param {*} id + * @param {*} block + * @param {*} schema + * @param {*} authToken + * @param {*} tagOptions + * @returns + */ export default async function getPageProperties(id, block, schema, authToken, tagOptions) { const rawProperties = Object.entries(block?.[id]?.value?.properties || []) const excludeProperties = ['date', 'select', 'multi_select', 'person'] @@ -108,6 +117,7 @@ export default async function getPageProperties(id, block, schema, authToken, ta properties.slug += '.html' } } + // 密码字段md5 properties.password = properties.password ? md5(properties.slug + properties.password) : '' return properties } diff --git a/next-sitemap.config.js b/next-sitemap.config.js index a094e809..29e1ca67 100644 --- a/next-sitemap.config.js +++ b/next-sitemap.config.js @@ -1,5 +1,8 @@ const BLOG = require('./blog.config') +/** + * 通常没啥用,sitemap交给 /pages/sitemap.xml.js 动态生成 + */ module.exports = { siteUrl: BLOG.LINK, changefreq: 'daily',