This commit is contained in:
tangly1024.com
2024-08-28 12:20:34 +08:00
30 changed files with 198 additions and 105 deletions

View File

@@ -28,16 +28,16 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v2 uses: actions/checkout@v4
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v3
# Login against a Docker registry except on PR # Login against a Docker registry except on PR
# https://github.com/docker/login-action # https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }} - name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request' if: github.event_name != 'pull_request'
uses: docker/login-action@v1 uses: docker/login-action@v3
with: with:
registry: ${{ env.REGISTRY }} registry: ${{ env.REGISTRY }}
username: ${{ github.actor }} username: ${{ github.actor }}
@@ -47,14 +47,14 @@ jobs:
# https://github.com/docker/metadata-action # https://github.com/docker/metadata-action
- name: Extract Docker metadata - name: Extract Docker metadata
id: meta id: meta
uses: docker/metadata-action@v3 uses: docker/metadata-action@v5
with: with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# Build and push Docker image with Buildx (don't push on PR) # Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action # https://github.com/docker/build-push-action
- name: Build and push Docker image - name: Build and push Docker image
uses: docker/build-push-action@v2 uses: docker/build-push-action@v5
with: with:
context: . context: .
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64

View File

@@ -24,11 +24,11 @@ jobs:
runs-on: ubuntu-latest # 运行环境为最新版的Ubuntu runs-on: ubuntu-latest # 运行环境为最新版的Ubuntu
steps: steps:
- name: 'Checkout codes' # 步骤一,获取仓库代码 - name: 'Checkout codes' # 步骤一,获取仓库代码
uses: actions/checkout@v2 uses: actions/checkout@v4
# - name: 'Run baiduPush' # 步骤二执行sh命令文件 # - name: 'Run baiduPush' # 步骤二执行sh命令文件
# run: npm install && npm run baiduPush # 运行目录是仓库根目录 # run: npm install && npm run baiduPush # 运行目录是仓库根目录
- name: Set up Python 3.8 - name: Set up Python 3.8
uses: actions/setup-python@v1 uses: actions/setup-python@v5
with: with:
python-version: 3.8 python-version: 3.8

View File

@@ -17,7 +17,7 @@ jobs:
steps: steps:
# Step 1: run a standard checkout action # Step 1: run a standard checkout action
- name: Checkout target repo - name: Checkout target repo
uses: actions/checkout@v3 uses: actions/checkout@v4
# Step 2: run the sync action # Step 2: run the sync action
- name: Sync upstream changes - name: Sync upstream changes

View File

@@ -545,7 +545,7 @@ const BLOG = {
process.env.ENABLE_CACHE || process.env.ENABLE_CACHE ||
process.env.npm_lifecycle_event === 'build' || process.env.npm_lifecycle_event === 'build' ||
process.env.npm_lifecycle_event === 'export', // 在打包过程中默认开启缓存,开发或运行时开启此功能意义不大。 process.env.npm_lifecycle_event === 'export', // 在打包过程中默认开启缓存,开发或运行时开启此功能意义不大。
isProd: process.env.VERCEL_ENV === 'production' || process.env.EXPORT, // distinguish between development and production environment (ref: https://vercel.com/docs/environment-variables#system-environment-variables) isProd: process.env.VERCEL_ENV === 'production' // distinguish between development and production environment (ref: https://vercel.com/docs/environment-variables#system-environment-variables) isProd: process.env.VERCEL_ENV === 'production' || process.env.EXPORT, // distinguish between development and production environment (ref: https://vercel.com/docs/environment-variables#system-environment-variables)
BUNDLE_ANALYZER: process.env.ANALYZE === 'true' || false, // 是否展示编译依赖内容与大小 BUNDLE_ANALYZER: process.env.ANALYZE === 'true' || false, // 是否展示编译依赖内容与大小
VERSION: process.env.NEXT_PUBLIC_VERSION // 版本号 VERSION: process.env.NEXT_PUBLIC_VERSION // 版本号
} }

