From 2ac6ff3fae78a7857de740a04256025029bcbd8f Mon Sep 17 00:00:00 2001 From: txs Date: Wed, 6 Apr 2022 04:26:19 +0800 Subject: [PATCH 1/7] Better SEO for Facebook Open Graph --- blog.config.js | 2 +- components/CommonHead.js | 7 ++++++- pages/article/[slug].js | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/blog.config.js b/blog.config.js index aec8fd3c..465f4925 100644 --- a/blog.config.js +++ b/blog.config.js @@ -9,7 +9,7 @@ const BLOG = { process.env.NOTION_PAGE_ID || '02ab3b8678004aa69e9e415905ef32a5', // Important page_id!!!Duplicate Template from https://www.notion.so/tanghh/02ab3b8678004aa69e9e415905ef32a5 NOTION_ACCESS_TOKEN: process.env.NOTION_ACCESS_TOKEN || '', // Useful if you prefer not to make your database public DEBUG: process.env.NEXT_PUBLIC_DEBUG || false, // 是否显示调试按钮 - + FACEBOOK_PAGE: 'https://www.facebook.com/tw.andys.pro', // Facebook Page 的連結 THEME: process.env.NEXT_PUBLIC_THEME || 'next', // 主题, 支持 ['next','hexo',"fukasawa','medium'] THEME_SWITCH: process.env.NEXT_PUBLIC_THEME_SWITCH || false, // 是否显示切换主题按钮 LANG: 'zh-CN', // e.g 'zh-CN','en-US' see /lib/lang.js for more. diff --git a/components/CommonHead.js b/components/CommonHead.js index aad15497..699226f2 100644 --- a/components/CommonHead.js +++ b/components/CommonHead.js @@ -12,6 +12,8 @@ const CommonHead = ({ meta, children }) => { const description = meta?.description || BLOG.DESCRIPTION const type = meta?.type || 'website' const keywords = meta?.tags || BLOG.KEYWORDS + const lang = BLOG.LANG.replace('-', '_') //Facebook OpenGraph 要 zh_CN 這樣的格式才抓得到語言 + const category = meta?.category || BLOG.KEYWORDS || '軟體科技' //section 主要是像是 category 這樣的分類,Facebook 用這個來抓連結的分類 return ( @@ -31,11 +33,12 @@ const CommonHead = ({ meta, children }) => { )} - + + @@ -50,6 +53,8 @@ const CommonHead = ({ meta, children }) => { content={meta.date || meta.createdTime} /> + + )} {children} diff --git a/pages/article/[slug].js b/pages/article/[slug].js index 9abf4b83..aba79897 100644 --- a/pages/article/[slug].js +++ b/pages/article/[slug].js @@ -63,6 +63,7 @@ const Slug = props => { type: 'article', slug: 'article/' + props.post.slug, image: props.post.page_cover, + category: props.post.category?.[0], tags: props.post.tags } From 44a87d193b5ed631a37746c372520811e2f6d528 Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Wed, 6 Apr 2022 09:27:23 +0800 Subject: [PATCH 2/7] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dbuild?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/CommonHead.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/CommonHead.js b/components/CommonHead.js index 699226f2..7f129995 100644 --- a/components/CommonHead.js +++ b/components/CommonHead.js @@ -12,8 +12,8 @@ const CommonHead = ({ meta, children }) => { const description = meta?.description || BLOG.DESCRIPTION const type = meta?.type || 'website' const keywords = meta?.tags || BLOG.KEYWORDS - const lang = BLOG.LANG.replace('-', '_') //Facebook OpenGraph 要 zh_CN 這樣的格式才抓得到語言 - const category = meta?.category || BLOG.KEYWORDS || '軟體科技' //section 主要是像是 category 這樣的分類,Facebook 用這個來抓連結的分類 + const lang = BLOG.LANG.replace('-', '_') // Facebook OpenGraph 要 zh_CN 這樣的格式才抓得到語言 + const category = meta?.category || BLOG.KEYWORDS || '軟體科技' // section 主要是像是 category 這樣的分類,Facebook 用這個來抓連結的分類 return ( From fdb1dcb62208e02f1472661eba12e19f1fd80f80 Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Wed, 6 Apr 2022 14:26:44 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E5=8D=87=E7=BA=A7react-notion-x=EF=BC=8C?= =?UTF-8?q?=E5=B0=81=E8=A3=85NotionPage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/NotionPage.js | 91 ++++++++++ lib/rss.js | 23 +-- package.json | 6 +- pages/_app.js | 23 +-- themes/example/LayoutSlug.js | 71 +------- themes/fukasawa/components/ArticleDetail.js | 136 +++++---------- themes/hexo/LayoutSlug.js | 66 +++++--- themes/hexo/components/ArticleDetail.js | 105 ------------ themes/hexo/components/BlogPostCard.js | 34 +--- themes/medium/LayoutSlug.js | 45 +---- themes/medium/components/ArticleDetail.js | 40 +---- themes/medium/components/BlogPostCard.js | 17 +- themes/next/components/ArticleDetail.js | 174 +++++++------------- themes/next/components/BlogPostCard.js | 34 +--- 14 files changed, 276 insertions(+), 589 deletions(-) create mode 100644 components/NotionPage.js delete mode 100644 themes/hexo/components/ArticleDetail.js diff --git a/components/NotionPage.js b/components/NotionPage.js new file mode 100644 index 00000000..c2fe6c3c --- /dev/null +++ b/components/NotionPage.js @@ -0,0 +1,91 @@ + +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 'prismjs/components/prism-java' + +import { NotionRenderer } from 'react-notion-x' +import mediumZoom from 'medium-zoom' +import { useEffect, useRef } from 'react' +import dynamic from 'next/dynamic' + +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 + } +) +const NotionPage = ({ post }) => { + 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 +} + +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 + } +} + +export default NotionPage diff --git a/lib/rss.js b/lib/rss.js index a2afe0d6..3d75d888 100644 --- a/lib/rss.js +++ b/lib/rss.js @@ -1,16 +1,8 @@ import { Feed } from 'feed' import BLOG from '@/blog.config' import ReactDOMServer from 'react-dom/server' -import { - NotionRenderer, - Equation, - Code, - Collection, - CollectionRow -} from 'react-notion-x' import { getPostBlocks } from './notion' - -const mapPageUrl = id => 'https://www.notion.so/' + id.replace(/-/g, '') +import NotionPage from '@/components/NotionPage' const createFeedContent = async post => { // 加密的文章内容只返回摘要 @@ -19,18 +11,7 @@ const createFeedContent = async post => { } const blockMap = await getPostBlocks(post.id, 'rss-content') if (blockMap) { - const content = ReactDOMServer.renderToString( - - ) + const content = ReactDOMServer.renderToString() const regexExp = /
.*?<\/svg>
.*?<\/div><\/div>
.*?<\/div><\/div><\/div><\/div>/g return content.replace(regexExp, '') diff --git a/package.json b/package.json index 5ac9819b..71e3aefb 100644 --- a/package.json +++ b/package.json @@ -32,15 +32,15 @@ "lodash.throttle": "^4.1.1", "memory-cache": "^0.2.0", "next": "^12.0.5", - "notion-client": "4.16.0", - "notion-utils": "4.16.0", + "notion-client": "6.5.0", + "notion-utils": "6.5.0", "preact": "^10.5.15", "qrcode.react": "^1.0.1", "react": "17.0.2", "react-cookies": "^0.1.1", "react-cusdis": "^2.1.3", "react-dom": "17.0.2", - "react-notion-x": "4.16.0", + "react-notion-x": "6.6.2", "smoothscroll-polyfill": "^0.4.4", "typed.js": "^2.0.12", "use-ackee": "^3.0.0" diff --git a/pages/_app.js b/pages/_app.js index 02ed2d14..3d815612 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -7,11 +7,12 @@ import 'react-notion-x/src/styles.css' import '@/styles/notion.css' // 重写部分样式 // used for collection views (optional) -import 'rc-dropdown/assets/index.css' +// import 'rc-dropdown/assets/index.css' // used for code syntax highlighting (optional) import 'prismjs/themes/prism-okaidia.css' // used for rendering equations (optional) -import 'katex/dist/katex.min.css' +import 'react-notion-x/build/third-party/equation.css' + import dynamic from 'next/dynamic' import { GlobalContextProvider } from '@/lib/global' import { DebugPanel } from '@/components/DebugPanel' @@ -25,15 +26,15 @@ const GoogleAdsense = dynamic(() => import('@/components/GoogleAdsense'), { ssr: const MyApp = ({ Component, pageProps }) => { return ( - {BLOG.THEME_SWITCH && } - {BLOG.DEBUG && } - {BLOG.ANALYTICS_ACKEE_TRACKER && } - {BLOG.ANALYTICS_GOOGLE_ID && } - {JSON.parse(BLOG.ANALYTICS_BUSUANZI_ENABLE) && } - {BLOG.ADSENSE_GOOGLE_ID && } - {/* FontawesomeCDN */} - - + {BLOG.THEME_SWITCH && } + {BLOG.DEBUG && } + {BLOG.ANALYTICS_ACKEE_TRACKER && } + {BLOG.ANALYTICS_GOOGLE_ID && } + {JSON.parse(BLOG.ANALYTICS_BUSUANZI_ENABLE) && } + {BLOG.ADSENSE_GOOGLE_ID && } + {/* FontawesomeCDN */} + + ) diff --git a/themes/example/LayoutSlug.js b/themes/example/LayoutSlug.js index fc7f81e1..0372d507 100644 --- a/themes/example/LayoutSlug.js +++ b/themes/example/LayoutSlug.js @@ -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 (
@@ -54,39 +18,10 @@ export const LayoutSlug = props => { {lock && } {!lock &&
- {post.blockMap && ( - - )} -
} + {post.blockMap && } + }
) } - -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 - } -} diff --git a/themes/fukasawa/components/ArticleDetail.js b/themes/fukasawa/components/ArticleDetail.js index 0e2b7187..20d06fbd 100644 --- a/themes/fukasawa/components/ArticleDetail.js +++ b/themes/fukasawa/components/ArticleDetail.js @@ -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 (
{post.type && !post.type.includes('Page') && post?.page_cover && ( -
+
{/* eslint-disable-next-line @next/next/no-img-element */} - {post.title} -
+ {post.title} +
)}
- {/* 文章Title */} -
- {post.title} -
+ {/* 文章Title */} +
+ {post.title} +
-
-
- - - - {post.category} +
+
+ + + + {post.category} + + + | + + {post.type[0] !== 'Page' && (<> + + + {date} | + )} - {post.type[0] !== 'Page' && (<> - - - {date} - - - | - )} - -
- -   - - | -
+
+ +   + + |
+
-
+
{/* Notion文章主体 */}
- {post.blockMap && ( - - )} + {post.blockMap && }
@@ -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" />
- + {/* 评论互动 */}
- +
) } - -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 - } -} diff --git a/themes/hexo/LayoutSlug.js b/themes/hexo/LayoutSlug.js index 2b0a63f5..e2fec724 100644 --- a/themes/hexo/LayoutSlug.js +++ b/themes/hexo/LayoutSlug.js @@ -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 &&
- { - drawerRight?.current?.handleSwitchVisible() - }} - /> -
} - - + {post?.toc?.length > 1 &&
+ { + drawerRight?.current?.handleSwitchVisible() + }} + /> +
} + + return ( } + headerSlot={} {...props} showCategory={false} showTag={false} floatSlot={floatSlot} >
- {!lock && } {lock && } + + {!lock &&
+ +
+ {/* Notion文章主体 */} +
+ {post.blockMap && } +
+ +
+ {/* 文章内嵌广告 */} + +
+ + + + +
+ +
+ + {/* 评论互动 */} +
+ +
+
}
diff --git a/themes/hexo/components/ArticleDetail.js b/themes/hexo/components/ArticleDetail.js deleted file mode 100644 index 7913e6c6..00000000 --- a/themes/hexo/components/ArticleDetail.js +++ /dev/null @@ -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 (
-
- - {/* Notion文章主体 */} -
- {post.blockMap && ( - - )} -
- -
- {/* 文章内嵌广告 */} - -
- - - - - -
- -
- - {/* 评论互动 */} -
- -
-
) -} - -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 - } -} diff --git a/themes/hexo/components/BlogPostCard.js b/themes/hexo/components/BlogPostCard.js index cb4fa647..d1ba0023 100644 --- a/themes/hexo/components/BlogPostCard.js +++ b/themes/hexo/components/BlogPostCard.js @@ -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 }) => {
{post.title}
{ {showPreview && (
- +
)} @@ -104,8 +86,4 @@ const BlogPostCard = ({ post, showSummary }) => { ) } -const mapPageUrl = id => { - return 'https://www.notion.so/' + id.replace(/-/g, '') -} - export default BlogPostCard diff --git a/themes/medium/LayoutSlug.js b/themes/medium/LayoutSlug.js index 073e5432..7433a8db 100644 --- a/themes/medium/LayoutSlug.js +++ b/themes/medium/LayoutSlug.js @@ -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 && (
@@ -50,27 +29,9 @@ export const LayoutSlug = props => { slotRight={slotRight} > - {!lock && } + {!lock && } - {lock && } + {lock && } ) } - -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 - } -} diff --git a/themes/medium/components/ArticleDetail.js b/themes/medium/components/ArticleDetail.js index 11add4fc..fec2baa7 100644 --- a/themes/medium/components/ArticleDetail.js +++ b/themes/medium/components/ArticleDetail.js @@ -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 => { {/* Notion文章主体 */}
- {post.blockMap && ( - - )} + {post.blockMap && ()}
@@ -90,10 +62,10 @@ export const ArticleDetail = props => {
- { CONFIG_MEDIUM.POST_DETAIL_CATEGORY && post.category && } -
- { CONFIG_MEDIUM.POST_DETAIL_TAG && post?.tagItems?.map(tag => )} -
+ {CONFIG_MEDIUM.POST_DETAIL_CATEGORY && post.category && } +
+ {CONFIG_MEDIUM.POST_DETAIL_TAG && post?.tagItems?.map(tag => )} +
diff --git a/themes/medium/components/BlogPostCard.js b/themes/medium/components/BlogPostCard.js index 0af31a13..b1ac3072 100644 --- a/themes/medium/components/BlogPostCard.js +++ b/themes/medium/components/BlogPostCard.js @@ -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 && (
- +
@@ -78,8 +69,4 @@ const BlogPostCard = ({ post, showSummary }) => { ) } -const mapPageUrl = id => { - return 'https://www.notion.so/' + id.replace(/-/g, '') -} - export default BlogPostCard diff --git a/themes/next/components/ArticleDetail.js b/themes/next/components/ArticleDetail.js index 194020dd..bccc778f 100644 --- a/themes/next/components/ArticleDetail.js +++ b/themes/next/components/ArticleDetail.js @@ -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 (
{post.type && !post.type.includes('Page') && post?.page_cover && ( -
- {/* eslint-disable-next-line @next/next/no-img-element */} - {post.title} -
+
+ {/* eslint-disable-next-line @next/next/no-img-element */} + {post.title} +
)} - {/* 文章Title */} -
- {post.title} -
+ {/* 文章Title */} +
+ {post.title} +
-
-
- {post.category && <> - +
+
+ {post.category && <> + {post.category} | - } - {post.type[0] !== 'Page' && (<> - - - {date} - - - | - )} + } + {post.type[0] !== 'Page' && (<> + + + {date} + + + | + )} -
- -   - - | -
+
+ +   + + |
-
- -
+
+
+ +
-
+
} {/* Notion内容主体 */}
- {post.blockMap && ( - - )} + {post.blockMap && ()}
@@ -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" />
{showArticleInfo && <> - {/* 版权声明 */} - + {/* 版权声明 */} + - {/* 推荐文章 */} - + {/* 推荐文章 */} + - {/* 标签列表 */} -
- {post.tagItems && ( -
-
- {locale.COMMON.TAGS}: + {/* 标签列表 */} +
+ {post.tagItems && ( +
+
+ {locale.COMMON.TAGS}: +
+ {post.tagItems.map(tag => ( + + ))}
- {post.tagItems.map(tag => ( - - ))} + )} +
+
- )} -
- -
-
+
- + } {/* 评论互动 */} @@ -167,25 +129,3 @@ export default function ArticleDetail (props) {
) } - -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 - } -} diff --git a/themes/next/components/BlogPostCard.js b/themes/next/components/BlogPostCard.js index d51baf68..382a7cf3 100644 --- a/themes/next/components/BlogPostCard.js +++ b/themes/next/components/BlogPostCard.js @@ -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 }) => {
{post.title}
{post.category && ( @@ -87,17 +79,7 @@ const BlogPostCard = ({ post, showSummary }) => { {showPreview && post?.blockMap && (
- +
)} @@ -130,8 +112,4 @@ const BlogPostCard = ({ post, showSummary }) => { ) } -const mapPageUrl = id => { - return 'https://www.notion.so/' + id.replace(/-/g, '') -} - export default BlogPostCard From ef62044a99032753dd8121806b83048ee09cb38c Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Wed, 6 Apr 2022 15:45:24 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E6=9C=80=E5=90=8E=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/lang/en-US.js | 4 +- lib/lang/zh-CN.js | 4 +- lib/lang/zh-TW.js | 4 +- lib/notion/getAllPosts.js | 11 +-- lib/notion/getPageProperties.js | 2 +- lib/notion/getPostBlocks.js | 10 +-- themes/example/LayoutSlug.js | 42 ++++++++++ themes/fukasawa/components/ArticleDetail.js | 6 +- themes/hexo/components/HeaderArticle.js | 87 +++++++++++---------- themes/medium/components/ArticleDetail.js | 3 + themes/next/components/ArticleDetail.js | 20 +++-- 11 files changed, 125 insertions(+), 68 deletions(-) diff --git a/lib/lang/en-US.js b/lib/lang/en-US.js index 00414875..d51c0a5a 100644 --- a/lib/lang/en-US.js +++ b/lib/lang/en-US.js @@ -32,7 +32,9 @@ export default { ARTICLE_DETAIL: 'Article Details', PASSWORD_ERROR: 'Password Error!', ARTICLE_LOCK_TIPS: 'Please Enter the password:', - SUBMIT: 'Submit' + SUBMIT: 'Submit', + POST_TIME: 'Post on', + LAST_EDITED_TIME: 'Last edited time' }, PAGINATION: { PREV: 'Prev', diff --git a/lib/lang/zh-CN.js b/lib/lang/zh-CN.js index 4417a270..435aeb96 100644 --- a/lib/lang/zh-CN.js +++ b/lib/lang/zh-CN.js @@ -34,7 +34,9 @@ export default { ARTICLE_DETAIL: '文章详情', PASSWORD_ERROR: '密码错误!', ARTICLE_LOCK_TIPS: '文章已上锁,请输入访问密码', - SUBMIT: '提交' + SUBMIT: '提交', + POST_TIME: '发布于', + LAST_EDITED_TIME: '最后更新' }, PAGINATION: { PREV: '上一页', diff --git a/lib/lang/zh-TW.js b/lib/lang/zh-TW.js index a7f648f4..4901fc37 100644 --- a/lib/lang/zh-TW.js +++ b/lib/lang/zh-TW.js @@ -34,7 +34,9 @@ export default { ARTICLE_DETAIL: '完整文章', PASSWORD_ERROR: '密碼錯誤!', ARTICLE_LOCK_TIPS: '文章已上鎖,請輸入訪問密碼', - SUBMIT: '提交' + SUBMIT: '提交', + POST_TIME: '发布于', + LAST_EDITED_TIME: '最后更新日期' }, PAGINATION: { PREV: '上一頁', diff --git a/lib/notion/getAllPosts.js b/lib/notion/getAllPosts.js index cfbbafa8..fbe588da 100644 --- a/lib/notion/getAllPosts.js +++ b/lib/notion/getAllPosts.js @@ -2,6 +2,7 @@ import BLOG from '@/blog.config' import getAllPageIds from './getAllPageIds' import getPageProperties from './getPageProperties' import { defaultMapImageUrl } from 'react-notion-x' +import formatDate from '@/lib/formatDate' import { getNotionPageData } from '@/lib/notion/getNotionData' import { delCacheData } from '@/lib/cache/cache_manager' @@ -12,7 +13,7 @@ import { delCacheData } from '@/lib/cache/cache_manager' * @param pageType 页面类型数组 ['Post','Page'] * @returns {Promise<*[]>} */ -export async function getAllPosts ({ notionPageData, from, pageType }) { +export async function getAllPosts({ notionPageData, from, pageType }) { if (!notionPageData) { notionPageData = await getNotionPageData({ from }) } @@ -31,8 +32,8 @@ export async function getAllPosts ({ notionPageData, from, pageType }) { const id = pageIds[i] const properties = (await getPageProperties(id, pageBlock, schema)) || null properties.slug = properties.slug ?? properties.id - properties.createdTime = new Date(pageBlock[id].value?.created_time).toString() // FIXME 似乎没有created_time 字段了 - properties.lastEditedTime = new Date(pageBlock[id].value?.last_edited_time).toString() // FIXME 似乎没有created_time 字段了 + properties.createdTime = formatDate(new Date(pageBlock[id].value?.created_time).toString(), BLOG.LANG) + properties.lastEditedTime = formatDate(new Date(pageBlock[id].value?.last_edited_time).toString(), BLOG.LANG) properties.fullWidth = pageBlock[id].value?.format?.page_full_width ?? false properties.page_cover = getPostCover(id, pageBlock) ?? null properties.content = pageBlock[id].value?.content ?? [] @@ -65,7 +66,7 @@ export async function getAllPosts ({ notionPageData, from, pageType }) { } // 从Block获取封面图;优先取PageCover,否则取内容图片 -function getPostCover (id, block) { +function getPostCover(id, block) { const pageCover = block[id].value?.format?.page_cover if (pageCover) { if (pageCover.startsWith('/')) return 'https://www.notion.so' + pageCover @@ -78,7 +79,7 @@ function getPostCover (id, block) { * @param {*} param0 * @returns */ -export async function getAllPostCount ({ notionPageData, from }) { +export async function getAllPostCount({ notionPageData, from }) { if (!notionPageData) { notionPageData = await getNotionPageData({ from }) } diff --git a/lib/notion/getPageProperties.js b/lib/notion/getPageProperties.js index 56ded539..3dcc7735 100644 --- a/lib/notion/getPageProperties.js +++ b/lib/notion/getPageProperties.js @@ -1,7 +1,7 @@ import { getTextContent, getDateValue } from 'notion-utils' import { NotionAPI } from 'notion-client' -async function getPageProperties (id, block, schema, authToken) { +async function getPageProperties(id, block, schema, authToken) { const rawProperties = Object.entries(block?.[id]?.value?.properties || []) const excludeProperties = ['date', 'select', 'multi_select', 'person'] const properties = {} diff --git a/lib/notion/getPostBlocks.js b/lib/notion/getPostBlocks.js index 0db5a582..52cbdf32 100644 --- a/lib/notion/getPostBlocks.js +++ b/lib/notion/getPostBlocks.js @@ -2,7 +2,7 @@ import BLOG from '@/blog.config' import { NotionAPI } from 'notion-client' import { getDataFromCache, setDataToCache } from '@/lib/cache/cache_manager' -export async function getPostBlocks (id, from, slice, retryCount = 3) { +export async function getPostBlocks(id, from, slice, retryCount = 3) { const cacheKey = 'page_block_' + id let pageBlock = await getDataFromCache(cacheKey) if (pageBlock) { @@ -32,13 +32,13 @@ export async function getPostBlocks (id, from, slice, retryCount = 3) { } /** - * + * 获取到的blockMap删除不需要的字段 * @param {*} id 页面ID * @param {*} pageBlock 页面元素 * @param {*} slice 截取数量 * @returns */ -function filterPostBlocks (id, pageBlock, slice) { +function filterPostBlocks(id, pageBlock, slice) { const clonePageBlock = deepClone(pageBlock) let count = 0 @@ -51,8 +51,6 @@ function filterPostBlocks (id, pageBlock, slice) { count++ delete b?.role delete b?.value?.version - delete b?.value?.created_time - delete b?.value?.last_edited_time delete b?.value?.created_by_table delete b?.value?.created_by_id delete b?.value?.last_edited_by_table @@ -67,7 +65,7 @@ function filterPostBlocks (id, pageBlock, slice) { return clonePageBlock } -function deepClone (obj) { +function deepClone(obj) { const newObj = Array.isArray(obj) ? [] : {} if (obj && typeof obj === 'object') { for (const key in obj) { diff --git a/themes/example/LayoutSlug.js b/themes/example/LayoutSlug.js index 0372d507..70482b5d 100644 --- a/themes/example/LayoutSlug.js +++ b/themes/example/LayoutSlug.js @@ -2,6 +2,9 @@ import { getPageTableOfContents } from 'notion-utils' import LayoutBase from './LayoutBase' import { ArticleLock } from './components/ArticleLock' import NotionPage from '@/components/NotionPage' +import Link from 'next/link' +import { useGlobal } from '@/lib/global' +import formatDate from '@/lib/formatDate' export const LayoutSlug = props => { const { post, lock, validPassword } = props @@ -10,6 +13,9 @@ export const LayoutSlug = props => { post.toc = getPageTableOfContents(post, post.blockMap) } + const { locale } = useGlobal() + const date = formatDate(post?.date?.start_date || post.createdTime, locale.LOCALE) + return (
@@ -18,6 +24,42 @@ export const LayoutSlug = props => { {lock && } {!lock &&
+
+
+ + + + {post.category} + + + | + + {post.type[0] !== 'Page' && (<> + + + {date} + + + | + + {locale.COMMON.LAST_EDITED_TIME}: {post.lastEditedTime} + + | + + )} + + + +   + + +
+ +
+ {post.blockMap && }
} diff --git a/themes/fukasawa/components/ArticleDetail.js b/themes/fukasawa/components/ArticleDetail.js index 20d06fbd..cbdfa0b7 100644 --- a/themes/fukasawa/components/ArticleDetail.js +++ b/themes/fukasawa/components/ArticleDetail.js @@ -51,13 +51,15 @@ export default function ArticleDetail({ post, recommendPosts, prev, next }) { | + + {locale.COMMON.LAST_EDITED_TIME}: {post.lastEditedTime} + )} -
+
  - |
diff --git a/themes/hexo/components/HeaderArticle.js b/themes/hexo/components/HeaderArticle.js index 23ebdaf0..ce9b3484 100644 --- a/themes/hexo/components/HeaderArticle.js +++ b/themes/hexo/components/HeaderArticle.js @@ -3,7 +3,7 @@ import { useGlobal } from '@/lib/global' import formatDate from '@/lib/formatDate' import { useEffect } from 'react' -export default function HeaderArticle ({ post, siteInfo }) { +export default function HeaderArticle({ post, siteInfo }) { const headerImage = post?.page_cover ? `url("${post.page_cover}")` : `url("${siteInfo?.pageCover}")` const { isDarkMode } = useGlobal() @@ -47,52 +47,53 @@ export default function HeaderArticle ({ post, siteInfo }) { } return ( -
+
+ +
) } diff --git a/themes/medium/components/ArticleDetail.js b/themes/medium/components/ArticleDetail.js index fec2baa7..a0ed321e 100644 --- a/themes/medium/components/ArticleDetail.js +++ b/themes/medium/components/ArticleDetail.js @@ -37,6 +37,9 @@ export const ArticleDetail = props => {
{date}
+
+ {locale.COMMON.LAST_EDITED_TIME}: {post.lastEditedTime} +
  diff --git a/themes/next/components/ArticleDetail.js b/themes/next/components/ArticleDetail.js index bccc778f..ba49b0a6 100644 --- a/themes/next/components/ArticleDetail.js +++ b/themes/next/components/ArticleDetail.js @@ -42,7 +42,7 @@ export default function ArticleDetail(props) {
-
+
{post.category && <> @@ -61,19 +61,23 @@ export default function ArticleDetail(props) { | +
+ +   + +
+ )} -
- -   - - | -
+ +
+ {locale.COMMON.LAST_EDITED_TIME} {post.lastEditedTime} +
+
-
} From 64d7056439c94316af79fd7727d44a58d13a70c7 Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Wed, 6 Apr 2022 15:46:10 +0800 Subject: [PATCH 5/7] =?UTF-8?q?=E6=9C=80=E5=90=8E=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/lang/en-US.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/lang/en-US.js b/lib/lang/en-US.js index d51c0a5a..9f8fc94a 100644 --- a/lib/lang/en-US.js +++ b/lib/lang/en-US.js @@ -34,7 +34,7 @@ export default { ARTICLE_LOCK_TIPS: 'Please Enter the password:', SUBMIT: 'Submit', POST_TIME: 'Post on', - LAST_EDITED_TIME: 'Last edited time' + LAST_EDITED_TIME: 'Last edited' }, PAGINATION: { PREV: 'Prev', From fde05676c2e57855cccb7786be7e9e7381cf2cfe Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Wed, 6 Apr 2022 15:46:14 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=E6=9C=80=E5=90=8E=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/lang/zh-TW.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/lang/zh-TW.js b/lib/lang/zh-TW.js index 4901fc37..673fe109 100644 --- a/lib/lang/zh-TW.js +++ b/lib/lang/zh-TW.js @@ -36,7 +36,7 @@ export default { ARTICLE_LOCK_TIPS: '文章已上鎖,請輸入訪問密碼', SUBMIT: '提交', POST_TIME: '发布于', - LAST_EDITED_TIME: '最后更新日期' + LAST_EDITED_TIME: '最后更新' }, PAGINATION: { PREV: '上一頁', From 391286c35bd8fe8ab9262b4e6f90027918ac461a Mon Sep 17 00:00:00 2001 From: tangly1024 Date: Wed, 6 Apr 2022 16:05:13 +0800 Subject: [PATCH 7/7] =?UTF-8?q?bug-=E6=BB=9A=E5=8A=A8=E5=88=B0=E8=AF=84?= =?UTF-8?q?=E8=AE=BA=E5=8C=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- themes/hexo/components/JumpToCommentButton.js | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/themes/hexo/components/JumpToCommentButton.js b/themes/hexo/components/JumpToCommentButton.js index cc96497c..85d93cf0 100644 --- a/themes/hexo/components/JumpToCommentButton.js +++ b/themes/hexo/components/JumpToCommentButton.js @@ -1,5 +1,6 @@ -import React from 'react' +import React, { useEffect } from 'react' import CONFIG_HEXO from '../config_hexo' +let wrapperTop = 0 /** * 跳转到评论区 @@ -10,16 +11,30 @@ const JumpToCommentButton = () => { if (!CONFIG_HEXO.WIDGET_TO_COMMENT) { return <> } - function navToComment () { - const commentElement = document.getElementById('comment') - if (commentElement) { - commentElement?.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'nearest' }) - } + + function updateHeaderHeight() { + setTimeout(() => { + if (window) { + const wrapperElement = document.getElementById('comment') + wrapperTop = wrapperElement?.offsetTop + } + }, 500) + } + function navToComment() { + window.scrollTo({ top: wrapperTop, behavior: 'smooth' }) + // 兼容性不好 + // const commentElement = document.getElementById('comment') + // if (commentElement) { + // commentElement?.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'nearest' }) } + useEffect(() => { + updateHeaderHeight() + }) + return (
- -
) + +
) } export default JumpToCommentButton