From 5ac6577058ce119f3187bc2c939da874d8fe9857 Mon Sep 17 00:00:00 2001 From: "tangly1024.com" Date: Mon, 18 Mar 2024 12:36:36 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=96=87=E7=AB=A0=E5=86=85?= =?UTF-8?q?=E5=AE=B9=E5=B5=8C=E5=85=A5=E5=B9=BF=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/GoogleAdsense.js | 136 +++++++++++++++++++++++++----------- components/NotionPage.js | 127 +++++++++++++++++---------------- 2 files changed, 164 insertions(+), 99 deletions(-) diff --git a/components/GoogleAdsense.js b/components/GoogleAdsense.js index 61606150..2add89e6 100644 --- a/components/GoogleAdsense.js +++ b/components/GoogleAdsense.js @@ -3,25 +3,33 @@ import { loadExternalResource } from '@/lib/utils' import { useRouter } from 'next/router' import { useEffect } from 'react' +function requestAd() { + const ads = document.getElementsByClassName('adsbygoogle') + const adsbygoogle = window.adsbygoogle + if (adsbygoogle && ads.length > 0) { + for (let i = 0; i <= ads.length; i++) { + try { + const adStatus = ads[i].getAttribute('data-adsbygoogle-status') + if (!adStatus || adStatus !== 'done') { + adsbygoogle.push(ads[i]) + } + } catch (e) {} + } + } +} + /** * 初始化谷歌广告 * @returns */ export default function GoogleAdsense() { const initGoogleAdsense = () => { - loadExternalResource(`https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${siteConfig('ADSENSE_GOOGLE_ID')}`, 'js').then(url => { + loadExternalResource( + `https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${siteConfig('ADSENSE_GOOGLE_ID')}`, + 'js' + ).then(url => { setTimeout(() => { - const ads = document.getElementsByClassName('adsbygoogle') - const adsbygoogle = window.adsbygoogle - if (ads.length > 0) { - for (let i = 0; i <= ads.length; i++) { - try { - adsbygoogle.push(ads[i]) - } catch (e) { - - } - } - } + requestAd() }, 100) }) } @@ -49,44 +57,92 @@ const AdSlot = ({ type = 'show' }) => { } // 文章内嵌广告 if (type === 'in-article') { - return + return ( + + ) } // 信息流广告 if (type === 'flow') { - return + return ( + + ) } // 原生广告 if (type === 'native') { - return + return ( + + ) } // 展示广告 - return + return ( + + ) } -export { AdSlot } +/** + * 嵌入到文章内部的广告单元 + * 检测文本内容 出现 关键词时自动替换为广告 + * @param {*} props + */ +const AdEmbed = () => { + useEffect(() => { + setTimeout(() => { + // 找到所有 class 为 notion-text 且内容为 '' 的 div 元素 + const notionTextElements = document.querySelectorAll('div.notion-text') + + // 遍历找到的元素 + notionTextElements?.forEach(element => { + // 检查元素的内容是否为 '' + if (element.innerHTML.trim() === '<ins/>') { + // 创建新的 元素 + const newInsElement = document.createElement('ins') + newInsElement.className = 'adsbygoogle w-full py-1' + newInsElement.style.display = 'block' + newInsElement.setAttribute('data-ad-client', siteConfig('ADSENSE_GOOGLE_ID')) + newInsElement.setAttribute('data-adtest', siteConfig('ADSENSE_GOOGLE_TEST') ? 'on' : 'off') + newInsElement.setAttribute('data-ad-slot', siteConfig('ADSENSE_GOOGLE_SLOT_AUTO')) + newInsElement.setAttribute('data-ad-format', 'auto') + newInsElement.setAttribute('data-full-width-responsive', 'true') + + // 用新创建的 元素替换掉原来的 div 元素 + element?.parentNode?.replaceChild(newInsElement, element) + } + }) + + requestAd() + }, 1000) + }, []) + return <> +} + +export { AdEmbed, AdSlot } diff --git a/components/NotionPage.js b/components/NotionPage.js index 0a3c44d5..9e0e9c24 100644 --- a/components/NotionPage.js +++ b/components/NotionPage.js @@ -1,33 +1,34 @@ -import dynamic from 'next/dynamic' -import mediumZoom from '@fisch0920/medium-zoom' -import { useEffect, useRef } from 'react' -import 'katex/dist/katex.min.css' +import { siteConfig } from '@/lib/config' import { compressImage, mapImgUrl } from '@/lib/notion/mapImage' import { isBrowser } from '@/lib/utils' -import { siteConfig } from '@/lib/config' +import mediumZoom from '@fisch0920/medium-zoom' +import 'katex/dist/katex.min.css' +import dynamic from 'next/dynamic' +import { useEffect, useRef } from 'react' import { NotionRenderer } from 'react-notion-x' -const Code = dynamic(() => - import('react-notion-x/build/third-party/code').then(async (m) => { - return m.Code - }), { ssr: false } +const Code = dynamic( + () => + import('react-notion-x/build/third-party/code').then(async m => { + return m.Code + }), + { ssr: false } ) // 公式 -const Equation = dynamic(() => - import('@/components/Equation').then(async (m) => { - // 化学方程式 - await import('@/lib/plugins/mhchem') - return m.Equation - }), { ssr: false } +const Equation = dynamic( + () => + import('@/components/Equation').then(async m => { + // 化学方程式 + await import('@/lib/plugins/mhchem') + return m.Equation + }), + { ssr: false } ) -const Pdf = dynamic( - () => import('react-notion-x/build/third-party/pdf').then((m) => m.Pdf), - { - ssr: false - } -) +const Pdf = dynamic(() => import('react-notion-x/build/third-party/pdf').then(m => m.Pdf), { + ssr: false +}) // https://github.com/txs // import PrismMac from '@/components/PrismMac' @@ -42,13 +43,16 @@ const TweetEmbed = dynamic(() => import('react-tweet-embed'), { ssr: false }) -const Collection = dynamic(() => - import('react-notion-x/build/third-party/collection').then((m) => m.Collection), { ssr: true } -) +/** + * 文内google广告 + */ +const AdEmbed = dynamic(() => import('@/components/GoogleAdsense').then(m => m.AdEmbed), { ssr: true }) -const Modal = dynamic( - () => import('react-notion-x/build/third-party/modal').then((m) => m.Modal), { ssr: false } -) +const Collection = dynamic(() => import('react-notion-x/build/third-party/collection').then(m => m.Collection), { + ssr: true +}) + +const Modal = dynamic(() => import('react-notion-x/build/third-party/modal').then(m => m.Modal), { ssr: false }) const Tweet = ({ id }) => { return @@ -64,15 +68,17 @@ const NotionPage = ({ post, className }) => { autoScrollToTarget() }, []) - const zoom = typeof window !== 'undefined' && mediumZoom({ - container: '.notion-viewport', - background: 'rgba(0, 0, 0, 0.2)', - margin: getMediumZoomMargin() - }) + 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(() => { - if (!isBrowser) return; + if (!isBrowser) return // 将相册gallery下的图片加入放大功能 if (siteConfig('POST_DISABLE_GALLERY_CLICK')) { @@ -81,7 +87,7 @@ const NotionPage = ({ post, className }) => { const imgList = document?.querySelectorAll('.notion-collection-card-cover img') if (imgList && zoomRef.current) { for (let i = 0; i < imgList.length; i++) { - (zoomRef.current).attach(imgList[i]) + zoomRef.current.attach(imgList[i]) } } @@ -119,45 +125,48 @@ const NotionPage = ({ post, className }) => { if (mutation.target.classList.contains('medium-zoom-image--opened')) { // 等待动画完成后替换为更高清的图像 setTimeout(() => { - // 获取该元素的 src 属性 - const src = mutation?.target?.getAttribute('src'); + // 获取该元素的 src 属性 + const src = mutation?.target?.getAttribute('src') // 替换为更高清的图像 - mutation?.target?.setAttribute('src', compressImage(src, siteConfig('IMAGE_ZOOM_IN_WIDTH', 1200))); - }, 800); + mutation?.target?.setAttribute('src', compressImage(src, siteConfig('IMAGE_ZOOM_IN_WIDTH', 1200))) + }, 800) } } - }); - }); + }) + }) // 监视整个文档中的元素和属性的变化 - observer.observe(document.body, { attributes: true, subtree: true, attributeFilter: ['class'] }); + observer.observe(document.body, { attributes: true, subtree: true, attributeFilter: ['class'] }) return () => { - observer.disconnect(); - }; + observer.disconnect() + } }, []) if (!post || !post.blockMap) { return <>{post?.summary || ''} } - return
- + return ( +
+ - - -
+ + +
+ ) } /**