import React from 'react' import Link from 'next/link' import Image from 'next/image' import dynamic from 'next/dynamic' import cs from 'classnames' import { useRouter } from 'next/router' import { useSearchParam } from 'react-use' import BodyClassName from 'react-body-classname' import useDarkMode from '@fisch0920/use-dark-mode' import { PageBlock } from 'notion-types' import { Tweet, TwitterContextProvider } from 'react-static-tweets' // core notion renderer import { NotionRenderer } from 'react-notion-x' // utils import { getBlockTitle, getPageProperty } from 'notion-utils' import { mapPageUrl, getCanonicalPageUrl } from 'lib/map-page-url' import { mapImageUrl } from 'lib/map-image-url' 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 { Loading } from './Loading' import { Page404 } from './Page404' import { PageHead } from './PageHead' import { PageActions } from './PageActions' import { Footer } from './Footer' import { PageSocial } from './PageSocial' import { NotionPageHeader } from './NotionPageHeader' import { GitHubShareButton } from './GitHubShareButton' import styles from './styles.module.css' // ----------------------------------------------------------------------------- // dynamic imports for optional components // ----------------------------------------------------------------------------- const Code = dynamic(() => import('react-notion-x/build/third-party/code').then((m) => m.Code) ) const Collection = dynamic(() => import('react-notion-x/build/third-party/collection').then( (m) => m.Collection ) ) const Equation = dynamic(() => import('react-notion-x/build/third-party/equation').then((m) => m.Equation) ) const Pdf = dynamic( () => import('react-notion-x/build/third-party/pdf').then((m) => m.Pdf), { ssr: false } ) const Modal = dynamic( () => import('react-notion-x/build/third-party/modal').then((m) => m.Modal), { ssr: false } ) export const NotionPage: React.FC = ({ site, recordMap, error, pageId }) => { const router = useRouter() const lite = useSearchParam('lite') const params: any = {} if (lite) params.lite = lite // lite mode is for oembed const isLiteMode = lite === 'true' const searchParams = new URLSearchParams(params) const darkMode = useDarkMode(false, { classNameDark: 'dark-mode' }) 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 to the window global for easy debugging const g = window as any g.pageId = pageId g.recordMap = recordMap g.block = block } const siteMapPageUrl = mapPageUrl(site, recordMap, searchParams) const canonicalPageUrl = !config.isDev && getCanonicalPageUrl(site, recordMap)(pageId) // const isRootPage = // parsePageId(block.id) === parsePageId(site.rootNotionPageId) const isBlogPost = block.type === 'page' && block.parent_table === 'collection' const showTableOfContents = !!isBlogPost const minTableOfContentsItems = 3 const socialImage = mapImageUrl( getPageProperty('Social Image', block, recordMap) || (block as PageBlock).format?.page_cover || config.defaultPageCover, block ) const socialDescription = getPageProperty('Description', block, recordMap) || config.description let pageAside: React.ReactNode = null // only display comments and page actions on blog post pages if (isBlogPost) { const tweet = getPageTweet(block, recordMap) if (tweet) { pageAside = } } else { pageAside = } return ( fetch(`/api/get-tweet-ast/${id}`).then((r) => r.json()) } }} > {isLiteMode && } } /> ) }