Merge pull request #597 from tangly1024/bug/h-toggle

Bug/h toggle
This commit is contained in:
tangly1024
2022-12-15 10:56:02 +08:00
committed by GitHub
19 changed files with 129 additions and 68 deletions

View File

@@ -212,17 +212,16 @@ async function getPageRecordMapByNotionAPI({ pageId, from }) {
collectionData.push(properties)
}
}
// 读取映射 配置
let postCount = 0
// 获取page作为自定义菜单
const customNav = getCustomNav({ allPages: collectionData.filter(post => post.type === 'Page' && post.status === 'Published') })
// 文章计数
let postCount = 0
const allPages = collectionData.filter(post => {
if (post.type === 'Post' && post.status === 'Published') {
postCount++
}
return post &&
post.type &&
(post.type === 'Post' || post.type === 'Page') &&

View File

@@ -3,6 +3,7 @@ import { NotionAPI } from 'notion-client'
import BLOG from '@/blog.config'
import formatDate from '../formatDate'
import { defaultMapImageUrl } from 'react-notion-x'
import md5 from 'js-md5'
export default async function getPageProperties(id, block, schema, authToken, tagOptions, siteInfo) {
const rawProperties = Object.entries(block?.[id]?.value?.properties || [])
@@ -89,6 +90,7 @@ export default async function getPageProperties(id, block, schema, authToken, ta
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) ?? siteInfo?.pageCover
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' }
}) || []

View File

@@ -0,0 +1,90 @@
import { getTextContent } from 'notion-utils'
const indentLevels = {
header: 0,
sub_header: 1,
sub_sub_header: 2
}
/**
* @see https://github.com/NotionX/react-notion-x/blob/master/packages/notion-utils/src/get-page-table-of-contents.ts
* Gets the metadata for a table of contents block by parsing the page's
* H1, H2, and H3 elements.
*/
export const getPageTableOfContents = (page, recordMap) => {
const contents = (page.content ?? [])
const toc = getBlockHeader(contents, recordMap)
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()
}
// eslint-disable-next-line no-constant-condition
} while (true)
}
return toc
}
/**
* 重写获取目录方法
*/
function getBlockHeader(contents, recordMap, toc) {
if (!toc) {
toc = []
}
if (!contents) {
return toc
}
for (const blockId of contents) {
const block = recordMap.block[blockId]?.value
if (!block) {
continue
}
const { type } = block
if (type.indexOf('header') >= 0) {
const existed = toc.find(e => e.id === blockId)
if (!existed) {
toc.push({
id: blockId,
type,
text: getTextContent(block.properties?.title),
indentLevel: indentLevels[type]
})
}
}
if (block.content?.length > 0) {
getBlockHeader(block.content, recordMap, toc)
}
}
return toc
}

View File

@@ -30,6 +30,7 @@
"eslint-plugin-react-hooks": "^4.6.0",
"feed": "^4.2.2",
"gitalk": "^1.7.2",
"js-md5": "^0.7.3",
"localStorage": "^1.0.4",
"lodash.throttle": "^4.1.1",
"mark.js": "^8.11.1",

View File

