Files
NotionNext/lib/notion/getPageProperties.js

177 lines
6.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { getTextContent, getDateValue } from 'notion-utils'
import { NotionAPI } from 'notion-client'
import BLOG from '@/blog.config'
import formatDate from '../formatDate'
import { defaultMapImageUrl } from 'react-notion-x'
// import { createHash } from 'crypto'
import md5 from 'js-md5'
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']
const value = block[id]?.value
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
}
case 'person': {
const rawUsers = val.flat()
const users = []
const api = new NotionAPI({ authToken })
for (let i = 0; i < rawUsers.length; i++) {
if (rawUsers[i][0][1]) {
const userId = rawUsers[i][0]
const res = await api.getUsers(userId)
const resValue =
res?.recordMapWithRoles?.notion_user?.[userId[1]]?.value
const user = {
id: resValue?.id,
first_name: resValue?.given_name,
last_name: resValue?.family_name,
profile_photo: resValue?.profile_photo
}
users.push(user)
}
}
properties[schema[key].name] = users
break
}
default:
break
}
}
}
// 映射键:用户自定义表头名
const fieldNames = BLOG.NOTION_PROPERTY_NAME
if (fieldNames) {
Object.keys(fieldNames).forEach(key => {
if (fieldNames[key] && properties[fieldNames[key]]) properties[key] = properties[fieldNames[key]]
})
}
// type\status是下拉选框 取数组第一个
properties.type = properties.type?.[0]
properties.status = properties.status?.[0]
// 映射值用户个性化type和status字段的下拉框选项在此映射回代码的英文标识
mapProperties(properties)
if (properties.type === BLOG.NOTION_PROPERTY_NAME.type_post) {
properties.slug = (BLOG.POST_URL_PREFIX) ? generateCustomizeUrl(properties) : (properties.slug ?? properties.id)
} else if (properties.type === BLOG.NOTION_PROPERTY_NAME.type_page) {
properties.slug = properties.slug ?? properties.id
} else if (properties.type === BLOG.NOTION_PROPERTY_NAME.type_menu || properties.type === BLOG.NOTION_PROPERTY_NAME.type_sub_menu) {
// 菜单路径为空、作为可展开菜单使用
properties.to = properties.slug ?? null
properties.name = properties.title ?? ''
}
// 开启伪静态路径
if (BLOG.PSEUDO_STATIC) {
if (!properties?.slug?.endsWith('.html') && !properties?.slug?.startsWith('http')) {
properties.slug += '.html'
}
}
properties.createdTime = formatDate(new Date(value.created_time).toString(), BLOG.LANG)
properties.lastEditedTime = formatDate(new Date(value?.last_edited_time).toString(), BLOG.LANG)
properties.fullWidth = value.format?.page_full_width ?? false
properties.pageIcon = getImageUrl(block[id].value?.format?.page_icon, block[id].value) ?? ''
properties.page_cover = getImageUrl(block[id].value?.format?.page_cover, block[id].value) ?? ''
properties.content = value.content ?? []
properties.password = properties.password
? md5(properties.slug + properties.password)
: ''
properties.tagItems = properties?.tags?.map(tag => {
return { name: tag, color: tagOptions?.find(t => t.value === tag)?.color || 'gray' }
}) || []
delete properties.content
return properties
}
// 从Block获取封面图;优先取PageCover否则取内容图片
function getImageUrl(imgObj, blockVal) {
if (!imgObj) {
return null
}
if (imgObj.startsWith('/')) {
return 'https://www.notion.so' + imgObj // notion内部图片转相对路径为绝对路径
}
if (imgObj.startsWith('http')) {
// 判断如果是notion上传的图片要拼接访问token
const u = new URL(imgObj)
if (u.pathname.startsWith('/secure.notion-static.com') && u.hostname.endsWith('.amazonaws.com')) {
return defaultMapImageUrl(imgObj, blockVal) // notion上传的图片需要转换请求地址
}
}
// 其他图片链接 或 emoji
return imgObj
}
function mapProperties(properties) {
if (properties?.type === BLOG.NOTION_PROPERTY_NAME.type_post) {
properties.type = 'Post'
}
if (properties?.type === BLOG.NOTION_PROPERTY_NAME.type_page) {
properties.type = 'Page'
}
if (properties?.type === BLOG.NOTION_PROPERTY_NAME.type_notice) {
properties.type = 'Notice'
}
if (properties?.status === BLOG.NOTION_PROPERTY_NAME.status_publish) {
properties.status = 'Published'
}
if (properties?.status === BLOG.NOTION_PROPERTY_NAME.status_invisible) {
properties.status = 'Invisible'
}
}
function generateCustomizeUrl(postProperties) {
let fullSlug = ''
const allSlugPatterns = BLOG.POST_URL_PREFIX.split('/')
allSlugPatterns.forEach((pattern, idx) => {
if (pattern === '%year%' && postProperties?.date?.start_date) {
const formatPostCreatedDate = new Date(postProperties?.date?.start_date)
fullSlug += formatPostCreatedDate.getUTCFullYear()
} else if (pattern === '%month%' && postProperties?.date?.start_date) {
const formatPostCreatedDate = new Date(postProperties?.date?.start_date)
fullSlug += String(formatPostCreatedDate.getUTCMonth() + 1).padStart(2, 0)
} else if (pattern === '%day%' && postProperties?.date?.start_date) {
const formatPostCreatedDate = new Date(postProperties?.date?.start_date)
fullSlug += String(formatPostCreatedDate.getUTCDate()).padStart(2, 0)
} else if (pattern === '%slug%') {
fullSlug += (postProperties.slug ?? postProperties.id)
} else if (!pattern.includes('%')) {
fullSlug += pattern
} else {
return
}
if (idx !== allSlugPatterns.length - 1) {
fullSlug += '/'
}
})
return `${fullSlug}/${(postProperties.slug ?? postProperties.id)}`
}