View File

@@ -24,19 +24,19 @@ const Ackee = () => {
}, },
{ {
/* /*
* Enable or disable tracking of personal data. * Enable or disable tracking of personal data.
* We recommend to ask the user for permission before turning this option on. * We recommend to ask the user for permission before turning this option on.
*/ */
detailed: true, detailed: true,
/* /*
* Enable or disable tracking when on localhost. * Enable or disable tracking when on localhost.
*/ */
ignoreLocalhost: false, ignoreLocalhost: false,
/* /*
* Enable or disable the tracking of your own visits. * Enable or disable the tracking of your own visits.
* This is enabled by default, but should be turned off when using a wildcard Access-Control-Allow-Origin header. * This is enabled by default, but should be turned off when using a wildcard Access-Control-Allow-Origin header.
* Some browsers strictly block third-party cookies. The option won't have an impact when this is the case. * Some browsers strictly block third-party cookies. The option won't have an impact when this is the case.
*/ */
ignoreOwnVisits: false ignoreOwnVisits: false
} }
) )

View File

@@ -117,12 +117,14 @@ export default function CustomContextMenu(props) {
function handleCopy() { function handleCopy() {
const selectedText = document.getSelection().toString() const selectedText = document.getSelection().toString()
if (selectedText) { if (selectedText) {
const tempInput = document.createElement('input') const tempInput = document.createElement('input');
tempInput.value = selectedText tempInput.value = selectedText;
document.body.appendChild(tempInput) document.body.appendChild(tempInput);
tempInput.select() tempInput.select();
document.execCommand('copy') document.execCommand('copy');
document.body.removeChild(tempInput) if (tempInput && tempInput.parentNode && tempInput.parentNode.contains(tempInput)) {
tempInput.parentNode.removeChild(tempInput);
}
// alert("Text copied: " + selectedText); // alert("Text copied: " + selectedText);
} else { } else {
// alert("Please select some text first."); // alert("Please select some text first.");

View File

@@ -24,7 +24,9 @@ export default function DifyChatbot() {
return () => { return () => {
// 在组件卸载时清理 script 标签 // 在组件卸载时清理 script 标签
const existingScript = document.getElementById(siteConfig('DIFY_CHATBOT_TOKEN')); // 注意调用 siteConfig() const existingScript = document.getElementById(siteConfig('DIFY_CHATBOT_TOKEN')); // 注意调用 siteConfig()
if (existingScript) document.body.removeChild(existingScript); if (existingScript && existingScript.parentNode && existingScript.parentNode.contains(existingScript)) {
existingScript.parentNode.removeChild(existingScript);
}
}; };
}, []); // 注意依赖数组为空,意味着脚本将仅在加载页面时执行一次 }, []); // 注意依赖数组为空,意味着脚本将仅在加载页面时执行一次

View File

@@ -186,10 +186,19 @@ const ExternalPlugin = props => {
async async
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: ` __html: `
(function(c,l,a,r,i,t,y){ (function(c, l, a, r, i, t, y) {
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)}; c[a] = c[a] || function() {
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i; (c[a].q = c[a].q || []).push(arguments);
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y); };
t = l.createElement(r);
t.async = 1;
t.src = "https://www.clarity.ms/tag/" + i;
y = l.getElementsByTagName(r)[0];
if (y && y.parentNode) {
y.parentNode.insertBefore(t, y);
} else {
l.head.appendChild(t);
}
})(window, document, "clarity", "script", "${CLARITY_ID}"); })(window, document, "clarity", "script", "${CLARITY_ID}");
` `
}} }}
@@ -204,8 +213,24 @@ const ExternalPlugin = props => {
async async
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: ` __html: `
(function(i,s,o,g,r,a,m){i["DaoVoiceObject"]=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;a.charset="utf-8";m.parentNode.insertBefore(a,m)})(window,document,"script",('https:' == document.location.protocol ? 'https:' : 'http:') + "//widget.daovoice.io/widget/daf1a94b.js","daovoice") (function(i, s, o, g, r, a, m) {
` i["DaoVoiceObject"] = r;
i[r] = i[r] || function() {
(i[r].q = i[r].q || []).push(arguments);
};
i[r].l = 1 * new Date();
a = s.createElement(o);
m = s.getElementsByTagName(o)[0];
a.async = 1;
a.src = g;
a.charset = "utf-8";
if (m && m.parentNode) {
m.parentNode.insertBefore(a, m);
} else {
s.head.appendChild(a);
}
})(window, document, "script", ('https:' == document.location.protocol ? 'https:' : 'http:') + "//widget.daovoice.io/widget/daf1a94b.js", "daovoice")
`
}} }}
/> />
<script <script

