From 5d8c852c52f4a4f1f2893b35f1c59fe727d7215d Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Tue, 13 Dec 2022 09:50:49 +0800 Subject: [PATCH 1/7] =?UTF-8?q?toggle-header=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- styles/notion.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/styles/notion.css b/styles/notion.css index 92acdb96f7c..d010bb0cfc6 100644 --- a/styles/notion.css +++ b/styles/notion.css @@ -392,7 +392,7 @@ .notion-h { position: relative; - display: block; + /* display: block; */ font-weight: 600; line-height: 1.3; padding: 3px 2px; From afe4c679fa537e6e824124132c18750f1077fdd5 Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Tue, 13 Dec 2022 21:21:32 +0800 Subject: [PATCH 2/7] =?UTF-8?q?hook=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- themes/hexo/LayoutSlug.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes/hexo/LayoutSlug.js b/themes/hexo/LayoutSlug.js index 7875c990d0a..0818ba01158 100644 --- a/themes/hexo/LayoutSlug.js +++ b/themes/hexo/LayoutSlug.js @@ -15,6 +15,7 @@ import { isBrowser } from '@/lib/utils' export const LayoutSlug = props => { const { post, lock, validPassword } = props + const drawerRight = useRef(null) if (!post) { return { post.toc = getPageTableOfContents(post, post.blockMap) } - const drawerRight = useRef(null) const targetRef = isBrowser() ? document.getElementById('container') : null const floatSlot = <> From ff24524aae59bce9187c5de59befabb434315cc9 Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Wed, 14 Dec 2022 12:19:28 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E5=B0=81=E8=A3=85=E5=8A=A0=E5=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/[...slug].js | 13 ++++++++++--- themes/example/LayoutSlug.js | 8 +------- themes/example/components/ArticleLock.js | 6 ++---- themes/fukasawa/LayoutSlug.js | 10 ++-------- themes/fukasawa/components/ArticleLock.js | 6 ++---- themes/hexo/LayoutSlug.js | 8 +------- themes/hexo/components/ArticleLock.js | 6 ++---- themes/hexo/components/HeaderArticle.js | 3 ++- themes/medium/LayoutSlug.js | 9 +-------- themes/medium/components/ArticleLock.js | 6 ++---- themes/next/LayoutSlug.js | 8 +------- themes/next/components/ArticleLock.js | 6 ++---- 12 files changed, 28 insertions(+), 61 deletions(-) diff --git a/pages/[...slug].js b/pages/[...slug].js index c790f211eae..cae6d4b1fd3 100644 --- a/pages/[...slug].js +++ b/pages/[...slug].js @@ -4,7 +4,7 @@ import { getGlobalNotionData } from '@/lib/notion/getNotionData' import { useGlobal } from '@/lib/global' import * as ThemeMap from '@/themes' import React from 'react' -import { idToUuid } from 'notion-utils' +import { idToUuid, getPageTableOfContents } from 'notion-utils' import Router from 'next/router' import { isBrowser } from '@/lib/utils' import { getNotion } from '@/lib/notion/getNotion' @@ -28,6 +28,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 +56,12 @@ const Slug = props => { * 验证文章密码 * @param {*} result */ - const validPassword = result => { - if (result) { + const validPassword = passInput => { + if (passInput && passInput === post.password) { setLock(false) + return true } + return false } props = { ...props, lock, setLock, validPassword } diff --git a/themes/example/LayoutSlug.js b/themes/example/LayoutSlug.js index 1f7fd4098fa..b16892b7bcc 100644 --- a/themes/example/LayoutSlug.js +++ b/themes/example/LayoutSlug.js @@ -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 } - if (!lock && post?.blockMap?.block) { - post.content = Object.keys(post.blockMap.block) - post.toc = getPageTableOfContents(post, post.blockMap) - } - return ( - {lock && } + {lock && } {!lock &&
diff --git a/themes/example/components/ArticleLock.js b/themes/example/components/ArticleLock.js index a9f5f59d8a4..43b6647e4f1 100644 --- a/themes/example/components/ArticleLock.js +++ b/themes/example/components/ArticleLock.js @@ -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 = '' diff --git a/themes/fukasawa/LayoutSlug.js b/themes/fukasawa/LayoutSlug.js index 30265a6c9d6..fb78690cce6 100644 --- a/themes/fukasawa/LayoutSlug.js +++ b/themes/fukasawa/LayoutSlug.js @@ -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 ( {!lock && } - {lock && } + {lock && } ) } diff --git a/themes/fukasawa/components/ArticleLock.js b/themes/fukasawa/components/ArticleLock.js index 23112eebe25..8ae18a4e82e 100644 --- a/themes/fukasawa/components/ArticleLock.js +++ b/themes/fukasawa/components/ArticleLock.js @@ -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 = '' diff --git a/themes/hexo/LayoutSlug.js b/themes/hexo/LayoutSlug.js index 0818ba01158..327497ac6f8 100644 --- a/themes/hexo/LayoutSlug.js +++ b/themes/hexo/LayoutSlug.js @@ -1,4 +1,3 @@ -import { getPageTableOfContents } from 'notion-utils' import { useRef } from 'react' import { ArticleLock } from './components/ArticleLock' import HeaderArticle from './components/HeaderArticle' @@ -26,11 +25,6 @@ export const LayoutSlug = props => { > } - if (!lock && post?.blockMap?.block) { - post.content = Object.keys(post.blockMap.block) - post.toc = getPageTableOfContents(post, post.blockMap) - } - const targetRef = isBrowser() ? document.getElementById('container') : null const floatSlot = <> @@ -53,7 +47,7 @@ export const LayoutSlug = props => { floatSlot={floatSlot} >
- {lock && } + {lock && } {!lock &&
diff --git a/themes/hexo/components/ArticleLock.js b/themes/hexo/components/ArticleLock.js index 84ef905fbfb..1a1bd193191 100644 --- a/themes/hexo/components/ArticleLock.js +++ b/themes/hexo/components/ArticleLock.js @@ -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 = '' diff --git a/themes/hexo/components/HeaderArticle.js b/themes/hexo/components/HeaderArticle.js index 918c75c77c6..8ebfe2bd0f6 100644 --- a/themes/hexo/components/HeaderArticle.js +++ b/themes/hexo/components/HeaderArticle.js @@ -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 diff --git a/themes/medium/LayoutSlug.js b/themes/medium/LayoutSlug.js index f7fdc4d0b4d..bdeec1a512f 100644 --- a/themes/medium/LayoutSlug.js +++ b/themes/medium/LayoutSlug.js @@ -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 && (
@@ -29,7 +22,7 @@ export const LayoutSlug = props => { return ( - {!lock ? : } + {!lock ? : } ) } diff --git a/themes/medium/components/ArticleLock.js b/themes/medium/components/ArticleLock.js index 4b969835a78..1e1bb228dbe 100644 --- a/themes/medium/components/ArticleLock.js +++ b/themes/medium/components/ArticleLock.js @@ -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 = '' diff --git a/themes/next/LayoutSlug.js b/themes/next/LayoutSlug.js index aa1cc4d2f47..fa1915a15db 100644 --- a/themes/next/LayoutSlug.js +++ b/themes/next/LayoutSlug.js @@ -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 && } - {lock && } + {lock && } {/* 悬浮目录按钮 */}
diff --git a/themes/next/components/ArticleLock.js b/themes/next/components/ArticleLock.js index 4bb2ef65938..3e4a2019f9e 100644 --- a/themes/next/components/ArticleLock.js +++ b/themes/next/components/ArticleLock.js @@ -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 = '' From 771819985aee595157182fc6dceb5293f27ffdfd Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Wed, 14 Dec 2022 13:47:14 +0800 Subject: [PATCH 4/7] encrypt-password --- lib/notion/getNotionData.js | 5 ++--- lib/notion/getPageProperties.js | 2 ++ package.json | 1 + pages/[...slug].js | 3 ++- themes/medium/LayoutCategory.js | 2 +- themes/medium/LayoutTag.js | 2 +- 6 files changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/notion/getNotionData.js b/lib/notion/getNotionData.js index 11913b2d9f4..80444cdb2e4 100644 --- a/lib/notion/getNotionData.js +++ b/lib/notion/getNotionData.js @@ -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') && diff --git a/lib/notion/getPageProperties.js b/lib/notion/getPageProperties.js index f4ee3282c78..ef93f84be69 100644 --- a/lib/notion/getPageProperties.js +++ b/lib/notion/getPageProperties.js @@ -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' } }) || [] diff --git a/package.json b/package.json index c9e3b948ff2..f022f9d0401 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/pages/[...slug].js b/pages/[...slug].js index cae6d4b1fd3..9d521d8f7f2 100644 --- a/pages/[...slug].js +++ b/pages/[...slug].js @@ -8,6 +8,7 @@ import { idToUuid, getPageTableOfContents } from 'notion-utils' import Router from 'next/router' import { isBrowser } from '@/lib/utils' import { getNotion } from '@/lib/notion/getNotion' +import md5 from 'js-md5' /** * 根据notion的slug访问页面 @@ -57,7 +58,7 @@ const Slug = props => { * @param {*} result */ const validPassword = passInput => { - if (passInput && passInput === post.password) { + if (passInput && md5(post.slug + passInput) === post.password) { setLock(false) return true } diff --git a/themes/medium/LayoutCategory.js b/themes/medium/LayoutCategory.js index a30181448c7..7522e264134 100644 --- a/themes/medium/LayoutCategory.js +++ b/themes/medium/LayoutCategory.js @@ -5,7 +5,7 @@ import BLOG from '@/blog.config' export const LayoutCategory = props => { const { category } = props - const slotTop =
分类:
{category}
+ const slotTop =
分类:
{category}
return {BLOG.POST_LIST_STYLE === 'page' ? : } diff --git a/themes/medium/LayoutTag.js b/themes/medium/LayoutTag.js index 6f072aa94c5..41164ce3930 100644 --- a/themes/medium/LayoutTag.js +++ b/themes/medium/LayoutTag.js @@ -5,7 +5,7 @@ import BlogPostListPage from './components/BlogPostListPage' export const LayoutTag = (props) => { const { tag } = props - const slotTop =
标签:
{tag}
+ const slotTop =
标签:
{tag}
return {BLOG.POST_LIST_STYLE === 'page' ? : } From 727fa0e2e605a25b791abafc0343bf1b1569e6b9 Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Wed, 14 Dec 2022 21:14:56 +0800 Subject: [PATCH 5/7] get-page-table-of-content --- lib/notion/getPageTableOfContents.js | 76 ++++++++++++++++++++++++++++ pages/[...slug].js | 3 +- 2 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 lib/notion/getPageTableOfContents.js diff --git a/lib/notion/getPageTableOfContents.js b/lib/notion/getPageTableOfContents.js new file mode 100644 index 00000000000..a15ebe2df49 --- /dev/null +++ b/lib/notion/getPageTableOfContents.js @@ -0,0 +1,76 @@ +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 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, + text: getTextContent(block.properties?.title), + indentLevel: indentLevels[type] + } + } + } + + return null + }).filter(e => e) + + console.log('目录', toc) + + 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 +} diff --git a/pages/[...slug].js b/pages/[...slug].js index 9d521d8f7f2..6ca98c93e6e 100644 --- a/pages/[...slug].js +++ b/pages/[...slug].js @@ -4,11 +4,12 @@ import { getGlobalNotionData } from '@/lib/notion/getNotionData' import { useGlobal } from '@/lib/global' import * as ThemeMap from '@/themes' import React from 'react' -import { idToUuid, getPageTableOfContents } from 'notion-utils' +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访问页面 From 068639647d1de773d8d0000d96ba360996815550 Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Thu, 15 Dec 2022 10:37:37 +0800 Subject: [PATCH 6/7] rewrite.toc. --- lib/notion/getPageTableOfContents.js | 64 +++++++++++++++++----------- styles/notion.css | 2 +- 2 files changed, 40 insertions(+), 26 deletions(-) diff --git a/lib/notion/getPageTableOfContents.js b/lib/notion/getPageTableOfContents.js index a15ebe2df49..a23be7cb30e 100644 --- a/lib/notion/getPageTableOfContents.js +++ b/lib/notion/getPageTableOfContents.js @@ -12,31 +12,8 @@ const indentLevels = { * H1, H2, and H3 elements. */ export const getPageTableOfContents = (page, recordMap) => { - 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, - text: getTextContent(block.properties?.title), - indentLevel: indentLevels[type] - } - } - } - - return null - }).filter(e => e) - - console.log('目录', toc) - + const contents = (page.content ?? []) + const toc = getBlockHeader(contents, recordMap) const indentLevelStack = [ { actual: -1, @@ -74,3 +51,40 @@ export const getPageTableOfContents = (page, recordMap) => { 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 +} diff --git a/styles/notion.css b/styles/notion.css index d010bb0cfc6..d55d8456d32 100644 --- a/styles/notion.css +++ b/styles/notion.css @@ -427,7 +427,7 @@ margin-top: 2px; } */ .notion-h2 { - font-size: 1.5em; + font-size: 1.4em; margin-top: 1.1em; } .notion-h3 { From 25f24d69c7418b7676345800ec31f7d0f1e0892d Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Thu, 15 Dec 2022 10:58:23 +0800 Subject: [PATCH 7/7] v3.6.3 --- .env.local | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.local b/.env.local index 618efc8733a..ffa9389376c 100644 --- a/.env.local +++ b/.env.local @@ -1,2 +1,2 @@ # 环境变量 @see https://www.nextjs.cn/docs/basic-features/environment-variables -NEXT_PUBLIC_VERSION=3.6.5 \ No newline at end of file +NEXT_PUBLIC_VERSION=3.6.6 \ No newline at end of file diff --git a/package.json b/package.json index f022f9d0401..b7d9f09fe14 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "notion-next", - "version": "3.6.5", + "version": "3.6.6", "homepage": "https://github.com/tangly1024/NotionNext.git", "license": "MIT", "repository": {