@@ -8,6 +8,8 @@ import { idToUuid } from 'notion-utils'
import Router from 'next/router'
import { isBrowser } from '@/lib/utils'
import { getNotion } from '@/lib/notion/getNotion'
import md5 from 'js-md5'
import { getPageTableOfContents } from '@/lib/notion/getPageTableOfContents'
/**
* 根据notion的slug访问页面
@@ -28,6 +30,11 @@ const Slug = props => {
if (post?.password && post?.password !== '') {
setLock(true)
} else {
if (!lock && post?.blockMap?.block) {
post.content = Object.keys(post.blockMap.block)
post.toc = getPageTableOfContents(post, post.blockMap)
}
setLock(false)
}
}, [post])
@@ -51,10 +58,12 @@ const Slug = props => {
* 验证文章密码
* @param {*} result
*/
const validPassword = result => {
if (result) {
const validPassword = passInput => {
if (passInput && md5(post.slug + passInput) === post.password) {
setLock(false)
return true
}
return false
}
props = { ...props, lock, setLock, validPassword }

View File

@@ -392,7 +392,7 @@
.notion-h {
position: relative;
display: block;
/* display: block; */
font-weight: 600;
line-height: 1.3;
padding: 3px 2px;
@@ -427,7 +427,7 @@
margin-top: 2px;
} */
.notion-h2 {
font-size: 1.5em;
font-size: 1.4em;
margin-top: 1.1em;
}
.notion-h3 {

View File

@@ -1,4 +1,3 @@
import { getPageTableOfContents } from 'notion-utils'
import LayoutBase from './LayoutBase'
import { ArticleLock } from './components/ArticleLock'
import NotionPage from '@/components/NotionPage'
@@ -12,15 +11,10 @@ export const LayoutSlug = props => {
return <LayoutBase {...props} />
}
if (!lock && post?.blockMap?.block) {
post.content = Object.keys(post.blockMap.block)
post.toc = getPageTableOfContents(post, post.blockMap)
}
return (
<LayoutBase {...props}>
{lock && <ArticleLock password={post.password} validPassword={validPassword} />}
{lock && <ArticleLock validPassword={validPassword} />}
{!lock && <div id="notion-article" className="px-2">

View File

@@ -8,14 +8,12 @@ import { useGlobal } from '@/lib/global'
* @returns
*/
export const ArticleLock = props => {
const { password, validPassword } = props
const { validPassword } = props
const { locale } = useGlobal()
const submitPassword = () => {
const p = document.getElementById('password')
if (p && p.value && p.value === password) {
validPassword(true)
} else {
if (!validPassword(p?.value)) {
const tips = document.getElementById('tips')
if (tips) {
tips.innerHTML = ''

View File

@@ -1,19 +1,13 @@
import { getPageTableOfContents } from 'notion-utils'
import ArticleDetail from './components/ArticleDetail'
import LayoutBase from './LayoutBase'
import { ArticleLock } from './components/ArticleLock'
export const LayoutSlug = (props) => {
const { post, lock, validPassword } = props
if (!lock && post?.blockMap?.block) {
post.content = Object.keys(post.blockMap.block)
post.toc = getPageTableOfContents(post, post.blockMap)
}
const { lock, validPassword } = props
return (
<LayoutBase {...props} >
{!lock && <ArticleDetail {...props} />}
{lock && <ArticleLock password={post.password} validPassword={validPassword} />}
{lock && <ArticleLock validPassword={validPassword} />}
</LayoutBase>
)
}

View File

@@ -8,14 +8,12 @@ import { useGlobal } from '@/lib/global'
* @returns
*/
export const ArticleLock = props => {
const { password, validPassword } = props
const { validPassword } = props
const { locale } = useGlobal()
const submitPassword = () => {
const p = document.getElementById('password')
if (p && p.value && p.value === password) {
validPassword(true)
} else {
if (!validPassword(p?.value)) {
const tips = document.getElementById('tips')
if (tips) {
tips.innerHTML = ''

View File

@@ -1,4 +1,3 @@
import { getPageTableOfContents } from 'notion-utils'
import { useRef } from 'react'
import { ArticleLock } from './components/ArticleLock'
import HeaderArticle from './components/HeaderArticle'
@@ -15,6 +14,7 @@ import { isBrowser } from '@/lib/utils'
export const LayoutSlug = props => {
const { post, lock, validPassword } = props
const drawerRight = useRef(null)
if (!post) {
return <LayoutBase
@@ -25,12 +25,6 @@ export const LayoutSlug = props => {
></LayoutBase>
}
if (!lock && post?.blockMap?.block) {
post.content = Object.keys(post.blockMap.block)
post.toc = getPageTableOfContents(post, post.blockMap)
}
const drawerRight = useRef(null)
const targetRef = isBrowser() ? document.getElementById('container') : null
const floatSlot = <>
@@ -53,7 +47,7 @@ export const LayoutSlug = props => {
floatSlot={floatSlot}
>
<div className="w-full lg:shadow-sm lg:hover:shadow lg:border lg:rounded-xl lg:px-2 lg:py-4 bg-white dark:bg-hexo-black-gray dark:border-black">
{lock && <ArticleLock password={post.password} validPassword={validPassword} />}
{lock && <ArticleLock validPassword={validPassword} />}
{!lock && <div id="container" className="overflow-x-auto flex-grow mx-auto md:w-full md:px-5 ">

View File

@@ -8,13 +8,11 @@ import { useGlobal } from '@/lib/global'
* @returns
*/
export const ArticleLock = props => {
const { password, validPassword } = props
const { validPassword } = props
const { locale } = useGlobal()
const submitPassword = () => {
const p = document.getElementById('password')
if (p && p.value && p.value === password) {
validPassword(true)
} else {
if (!validPassword(p?.value)) {
const tips = document.getElementById('tips')
if (tips) {
tips.innerHTML = ''

View File

@@ -4,12 +4,13 @@ import formatDate from '@/lib/formatDate'
import BLOG from '@/blog.config'
export default function HeaderArticle({ post, siteInfo }) {
const { locale } = useGlobal()
if (!post) {
return <></>
}
const headerImage = post?.page_cover ? `url("${post.page_cover}")` : `url("${siteInfo?.pageCover}")`
const { locale } = useGlobal()
const date = formatDate(
post?.date?.start_date || post?.createdTime,
locale.LOCALE

View File

@@ -5,7 +5,7 @@ import BLOG from '@/blog.config'
export const LayoutCategory = props => {
const { category } = props
const slotTop = <div className='flex items-center font-sans p-8'><div className='text-xl'><i className='mr-2 fas fa-th' />分类</div>{category}</div>
const slotTop = <div className='flex items-center font-sans py-8'><div className='text-xl'><i className='mr-2 fas fa-th' />分类</div>{category}</div>
return <LayoutBase {...props} slotTop={slotTop}>
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}

View File

@@ -1,5 +1,3 @@
import { getPageTableOfContents } from 'notion-utils'
import LayoutBase from './LayoutBase'
import { useGlobal } from '@/lib/global'
import React from 'react'
@@ -16,11 +14,6 @@ export const LayoutSlug = props => {
/>
}
if (!lock && post?.blockMap?.block) {
post.content = Object.keys(post.blockMap.block)
post.toc = getPageTableOfContents(post, post.blockMap)
}
const slotRight = post?.toc && post?.toc?.length > 3 && (
<div key={locale.COMMON.TABLE_OF_CONTENTS} >
<Catalog toc={post.toc} />
@@ -29,7 +22,7 @@ export const LayoutSlug = props => {
return (
<LayoutBase showInfoCard={true} slotRight={slotRight} {...props} >
{!lock ? <ArticleDetail {...props} /> : <ArticleLock password={post.password} validPassword={validPassword} />}
{!lock ? <ArticleDetail {...props} /> : <ArticleLock validPassword={validPassword} />}
</LayoutBase>
)
}

View File

@@ -5,7 +5,7 @@ import BlogPostListPage from './components/BlogPostListPage'
export const LayoutTag = (props) => {
const { tag } = props
const slotTop = <div className='flex items-center font-sans p-8'><div className='text-xl'><i className='mr-2 fas fa-tag'/>标签</div>{tag}</div>
const slotTop = <div className='flex items-center font-sans py-8'><div className='text-xl'><i className='mr-2 fas fa-tag'/>标签</div>{tag}</div>
return <LayoutBase {...props} slotTop={slotTop}>
{BLOG.POST_LIST_STYLE === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}

View File

@@ -8,14 +8,12 @@ import { useGlobal } from '@/lib/global'
* @returns
*/
export const ArticleLock = props => {
const { password, validPassword } = props
const { validPassword } = props
const { locale } = useGlobal()
const submitPassword = () => {
const p = document.getElementById('password')
if (p && p.value && p.value === password) {
validPassword(true)
} else {
if (!validPassword(p?.value)) {
const tips = document.getElementById('tips')
if (tips) {
tips.innerHTML = ''

View File

@@ -1,4 +1,3 @@
import { getPageTableOfContents } from 'notion-utils'
import TocDrawerButton from './components/TocDrawerButton'
import LayoutBase from './LayoutBase'
import Card from './components/Card'
@@ -12,11 +11,6 @@ import { isBrowser } from '@/lib/utils'
export const LayoutSlug = (props) => {
const { post, latestPosts, lock, validPassword } = props
if (!lock && post?.blockMap?.block) {
post.content = Object.keys(post.blockMap.block)
post.toc = getPageTableOfContents(post, post.blockMap)
}
const drawerRight = useRef(null)
const targetRef = isBrowser() ? document.getElementById('container') : null
const floatSlot = post?.toc?.length > 1
@@ -45,7 +39,7 @@ export const LayoutSlug = (props) => {
{!lock && <ArticleDetail {...props} />}
{lock && <ArticleLock password={post.password} validPassword={validPassword} />}
{lock && <ArticleLock validPassword={validPassword} />}
{/* 悬浮目录按钮 */}
<div className='block lg:hidden'>

View File

@@ -8,14 +8,12 @@ import { useGlobal } from '@/lib/global'
* @returns
*/
export const ArticleLock = props => {
const { password, validPassword } = props
const { validPassword } = props
const { locale } = useGlobal()
const submitPassword = () => {
const p = document.getElementById('password')
if (p && p.value && p.value === password) {
validPassword(true)
} else {
if (!validPassword(p?.value)) {
const tips = document.getElementById('tips')
if (tips) {
tips.innerHTML = ''