mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-06-04 15:10:23 +00:00
Code🤣
This commit is contained in:
20
lib/notion/getAllPageIds.js
Normal file
20
lib/notion/getAllPageIds.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import { idToUuid } from 'notion-utils'
|
||||
|
||||
export default function getAllPageIds (collectionQuery, viewId) {
|
||||
const views = Object.values(collectionQuery)[0]
|
||||
if (!views) {
|
||||
return []
|
||||
}
|
||||
let pageIds = []
|
||||
if (viewId) {
|
||||
const vId = idToUuid(viewId)
|
||||
pageIds = views[vId]?.blockIds
|
||||
} else {
|
||||
const pageSet = new Set()
|
||||
Object.values(views).forEach(view => {
|
||||
view?.blockIds?.forEach(id => pageSet.add(id))
|
||||
})
|
||||
pageIds = [...pageSet]
|
||||
}
|
||||
return pageIds
|
||||
}
|
||||
101
lib/notion/getAllPosts.js
Normal file
101
lib/notion/getAllPosts.js
Normal file
@@ -0,0 +1,101 @@
|
||||
import BLOG from '@/blog.config'
|
||||
import { idToUuid } from 'notion-utils'
|
||||
import getAllPageIds from './getAllPageIds'
|
||||
import getPageProperties from './getPageProperties'
|
||||
import { defaultMapImageUrl } from 'react-notion-x'
|
||||
import { getDataFromCache, setDataToCache } from '@/lib/cache/cache_manager'
|
||||
import { getPostBlocks } from '@/lib/notion/getPostBlocks'
|
||||
|
||||
export async function getAllPosts () {
|
||||
const data = await getDataFromCache('posts_list')
|
||||
if (data) {
|
||||
return data
|
||||
}
|
||||
let id = BLOG.notionPageId
|
||||
const pageRecordMap = await getPostBlocks(id)
|
||||
if (!pageRecordMap) {
|
||||
return <>获取数据异常</>
|
||||
}
|
||||
|
||||
id = idToUuid(id)
|
||||
const collection = Object.values(pageRecordMap.collection)[0]?.value
|
||||
const collectionQuery = pageRecordMap.collection_query
|
||||
const block = pageRecordMap.block
|
||||
const schema = collection?.schema
|
||||
|
||||
const rawMetadata = block[id].value
|
||||
|
||||
// Check Type 兼容Page-Database和Inline-Database
|
||||
if (rawMetadata?.type !== 'collection_view_page' && rawMetadata?.type !== 'collection_view') {
|
||||
console.warn(`pageId "${id}" is not a database`)
|
||||
return null
|
||||
} else {
|
||||
// Construct Data
|
||||
const pageIds = getAllPageIds(collectionQuery)
|
||||
const data = []
|
||||
for (let i = 0; i < pageIds.length; i++) {
|
||||
const id = pageIds[i]
|
||||
const properties = (await getPageProperties(id, block, schema)) || null
|
||||
|
||||
// Add fullwidth, createdtime to properties
|
||||
properties.createdTime = new Date(
|
||||
block[id].value?.created_time
|
||||
).toString()
|
||||
properties.fullWidth = block[id].value?.format?.page_full_width ?? false
|
||||
properties.page_cover = getPostCover(id, block, pageRecordMap) ?? getContentFirstImage(id, block, pageRecordMap)
|
||||
properties.content = block[id].value?.content ?? []
|
||||
data.push(properties)
|
||||
}
|
||||
// remove all the the items doesn't meet requirements
|
||||
const posts = data.filter(post => {
|
||||
return (
|
||||
post.title &&
|
||||
post.slug &&
|
||||
post?.status?.[0] === 'Published' &&
|
||||
(post?.type?.[0] === 'Post' || post?.type?.[0] === 'Page')
|
||||
)
|
||||
})
|
||||
|
||||
// Sort by date
|
||||
if (BLOG.sortByDate) {
|
||||
posts.sort((a, b) => {
|
||||
const dateA = new Date(a?.date?.start_date || a.createdTime)
|
||||
const dateB = new Date(b?.date?.start_date || b.createdTime)
|
||||
return dateB - dateA
|
||||
})
|
||||
}
|
||||
if (posts) {
|
||||
await setDataToCache('posts_list', posts)
|
||||
}
|
||||
return posts
|
||||
}
|
||||
}
|
||||
|
||||
// 从Block获取封面图;优先取PageCover,否则取内容图片
|
||||
function getPostCover (id, block, pageRecordMap) {
|
||||
const pageCover = block[id].value?.format?.page_cover
|
||||
if (pageCover) {
|
||||
if (pageCover.startsWith('/')) return 'https://www.notion.so' + pageCover
|
||||
if (pageCover.startsWith('http')) return defaultMapImageUrl(pageCover, block[id].value)
|
||||
}
|
||||
}
|
||||
|
||||
// 取文章的第一个图片内容作为封面
|
||||
function getContentFirstImage (id, block, pageRecordMap) {
|
||||
const pageBlock = block[id]?.value
|
||||
|
||||
const contentBlockId = pageBlock?.content?.find((blockId) => {
|
||||
const block = pageRecordMap.block[blockId]?.value
|
||||
if (block?.type === 'image') {
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
if (contentBlockId) {
|
||||
const contentBlock = pageRecordMap.block[contentBlockId]?.value
|
||||
const source = contentBlock.properties?.source?.[0]?.[0] ??
|
||||
contentBlock.format?.display_source
|
||||
return defaultMapImageUrl(source, contentBlock)
|
||||
}
|
||||
return ''
|
||||
}
|
||||
23
lib/notion/getAllTags.js
Normal file
23
lib/notion/getAllTags.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import { getAllPosts } from './getAllPosts'
|
||||
|
||||
export async function getAllTags (posts) {
|
||||
if (!posts) {
|
||||
const response = await getAllPosts()
|
||||
posts = response.filter(
|
||||
post =>
|
||||
post.status[0] === 'Published' && post.type[0] === 'Post' && post.tags
|
||||
)
|
||||
}
|
||||
|
||||
let tags = posts.map(p => p.tags)
|
||||
tags = [...tags.flat()]
|
||||
const tagObj = {}
|
||||
tags.forEach(tag => {
|
||||
if (tag in tagObj) {
|
||||
tagObj[tag]++
|
||||
} else {
|
||||
tagObj[tag] = 1
|
||||
}
|
||||
})
|
||||
return tagObj
|
||||
}
|
||||
11
lib/notion/getMetadata.js
Normal file
11
lib/notion/getMetadata.js
Normal file
@@ -0,0 +1,11 @@
|
||||
export default function getMetadata(rawMetadata) {
|
||||
const metadata = {
|
||||
locked: rawMetadata?.format?.block_locked,
|
||||
page_full_width: rawMetadata?.format?.page_full_width,
|
||||
page_font: rawMetadata?.format?.page_font,
|
||||
page_small_text: rawMetadata?.format?.page_small_text,
|
||||
created_time: rawMetadata.created_time,
|
||||
last_edited_time: rawMetadata.last_edited_time
|
||||
}
|
||||
return metadata
|
||||
}
|
||||
60
lib/notion/getPageProperties.js
Normal file
60
lib/notion/getPageProperties.js
Normal file
@@ -0,0 +1,60 @@
|
||||
import { getTextContent, getDateValue } from 'notion-utils'
|
||||
import { NotionAPI } from 'notion-client'
|
||||
|
||||
async function getPageProperties (id, block, schema, authToken) {
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
return properties
|
||||
}
|
||||
|
||||
export { getPageProperties as default }
|
||||
69
lib/notion/getPageTableOfContents.js
Normal file
69
lib/notion/getPageTableOfContents.js
Normal file
@@ -0,0 +1,69 @@
|
||||
|
||||
const indentLevels = {
|
||||
header: 0,
|
||||
sub_header: 1,
|
||||
sub_sub_header: 2
|
||||
}
|
||||
|
||||
|
||||
export const getPageTableOfContents = (page,recordMap)=> {
|
||||
// 获取 header sub_header sub_sub_header
|
||||
const toc = (page.content ?? [])
|
||||
.map((blockId) => {
|
||||
const block = recordMap.block[blockId]?.value
|
||||
|
||||
if (block) {
|
||||
const { type } = block
|
||||
|
||||
if (
|
||||
type === 'header' ||
|
||||
type === 'sub_header' ||
|
||||
type === 'sub_sub_header'
|
||||
) {
|
||||
return {
|
||||
id: blockId,
|
||||
type,
|
||||
indentLevel: indentLevels[type]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
})
|
||||
.filter(Boolean)
|
||||
|
||||
const indentLevelStack = [
|
||||
{
|
||||
actual: -1,
|
||||
effective: -1
|
||||
}
|
||||
]
|
||||
|
||||
// Adjust indent levels to always change smoothly.
|
||||
// This is a little tricky, but the key is that when increasing indent levels,
|
||||
// they should never jump more than one at a time.
|
||||
for (const tocItem of toc) {
|
||||
const { indentLevel } = tocItem
|
||||
const actual = indentLevel
|
||||
|
||||
do {
|
||||
const prevIndent = indentLevelStack[indentLevelStack.length - 1]
|
||||
const { actual: prevActual, effective: prevEffective } = prevIndent
|
||||
|
||||
if (actual > prevActual) {
|
||||
tocItem.indentLevel = prevEffective + 1
|
||||
indentLevelStack.push({
|
||||
actual,
|
||||
effective: tocItem.indentLevel
|
||||
})
|
||||
} else if (actual === prevActual) {
|
||||
tocItem.indentLevel = prevEffective
|
||||
break
|
||||
} else {
|
||||
indentLevelStack.pop()
|
||||
}
|
||||
} while (true)
|
||||
}
|
||||
|
||||
return toc
|
||||
}
|
||||
17
lib/notion/getPostBlocks.js
Normal file
17
lib/notion/getPostBlocks.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import BLOG from '@/blog.config'
|
||||
import { NotionAPI } from 'notion-client'
|
||||
import { getDataFromCache, setDataToCache } from '@/lib/cache/cache_manager'
|
||||
|
||||
export async function getPostBlocks (id) {
|
||||
let pageBlock = await getDataFromCache('page_block_' + id)
|
||||
if (pageBlock) {
|
||||
return pageBlock
|
||||
}
|
||||
const authToken = BLOG.notionAccessToken || null
|
||||
const api = new NotionAPI({ authToken })
|
||||
pageBlock = await api.getPage(id)
|
||||
if (pageBlock) {
|
||||
await setDataToCache('page_block_' + id, pageBlock)
|
||||
}
|
||||
return pageBlock
|
||||
}
|
||||
Reference in New Issue
Block a user