import * as React from 'react' import Head from 'next/head' import Link from 'next/link' import cs from 'classnames' import { useRouter } from 'next/router' import { useLocalStorage, useSearchParam } from 'react-use' import BodyClassName from 'react-body-classname' // core notion renderer import { NotionRenderer } from 'react-notion-x' // utils import { getBlockTitle } from 'notion-utils' import { mapPageUrl, getCanonicalPageUrl } from 'lib/map-page-url' import { mapNotionImageUrl } from 'lib/map-image-url' import { getPageDescription } from 'lib/get-page-description' import { getPageTweet } from 'lib/get-page-tweet' import { searchNotion } from 'lib/search-notion' import * as types from 'lib/types' import * as config from 'lib/config' // components import { CustomFont } from './CustomFont' import { CustomHtml } from './CustomHtml' import { Loading } from './Loading' import { Page404 } from './Page404' import { PageHead } from './PageHead' import { PageActions } from './PageActions' import { Footer } from './Footer' import { ReactUtterances } from './ReactUtterances' import styles from './styles.module.css' export const NotionPage: React.FC = ({ site, recordMap, error, pageId }) => { const router = useRouter() const dark = useSearchParam('dark') const lite = useSearchParam('lite') const params: any = {} if (dark) params.dark = dark if (lite) params.lite = lite const searchParams = new URLSearchParams(params) // TODO: add ability to toggle dark mode const [isDarkMode, setDarkMode] = useLocalStorage( 'notionx-dark-mode', dark !== null ? dark === 'true' : !!site?.darkMode ) const isLiteMode = lite === 'true' if (router.isFallback) { return } const keys = Object.keys(recordMap?.block || {}) const block = recordMap?.block?.[keys[0]]?.value if (error || !site || !keys.length || !block) { return } const title = getBlockTitle(block, recordMap) || site.name console.log('notion page', { isDev: config.isDev, title, pageId, rootNotionPageId: site.rootNotionPageId, recordMap }) if (!config.isServer) { // add important objects global window for easy debugging const g = window as any g.recordMap = recordMap g.block = block } const siteMapPageUrl = mapPageUrl(site, recordMap, searchParams) const canonicalPageUrl = !config.isDev && getCanonicalPageUrl(site, recordMap)(pageId) const isBlogPost = block.type === 'page' && block.parent_table === 'collection' const showTableOfContents = !!isBlogPost const minTableOfContentsItems = 3 const socialImage = config.api.renderSocialImage(pageId) const socialDescription = getPageDescription(block, recordMap) ?? config.description let comments: React.ReactNode = null let pageAside: React.ReactChild = null // only display comments and page actions on blog post pages if (isBlogPost) { if (config.utterancesGitHubRepo) { comments = ( ) } const tweet = getPageTweet(block, recordMap) if (tweet) { pageAside = } } return ( <> {config.twitter && ( )} {socialDescription && ( <> )} {socialImage ? ( <> ) : ( )} {canonicalPageUrl && ( <> )} {title} {isLiteMode && } ( ) }} recordMap={recordMap} rootPageId={site.rootNotionPageId} fullPage={!isLiteMode} darkMode={isDarkMode} previewImages={site.previewImages !== false} showCollectionViewDropdown={false} showTableOfContents={showTableOfContents} minTableOfContentsItems={minTableOfContentsItems} defaultPageIcon={config.defaultPageIcon} defaultPageCover={config.defaultPageCover} defaultPageCoverPosition={config.defaultPageCoverPosition} mapPageUrl={siteMapPageUrl} mapImageUrl={mapNotionImageUrl} searchNotion={searchNotion} pageFooter={comments} pageAside={pageAside} footer={