From 727fa0e2e605a25b791abafc0343bf1b1569e6b9 Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Wed, 14 Dec 2022 21:14:56 +0800 Subject: [PATCH] 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 00000000..a15ebe2d --- /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 9d521d8f..6ca98c93 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访问页面