mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-24 23:16:52 +00:00
升级react-notion-x,封装NotionPage
This commit is contained in:
@@ -1,25 +1,7 @@
|
||||
import { getPageTableOfContents } from 'notion-utils'
|
||||
import 'prismjs'
|
||||
import 'prismjs/components/prism-bash'
|
||||
import 'prismjs/components/prism-javascript'
|
||||
import 'prismjs/components/prism-markup'
|
||||
import 'prismjs/components/prism-python'
|
||||
import 'prismjs/components/prism-typescript'
|
||||
import {
|
||||
Code,
|
||||
Collection,
|
||||
CollectionRow,
|
||||
Equation,
|
||||
NotionRenderer
|
||||
} from 'react-notion-x'
|
||||
import LayoutBase from './LayoutBase'
|
||||
import { useRef, useEffect } from 'react'
|
||||
import { ArticleLock } from './components/ArticleLock'
|
||||
import mediumZoom from 'medium-zoom'
|
||||
|
||||
const mapPageUrl = id => {
|
||||
return 'https://www.notion.so/' + id.replace(/-/g, '')
|
||||
}
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
|
||||
export const LayoutSlug = props => {
|
||||
const { post, lock, validPassword } = props
|
||||
@@ -28,24 +10,6 @@ export const LayoutSlug = props => {
|
||||
post.toc = getPageTableOfContents(post, post.blockMap)
|
||||
}
|
||||
|
||||
const zoom =
|
||||
typeof window !== 'undefined' &&
|
||||
mediumZoom({
|
||||
container: '.notion-viewport',
|
||||
background: 'rgba(0, 0, 0, 0.2)',
|
||||
margin: getMediumZoomMargin()
|
||||
})
|
||||
const zoomRef = useRef(zoom ? zoom.clone() : null)
|
||||
useEffect(() => {
|
||||
// 将所有container下的所有图片添加medium-zoom
|
||||
const container = document.getElementById('notion-article')
|
||||
const imgList = container?.getElementsByTagName('img')
|
||||
if (imgList && zoomRef.current) {
|
||||
for (let i = 0; i < imgList.length; i++) {
|
||||
zoomRef.current.attach(imgList[i])
|
||||
}
|
||||
}
|
||||
})
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
<div>
|
||||
@@ -54,39 +18,10 @@ export const LayoutSlug = props => {
|
||||
{lock && <ArticleLock password={post.password} validPassword={validPassword} />}
|
||||
|
||||
{!lock && <section id="notion-article" className="px-1">
|
||||
{post.blockMap && (
|
||||
<NotionRenderer
|
||||
recordMap={post.blockMap}
|
||||
mapPageUrl={mapPageUrl}
|
||||
components={{
|
||||
equation: Equation,
|
||||
code: Code,
|
||||
collectionRow: CollectionRow,
|
||||
collection: Collection
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</section>}
|
||||
{post.blockMap && <NotionPage post={post} />}
|
||||
</section>}
|
||||
|
||||
</div>
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
function getMediumZoomMargin () {
|
||||
const width = window.innerWidth
|
||||
|
||||
if (width < 500) {
|
||||
return 8
|
||||
} else if (width < 800) {
|
||||
return 20
|
||||
} else if (width < 1280) {
|
||||
return 30
|
||||
} else if (width < 1600) {
|
||||
return 40
|
||||
} else if (width < 1920) {
|
||||
return 48
|
||||
} else {
|
||||
return 72
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
import Comment from '@/components/Comment'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
import formatDate from '@/lib/formatDate'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import mediumZoom from 'medium-zoom'
|
||||
import Link from 'next/link'
|
||||
import 'prismjs'
|
||||
import 'prismjs/components/prism-bash'
|
||||
import 'prismjs/components/prism-javascript'
|
||||
import 'prismjs/components/prism-markup'
|
||||
import 'prismjs/components/prism-python'
|
||||
import 'prismjs/components/prism-typescript'
|
||||
import { useEffect, useRef } from 'react'
|
||||
import { Code, Collection, CollectionRow, Equation, NotionRenderer } from 'react-notion-x'
|
||||
import ArticleAround from './ArticleAround'
|
||||
|
||||
/**
|
||||
@@ -18,34 +10,15 @@ import ArticleAround from './ArticleAround'
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
export default function ArticleDetail ({ post, recommendPosts, prev, next }) {
|
||||
export default function ArticleDetail({ post, recommendPosts, prev, next }) {
|
||||
const { locale } = useGlobal()
|
||||
const date = formatDate(post?.date?.start_date || post.createdTime, locale.LOCALE)
|
||||
|
||||
const zoom = typeof window !== 'undefined' && mediumZoom({
|
||||
container: '.notion-viewport',
|
||||
background: 'rgba(0, 0, 0, 0.2)',
|
||||
margin: getMediumZoomMargin()
|
||||
})
|
||||
const zoomRef = useRef(zoom ? zoom.clone() : null)
|
||||
|
||||
useEffect(() => {
|
||||
// 将所有container下的所有图片添加medium-zoom
|
||||
const container = document.getElementById('container')
|
||||
const imgList = container.getElementsByTagName('img')
|
||||
if (imgList && zoomRef.current) {
|
||||
for (let i = 0; i < imgList.length; i++) {
|
||||
(zoomRef.current).attach(imgList[i])
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return (<div id="container" className="max-w-5xl overflow-x-auto flex-grow mx-auto w-screen md:w-full ">
|
||||
{post.type && !post.type.includes('Page') && post?.page_cover && (
|
||||
<div className="w-full relative md:flex-shrink-0 overflow-hidden">
|
||||
<div className="w-full relative md:flex-shrink-0 overflow-hidden">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img alt={post.title} src={post?.page_cover} className='object-center w-full' />
|
||||
</div>
|
||||
<img alt={post.title} src={post?.page_cover} className='object-center w-full' />
|
||||
</div>
|
||||
)}
|
||||
<article itemScope itemType="https://schema.org/Movie"
|
||||
className="subpixel-antialiased py-10 px-5 lg:pt-24 md:px-32 dark:border-gray-700 bg-white dark:bg-gray-800"
|
||||
@@ -53,59 +26,48 @@ export default function ArticleDetail ({ post, recommendPosts, prev, next }) {
|
||||
|
||||
<header className='animate__slideInDown animate__animated'>
|
||||
|
||||
{/* 文章Title */}
|
||||
<div className="font-bold text-3xl text-black dark:text-white font-serif pt-10">
|
||||
{post.title}
|
||||
</div>
|
||||
{/* 文章Title */}
|
||||
<div className="font-bold text-3xl text-black dark:text-white font-serif pt-10">
|
||||
{post.title}
|
||||
</div>
|
||||
|
||||
<section className="flex-wrap flex mt-2 text-gray-400 dark:text-gray-400 font-light leading-8">
|
||||
<div>
|
||||
<Link href={`/category/${post.category}`} passHref>
|
||||
<a className="cursor-pointer text-md mr-2 hover:text-black dark:hover:text-white border-b dark:border-gray-500 border-dashed">
|
||||
<i className="mr-1 fas fa-folder-open" />
|
||||
{post.category}
|
||||
<section className="flex-wrap flex mt-2 text-gray-400 dark:text-gray-400 font-light leading-8">
|
||||
<div>
|
||||
<Link href={`/category/${post.category}`} passHref>
|
||||
<a className="cursor-pointer text-md mr-2 hover:text-black dark:hover:text-white border-b dark:border-gray-500 border-dashed">
|
||||
<i className="mr-1 fas fa-folder-open" />
|
||||
{post.category}
|
||||
</a>
|
||||
</Link>
|
||||
<span className='mr-2'>|</span>
|
||||
|
||||
{post.type[0] !== 'Page' && (<>
|
||||
<Link
|
||||
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
||||
passHref
|
||||
>
|
||||
<a className="pl-1 mr-2 cursor-pointer hover:text-gray-700 dark:hover:text-gray-200 border-b dark:border-gray-500 border-dashed">
|
||||
{date}
|
||||
</a>
|
||||
</Link>
|
||||
<span className='mr-2'>|</span>
|
||||
</>)}
|
||||
|
||||
{post.type[0] !== 'Page' && (<>
|
||||
<Link
|
||||
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
||||
passHref
|
||||
>
|
||||
<a className="pl-1 mr-2 cursor-pointer hover:text-gray-700 dark:hover:text-gray-200 border-b dark:border-gray-500 border-dashed">
|
||||
{date}
|
||||
</a>
|
||||
</Link>
|
||||
<span className='mr-2'>|</span>
|
||||
</>)}
|
||||
|
||||
<div className="hidden busuanzi_container_page_pv font-light mr-2">
|
||||
<i className='mr-1 fas fa-eye'/>
|
||||
|
||||
<span className="mr-2 busuanzi_value_page_pv"/>
|
||||
<span className='mr-2'>|</span>
|
||||
</div>
|
||||
<div className="hidden busuanzi_container_page_pv font-light mr-2">
|
||||
<i className='mr-1 fas fa-eye' />
|
||||
|
||||
<span className="mr-2 busuanzi_value_page_pv" />
|
||||
<span className='mr-2'>|</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
</header>
|
||||
|
||||
{/* Notion文章主体 */}
|
||||
<section id='notion-article' className='px-1'>
|
||||
{post.blockMap && (
|
||||
<NotionRenderer
|
||||
recordMap={post.blockMap}
|
||||
mapPageUrl={mapPageUrl}
|
||||
components={{
|
||||
equation: Equation,
|
||||
code: Code,
|
||||
collectionRow: CollectionRow,
|
||||
collection: Collection
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{post.blockMap && <NotionPage post={post} />}
|
||||
</section>
|
||||
|
||||
<section className="px-1 py-2 my-1 text-sm font-light overflow-auto text-gray-600 dark:text-gray-400">
|
||||
@@ -116,38 +78,16 @@ export default function ArticleDetail ({ post, recommendPosts, prev, next }) {
|
||||
data-ad-layout="in-article"
|
||||
data-ad-format="fluid"
|
||||
data-ad-client="ca-pub-2708419466378217"
|
||||
data-ad-slot="3806269138"/>
|
||||
data-ad-slot="3806269138" />
|
||||
</section>
|
||||
|
||||
</article>
|
||||
|
||||
<ArticleAround prev={prev} next={next}/>
|
||||
<ArticleAround prev={prev} next={next} />
|
||||
|
||||
{/* 评论互动 */}
|
||||
<div className="duration-200 shadow px-12 w-screen md:w-full overflow-x-auto dark:border-gray-700 bg-white dark:bg-gray-800">
|
||||
<Comment frontMatter={post} />
|
||||
<Comment frontMatter={post} />
|
||||
</div>
|
||||
</div>)
|
||||
}
|
||||
|
||||
const mapPageUrl = id => {
|
||||
return 'https://www.notion.so/' + id.replace(/-/g, '')
|
||||
}
|
||||
|
||||
function getMediumZoomMargin () {
|
||||
const width = window.innerWidth
|
||||
|
||||
if (width < 500) {
|
||||
return 8
|
||||
} else if (width < 800) {
|
||||
return 20
|
||||
} else if (width < 1280) {
|
||||
return 30
|
||||
} else if (width < 1600) {
|
||||
return 40
|
||||
} else if (width < 1920) {
|
||||
return 48
|
||||
} else {
|
||||
return 72
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
import { getPageTableOfContents } from 'notion-utils'
|
||||
import 'prismjs'
|
||||
import 'prismjs/components/prism-bash'
|
||||
import 'prismjs/components/prism-java'
|
||||
import 'prismjs/components/prism-javascript'
|
||||
import 'prismjs/components/prism-markup'
|
||||
import 'prismjs/components/prism-python'
|
||||
import 'prismjs/components/prism-typescript'
|
||||
import { useRef } from 'react'
|
||||
import ArticleDetail from './components/ArticleDetail'
|
||||
import { ArticleLock } from './components/ArticleLock'
|
||||
import HeaderArticle from './components/HeaderArticle'
|
||||
import JumpToCommentButton from './components/JumpToCommentButton'
|
||||
import TocDrawer from './components/TocDrawer'
|
||||
import TocDrawerButton from './components/TocDrawerButton'
|
||||
import LayoutBase from './LayoutBase'
|
||||
import Comment from '@/components/Comment'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
import ArticleAdjacent from './components/ArticleAdjacent'
|
||||
import ArticleCopyright from './components/ArticleCopyright'
|
||||
import ArticleRecommend from './components/ArticleRecommend'
|
||||
|
||||
export const LayoutSlug = props => {
|
||||
const { post, lock, validPassword } = props
|
||||
@@ -27,27 +24,58 @@ export const LayoutSlug = props => {
|
||||
const targetRef = typeof window !== 'undefined' ? document.getElementById('container') : null
|
||||
|
||||
const floatSlot = <>
|
||||
{post?.toc?.length > 1 && <div className="block lg:hidden">
|
||||
<TocDrawerButton
|
||||
onClick={() => {
|
||||
drawerRight?.current?.handleSwitchVisible()
|
||||
}}
|
||||
/>
|
||||
</div>}
|
||||
<JumpToCommentButton/>
|
||||
</>
|
||||
{post?.toc?.length > 1 && <div className="block lg:hidden">
|
||||
<TocDrawerButton
|
||||
onClick={() => {
|
||||
drawerRight?.current?.handleSwitchVisible()
|
||||
}}
|
||||
/>
|
||||
</div>}
|
||||
<JumpToCommentButton />
|
||||
</>
|
||||
|
||||
return (
|
||||
<LayoutBase
|
||||
headerSlot={<HeaderArticle {...props}/>}
|
||||
headerSlot={<HeaderArticle {...props} />}
|
||||
{...props}
|
||||
showCategory={false}
|
||||
showTag={false}
|
||||
floatSlot={floatSlot}
|
||||
>
|
||||
<div className="w-full lg:shadow-sm lg:hover:shadow lg:border lg:rounded-xl lg:px-2 lg:py-4 bg-white dark:bg-hexo-black-gray dark:border-black">
|
||||
{!lock && <ArticleDetail {...props} />}
|
||||
{lock && <ArticleLock password={post.password} validPassword={validPassword} />}
|
||||
|
||||
{!lock && <div id="container" className="max-w-5xl overflow-x-auto flex-grow mx-auto md:w-full md:px-5 ">
|
||||
|
||||
<article itemScope itemType="https://schema.org/Movie" className="subpixel-antialiased" >
|
||||
{/* Notion文章主体 */}
|
||||
<section id='notion-article' className='px-5'>
|
||||
{post.blockMap && <NotionPage post={post} />}
|
||||
</section>
|
||||
|
||||
<section className="px-1 py-2 my-1 text-sm font-light overflow-auto text-gray-600 dark:text-gray-400">
|
||||
{/* 文章内嵌广告 */}
|
||||
<ins className="adsbygoogle"
|
||||
style={{ display: 'block', textAlign: 'center' }}
|
||||
data-adtest="on"
|
||||
data-ad-layout="in-article"
|
||||
data-ad-format="fluid"
|
||||
data-ad-client="ca-pub-2708419466378217"
|
||||
data-ad-slot="3806269138" />
|
||||
</section>
|
||||
|
||||
<ArticleCopyright {...props} />
|
||||
<ArticleRecommend {...props} />
|
||||
<ArticleAdjacent {...props} />
|
||||
</article>
|
||||
|
||||
<hr className='border-dashed' />
|
||||
|
||||
{/* 评论互动 */}
|
||||
<div className="duration-200 overflow-x-auto bg-white dark:bg-hexo-black-gray px-3">
|
||||
<Comment frontMatter={post} />
|
||||
</div>
|
||||
</div>}
|
||||
</div>
|
||||
|
||||
<div className='block lg:hidden'>
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
import Comment from '@/components/Comment'
|
||||
import mediumZoom from 'medium-zoom'
|
||||
import 'prismjs'
|
||||
import 'prismjs/components/prism-bash'
|
||||
import 'prismjs/components/prism-javascript'
|
||||
import 'prismjs/components/prism-markup'
|
||||
import 'prismjs/components/prism-python'
|
||||
import 'prismjs/components/prism-typescript'
|
||||
import { useEffect, useRef } from 'react'
|
||||
import { Code, Collection, CollectionRow, Equation, NotionRenderer } from 'react-notion-x'
|
||||
import ArticleAdjacent from './ArticleAdjacent'
|
||||
import ArticleCopyright from './ArticleCopyright'
|
||||
import ArticleRecommend from './ArticleRecommend'
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
export default function ArticleDetail (props) {
|
||||
const { post } = props
|
||||
const zoom = typeof window !== 'undefined' && mediumZoom({
|
||||
container: '.notion-viewport',
|
||||
background: 'rgba(0, 0, 0, 0.2)',
|
||||
margin: getMediumZoomMargin()
|
||||
})
|
||||
const zoomRef = useRef(zoom ? zoom.clone() : null)
|
||||
|
||||
useEffect(() => {
|
||||
// 将所有container下的所有图片添加medium-zoom
|
||||
const container = document?.getElementById('container')
|
||||
const imgList = container?.getElementsByTagName('img')
|
||||
if (imgList && zoomRef.current) {
|
||||
for (let i = 0; i < imgList.length; i++) {
|
||||
(zoomRef.current).attach(imgList[i])
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return (<div id="container" className="max-w-5xl overflow-x-auto flex-grow mx-auto md:w-full md:px-5 ">
|
||||
<article itemScope itemType="https://schema.org/Movie" className="subpixel-antialiased" >
|
||||
|
||||
{/* Notion文章主体 */}
|
||||
<section id='notion-article' className='px-5'>
|
||||
{post.blockMap && (
|
||||
<NotionRenderer
|
||||
recordMap={post.blockMap}
|
||||
mapPageUrl={mapPageUrl}
|
||||
components={{
|
||||
equation: Equation,
|
||||
code: Code,
|
||||
collectionRow: CollectionRow,
|
||||
collection: Collection
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</section>
|
||||
|
||||
<section className="px-1 py-2 my-1 text-sm font-light overflow-auto text-gray-600 dark:text-gray-400">
|
||||
{/* 文章内嵌广告 */}
|
||||
<ins className="adsbygoogle"
|
||||
style={{ display: 'block', textAlign: 'center' }}
|
||||
data-adtest="on"
|
||||
data-ad-layout="in-article"
|
||||
data-ad-format="fluid"
|
||||
data-ad-client="ca-pub-2708419466378217"
|
||||
data-ad-slot="3806269138"/>
|
||||
</section>
|
||||
|
||||
<ArticleCopyright {...props}/>
|
||||
<ArticleRecommend {...props}/>
|
||||
<ArticleAdjacent {...props}/>
|
||||
|
||||
</article>
|
||||
|
||||
<hr className='border-dashed'/>
|
||||
|
||||
{/* 评论互动 */}
|
||||
<div className="duration-200 overflow-x-auto bg-white dark:bg-hexo-black-gray px-3">
|
||||
<Comment frontMatter={post} />
|
||||
</div>
|
||||
</div>)
|
||||
}
|
||||
|
||||
const mapPageUrl = id => {
|
||||
return 'https://www.notion.so/' + id.replace(/-/g, '')
|
||||
}
|
||||
|
||||
function getMediumZoomMargin () {
|
||||
const width = window.innerWidth
|
||||
|
||||
if (width < 500) {
|
||||
return 8
|
||||
} else if (width < 800) {
|
||||
return 20
|
||||
} else if (width < 1280) {
|
||||
return 30
|
||||
} else if (width < 1600) {
|
||||
return 40
|
||||
} else if (width < 1920) {
|
||||
return 48
|
||||
} else {
|
||||
return 72
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,9 @@
|
||||
import BLOG from '@/blog.config'
|
||||
import Link from 'next/link'
|
||||
import React from 'react'
|
||||
import {
|
||||
Code,
|
||||
Collection,
|
||||
CollectionRow,
|
||||
Equation,
|
||||
NotionRenderer
|
||||
} from 'react-notion-x'
|
||||
import TagItemMini from './TagItemMini'
|
||||
import CONFIG_HEXO from '../config_hexo'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
|
||||
const BlogPostCard = ({ post, showSummary }) => {
|
||||
const showPreview = CONFIG_HEXO.POST_LIST_PREVIEW && post.blockMap
|
||||
@@ -22,18 +16,16 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
<div className="lg:p-8 p-4 flex flex-col w-full">
|
||||
<Link href={`${BLOG.SUB_PATH}/article/${post.slug}`} passHref>
|
||||
<a
|
||||
className={`replace cursor-pointer hover:underline text-2xl font-sans ${
|
||||
showPreview ? 'text-center' : ''
|
||||
} leading-tight text-gray-700 dark:text-gray-100 hover:text-indigo-700 dark:hover:text-indigo-400`}
|
||||
className={`replace cursor-pointer hover:underline text-2xl font-sans ${showPreview ? 'text-center' : ''
|
||||
} leading-tight text-gray-700 dark:text-gray-100 hover:text-indigo-700 dark:hover:text-indigo-400`}
|
||||
>
|
||||
{post.title}
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
<div
|
||||
className={`flex mt-2 items-center ${
|
||||
showPreview ? 'justify-center' : 'justify-start'
|
||||
} flex-wrap dark:text-gray-500 text-gray-400 hover:text-indigo-700 dark:hover:text-indigo-400`}
|
||||
className={`flex mt-2 items-center ${showPreview ? 'justify-center' : 'justify-start'
|
||||
} flex-wrap dark:text-gray-500 text-gray-400 hover:text-indigo-700 dark:hover:text-indigo-400`}
|
||||
>
|
||||
<Link
|
||||
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
||||
@@ -54,17 +46,7 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
|
||||
{showPreview && (
|
||||
<div className="overflow-ellipsis truncate">
|
||||
<NotionRenderer
|
||||
bodyClassName="max-h-full"
|
||||
recordMap={post.blockMap}
|
||||
mapPageUrl={mapPageUrl}
|
||||
components={{
|
||||
equation: Equation,
|
||||
code: Code,
|
||||
collectionRow: CollectionRow,
|
||||
collection: Collection
|
||||
}}
|
||||
/>
|
||||
<NotionPage post={post} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -104,8 +86,4 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
)
|
||||
}
|
||||
|
||||
const mapPageUrl = id => {
|
||||
return 'https://www.notion.so/' + id.replace(/-/g, '')
|
||||
}
|
||||
|
||||
export default BlogPostCard
|
||||
|
||||
@@ -2,8 +2,7 @@ import { getPageTableOfContents } from 'notion-utils'
|
||||
|
||||
import LayoutBase from './LayoutBase'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import mediumZoom from 'medium-zoom'
|
||||
import React, { useEffect, useRef } from 'react'
|
||||
import React from 'react'
|
||||
import Catalog from './components/Catalog'
|
||||
import { ArticleDetail } from './components/ArticleDetail'
|
||||
import { ArticleLock } from './components/ArticleLock'
|
||||
@@ -17,26 +16,6 @@ export const LayoutSlug = props => {
|
||||
}
|
||||
const { locale } = useGlobal()
|
||||
|
||||
const zoom =
|
||||
typeof window !== 'undefined' &&
|
||||
mediumZoom({
|
||||
container: '.notion-viewport',
|
||||
background: 'rgba(0, 0, 0, 0.2)',
|
||||
margin: getMediumZoomMargin()
|
||||
})
|
||||
const zoomRef = useRef(zoom ? zoom.clone() : null)
|
||||
|
||||
useEffect(() => {
|
||||
// 将所有container下的所有图片添加medium-zoom
|
||||
const container = document.getElementById('notion-article')
|
||||
const imgList = container?.getElementsByTagName('img')
|
||||
if (imgList && zoomRef.current) {
|
||||
for (let i = 0; i < imgList.length; i++) {
|
||||
zoomRef.current.attach(imgList[i])
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const slotRight = post?.toc && post?.toc?.length > 3 && (
|
||||
<div key={locale.COMMON.TABLE_OF_CONTENTS} >
|
||||
<Catalog toc={post.toc} />
|
||||
@@ -50,27 +29,9 @@ export const LayoutSlug = props => {
|
||||
slotRight={slotRight}
|
||||
>
|
||||
|
||||
{!lock && <ArticleDetail {...props} />}
|
||||
{!lock && <ArticleDetail {...props} />}
|
||||
|
||||
{lock && <ArticleLock password={post.password} validPassword={validPassword} />}
|
||||
{lock && <ArticleLock password={post.password} validPassword={validPassword} />}
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
function getMediumZoomMargin () {
|
||||
const width = window.innerWidth
|
||||
|
||||
if (width < 500) {
|
||||
return 8
|
||||
} else if (width < 800) {
|
||||
return 20
|
||||
} else if (width < 1280) {
|
||||
return 30
|
||||
} else if (width < 1600) {
|
||||
return 40
|
||||
} else if (width < 1920) {
|
||||
return 48
|
||||
} else {
|
||||
return 72
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
import {
|
||||
Code,
|
||||
Collection,
|
||||
CollectionRow,
|
||||
Equation,
|
||||
NotionRenderer
|
||||
} from 'react-notion-x'
|
||||
import Comment from '@/components/Comment'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
@@ -14,18 +7,8 @@ import TagItemMini from './TagItemMini'
|
||||
import CONFIG_MEDIUM from '../config_medium'
|
||||
import formatDate from '@/lib/formatDate'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
|
||||
import 'prismjs'
|
||||
import 'prismjs/components/prism-bash'
|
||||
import 'prismjs/components/prism-javascript'
|
||||
import 'prismjs/components/prism-markup'
|
||||
import 'prismjs/components/prism-python'
|
||||
import 'prismjs/components/prism-typescript'
|
||||
import BLOG from '@/blog.config'
|
||||
|
||||
const mapPageUrl = id => {
|
||||
return 'https://www.notion.so/' + id.replace(/-/g, '')
|
||||
}
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
|
||||
export const ArticleDetail = props => {
|
||||
const { post, prev, next } = props
|
||||
@@ -62,18 +45,7 @@ export const ArticleDetail = props => {
|
||||
</section>
|
||||
{/* Notion文章主体 */}
|
||||
<section id="notion-article" className="px-1 max-w-5xl">
|
||||
{post.blockMap && (
|
||||
<NotionRenderer
|
||||
recordMap={post.blockMap}
|
||||
mapPageUrl={mapPageUrl}
|
||||
components={{
|
||||
equation: Equation,
|
||||
code: Code,
|
||||
collectionRow: CollectionRow,
|
||||
collection: Collection
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{post.blockMap && (<NotionPage post={post} />)}
|
||||
</section>
|
||||
|
||||
<section className="px-1 py-2 my-1 text-sm font-light overflow-auto text-gray-600 dark:text-gray-400">
|
||||
@@ -90,10 +62,10 @@ export const ArticleDetail = props => {
|
||||
</section>
|
||||
<section>
|
||||
<div className='flex justify-between'>
|
||||
{ CONFIG_MEDIUM.POST_DETAIL_CATEGORY && post.category && <CategoryItem category={post.category}/>}
|
||||
<div>
|
||||
{ CONFIG_MEDIUM.POST_DETAIL_TAG && post?.tagItems?.map(tag => <TagItemMini key={tag.name} tag={tag} />)}
|
||||
</div>
|
||||
{CONFIG_MEDIUM.POST_DETAIL_CATEGORY && post.category && <CategoryItem category={post.category} />}
|
||||
<div>
|
||||
{CONFIG_MEDIUM.POST_DETAIL_TAG && post?.tagItems?.map(tag => <TagItemMini key={tag.name} tag={tag} />)}
|
||||
</div>
|
||||
</div>
|
||||
<ArticleAround prev={prev} next={next} />
|
||||
<Comment frontMatter={post} />
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import BLOG from '@/blog.config'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import Link from 'next/link'
|
||||
import React from 'react'
|
||||
import { Code, Collection, Equation, NotionRenderer } from 'react-notion-x'
|
||||
import CONFIG_MEDIUM from '../config_medium'
|
||||
import CategoryItem from './CategoryItem'
|
||||
import TagItemMini from './TagItemMini'
|
||||
@@ -51,16 +51,7 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
|
||||
{showPreview && (
|
||||
<div className="overflow-ellipsis truncate">
|
||||
<NotionRenderer
|
||||
bodyClassName="max-h-full"
|
||||
recordMap={post.blockMap}
|
||||
mapPageUrl={mapPageUrl}
|
||||
components={{
|
||||
equation: Equation,
|
||||
code: Code,
|
||||
collection: Collection
|
||||
}}
|
||||
/>
|
||||
<NotionPage post={post} />
|
||||
<div className="pointer-events-none border-t pt-8 border-dashed">
|
||||
<div className="w-full justify-start flex">
|
||||
<Link href={`${BLOG.SUB_PATH}/article/${post.slug}`} passHref>
|
||||
@@ -78,8 +69,4 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
)
|
||||
}
|
||||
|
||||
const mapPageUrl = id => {
|
||||
return 'https://www.notion.so/' + id.replace(/-/g, '')
|
||||
}
|
||||
|
||||
export default BlogPostCard
|
||||
|
||||
@@ -6,50 +6,23 @@ import ShareBar from './ShareBar'
|
||||
import TagItem from './TagItem'
|
||||
import formatDate from '@/lib/formatDate'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import mediumZoom from 'medium-zoom'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import 'prismjs'
|
||||
import 'prismjs/components/prism-bash'
|
||||
import 'prismjs/components/prism-c'
|
||||
import 'prismjs/components/prism-java'
|
||||
import 'prismjs/components/prism-markup'
|
||||
import 'prismjs/components/prism-python'
|
||||
import 'prismjs/components/prism-typescript'
|
||||
import { useEffect, useRef } from 'react'
|
||||
import { Code, Collection, CollectionRow, Equation, NotionRenderer } from 'react-notion-x'
|
||||
import ArticleCopyright from './ArticleCopyright'
|
||||
import WordCount from './WordCount'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
export default function ArticleDetail (props) {
|
||||
export default function ArticleDetail(props) {
|
||||
const { post, recommendPosts, prev, next, showArticleInfo } = props
|
||||
const url = BLOG.LINK + useRouter().asPath
|
||||
const { locale } = useGlobal()
|
||||
const date = formatDate(post?.date?.start_date || post.createdTime, locale.LOCALE)
|
||||
|
||||
const zoom = typeof window !== 'undefined' && mediumZoom({
|
||||
container: '.notion-viewport',
|
||||
background: 'rgba(0, 0, 0, 0.2)',
|
||||
margin: getMediumZoomMargin()
|
||||
})
|
||||
const zoomRef = useRef(zoom ? zoom.clone() : null)
|
||||
|
||||
useEffect(() => {
|
||||
// 将所有container下的所有图片添加medium-zoom
|
||||
const container = document.getElementById('container')
|
||||
const imgList = container.getElementsByTagName('img')
|
||||
if (imgList && zoomRef.current) {
|
||||
for (let i = 0; i < imgList.length; i++) {
|
||||
(zoomRef.current).attach(imgList[i])
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return (<div id="container" className="shadow md:hover:shadow-2xl overflow-x-auto flex-grow mx-auto w-screen md:w-full ">
|
||||
<div itemScope itemType="https://schema.org/Movie"
|
||||
className="subpixel-antialiased py-10 px-5 lg:pt-24 md:px-24 dark:border-gray-700 bg-white dark:bg-gray-800"
|
||||
@@ -57,68 +30,57 @@ export default function ArticleDetail (props) {
|
||||
|
||||
{showArticleInfo && <header className='animate__slideInDown animate__animated'>
|
||||
{post.type && !post.type.includes('Page') && post?.page_cover && (
|
||||
<div className="w-full relative md:flex-shrink-0 overflow-hidden">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img alt={post.title} src={post?.page_cover} className='object-center w-full' />
|
||||
</div>
|
||||
<div className="w-full relative md:flex-shrink-0 overflow-hidden">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img alt={post.title} src={post?.page_cover} className='object-center w-full' />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 文章Title */}
|
||||
<div className="font-bold text-3xl text-black dark:text-white font-serif pt-10">
|
||||
{post.title}
|
||||
</div>
|
||||
{/* 文章Title */}
|
||||
<div className="font-bold text-3xl text-black dark:text-white font-serif pt-10">
|
||||
{post.title}
|
||||
</div>
|
||||
|
||||
<section className="flex-wrap flex mt-2 text-gray-400 dark:text-gray-400 font-light leading-8">
|
||||
<div>
|
||||
{post.category && <>
|
||||
<Link href={`/category/${post.category}`} passHref>
|
||||
<section className="flex-wrap flex mt-2 text-gray-400 dark:text-gray-400 font-light leading-8">
|
||||
<div>
|
||||
{post.category && <>
|
||||
<Link href={`/category/${post.category}`} passHref>
|
||||
<a className="cursor-pointer text-md mr-2 hover:text-black dark:hover:text-white border-b dark:border-gray-500 border-dashed">
|
||||
<i className="mr-1 far fa-folder-open" /> {post.category}
|
||||
</a>
|
||||
</Link>
|
||||
<span className='mr-2'>|</span>
|
||||
</>}
|
||||
{post.type[0] !== 'Page' && (<>
|
||||
<Link
|
||||
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
||||
passHref
|
||||
>
|
||||
<a className="pl-1 mr-2 cursor-pointer hover:text-gray-700 dark:hover:text-gray-200 border-b dark:border-gray-500 border-dashed">
|
||||
{date}
|
||||
</a>
|
||||
</Link>
|
||||
<span className='mr-2'>|</span>
|
||||
</>)}
|
||||
</>}
|
||||
{post.type[0] !== 'Page' && (<>
|
||||
<Link
|
||||
href={`/archive#${post?.date?.start_date?.substr(0, 7)}`}
|
||||
passHref
|
||||
>
|
||||
<a className="pl-1 mr-2 cursor-pointer hover:text-gray-700 dark:hover:text-gray-200 border-b dark:border-gray-500 border-dashed">
|
||||
{date}
|
||||
</a>
|
||||
</Link>
|
||||
<span className='mr-2'>|</span>
|
||||
</>)}
|
||||
|
||||
<div className="hidden busuanzi_container_page_pv font-light mr-2">
|
||||
<i className='mr-1 fas fa-eye'/>
|
||||
|
||||
<span className="mr-2 busuanzi_value_page_pv"/>
|
||||
<span className='mr-2'>|</span>
|
||||
</div>
|
||||
<div className="hidden busuanzi_container_page_pv font-light mr-2">
|
||||
<i className='mr-1 fas fa-eye' />
|
||||
|
||||
<span className="mr-2 busuanzi_value_page_pv" />
|
||||
<span className='mr-2'>|</span>
|
||||
</div>
|
||||
<div className='flex flex-nowrap whitespace-nowrap items-center font-light text-md'>
|
||||
<WordCount/>
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex flex-nowrap whitespace-nowrap items-center font-light text-md'>
|
||||
<WordCount />
|
||||
</div>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
</header>}
|
||||
|
||||
{/* Notion内容主体 */}
|
||||
<article id='notion-article' className='px-1'>
|
||||
{post.blockMap && (
|
||||
<NotionRenderer
|
||||
recordMap={post.blockMap}
|
||||
mapPageUrl={mapPageUrl}
|
||||
components={{
|
||||
equation: Equation,
|
||||
code: Code,
|
||||
collectionRow: CollectionRow,
|
||||
collection: Collection
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{post.blockMap && (<NotionPage post={post} />)}
|
||||
</article>
|
||||
|
||||
<section className="px-1 py-2 my-1 text-sm font-light overflow-auto text-gray-600 dark:text-gray-400">
|
||||
@@ -129,34 +91,34 @@ export default function ArticleDetail (props) {
|
||||
data-ad-layout="in-article"
|
||||
data-ad-format="fluid"
|
||||
data-ad-client="ca-pub-2708419466378217"
|
||||
data-ad-slot="3806269138"/>
|
||||
data-ad-slot="3806269138" />
|
||||
</section>
|
||||
|
||||
{showArticleInfo && <>
|
||||
{/* 版权声明 */}
|
||||
<ArticleCopyright author={BLOG.AUTHOR} url={url} />
|
||||
{/* 版权声明 */}
|
||||
<ArticleCopyright author={BLOG.AUTHOR} url={url} />
|
||||
|
||||
{/* 推荐文章 */}
|
||||
<RecommendPosts currentPost={post} recommendPosts={recommendPosts} />
|
||||
{/* 推荐文章 */}
|
||||
<RecommendPosts currentPost={post} recommendPosts={recommendPosts} />
|
||||
|
||||
{/* 标签列表 */}
|
||||
<section className="md:flex md:justify-between">
|
||||
{post.tagItems && (
|
||||
<div className="flex flex-nowrap leading-8 p-1 py-4 overflow-x-auto">
|
||||
<div className="hidden md:block dark:text-gray-300 whitespace-nowrap">
|
||||
{locale.COMMON.TAGS}:
|
||||
{/* 标签列表 */}
|
||||
<section className="md:flex md:justify-between">
|
||||
{post.tagItems && (
|
||||
<div className="flex flex-nowrap leading-8 p-1 py-4 overflow-x-auto">
|
||||
<div className="hidden md:block dark:text-gray-300 whitespace-nowrap">
|
||||
{locale.COMMON.TAGS}:
|
||||
</div>
|
||||
{post.tagItems.map(tag => (
|
||||
<TagItem key={tag.name} tag={tag} />
|
||||
))}
|
||||
</div>
|
||||
{post.tagItems.map(tag => (
|
||||
<TagItem key={tag.name} tag={tag} />
|
||||
))}
|
||||
)}
|
||||
<div>
|
||||
<ShareBar post={post} />
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<ShareBar post={post} />
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<BlogAround prev={prev} next={next} />
|
||||
<BlogAround prev={prev} next={next} />
|
||||
</>}
|
||||
|
||||
{/* 评论互动 */}
|
||||
@@ -167,25 +129,3 @@ export default function ArticleDetail (props) {
|
||||
|
||||
</div>)
|
||||
}
|
||||
|
||||
const mapPageUrl = id => {
|
||||
return 'https://www.notion.so/' + id.replace(/-/g, '')
|
||||
}
|
||||
|
||||
function getMediumZoomMargin () {
|
||||
const width = window.innerWidth
|
||||
|
||||
if (width < 500) {
|
||||
return 8
|
||||
} else if (width < 800) {
|
||||
return 20
|
||||
} else if (width < 1280) {
|
||||
return 30
|
||||
} else if (width < 1600) {
|
||||
return 40
|
||||
} else if (width < 1920) {
|
||||
return 48
|
||||
} else {
|
||||
return 72
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,16 +3,10 @@ import { useGlobal } from '@/lib/global'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import React from 'react'
|
||||
import {
|
||||
Code,
|
||||
Collection,
|
||||
CollectionRow,
|
||||
Equation,
|
||||
NotionRenderer
|
||||
} from 'react-notion-x'
|
||||
import Card from './Card'
|
||||
import TagItemMini from './TagItemMini'
|
||||
import CONFIG_NEXT from '../config_next'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
|
||||
const BlogPostCard = ({ post, showSummary }) => {
|
||||
const { locale } = useGlobal()
|
||||
@@ -26,18 +20,16 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
<div className="lg:p-8 p-4 flex flex-col w-full">
|
||||
<Link href={`${BLOG.SUB_PATH}/article/${post.slug}`} passHref>
|
||||
<a
|
||||
className={`cursor-pointer font-bold hover:underline text-3xl ${
|
||||
showPreview ? 'text-center' : ''
|
||||
} leading-tight text-gray-700 dark:text-gray-100 hover:text-blue-500 dark:hover:text-blue-400`}
|
||||
className={`cursor-pointer font-bold hover:underline text-3xl ${showPreview ? 'text-center' : ''
|
||||
} leading-tight text-gray-700 dark:text-gray-100 hover:text-blue-500 dark:hover:text-blue-400`}
|
||||
>
|
||||
{post.title}
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
<div
|
||||
className={`flex mt-2 items-center ${
|
||||
showPreview ? 'justify-center' : 'justify-start'
|
||||
} flex-wrap dark:text-gray-500 text-gray-400 hover:text-blue-500 dark:hover:text-blue-400 `}
|
||||
className={`flex mt-2 items-center ${showPreview ? 'justify-center' : 'justify-start'
|
||||
} flex-wrap dark:text-gray-500 text-gray-400 hover:text-blue-500 dark:hover:text-blue-400 `}
|
||||
>
|
||||
<div>
|
||||
{post.category && (
|
||||
@@ -87,17 +79,7 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
|
||||
{showPreview && post?.blockMap && (
|
||||
<div className="overflow-ellipsis truncate">
|
||||
<NotionRenderer
|
||||
bodyClassName="max-h-full"
|
||||
recordMap={post.blockMap}
|
||||
mapPageUrl={mapPageUrl}
|
||||
components={{
|
||||
equation: Equation,
|
||||
code: Code,
|
||||
collectionRow: CollectionRow,
|
||||
collection: Collection
|
||||
}}
|
||||
/>
|
||||
<NotionPage post={post} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -130,8 +112,4 @@ const BlogPostCard = ({ post, showSummary }) => {
|
||||
)
|
||||
}
|
||||
|
||||
const mapPageUrl = id => {
|
||||
return 'https://www.notion.so/' + id.replace(/-/g, '')
|
||||
}
|
||||
|
||||
export default BlogPostCard
|
||||
|
||||
Reference in New Issue
Block a user