支持文章内容嵌入广告

This commit is contained in:
tangly1024.com
2024-03-18 12:36:36 +08:00
parent b35a2135a1
commit 5ac6577058
2 changed files with 164 additions and 99 deletions

View File

@@ -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 <ins className="adsbygoogle"
style={{ display: 'block', textAlign: 'center' }}
data-ad-layout="in-article"
data-ad-format="fluid"
data-adtest={siteConfig('ADSENSE_GOOGLE_TEST') ? 'on' : 'off'}
data-ad-client={siteConfig('ADSENSE_GOOGLE_ID')}
data-ad-slot={siteConfig('ADSENSE_GOOGLE_SLOT_IN_ARTICLE')}></ins>
return (
<ins
className='adsbygoogle'
style={{ display: 'block', textAlign: 'center' }}
data-ad-layout='in-article'
data-ad-format='fluid'
data-adtest={siteConfig('ADSENSE_GOOGLE_TEST') ? 'on' : 'off'}
data-ad-client={siteConfig('ADSENSE_GOOGLE_ID')}
data-ad-slot={siteConfig('ADSENSE_GOOGLE_SLOT_IN_ARTICLE')}></ins>
)
}
// 信息流广告
if (type === 'flow') {
return <ins className="adsbygoogle"
data-ad-format="fluid"
data-ad-layout-key="-5j+cz+30-f7+bf"
style={{ display: 'block' }}
data-adtest={siteConfig('ADSENSE_GOOGLE_TEST') ? 'on' : 'off'}
data-ad-client={siteConfig('ADSENSE_GOOGLE_ID')}
data-ad-slot={siteConfig('ADSENSE_GOOGLE_SLOT_FLOW')}></ins>
return (
<ins
className='adsbygoogle'
data-ad-format='fluid'
data-ad-layout-key='-5j+cz+30-f7+bf'
style={{ display: 'block' }}
data-adtest={siteConfig('ADSENSE_GOOGLE_TEST') ? 'on' : 'off'}
data-ad-client={siteConfig('ADSENSE_GOOGLE_ID')}
data-ad-slot={siteConfig('ADSENSE_GOOGLE_SLOT_FLOW')}></ins>
)
}
// 原生广告
if (type === 'native') {
return <ins className="adsbygoogle"
style={{ display: 'block', textAlign: 'center' }}
data-ad-format="autorelaxed"
data-adtest={siteConfig('ADSENSE_GOOGLE_TEST') ? 'on' : 'off'}
data-ad-client={siteConfig('ADSENSE_GOOGLE_ID')}
data-ad-slot={siteConfig('ADSENSE_GOOGLE_SLOT_NATIVE')}></ins>
return (
<ins
className='adsbygoogle'
style={{ display: 'block', textAlign: 'center' }}
data-ad-format='autorelaxed'
data-adtest={siteConfig('ADSENSE_GOOGLE_TEST') ? 'on' : 'off'}
data-ad-client={siteConfig('ADSENSE_GOOGLE_ID')}
data-ad-slot={siteConfig('ADSENSE_GOOGLE_SLOT_NATIVE')}></ins>
)
}
// 展示广告
return <ins className="adsbygoogle"
style={{ display: 'block' }}
data-ad-client={siteConfig('ADSENSE_GOOGLE_ID')}
data-adtest={siteConfig('ADSENSE_GOOGLE_TEST') ? 'on' : 'off'}
data-ad-slot={siteConfig('ADSENSE_GOOGLE_SLOT_AUTO')}
data-ad-format="auto"
data-full-width-responsive="true"></ins>
return (
<ins
className='adsbygoogle'
style={{ display: 'block' }}
data-ad-client={siteConfig('ADSENSE_GOOGLE_ID')}
data-adtest={siteConfig('ADSENSE_GOOGLE_TEST') ? 'on' : 'off'}
data-ad-slot={siteConfig('ADSENSE_GOOGLE_SLOT_AUTO')}
data-ad-format='auto'
data-full-width-responsive='true'></ins>
)
}
export { AdSlot }
/**
* 嵌入到文章内部的广告单元
* 检测文本内容 出现<ins/> 关键词时自动替换为广告
* @param {*} props
*/
const AdEmbed = () => {
useEffect(() => {
setTimeout(() => {
// 找到所有 class 为 notion-text 且内容为 '<ins/>' 的 div 元素
const notionTextElements = document.querySelectorAll('div.notion-text')
// 遍历找到的元素
notionTextElements?.forEach(element => {
// 检查元素的内容是否为 '<ins/>'
if (element.innerHTML.trim() === '&lt;ins/&gt;') {
// 创建新的 <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')
// 用新创建的 <ins> 元素替换掉原来的 div 元素
element?.parentNode?.replaceChild(newInsElement, element)
}
})
requestAd()
}, 1000)
}, [])
return <></>
}
export { AdEmbed, AdSlot }

View File

@@ -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 <TweetEmbed tweetId={id} />
@@ -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 <div id='notion-article' className={`mx-auto overflow-hidden ${className || ''}`}>
<NotionRenderer
recordMap={post.blockMap}
mapPageUrl={mapPageUrl}
mapImageUrl={mapImgUrl}
components={{
Code,
Collection,
Equation,
Modal,
Pdf,
Tweet
}} />
return (
<div id='notion-article' className={`mx-auto overflow-hidden ${className || ''}`}>
<NotionRenderer
recordMap={post.blockMap}
mapPageUrl={mapPageUrl}
mapImageUrl={mapImgUrl}
components={{
Code,
Collection,
Equation,
Modal,
Pdf,
Tweet
}}
/>
<PrismMac/>
</div>
<AdEmbed />
<PrismMac />
</div>
)
}
/**