View File

@@ -116,7 +116,11 @@ class MessengerCustomerChat extends Component {
js = d.createElement(s); js = d.createElement(s);
js.id = id; js.id = id;
js.src = `https://connect.facebook.net/${language}/sdk/xfbml.customerchat.js`; js.src = `https://connect.facebook.net/${language}/sdk/xfbml.customerchat.js`;
fjs.parentNode.insertBefore(js, fjs); if (fjs && fjs.parentNode && fjs.parentNode.contains(fjs)) {
fjs.parentNode.insertBefore(js, fjs);
} else {
document.body.appendChild(js);
}
})(document, 'script', 'facebook-jssdk'); })(document, 'script', 'facebook-jssdk');
/* eslint-enable */ /* eslint-enable */
} }

View File

@@ -18,7 +18,7 @@ const Fireworks = () => {
// 异步加载 // 异步加载
async function loadFireworks() { async function loadFireworks() {
loadExternalResource( loadExternalResource(
'https://cdn.bootcdn.net/ajax/libs/animejs/3.2.1/anime.min.js', 'https://cdnjs.snrat.com/ajax/libs/animejs/3.2.1/anime.min.js',
'js' 'js'
).then(() => { ).then(() => {
loadExternalResource('/js/fireworks.js', 'js').then(() => { loadExternalResource('/js/fireworks.js', 'js').then(() => {

View File

@@ -11,7 +11,7 @@ export default function LoadingProgress() {
// 加载进度条 // 加载进度条
useEffect(() => { useEffect(() => {
loadExternalResource( loadExternalResource(
'https://cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.min.js', 'https://cdnjs.snrat.com/ajax/libs/nprogress/0.2.0/nprogress.min.js',
'js' 'js'
).then(() => { ).then(() => {
if (window.NProgress) { if (window.NProgress) {
@@ -19,7 +19,7 @@ export default function LoadingProgress() {
// 调速 // 调速
window.NProgress.settings.minimun = 0.1 window.NProgress.settings.minimun = 0.1
loadExternalResource( loadExternalResource(
'https://cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.min.css', 'https://cdnjs.snrat.com/ajax/libs/nprogress/0.2.0/nprogress.min.css',
'css' 'css'
) )
} }

View File

@@ -34,7 +34,7 @@ export function PWA(post, siteInfo) {
// 删除已有的 manifest link 元素(如果存在) // 删除已有的 manifest link 元素(如果存在)
const existingManifest = document.querySelector('link[rel="manifest"]') const existingManifest = document.querySelector('link[rel="manifest"]')
if (existingManifest) { if (existingManifest && existingManifest.parentNode && existingManifest.parentNode.contains(existingManifest)) {
existingManifest.parentNode.removeChild(existingManifest) existingManifest.parentNode.removeChild(existingManifest)
} }

View File

@@ -74,7 +74,7 @@ const loadPrismThemeCSS = (isDarkMode, prismThemeSwitch, prismThemeDarkPath, pri
PRISM_PREVIOUS = prismThemeDarkPath PRISM_PREVIOUS = prismThemeDarkPath
} }
const previousTheme = document.querySelector(`link[href="${PRISM_PREVIOUS}"]`) const previousTheme = document.querySelector(`link[href="${PRISM_PREVIOUS}"]`)
if (previousTheme) { if (previousTheme && previousTheme.parentNode && previousTheme.parentNode.contains(previousTheme)) {
previousTheme.parentNode.removeChild(previousTheme) previousTheme.parentNode.removeChild(previousTheme)
} }
loadExternalResource(PRISM_THEME, 'css') loadExternalResource(PRISM_THEME, 'css')

View File

@@ -6,8 +6,8 @@ import { useEffect } from 'react';
*/ */
const useAdjustStyle = () => { const useAdjustStyle = () => {
/** /**
* 避免 callout 含有图片时溢出撑开父容器 * 避免 callout 含有图片时溢出撑开父容器
*/ */
const adjustCalloutImg = () => { const adjustCalloutImg = () => {
const callOuts = document.querySelectorAll('.notion-callout-text'); const callOuts = document.querySelectorAll('.notion-callout-text');
callOuts.forEach((callout) => { callOuts.forEach((callout) => {

View File

@@ -22,6 +22,7 @@ export default {
COMMON: { COMMON: {
THEME: 'Theme', THEME: 'Theme',
ARTICLE_LIST: 'Article List', ARTICLE_LIST: 'Article List',
RECOMMEND_POSTS: 'Recommend Posts',
MORE: 'More', MORE: 'More',
NO_MORE: 'No More', NO_MORE: 'No More',
LATEST_POSTS: 'Latest posts', LATEST_POSTS: 'Latest posts',

View File

@@ -22,6 +22,7 @@ export default {
COMMON: { COMMON: {
THEME: 'Theme', THEME: 'Theme',
ARTICLE_LIST: '文章列表', ARTICLE_LIST: '文章列表',
RECOMMEND_POSTS: '推荐文章',
MORE: '更多', MORE: '更多',
NO_MORE: '没有更多了', NO_MORE: '没有更多了',
LATEST_POSTS: '最新发布', LATEST_POSTS: '最新发布',

View File

@@ -81,49 +81,69 @@ export async function getPageWithRetry(id, from, retryAttempts = 3) {
function filterPostBlocks(id, blockMap, slice) { function filterPostBlocks(id, blockMap, slice) {
const clonePageBlock = deepClone(blockMap) const clonePageBlock = deepClone(blockMap)
let count = 0 let count = 0
const blocksToProcess = Object.keys(clonePageBlock?.block || {})
// 循环遍历文档的每个block // 循环遍历文档的每个block
for (const i in clonePageBlock?.block) { for (let i = 0; i < blocksToProcess.length; i++) {
const b = clonePageBlock?.block[i] const blockId = blocksToProcess[i]
if (slice && slice > 0 && count > slice) { const b = clonePageBlock?.block[blockId]
delete clonePageBlock?.block[i]
continue if (slice && slice > 0 && count > slice) {
delete clonePageBlock?.block[blockId]
continue
}
// 当BlockId等于PageId时移除
if (b?.value?.id === id) {
// 此block含有敏感信息
delete b?.value?.properties
continue
}
count++
if (b?.value?.type === 'sync_block' && b?.value?.children) {
const childBlocks = b.value.children
// 移除同步块
delete clonePageBlock.block[blockId]
// 用子块替代同步块
childBlocks.forEach((childBlock, index) => {
const newBlockId = `${blockId}_child_${index}`
clonePageBlock.block[newBlockId] = childBlock
blocksToProcess.splice(i + index + 1, 0, newBlockId)
})
// 重新处理新加入的子块
i--
continue
}
// 处理 c++、c#、汇编等语言名字映射
if (b?.value?.type === 'code') {
if (b?.value?.properties?.language?.[0][0] === 'C++') {
b.value.properties.language[0][0] = 'cpp'
} }
// 当BlockId等于PageId时移除 if (b?.value?.properties?.language?.[0][0] === 'C#') {
if (b?.value?.id === id) { b.value.properties.language[0][0] = 'csharp'
// 此block含有敏感信息
delete b?.value?.properties
continue
} }
if (b?.value?.properties?.language?.[0][0] === 'Assembly') {
count++ b.value.properties.language[0][0] = 'asm6502'
// 处理 c++、c#、汇编等语言名字映射
if (b?.value?.type === 'code') {
if (b?.value?.properties?.language?.[0][0] === 'C++') {
b.value.properties.language[0][0] = 'cpp'
}
if (b?.value?.properties?.language?.[0][0] === 'C#') {
b.value.properties.language[0][0] = 'csharp'
}
if (b?.value?.properties?.language?.[0][0] === 'Assembly') {
b.value.properties.language[0][0] = 'asm6502'
}
}
// 如果是文件或嵌入式PDF需要重新加密签名
if (
(b?.value?.type === 'file' ||
b?.value?.type === 'pdf' ||
b?.value?.type === 'video' ||
b?.value?.type === 'audio') &&
b?.value?.properties?.source?.[0][0] &&
b?.value?.properties?.source?.[0][0].indexOf('amazonaws.com') > 0
) {
const oldUrl = b?.value?.properties?.source?.[0][0]
const newUrl = `https://notion.so/signed/${encodeURIComponent(oldUrl)}?table=block&id=${b?.value?.id}`
b.value.properties.source[0][0] = newUrl
} }
} }
// 如果是文件或嵌入式PDF需要重新加密签名
if (
(b?.value?.type === 'file' ||
b?.value?.type === 'pdf' ||
b?.value?.type === 'video' ||
b?.value?.type === 'audio') &&
b?.value?.properties?.source?.[0][0] &&
b?.value?.properties?.source?.[0][0].indexOf('amazonaws.com') > 0
) {
const oldUrl = b?.value?.properties?.source?.[0][0]
const newUrl = `https://notion.so/signed/${encodeURIComponent(oldUrl)}?table=block&id=${b?.value?.id}`
b.value.properties.source[0][0] = newUrl
}
}
// 去掉不用的字段 // 去掉不用的字段
if (id === BLOG.NOTION_PAGE_ID) { if (id === BLOG.NOTION_PAGE_ID) {

View File

@@ -43,7 +43,10 @@ bszCaller = {
return function (t) { return function (t) {
ready(function () { ready(function () {
try { try {
e(t), scriptTag && scriptTag.parentElement && scriptTag.parentElement.removeChild && scriptTag.parentElement.removeChild(scriptTag) e(t)
if (scriptTag && scriptTag.parentElement && scriptTag.parentElement.contains(scriptTag)) {
scriptTag.parentElement.removeChild(scriptTag)
}
} catch (t) { } catch (t) {
// console.log(t), bszTag.hides() // console.log(t), bszTag.hides()
} }

View File

@@ -185,6 +185,10 @@ const nextConfig = {
'themes', 'themes',
THEME THEME
) )
// Enable source maps in development mode
if (process.env.NODE_ENV_API === 'development') {
config.devtool = 'source-map'
}
return config return config
}, },
experimental: { experimental: {
@@ -201,7 +205,6 @@ const nextConfig = {
}, },
publicRuntimeConfig: { publicRuntimeConfig: {
// 这里的配置既可以服务端获取到,也可以在浏览器端获取到 // 这里的配置既可以服务端获取到,也可以在浏览器端获取到
NODE_ENV_API: process.env.NODE_ENV_API || 'prod',
THEMES: themes THEMES: themes
} }
} }

View File

@@ -3,7 +3,7 @@ const idFlutteringRibbon = 'canvasFlutteringRibbon'
function destroyFlutteringRibbon() { function destroyFlutteringRibbon() {
const ribbon = document.getElementById(idFlutteringRibbon) const ribbon = document.getElementById(idFlutteringRibbon)
if (ribbon && ribbon.parentNode) { if (ribbon && ribbon.parentNode && ribbon.parentNode.contains(ribbon)) {
ribbon.parentNode.removeChild(ribbon) ribbon.parentNode.removeChild(ribbon)
} }
} }

View File

@@ -109,7 +109,7 @@ function createNest() {
function destroyNest() { function destroyNest() {
const nest = document.getElementById(idNest) const nest = document.getElementById(idNest)
if(nest && nest.parentNode){ if (nest && nest.parentNode && nest.parentNode.contains(nest)) {
nest.parentNode.removeChild(nest) nest.parentNode.removeChild(nest)
} }
} }

View File

@@ -80,7 +80,7 @@ function createRibbon() {
function destroyRibbon() { function destroyRibbon() {
const ribbon = document.getElementById(idRibbon) const ribbon = document.getElementById(idRibbon)
if (ribbon && ribbon.parentNode) { if (ribbon && ribbon.parentNode && ribbon.parentNode.contains(ribbon)) {
ribbon.parentNode.removeChild(ribbon) ribbon.parentNode.removeChild(ribbon)
} }
} }

View File

@@ -165,9 +165,11 @@ function createSakura() {
function stopp() { function stopp() {
if (staticx) { if (staticx) {
var child = document.getElementById(id) var child = document.getElementById(id)
child.parentNode.removeChild(child) if (child && child.parentNode && child.parentNode.contains(child)) {
window.cancelAnimationFrame(stop) child.parentNode.removeChild(child)
staticx = false window.cancelAnimationFrame(stop)
staticx = false
}
} else { } else {
startSakura() startSakura()
} }
@@ -177,7 +179,7 @@ function createSakura() {
// 销毁樱花雨 // 销毁樱花雨
function destroySakura() { function destroySakura() {
const sakura = document.getElementById(idSakura) const sakura = document.getElementById(idSakura)
if (sakura && sakura.parentNode) { if (sakura && sakura.parentNode && sakura.parentNode.contains(sakura)) {
sakura.parentNode.removeChild(sakura) sakura.parentNode.removeChild(sakura)
} }
} }

View File

@@ -1,3 +1,4 @@
import { siteConfig } from '@/lib/config'
import { useGlobal } from '@/lib/global' import { useGlobal } from '@/lib/global'
import { GameListIndexCombine } from './GameListIndexCombine' import { GameListIndexCombine } from './GameListIndexCombine'
import PaginationSimple from './PaginationSimple' import PaginationSimple from './PaginationSimple'
@@ -9,7 +10,8 @@ import PaginationSimple from './PaginationSimple'
export const BlogListPage = props => { export const BlogListPage = props => {
const { page = 1, postCount } = props const { page = 1, postCount } = props
const { NOTION_CONFIG } = useGlobal() const { NOTION_CONFIG } = useGlobal()
const totalPage = Math.ceil(postCount / NOTION_CONFIG) const POSTS_PER_PAGE = siteConfig('POSTS_PER_PAGE', null, NOTION_CONFIG)
const totalPage = Math.ceil(postCount / POSTS_PER_PAGE)
const showNext = page < totalPage const showNext = page < totalPage
return ( return (

View File

@@ -30,7 +30,7 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
{/* 图片封面 */} {/* 图片封面 */}
{showPageCover && ( {showPageCover && (
<Link href={post?.href} passHref legacyBehavior> <Link href={post?.href} passHref legacyBehavior>
<div className='w-full md:w-5/12 2xl:w-full overflow-hidden'> <div className='w-full md:w-5/12 2xl:w-full overflow-hidden cursor-pointer select-none'>
<LazyImage <LazyImage
priority={index === 0} priority={index === 0}
src={post?.pageCoverThumbnail} src={post?.pageCoverThumbnail}

View File

@@ -383,7 +383,7 @@ function TodayCard({ cRef, siteInfo }) {
} }
/> />
<div id='more' className='select-none'> <div id='more' className='select-none'>
{locale.COMMON.MORE} {locale.COMMON.RECOMMEND_POSTS}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,18 +1,37 @@
import { useGlobal } from '@/lib/global'
import CategoryItem from './CategoryItem' import CategoryItem from './CategoryItem'
/**
* 分类
* @param {*} param0
* @returns
*/
const CategoryGroup = ({ currentCategory, categoryOptions }) => { const CategoryGroup = ({ currentCategory, categoryOptions }) => {
const { locale } = useGlobal()
if (!categoryOptions) { if (!categoryOptions) {
return <></> return <></>
} }
return <div id='category-list' className='pt-4'> return (
<div className='mb-2'><i className='mr-2 fas fa-th' />分类</div> <div id='category-list' className='pt-4'>
<div className='flex flex-wrap'> <div className='mb-2'>
{categoryOptions?.map(category => { <i className='mr-2 fas fa-th' />
const selected = currentCategory === category.name {locale.COMMON.CATEGORY}
return <CategoryItem key={category.name} selected={selected} category={category.name} categoryCount={category.count} /> </div>
})} <div className='flex flex-wrap'>
{categoryOptions?.map(category => {
const selected = currentCategory === category.name
return (
<CategoryItem
key={category.name}
selected={selected}
category={category.name}
categoryCount={category.count}
/>
)
})}
</div>
</div> </div>
</div> )
} }
export default CategoryGroup export default CategoryGroup

View File

@@ -1,3 +1,4 @@
import { useGlobal } from '@/lib/global'
import TagItemMini from './TagItemMini' import TagItemMini from './TagItemMini'
/** /**
@@ -8,17 +9,19 @@ import TagItemMini from './TagItemMini'
* @constructor * @constructor
*/ */
const TagGroups = ({ tagOptions, currentTag }) => { const TagGroups = ({ tagOptions, currentTag }) => {
const { locale } = useGlobal()
if (!tagOptions) return <></> if (!tagOptions) return <></>
return ( return (
<div id='tags-group' className='dark:border-gray-600 py-4'> <div id='tags-group' className='dark:border-gray-600 py-4'>
<div className='mb-2'><i className='mr-2 fas fa-tag' />标签</div> <div className='mb-2'>
<i className='mr-2 fas fa-tag' />
{locale.COMMON.TAGS}
</div>
<div className='space-y-2'> <div className='space-y-2'>
{ {tagOptions?.map(tag => {
tagOptions?.map(tag => { const selected = tag.name === currentTag
const selected = tag.name === currentTag return <TagItemMini key={tag.name} tag={tag} selected={selected} />
return <TagItemMini key={tag.name} tag={tag} selected={selected} /> })}
})
}
</div> </div>
</div> </div>
) )

View File

@@ -258,7 +258,11 @@ const LayoutSlug = props => {
videoWrapper.appendChild(figCaptionWrapper) videoWrapper.appendChild(figCaptionWrapper)
} }
// 放入页面 // 放入页面
notionArticle.insertBefore(videoWrapper, notionArticle.firstChild) if (notionArticle.firstChild && notionArticle.contains(notionArticle.firstChild)) {
notionArticle.insertBefore(videoWrapper, notionArticle.firstChild)
} else {
notionArticle.appendChild(videoWrapper)
}
} }
} }

View File

@@ -102,7 +102,9 @@ const checkThemeDOM = () => {
elements[elements.length - 1].scrollIntoView() elements[elements.length - 1].scrollIntoView()
// 删除前面的元素,只保留最后一个元素 // 删除前面的元素,只保留最后一个元素
for (let i = 0; i < elements.length - 1; i++) { for (let i = 0; i < elements.length - 1; i++) {
elements[i].parentNode.removeChild(elements[i]) if (elements[i] && elements[i].parentNode && elements[i].parentNode.contains(elements[i])) {
elements[i].parentNode.removeChild(elements[i])
}
} }
} }
} }