import * as React from 'react' import Head from 'next/head' import Link from 'next/link' 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 'use-dark-mode' import { PageBlock } from 'notion-types' import { Tweet, Twitter } from 'react-static-tweets' // core notion renderer import { NotionRenderer, Code, Collection, CollectionRow } 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 { PageSocial } from './PageSocial' import { GitHubShareButton } from './GitHubShareButton' import { ReactUtterances } from './ReactUtterances' import styles from './styles.module.css' // const Code = dynamic(() => // import('react-notion-x').then((notion) => notion.Code) // ) // // const Collection = dynamic(() => // import('react-notion-x').then((notion) => notion.Collection) // ) // // const CollectionRow = dynamic( // () => import('react-notion-x').then((notion) => notion.CollectionRow), // { // ssr: false // } // ) const Pdf = dynamic(() => import('react-notion-x').then((notion) => notion.Pdf)) const Equation = dynamic(() => import('react-notion-x').then((notion) => notion.Equation) ) // we're now using a much lighter-weight tweet renderer react-static-tweets // instead of the official iframe-based embed widget from twitter // const Tweet = dynamic(() => import('react-tweet-embed')) const Modal = dynamic( () => import('react-notion-x').then((notion) => notion.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 = mapNotionImageUrl( (block as PageBlock).format?.page_cover || config.defaultPageCover, block ) || 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 = } } else { pageAside = } return ( fetch(`/api/get-tweet-ast/${id}`).then((r) => r.json()) } }} > {config.twitter && ( )} {socialDescription && ( <> )} {socialImage ? ( <> ) : ( )} {canonicalPageUrl && ( <> )} {title} {isLiteMode && } ( ), code: Code, collection: Collection, collectionRow: CollectionRow, tweet: Tweet, modal: Modal, pdf: Pdf, equation: Equation }} recordMap={recordMap} rootPageId={site.rootNotionPageId} fullPage={!isLiteMode} darkMode={darkMode.value} 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={