mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-14 07:26:52 +00:00
Merge branch 'main' of https://github.com/tangly1024/NotionNext into feature/user-auth-clerk
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# 环境变量 @see https://www.nextjs.cn/docs/basic-features/environment-variables
|
||||
NEXT_PUBLIC_VERSION=4.6.1
|
||||
NEXT_PUBLIC_VERSION=4.7.0
|
||||
|
||||
|
||||
# 可在此添加环境变量,去掉最左边的(# )注释即可
|
||||
|
||||
10
.github/workflows/docker-ghcr.yaml
vendored
10
.github/workflows/docker-ghcr.yaml
vendored
@@ -28,16 +28,16 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- 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
|
||||
# https://github.com/docker/login-action
|
||||
- name: Log into registry ${{ env.REGISTRY }}
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
@@ -47,14 +47,14 @@ jobs:
|
||||
# https://github.com/docker/metadata-action
|
||||
- name: Extract Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v3
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
|
||||
# Build and push Docker image with Buildx (don't push on PR)
|
||||
# https://github.com/docker/build-push-action
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v2
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
||||
4
.github/workflows/pushUrl.yml
vendored
4
.github/workflows/pushUrl.yml
vendored
@@ -24,11 +24,11 @@ jobs:
|
||||
runs-on: ubuntu-latest # 运行环境为最新版的Ubuntu
|
||||
steps:
|
||||
- name: 'Checkout codes' # 步骤一,获取仓库代码
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
# - name: 'Run baiduPush' # 步骤二,执行sh命令文件
|
||||
# run: npm install && npm run baiduPush # 运行目录是仓库根目录
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v1
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.8
|
||||
|
||||
|
||||
2
.github/workflows/sync.yaml
vendored
2
.github/workflows/sync.yaml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
steps:
|
||||
# Step 1: run a standard checkout action
|
||||
- name: Checkout target repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Step 2: run the sync action
|
||||
- name: Sync upstream changes
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -45,7 +45,7 @@ yarn-error.log*
|
||||
/public/robots.txt
|
||||
/public/sitemap.xml
|
||||
/public/rss/*
|
||||
|
||||
/sitemap.xml
|
||||
|
||||
# yarn
|
||||
package-lock.json
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
ARG NOTION_PAGE_ID
|
||||
ARG NEXT_PUBLIC_THEME
|
||||
|
||||
# Install dependencies only when needed
|
||||
FROM node:18-alpine3.18 AS deps
|
||||
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
|
||||
|
||||
24
README.md
24
README.md
@@ -1,3 +1,13 @@
|
||||
# 帮助教程
|
||||
|
||||
访问帮助:[NotionNext帮助手册](https://docs.tangly1024.com/)
|
||||
|
||||
> 本项目教程为免费、公开资源,仅限个人学习使用。严禁任何个人或组织将本教程用于商业用途,包括但不限于直接售卖、间接收费、或其他变相盈利行为。转载、复制或介绍本教程内容时,须保留作者信息并明确注明来源。
|
||||
> 本项目仅提供由作者团队授权的付费咨询服务,请注意辨别,谨防诈骗行为。任何未经授权的收费服务均可能存在法律风险。
|
||||
|
||||
Notion是一个能让效率暴涨的生产力引擎,可以帮你书写文档、管理笔记,搭建知识库,甚至可以为你规划项目、时间管理、组织团队、提高生产力、还有当前最强大的AI技术加持。
|
||||
> 如果希望进一步探索Notion的功能,欢迎购买《[Notion笔记从入门到精通进阶课程](https://docs.tangly1024.com/article/notion-tutorial)》
|
||||
|
||||
# NotionNext
|
||||
|
||||
<p>
|
||||
@@ -31,20 +41,6 @@
|
||||
|--|--|--|--|
|
||||
| <img src='./docs/theme-next.png' width='300'/> [预览NEXT](https://preview.tangly1024.com/?theme=next) | <img src='./docs/theme-medium.png' width='300'/> [预览MEDIUM](https://preview.tangly1024.com/?theme=medium) | <img src='./docs/theme-hexo.png' width='300'/> [预览HEXO](https://preview.tangly1024.com/?theme=hexo) | <img src='./docs/theme-fukasawa.png' width='300'/> [预览FUKASAWA](https://preview.tangly1024.com/?theme=fukasawa) |
|
||||
|
||||
## 我要如何开始?
|
||||
|
||||
只需几分钟即可搭建您的个人站点:
|
||||
|
||||
- [部署教程 (支持多方案)](https://docs.tangly1024.com/)
|
||||
|
||||
- [配置手册 - (自定义插件)](https://docs.tangly1024.com/article/notion-next-guide)
|
||||
|
||||
- [二次开发 - (开发手册)](https://docs.tangly1024.com/article/notion-next-secondary-menu)
|
||||
|
||||
- [更新指南 - (升级您的代码)](https://docs.tangly1024.com/article/how-to-update-notionnext)
|
||||
|
||||
- [版本汇总 - (查询变动功能)](https://docs.tangly1024.com/article/notion-next-changelogs)
|
||||
|
||||
## 致谢
|
||||
感谢Craig Hart发起的Nobelium项目
|
||||
|
||||
|
||||
26
README_EN.md
26
README_EN.md
@@ -1,3 +1,15 @@
|
||||
# Free Installation and Usage Guide
|
||||
|
||||
Click here to access the help documentation: NotionNext Help Manual - (Completely Free)
|
||||
|
||||
## Rights Statement
|
||||
|
||||
This project's tutorial is a free and open resource intended solely for personal learning use. It is strictly prohibited for any individual or organization to use this tutorial for commercial purposes, including but not limited to direct sales, indirect charges, or any other forms of profit. When reproducing, copying, or sharing this tutorial, the author's information must be retained, and the source clearly cited.
|
||||
|
||||
This project only offers paid consultation services authorized by the author's team. Please be vigilant against fraud. Any unauthorized paid services may be subject to legal risks.
|
||||
|
||||
You can set up your personal website in just a few minutes. Here is the link to my free tutorial:
|
||||
|
||||
# NotionNext
|
||||
|
||||
<p>
|
||||
@@ -31,20 +43,6 @@ Live Demo:[https://preview.tangly1024.com/](https://preview.tangly1024.com/)
|
||||
|--|--|--|--|
|
||||
| <img src='./docs/theme-next.png' width='300'/> [NEXT](https://preview.tangly1024.com/?theme=next) | <img src='./docs/theme-medium.png' width='300'/> [MEDIUM](https://preview.tangly1024.com/?theme=medium) | <img src='./docs/theme-hexo.png' width='300'/> [HEXO](https://preview.tangly1024.com/?theme=hexo) | <img src='./docs/theme-fukasawa.png' width='300'/> [FUKASAWA](https://preview.tangly1024.com/?theme=fukasawa) |
|
||||
|
||||
## Get Start!
|
||||
|
||||
It only takes a few minutes to set up your personal site:
|
||||
|
||||
- [Quick Deployment Tutorial - Multiple Options Available](https://docs.tangly1024.com/article/vercel-deploy-notion-next)
|
||||
|
||||
- [Customization Guide - How to Configure Feature Plugins](https://docs.tangly1024.com/article/how-to-config-notion-next)
|
||||
|
||||
- [Development Guide - How to Conduct Local Development](https://docs.tangly1024.com/article/how-to-develop-with-notion-next)
|
||||
|
||||
- [Update Guide - How to Get the Latest Upgrade Patch](https://docs.tangly1024.com/article/how-to-update-notionnext)
|
||||
|
||||
- [Version History - Check Feature Highlights for Each Version](https://docs.tangly1024.com/article/latest)
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
Special thanks to Craig Hart for initiating the Nobelium project.
|
||||
|
||||
@@ -546,7 +546,7 @@ const BLOG = {
|
||||
process.env.ENABLE_CACHE ||
|
||||
process.env.npm_lifecycle_event === 'build' ||
|
||||
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, // 是否展示编译依赖内容与大小
|
||||
VERSION: process.env.NEXT_PUBLIC_VERSION // 版本号
|
||||
}
|
||||
|
||||
@@ -10,14 +10,8 @@ import { useEffect } from 'react'
|
||||
export default function AOSAnimation() {
|
||||
const initAOS = async () => {
|
||||
Promise.all([
|
||||
loadExternalResource(
|
||||
'https://cdn.bootcdn.net/ajax/libs/aos/2.3.4/aos.js',
|
||||
'js'
|
||||
),
|
||||
loadExternalResource(
|
||||
'https://cdn.bootcdn.net/ajax/libs/aos/2.3.4/aos.css',
|
||||
'css'
|
||||
)
|
||||
loadExternalResource('/js/aos.js', 'js'),
|
||||
loadExternalResource('/css/aos.css', 'css')
|
||||
]).then(() => {
|
||||
if (window.AOS) {
|
||||
window.AOS.init()
|
||||
|
||||
@@ -24,19 +24,19 @@ const Ackee = () => {
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Enable or disable tracking of personal data.
|
||||
* We recommend to ask the user for permission before turning this option on.
|
||||
*/
|
||||
* Enable or disable tracking of personal data.
|
||||
* We recommend to ask the user for permission before turning this option on.
|
||||
*/
|
||||
detailed: true,
|
||||
/*
|
||||
* Enable or disable tracking when on localhost.
|
||||
*/
|
||||
* Enable or disable tracking when on localhost.
|
||||
*/
|
||||
ignoreLocalhost: false,
|
||||
/*
|
||||
* 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.
|
||||
* Some browsers strictly block third-party cookies. The option won't have an impact when this is the case.
|
||||
*/
|
||||
* 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.
|
||||
* Some browsers strictly block third-party cookies. The option won't have an impact when this is the case.
|
||||
*/
|
||||
ignoreOwnVisits: false
|
||||
}
|
||||
)
|
||||
|
||||
@@ -117,12 +117,14 @@ export default function CustomContextMenu(props) {
|
||||
function handleCopy() {
|
||||
const selectedText = document.getSelection().toString()
|
||||
if (selectedText) {
|
||||
const tempInput = document.createElement('input')
|
||||
tempInput.value = selectedText
|
||||
document.body.appendChild(tempInput)
|
||||
tempInput.select()
|
||||
document.execCommand('copy')
|
||||
document.body.removeChild(tempInput)
|
||||
const tempInput = document.createElement('input');
|
||||
tempInput.value = selectedText;
|
||||
document.body.appendChild(tempInput);
|
||||
tempInput.select();
|
||||
document.execCommand('copy');
|
||||
if (tempInput && tempInput.parentNode && tempInput.parentNode.contains(tempInput)) {
|
||||
tempInput.parentNode.removeChild(tempInput);
|
||||
}
|
||||
// alert("Text copied: " + selectedText);
|
||||
} else {
|
||||
// alert("Please select some text first.");
|
||||
|
||||
@@ -24,7 +24,9 @@ export default function DifyChatbot() {
|
||||
return () => {
|
||||
// 在组件卸载时清理 script 标签
|
||||
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);
|
||||
}
|
||||
};
|
||||
}, []); // 注意依赖数组为空,意味着脚本将仅在加载页面时执行一次
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ const ExternalPlugin = props => {
|
||||
const MOUSE_FOLLOW = siteConfig('MOUSE_FOLLOW')
|
||||
const CUSTOM_EXTERNAL_CSS = siteConfig('CUSTOM_EXTERNAL_CSS')
|
||||
const CUSTOM_EXTERNAL_JS = siteConfig('CUSTOM_EXTERNAL_JS')
|
||||
const ENABLE_NPROGRSS = siteConfig('ENABLE_NPROGRSS', true)
|
||||
|
||||
// 自定义样式css和js引入
|
||||
if (isBrowser) {
|
||||
@@ -145,7 +146,7 @@ const ExternalPlugin = props => {
|
||||
{AD_WWADS_BLOCK_DETECT && <AdBlockDetect />}
|
||||
{TIANLI_KEY && <TianLiGPT />}
|
||||
<VConsole />
|
||||
<LoadingProgress />
|
||||
{ENABLE_NPROGRSS && <LoadingProgress />}
|
||||
<AosAnimation />
|
||||
{ANALYTICS_51LA_ID && ANALYTICS_51LA_CK && <LA51 />}
|
||||
|
||||
@@ -186,10 +187,19 @@ const ExternalPlugin = props => {
|
||||
async
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
(function(c,l,a,r,i,t,y){
|
||||
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
|
||||
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
|
||||
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
|
||||
(function(c, l, a, r, i, t, y) {
|
||||
c[a] = c[a] || function() {
|
||||
(c[a].q = c[a].q || []).push(arguments);
|
||||
};
|
||||
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}");
|
||||
`
|
||||
}}
|
||||
@@ -204,8 +214,24 @@ const ExternalPlugin = props => {
|
||||
async
|
||||
dangerouslySetInnerHTML={{
|
||||
__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
|
||||
|
||||
@@ -116,7 +116,11 @@ class MessengerCustomerChat extends Component {
|
||||
js = d.createElement(s);
|
||||
js.id = id;
|
||||
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');
|
||||
/* eslint-enable */
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ const Fireworks = () => {
|
||||
// 异步加载
|
||||
async function loadFireworks() {
|
||||
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'
|
||||
).then(() => {
|
||||
loadExternalResource('/js/fireworks.js', 'js').then(() => {
|
||||
|
||||
71
components/LoadingCover.js
Normal file
71
components/LoadingCover.js
Normal file
@@ -0,0 +1,71 @@
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { useEffect, useState } from 'react'
|
||||
/**
|
||||
* @see https://css-loaders.com/
|
||||
* @returns 加载动画
|
||||
*/
|
||||
export default function LoadingCover() {
|
||||
const { onLoading, setOnLoading } = useGlobal()
|
||||
const [isVisible, setIsVisible] = useState(false) // 初始状态设置为false,避免服务端渲染与客户端渲染不一致
|
||||
|
||||
useEffect(() => {
|
||||
// 确保在客户端渲染时才设置可见性
|
||||
if (onLoading) {
|
||||
setIsVisible(true)
|
||||
} else {
|
||||
const timeout = setTimeout(() => setIsVisible(false), 1500) // 等待淡出动画结束
|
||||
return () => clearTimeout(timeout)
|
||||
}
|
||||
}, [onLoading])
|
||||
|
||||
const handleClick = () => {
|
||||
setOnLoading(false) // 强行关闭 LoadingCover
|
||||
}
|
||||
|
||||
if (typeof window === 'undefined') {
|
||||
return null // 避免在服务端渲染时渲染出这个组件
|
||||
}
|
||||
|
||||
return isVisible ? (
|
||||
<div
|
||||
id='loading-cover'
|
||||
onClick={handleClick}
|
||||
className={`dark:text-white text-black bg-white dark:bg-black animate__animated animate__faster ${
|
||||
onLoading ? 'animate__fadeIn' : 'animate__fadeOut'
|
||||
} flex flex-col justify-center z-50 w-full h-screen fixed top-0 left-0`}>
|
||||
<div className='mx-auto'>
|
||||
<style global>
|
||||
{`
|
||||
.loader {
|
||||
width: 20px;
|
||||
aspect-ratio: 1;
|
||||
border-radius: 50%;
|
||||
background: #000;
|
||||
box-shadow: 0 0 0 0 #0004;
|
||||
animation: l2 1.5s infinite linear;
|
||||
position: relative;
|
||||
}
|
||||
.loader:before,
|
||||
.loader:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: inherit;
|
||||
box-shadow: 0 0 0 0 #0004;
|
||||
animation: inherit;
|
||||
animation-delay: -0.5s;
|
||||
}
|
||||
.loader:after {
|
||||
animation-delay: -1s;
|
||||
}
|
||||
@keyframes l2 {
|
||||
100% {
|
||||
box-shadow: 0 0 0 40px #0000;
|
||||
}
|
||||
}`}
|
||||
</style>
|
||||
<div className='loader'></div>
|
||||
</div>
|
||||
</div>
|
||||
) : null
|
||||
}
|
||||
@@ -3,7 +3,8 @@ import { useRouter } from 'next/router'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
/**
|
||||
* 出现页面加载进度条
|
||||
* 加载进度条
|
||||
* NProgress实现
|
||||
*/
|
||||
export default function LoadingProgress() {
|
||||
const router = useRouter()
|
||||
@@ -11,7 +12,7 @@ export default function LoadingProgress() {
|
||||
// 加载进度条
|
||||
useEffect(() => {
|
||||
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'
|
||||
).then(() => {
|
||||
if (window.NProgress) {
|
||||
@@ -19,7 +20,7 @@ export default function LoadingProgress() {
|
||||
// 调速
|
||||
window.NProgress.settings.minimun = 0.1
|
||||
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'
|
||||
)
|
||||
}
|
||||
|
||||
140
components/OpenWrite.js
Normal file
140
components/OpenWrite.js
Normal file
@@ -0,0 +1,140 @@
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { isBrowser, loadExternalResource } from '@/lib/utils'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useEffect } from 'react'
|
||||
/**
|
||||
* OpenWrite公众号导流插件
|
||||
* 使用介绍:https://openwrite.cn/guide/readmore/readmore.html#%E4%BA%8C%E3%80%81%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8
|
||||
* 登录后台配置你的博客:https://readmore.openwrite.cn/
|
||||
* @returns
|
||||
*/
|
||||
const OpenWrite = () => {
|
||||
const router = useRouter()
|
||||
const qrcode = siteConfig('OPEN_WRITE_QRCODE', '请配置公众号二维码')
|
||||
const blogId = siteConfig('OPEN_WRITE_BLOG_ID')
|
||||
const name = siteConfig('OPEN_WRITE_NAME', '请配置公众号名')
|
||||
const id = 'article-wrapper'
|
||||
const keyword = siteConfig('OPEN_WRITE_KEYWORD', '请配置公众号关键词')
|
||||
const btnText = siteConfig(
|
||||
'OPEN_WRITE_BTN_TEXT',
|
||||
'原创不易,完成人机检测,阅读全文'
|
||||
)
|
||||
// 验证一次后的有效时长,单位小时
|
||||
const cookieAge = siteConfig('OPEN_WRITE_VALIDITY_DURATION', 1)
|
||||
// 白名单
|
||||
const whiteList = siteConfig('OPEN_WRITE_WHITE_LIST', '')
|
||||
|
||||
const loadOpenWrite = async () => {
|
||||
const existWhite = existedWhiteList(router.asPath, whiteList)
|
||||
|
||||
// 如果当前页面在白名单中,则屏蔽加锁
|
||||
if (existWhite) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await loadExternalResource(
|
||||
'https://readmore.openwrite.cn/js/readmore-2.0.js',
|
||||
'js'
|
||||
)
|
||||
const BTWPlugin = window?.BTWPlugin
|
||||
|
||||
if (BTWPlugin) {
|
||||
const btw = new BTWPlugin()
|
||||
window.btw = btw
|
||||
btw.init({
|
||||
qrcode,
|
||||
id,
|
||||
name,
|
||||
btnText,
|
||||
keyword,
|
||||
blogId,
|
||||
cookieAge
|
||||
})
|
||||
|
||||
// btw初始化后,开始监听read-more-wrap何时消失
|
||||
const intervalId = setInterval(() => {
|
||||
const readMoreWrapElement = document.getElementById('read-more-wrap')
|
||||
const articleWrapElement = document.getElementById('article-wrapper')
|
||||
|
||||
if (!readMoreWrapElement && articleWrapElement) {
|
||||
toggleTocItems(false) // 恢复目录项的点击
|
||||
// 自动调整文章区域的高度
|
||||
articleWrapElement.style.height = 'auto'
|
||||
// 停止定时器
|
||||
clearInterval(intervalId)
|
||||
}
|
||||
}, 1000) // 每秒检查一次
|
||||
|
||||
// Return cleanup function to clear the interval if the component unmounts
|
||||
return () => clearInterval(intervalId)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('OpenWrite 加载异常', error)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (isBrowser && blogId) {
|
||||
// Check if the element with id 'read-more-wrap' already exists
|
||||
const readMoreWrap = document.getElementById('read-more-wrap')
|
||||
|
||||
// Only load the script if the element doesn't exist
|
||||
if (!readMoreWrap) {
|
||||
loadOpenWrite()
|
||||
toggleTocItems(true) // 禁止目录项的点击
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 启动一个监听器,当页面上存在#read-more-wrap对象时,所有的 a .notion-table-of-contents-item 对象都禁止点击
|
||||
|
||||
return <></>
|
||||
}
|
||||
|
||||
// 定义禁用和恢复目录项点击的函数
|
||||
const toggleTocItems = disable => {
|
||||
const tocItems = document.querySelectorAll('a.notion-table-of-contents-item')
|
||||
tocItems.forEach(item => {
|
||||
if (disable) {
|
||||
item.style.pointerEvents = 'none'
|
||||
item.style.opacity = '0.5'
|
||||
} else {
|
||||
item.style.pointerEvents = 'auto'
|
||||
item.style.opacity = '1'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查白名单
|
||||
* @param {*} path 当前url的字符串
|
||||
* @param {*} whiteListStr 白名单字符串
|
||||
*/
|
||||
function existedWhiteList(path, whiteListStr) {
|
||||
// 参数检查
|
||||
if (!path || !whiteListStr) {
|
||||
return true
|
||||
}
|
||||
|
||||
// 提取 path 最后一个斜杠后的内容,去掉前面的斜杆
|
||||
// 移除查询参数(从 '?' 开始的部分)和 `.html` 后缀
|
||||
const processedPath = path
|
||||
.replace(/\?.*$/, '') // 移除查询参数
|
||||
.replace(/.*\/([^/]+)(?:\.html)?$/, '$1') // 去掉前面的路径和 .html
|
||||
|
||||
// 严格检查白名单字符串中是否包含处理后的 path
|
||||
// const whiteListArray = whiteListStr.split(',')
|
||||
// return whiteListArray.includes(processedPath)
|
||||
|
||||
// 放宽判断
|
||||
const isWhite = whiteListStr.includes(processedPath)
|
||||
|
||||
if (isWhite) {
|
||||
console.log('OpenWrite白名单', processedPath)
|
||||
}
|
||||
|
||||
return isWhite
|
||||
}
|
||||
|
||||
export default OpenWrite
|
||||
@@ -34,7 +34,7 @@ export function PWA(post, siteInfo) {
|
||||
|
||||
// 删除已有的 manifest link 元素(如果存在)
|
||||
const existingManifest = document.querySelector('link[rel="manifest"]')
|
||||
if (existingManifest) {
|
||||
if (existingManifest && existingManifest.parentNode && existingManifest.parentNode.contains(existingManifest)) {
|
||||
existingManifest.parentNode.removeChild(existingManifest)
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ const loadPrismThemeCSS = (isDarkMode, prismThemeSwitch, prismThemeDarkPath, pri
|
||||
PRISM_PREVIOUS = prismThemeDarkPath
|
||||
}
|
||||
const previousTheme = document.querySelector(`link[href="${PRISM_PREVIOUS}"]`)
|
||||
if (previousTheme) {
|
||||
if (previousTheme && previousTheme.parentNode && previousTheme.parentNode.contains(previousTheme)) {
|
||||
previousTheme.parentNode.removeChild(previousTheme)
|
||||
}
|
||||
loadExternalResource(PRISM_THEME, 'css')
|
||||
|
||||
@@ -6,8 +6,8 @@ import { useEffect } from 'react';
|
||||
*/
|
||||
const useAdjustStyle = () => {
|
||||
/**
|
||||
* 避免 callout 含有图片时溢出撑开父容器
|
||||
*/
|
||||
* 避免 callout 含有图片时溢出撑开父容器
|
||||
*/
|
||||
const adjustCalloutImg = () => {
|
||||
const callOuts = document.querySelectorAll('.notion-callout-text');
|
||||
callOuts.forEach((callout) => {
|
||||
|
||||
@@ -15,12 +15,6 @@ import {
|
||||
} from './lang'
|
||||
const GlobalContext = createContext()
|
||||
|
||||
/**
|
||||
* 定义全局变量,包括语言、主题、深色模式、加载状态
|
||||
* @param children
|
||||
* @returns {JSX.Element}
|
||||
* @constructor
|
||||
*/
|
||||
export function GlobalContextProvider(props) {
|
||||
const {
|
||||
post,
|
||||
@@ -40,7 +34,7 @@ export function GlobalContextProvider(props) {
|
||||
|
||||
const defaultDarkMode = NOTION_CONFIG?.APPEARANCE || APPEARANCE
|
||||
const [isDarkMode, updateDarkMode] = useState(defaultDarkMode === 'dark') // 默认深色模式
|
||||
const [onLoading, setOnLoading] = useState(false) // 抓取文章数据
|
||||
const [onLoading, setOnLoading] = useState(true) // 抓取文章数据
|
||||
const router = useRouter()
|
||||
|
||||
// 是否全屏
|
||||
@@ -74,10 +68,6 @@ export function GlobalContextProvider(props) {
|
||||
htmlElement.classList?.add(newStatus ? 'dark' : 'light')
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新语言
|
||||
* 这里是代码级别的多语言,整个站点和文章内容的多语言不在此处理
|
||||
*/
|
||||
function changeLang(lang) {
|
||||
if (lang) {
|
||||
saveLangToLocalStorage(lang)
|
||||
@@ -89,13 +79,12 @@ export function GlobalContextProvider(props) {
|
||||
useEffect(() => {
|
||||
initDarkMode(updateDarkMode, defaultDarkMode)
|
||||
initLocale(lang, locale, updateLang, updateLocale)
|
||||
// 可以
|
||||
if (NOTION_CONFIG?.REDIRECT_LANG) {
|
||||
redirectUserLang(NOTION_PAGE_ID)
|
||||
}
|
||||
setOnLoading(false)
|
||||
}, [])
|
||||
|
||||
// 加载进度条
|
||||
useEffect(() => {
|
||||
const handleStart = url => {
|
||||
const { theme } = router.query
|
||||
@@ -103,10 +92,15 @@ export function GlobalContextProvider(props) {
|
||||
const newUrl = `${url}${url.includes('?') ? '&' : '?'}theme=${theme}`
|
||||
router.push(newUrl)
|
||||
}
|
||||
setOnLoading(true)
|
||||
if (!onLoading) {
|
||||
setOnLoading(true)
|
||||
}
|
||||
}
|
||||
|
||||
const handleStop = () => {
|
||||
setOnLoading(false)
|
||||
if (onLoading) {
|
||||
setOnLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
const currentTheme = router?.query?.theme || theme
|
||||
@@ -120,7 +114,7 @@ export function GlobalContextProvider(props) {
|
||||
router.events.off('routeChangeComplete', handleStop)
|
||||
router.events.off('routeChangeError', handleStop)
|
||||
}
|
||||
}, [router])
|
||||
}, [router, onLoading])
|
||||
|
||||
return (
|
||||
<GlobalContext.Provider
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import BLOG from '@/blog.config'
|
||||
import { getQueryVariable, isBrowser, mergeDeep } from '@/lib/utils'
|
||||
import enUS from './lang/en-US'
|
||||
import frFR from './lang/fr-FR'
|
||||
@@ -127,6 +128,10 @@ export const redirectUserLang = (lang, pageId) => {
|
||||
if (!window.location.pathname === '/') {
|
||||
return
|
||||
}
|
||||
// 没有开启多语言
|
||||
if (BLOG.NOTION_PAGE_ID.indexOf(',') < 0) {
|
||||
return
|
||||
}
|
||||
|
||||
const userLang =
|
||||
getQueryVariable('locale') ||
|
||||
|
||||
@@ -22,6 +22,7 @@ export default {
|
||||
COMMON: {
|
||||
THEME: 'Theme',
|
||||
ARTICLE_LIST: 'Article List',
|
||||
RECOMMEND_POSTS: 'Recommend Posts',
|
||||
MORE: 'More',
|
||||
NO_MORE: 'No More',
|
||||
LATEST_POSTS: 'Latest posts',
|
||||
|
||||
@@ -22,6 +22,7 @@ export default {
|
||||
COMMON: {
|
||||
THEME: 'Theme',
|
||||
ARTICLE_LIST: '文章列表',
|
||||
RECOMMEND_POSTS: '推荐文章',
|
||||
MORE: '更多',
|
||||
NO_MORE: '没有更多了',
|
||||
LATEST_POSTS: '最新发布',
|
||||
|
||||
@@ -81,49 +81,69 @@ export async function getPageWithRetry(id, from, retryAttempts = 3) {
|
||||
function filterPostBlocks(id, blockMap, slice) {
|
||||
const clonePageBlock = deepClone(blockMap)
|
||||
let count = 0
|
||||
const blocksToProcess = Object.keys(clonePageBlock?.block || {})
|
||||
|
||||
// 循环遍历文档的每个block
|
||||
for (const i in clonePageBlock?.block) {
|
||||
const b = clonePageBlock?.block[i]
|
||||
if (slice && slice > 0 && count > slice) {
|
||||
delete clonePageBlock?.block[i]
|
||||
continue
|
||||
for (let i = 0; i < blocksToProcess.length; i++) {
|
||||
const blockId = blocksToProcess[i]
|
||||
const b = clonePageBlock?.block[blockId]
|
||||
|
||||
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?.id === id) {
|
||||
// 此block含有敏感信息
|
||||
delete b?.value?.properties
|
||||
continue
|
||||
if (b?.value?.properties?.language?.[0][0] === 'C#') {
|
||||
b.value.properties.language[0][0] = 'csharp'
|
||||
}
|
||||
|
||||
count++
|
||||
// 处理 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
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// 去掉不用的字段
|
||||
if (id === BLOG.NOTION_PAGE_ID) {
|
||||
|
||||
@@ -43,7 +43,10 @@ bszCaller = {
|
||||
return function (t) {
|
||||
ready(function () {
|
||||
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) {
|
||||
// console.log(t), bszTag.hides()
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ export function getLastPartOfUrl(url) {
|
||||
* @param type js 或 css
|
||||
* @returns {Promise<unknown>}
|
||||
*/
|
||||
export function loadExternalResource(url, type) {
|
||||
export function loadExternalResource(url, type = 'js') {
|
||||
// 检查是否已存在
|
||||
const elements =
|
||||
type === 'js'
|
||||
|
||||
@@ -15,7 +15,7 @@ const themes = scanSubdirectories(path.resolve(__dirname, 'themes'))
|
||||
const locales = (function () {
|
||||
// 根据BLOG_NOTION_PAGE_ID 检查支持多少种语言数据.
|
||||
// 支持如下格式配置多个语言的页面id xxx,zh:xxx,en:xxx
|
||||
const langs = ['zh', 'en']
|
||||
let langs = [BLOG.LANG.slice(0, 2)]
|
||||
if (BLOG.NOTION_PAGE_ID.indexOf(',') > 0) {
|
||||
const siteIds = BLOG.NOTION_PAGE_ID.split(',')
|
||||
for (let index = 0; index < siteIds.length; index++) {
|
||||
@@ -33,14 +33,26 @@ const locales = (function () {
|
||||
})()
|
||||
|
||||
// 编译前执行
|
||||
// const preBuild = (function () {
|
||||
// // 删除 public/sitemap.xml 文件 ; 否则会和/pages/sitemap.xml.js 冲突。
|
||||
// const sitemapPath = path.resolve(__dirname, 'public', 'sitemap.xml')
|
||||
// if (fs.existsSync(sitemapPath)) {
|
||||
// fs.unlinkSync(sitemapPath)
|
||||
// console.log('Deleted existing sitemap.xml from public directory')
|
||||
// }
|
||||
// })()
|
||||
const preBuild = (function () {
|
||||
if (
|
||||
!process.env.npm_lifecycle_event === 'export' &&
|
||||
!process.env.npm_lifecycle_event === 'build'
|
||||
) {
|
||||
return
|
||||
}
|
||||
// 删除 public/sitemap.xml 文件 ; 否则会和/pages/sitemap.xml.js 冲突。
|
||||
const sitemapPath = path.resolve(__dirname, 'public', 'sitemap.xml')
|
||||
if (fs.existsSync(sitemapPath)) {
|
||||
fs.unlinkSync(sitemapPath)
|
||||
console.log('Deleted existing sitemap.xml from public directory')
|
||||
}
|
||||
|
||||
const sitemap2Path = path.resolve(__dirname, 'sitemap.xml')
|
||||
if (fs.existsSync(sitemap2Path)) {
|
||||
fs.unlinkSync(sitemap2Path)
|
||||
console.log('Deleted existing sitemap.xml from root directory')
|
||||
}
|
||||
})()
|
||||
|
||||
/**
|
||||
* 扫描指定目录下的文件夹名,用于获取所有主题
|
||||
@@ -188,6 +200,10 @@ const nextConfig = {
|
||||
'themes',
|
||||
THEME
|
||||
)
|
||||
// Enable source maps in development mode
|
||||
if (process.env.NODE_ENV_API === 'development') {
|
||||
config.devtool = 'source-map'
|
||||
}
|
||||
return config
|
||||
},
|
||||
experimental: {
|
||||
@@ -204,7 +220,6 @@ const nextConfig = {
|
||||
},
|
||||
publicRuntimeConfig: {
|
||||
// 这里的配置既可以服务端获取到,也可以在浏览器端获取到
|
||||
NODE_ENV_API: process.env.NODE_ENV_API || 'prod',
|
||||
THEMES: themes
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "notion-next",
|
||||
"version": "4.6.1",
|
||||
"version": "4.7.0",
|
||||
"homepage": "https://github.com/tangly1024/NotionNext.git",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import BLOG from '@/blog.config'
|
||||
import useNotification from '@/components/Notification'
|
||||
import OpenWrite from '@/components/OpenWrite'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { getGlobalData, getPost, getPostBlocks } from '@/lib/db/getSiteData'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
@@ -95,8 +96,12 @@ const Slug = props => {
|
||||
})
|
||||
return (
|
||||
<>
|
||||
{/* 文章布局 */}
|
||||
<Layout {...props} />
|
||||
{/* 解锁密码提示框 */}
|
||||
{post?.password && post?.password !== '' && !lock && <Notification />}
|
||||
{/* 导流工具 */}
|
||||
<OpenWrite />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { siteConfig } from '@/lib/config'
|
||||
import { getGlobalData, getPostBlocks } from '@/lib/db/getSiteData'
|
||||
import { generateRobotsTxt } from '@/lib/robots.txt'
|
||||
import { generateRss } from '@/lib/rss'
|
||||
import { generateSitemapXml } from '@/lib/sitemap.xml'
|
||||
import { getLayoutByTheme } from '@/themes/theme'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
@@ -62,6 +63,8 @@ export async function getStaticProps(req) {
|
||||
generateRobotsTxt(props)
|
||||
// 生成Feed订阅
|
||||
generateRss(props)
|
||||
// 生成
|
||||
generateSitemapXml(props)
|
||||
|
||||
// 生成全文索引 - 仅在 yarn build 时执行 && process.env.npm_lifecycle_event === 'build'
|
||||
|
||||
|
||||
916
public/css/aos.css
Normal file
916
public/css/aos.css
Normal file
@@ -0,0 +1,916 @@
|
||||
[data-aos][data-aos][data-aos-duration='50'],
|
||||
body[data-aos-duration='50'] [data-aos] {
|
||||
transition-duration: 50ms;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='50'],
|
||||
body[data-aos-delay='50'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='50'].aos-animate,
|
||||
body[data-aos-delay='50'] [data-aos].aos-animate {
|
||||
transition-delay: 50ms;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='100'],
|
||||
body[data-aos-duration='100'] [data-aos] {
|
||||
transition-duration: 0.1s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='100'],
|
||||
body[data-aos-delay='100'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='100'].aos-animate,
|
||||
body[data-aos-delay='100'] [data-aos].aos-animate {
|
||||
transition-delay: 0.1s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='150'],
|
||||
body[data-aos-duration='150'] [data-aos] {
|
||||
transition-duration: 0.15s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='150'],
|
||||
body[data-aos-delay='150'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='150'].aos-animate,
|
||||
body[data-aos-delay='150'] [data-aos].aos-animate {
|
||||
transition-delay: 0.15s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='200'],
|
||||
body[data-aos-duration='200'] [data-aos] {
|
||||
transition-duration: 0.2s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='200'],
|
||||
body[data-aos-delay='200'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='200'].aos-animate,
|
||||
body[data-aos-delay='200'] [data-aos].aos-animate {
|
||||
transition-delay: 0.2s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='250'],
|
||||
body[data-aos-duration='250'] [data-aos] {
|
||||
transition-duration: 0.25s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='250'],
|
||||
body[data-aos-delay='250'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='250'].aos-animate,
|
||||
body[data-aos-delay='250'] [data-aos].aos-animate {
|
||||
transition-delay: 0.25s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='300'],
|
||||
body[data-aos-duration='300'] [data-aos] {
|
||||
transition-duration: 0.3s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='300'],
|
||||
body[data-aos-delay='300'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='300'].aos-animate,
|
||||
body[data-aos-delay='300'] [data-aos].aos-animate {
|
||||
transition-delay: 0.3s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='350'],
|
||||
body[data-aos-duration='350'] [data-aos] {
|
||||
transition-duration: 0.35s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='350'],
|
||||
body[data-aos-delay='350'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='350'].aos-animate,
|
||||
body[data-aos-delay='350'] [data-aos].aos-animate {
|
||||
transition-delay: 0.35s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='400'],
|
||||
body[data-aos-duration='400'] [data-aos] {
|
||||
transition-duration: 0.4s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='400'],
|
||||
body[data-aos-delay='400'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='400'].aos-animate,
|
||||
body[data-aos-delay='400'] [data-aos].aos-animate {
|
||||
transition-delay: 0.4s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='450'],
|
||||
body[data-aos-duration='450'] [data-aos] {
|
||||
transition-duration: 0.45s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='450'],
|
||||
body[data-aos-delay='450'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='450'].aos-animate,
|
||||
body[data-aos-delay='450'] [data-aos].aos-animate {
|
||||
transition-delay: 0.45s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='500'],
|
||||
body[data-aos-duration='500'] [data-aos] {
|
||||
transition-duration: 0.5s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='500'],
|
||||
body[data-aos-delay='500'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='500'].aos-animate,
|
||||
body[data-aos-delay='500'] [data-aos].aos-animate {
|
||||
transition-delay: 0.5s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='550'],
|
||||
body[data-aos-duration='550'] [data-aos] {
|
||||
transition-duration: 0.55s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='550'],
|
||||
body[data-aos-delay='550'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='550'].aos-animate,
|
||||
body[data-aos-delay='550'] [data-aos].aos-animate {
|
||||
transition-delay: 0.55s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='600'],
|
||||
body[data-aos-duration='600'] [data-aos] {
|
||||
transition-duration: 0.6s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='600'],
|
||||
body[data-aos-delay='600'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='600'].aos-animate,
|
||||
body[data-aos-delay='600'] [data-aos].aos-animate {
|
||||
transition-delay: 0.6s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='650'],
|
||||
body[data-aos-duration='650'] [data-aos] {
|
||||
transition-duration: 0.65s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='650'],
|
||||
body[data-aos-delay='650'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='650'].aos-animate,
|
||||
body[data-aos-delay='650'] [data-aos].aos-animate {
|
||||
transition-delay: 0.65s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='700'],
|
||||
body[data-aos-duration='700'] [data-aos] {
|
||||
transition-duration: 0.7s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='700'],
|
||||
body[data-aos-delay='700'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='700'].aos-animate,
|
||||
body[data-aos-delay='700'] [data-aos].aos-animate {
|
||||
transition-delay: 0.7s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='750'],
|
||||
body[data-aos-duration='750'] [data-aos] {
|
||||
transition-duration: 0.75s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='750'],
|
||||
body[data-aos-delay='750'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='750'].aos-animate,
|
||||
body[data-aos-delay='750'] [data-aos].aos-animate {
|
||||
transition-delay: 0.75s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='800'],
|
||||
body[data-aos-duration='800'] [data-aos] {
|
||||
transition-duration: 0.8s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='800'],
|
||||
body[data-aos-delay='800'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='800'].aos-animate,
|
||||
body[data-aos-delay='800'] [data-aos].aos-animate {
|
||||
transition-delay: 0.8s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='850'],
|
||||
body[data-aos-duration='850'] [data-aos] {
|
||||
transition-duration: 0.85s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='850'],
|
||||
body[data-aos-delay='850'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='850'].aos-animate,
|
||||
body[data-aos-delay='850'] [data-aos].aos-animate {
|
||||
transition-delay: 0.85s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='900'],
|
||||
body[data-aos-duration='900'] [data-aos] {
|
||||
transition-duration: 0.9s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='900'],
|
||||
body[data-aos-delay='900'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='900'].aos-animate,
|
||||
body[data-aos-delay='900'] [data-aos].aos-animate {
|
||||
transition-delay: 0.9s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='950'],
|
||||
body[data-aos-duration='950'] [data-aos] {
|
||||
transition-duration: 0.95s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='950'],
|
||||
body[data-aos-delay='950'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='950'].aos-animate,
|
||||
body[data-aos-delay='950'] [data-aos].aos-animate {
|
||||
transition-delay: 0.95s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='1000'],
|
||||
body[data-aos-duration='1000'] [data-aos] {
|
||||
transition-duration: 1s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1000'],
|
||||
body[data-aos-delay='1000'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1000'].aos-animate,
|
||||
body[data-aos-delay='1000'] [data-aos].aos-animate {
|
||||
transition-delay: 1s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='1050'],
|
||||
body[data-aos-duration='1050'] [data-aos] {
|
||||
transition-duration: 1.05s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1050'],
|
||||
body[data-aos-delay='1050'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1050'].aos-animate,
|
||||
body[data-aos-delay='1050'] [data-aos].aos-animate {
|
||||
transition-delay: 1.05s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='1100'],
|
||||
body[data-aos-duration='1100'] [data-aos] {
|
||||
transition-duration: 1.1s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1100'],
|
||||
body[data-aos-delay='1100'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1100'].aos-animate,
|
||||
body[data-aos-delay='1100'] [data-aos].aos-animate {
|
||||
transition-delay: 1.1s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='1150'],
|
||||
body[data-aos-duration='1150'] [data-aos] {
|
||||
transition-duration: 1.15s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1150'],
|
||||
body[data-aos-delay='1150'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1150'].aos-animate,
|
||||
body[data-aos-delay='1150'] [data-aos].aos-animate {
|
||||
transition-delay: 1.15s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='1200'],
|
||||
body[data-aos-duration='1200'] [data-aos] {
|
||||
transition-duration: 1.2s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1200'],
|
||||
body[data-aos-delay='1200'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1200'].aos-animate,
|
||||
body[data-aos-delay='1200'] [data-aos].aos-animate {
|
||||
transition-delay: 1.2s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='1250'],
|
||||
body[data-aos-duration='1250'] [data-aos] {
|
||||
transition-duration: 1.25s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1250'],
|
||||
body[data-aos-delay='1250'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1250'].aos-animate,
|
||||
body[data-aos-delay='1250'] [data-aos].aos-animate {
|
||||
transition-delay: 1.25s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='1300'],
|
||||
body[data-aos-duration='1300'] [data-aos] {
|
||||
transition-duration: 1.3s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1300'],
|
||||
body[data-aos-delay='1300'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1300'].aos-animate,
|
||||
body[data-aos-delay='1300'] [data-aos].aos-animate {
|
||||
transition-delay: 1.3s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='1350'],
|
||||
body[data-aos-duration='1350'] [data-aos] {
|
||||
transition-duration: 1.35s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1350'],
|
||||
body[data-aos-delay='1350'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1350'].aos-animate,
|
||||
body[data-aos-delay='1350'] [data-aos].aos-animate {
|
||||
transition-delay: 1.35s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='1400'],
|
||||
body[data-aos-duration='1400'] [data-aos] {
|
||||
transition-duration: 1.4s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1400'],
|
||||
body[data-aos-delay='1400'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1400'].aos-animate,
|
||||
body[data-aos-delay='1400'] [data-aos].aos-animate {
|
||||
transition-delay: 1.4s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='1450'],
|
||||
body[data-aos-duration='1450'] [data-aos] {
|
||||
transition-duration: 1.45s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1450'],
|
||||
body[data-aos-delay='1450'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1450'].aos-animate,
|
||||
body[data-aos-delay='1450'] [data-aos].aos-animate {
|
||||
transition-delay: 1.45s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='1500'],
|
||||
body[data-aos-duration='1500'] [data-aos] {
|
||||
transition-duration: 1.5s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1500'],
|
||||
body[data-aos-delay='1500'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1500'].aos-animate,
|
||||
body[data-aos-delay='1500'] [data-aos].aos-animate {
|
||||
transition-delay: 1.5s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='1550'],
|
||||
body[data-aos-duration='1550'] [data-aos] {
|
||||
transition-duration: 1.55s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1550'],
|
||||
body[data-aos-delay='1550'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1550'].aos-animate,
|
||||
body[data-aos-delay='1550'] [data-aos].aos-animate {
|
||||
transition-delay: 1.55s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='1600'],
|
||||
body[data-aos-duration='1600'] [data-aos] {
|
||||
transition-duration: 1.6s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1600'],
|
||||
body[data-aos-delay='1600'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1600'].aos-animate,
|
||||
body[data-aos-delay='1600'] [data-aos].aos-animate {
|
||||
transition-delay: 1.6s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='1650'],
|
||||
body[data-aos-duration='1650'] [data-aos] {
|
||||
transition-duration: 1.65s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1650'],
|
||||
body[data-aos-delay='1650'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1650'].aos-animate,
|
||||
body[data-aos-delay='1650'] [data-aos].aos-animate {
|
||||
transition-delay: 1.65s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='1700'],
|
||||
body[data-aos-duration='1700'] [data-aos] {
|
||||
transition-duration: 1.7s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1700'],
|
||||
body[data-aos-delay='1700'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1700'].aos-animate,
|
||||
body[data-aos-delay='1700'] [data-aos].aos-animate {
|
||||
transition-delay: 1.7s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='1750'],
|
||||
body[data-aos-duration='1750'] [data-aos] {
|
||||
transition-duration: 1.75s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1750'],
|
||||
body[data-aos-delay='1750'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1750'].aos-animate,
|
||||
body[data-aos-delay='1750'] [data-aos].aos-animate {
|
||||
transition-delay: 1.75s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='1800'],
|
||||
body[data-aos-duration='1800'] [data-aos] {
|
||||
transition-duration: 1.8s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1800'],
|
||||
body[data-aos-delay='1800'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1800'].aos-animate,
|
||||
body[data-aos-delay='1800'] [data-aos].aos-animate {
|
||||
transition-delay: 1.8s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='1850'],
|
||||
body[data-aos-duration='1850'] [data-aos] {
|
||||
transition-duration: 1.85s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1850'],
|
||||
body[data-aos-delay='1850'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1850'].aos-animate,
|
||||
body[data-aos-delay='1850'] [data-aos].aos-animate {
|
||||
transition-delay: 1.85s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='1900'],
|
||||
body[data-aos-duration='1900'] [data-aos] {
|
||||
transition-duration: 1.9s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1900'],
|
||||
body[data-aos-delay='1900'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1900'].aos-animate,
|
||||
body[data-aos-delay='1900'] [data-aos].aos-animate {
|
||||
transition-delay: 1.9s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='1950'],
|
||||
body[data-aos-duration='1950'] [data-aos] {
|
||||
transition-duration: 1.95s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1950'],
|
||||
body[data-aos-delay='1950'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='1950'].aos-animate,
|
||||
body[data-aos-delay='1950'] [data-aos].aos-animate {
|
||||
transition-delay: 1.95s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='2000'],
|
||||
body[data-aos-duration='2000'] [data-aos] {
|
||||
transition-duration: 2s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2000'],
|
||||
body[data-aos-delay='2000'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2000'].aos-animate,
|
||||
body[data-aos-delay='2000'] [data-aos].aos-animate {
|
||||
transition-delay: 2s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='2050'],
|
||||
body[data-aos-duration='2050'] [data-aos] {
|
||||
transition-duration: 2.05s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2050'],
|
||||
body[data-aos-delay='2050'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2050'].aos-animate,
|
||||
body[data-aos-delay='2050'] [data-aos].aos-animate {
|
||||
transition-delay: 2.05s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='2100'],
|
||||
body[data-aos-duration='2100'] [data-aos] {
|
||||
transition-duration: 2.1s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2100'],
|
||||
body[data-aos-delay='2100'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2100'].aos-animate,
|
||||
body[data-aos-delay='2100'] [data-aos].aos-animate {
|
||||
transition-delay: 2.1s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='2150'],
|
||||
body[data-aos-duration='2150'] [data-aos] {
|
||||
transition-duration: 2.15s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2150'],
|
||||
body[data-aos-delay='2150'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2150'].aos-animate,
|
||||
body[data-aos-delay='2150'] [data-aos].aos-animate {
|
||||
transition-delay: 2.15s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='2200'],
|
||||
body[data-aos-duration='2200'] [data-aos] {
|
||||
transition-duration: 2.2s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2200'],
|
||||
body[data-aos-delay='2200'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2200'].aos-animate,
|
||||
body[data-aos-delay='2200'] [data-aos].aos-animate {
|
||||
transition-delay: 2.2s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='2250'],
|
||||
body[data-aos-duration='2250'] [data-aos] {
|
||||
transition-duration: 2.25s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2250'],
|
||||
body[data-aos-delay='2250'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2250'].aos-animate,
|
||||
body[data-aos-delay='2250'] [data-aos].aos-animate {
|
||||
transition-delay: 2.25s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='2300'],
|
||||
body[data-aos-duration='2300'] [data-aos] {
|
||||
transition-duration: 2.3s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2300'],
|
||||
body[data-aos-delay='2300'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2300'].aos-animate,
|
||||
body[data-aos-delay='2300'] [data-aos].aos-animate {
|
||||
transition-delay: 2.3s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='2350'],
|
||||
body[data-aos-duration='2350'] [data-aos] {
|
||||
transition-duration: 2.35s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2350'],
|
||||
body[data-aos-delay='2350'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2350'].aos-animate,
|
||||
body[data-aos-delay='2350'] [data-aos].aos-animate {
|
||||
transition-delay: 2.35s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='2400'],
|
||||
body[data-aos-duration='2400'] [data-aos] {
|
||||
transition-duration: 2.4s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2400'],
|
||||
body[data-aos-delay='2400'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2400'].aos-animate,
|
||||
body[data-aos-delay='2400'] [data-aos].aos-animate {
|
||||
transition-delay: 2.4s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='2450'],
|
||||
body[data-aos-duration='2450'] [data-aos] {
|
||||
transition-duration: 2.45s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2450'],
|
||||
body[data-aos-delay='2450'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2450'].aos-animate,
|
||||
body[data-aos-delay='2450'] [data-aos].aos-animate {
|
||||
transition-delay: 2.45s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='2500'],
|
||||
body[data-aos-duration='2500'] [data-aos] {
|
||||
transition-duration: 2.5s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2500'],
|
||||
body[data-aos-delay='2500'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2500'].aos-animate,
|
||||
body[data-aos-delay='2500'] [data-aos].aos-animate {
|
||||
transition-delay: 2.5s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='2550'],
|
||||
body[data-aos-duration='2550'] [data-aos] {
|
||||
transition-duration: 2.55s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2550'],
|
||||
body[data-aos-delay='2550'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2550'].aos-animate,
|
||||
body[data-aos-delay='2550'] [data-aos].aos-animate {
|
||||
transition-delay: 2.55s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='2600'],
|
||||
body[data-aos-duration='2600'] [data-aos] {
|
||||
transition-duration: 2.6s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2600'],
|
||||
body[data-aos-delay='2600'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2600'].aos-animate,
|
||||
body[data-aos-delay='2600'] [data-aos].aos-animate {
|
||||
transition-delay: 2.6s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='2650'],
|
||||
body[data-aos-duration='2650'] [data-aos] {
|
||||
transition-duration: 2.65s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2650'],
|
||||
body[data-aos-delay='2650'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2650'].aos-animate,
|
||||
body[data-aos-delay='2650'] [data-aos].aos-animate {
|
||||
transition-delay: 2.65s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='2700'],
|
||||
body[data-aos-duration='2700'] [data-aos] {
|
||||
transition-duration: 2.7s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2700'],
|
||||
body[data-aos-delay='2700'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2700'].aos-animate,
|
||||
body[data-aos-delay='2700'] [data-aos].aos-animate {
|
||||
transition-delay: 2.7s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='2750'],
|
||||
body[data-aos-duration='2750'] [data-aos] {
|
||||
transition-duration: 2.75s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2750'],
|
||||
body[data-aos-delay='2750'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2750'].aos-animate,
|
||||
body[data-aos-delay='2750'] [data-aos].aos-animate {
|
||||
transition-delay: 2.75s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='2800'],
|
||||
body[data-aos-duration='2800'] [data-aos] {
|
||||
transition-duration: 2.8s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2800'],
|
||||
body[data-aos-delay='2800'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2800'].aos-animate,
|
||||
body[data-aos-delay='2800'] [data-aos].aos-animate {
|
||||
transition-delay: 2.8s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='2850'],
|
||||
body[data-aos-duration='2850'] [data-aos] {
|
||||
transition-duration: 2.85s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2850'],
|
||||
body[data-aos-delay='2850'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2850'].aos-animate,
|
||||
body[data-aos-delay='2850'] [data-aos].aos-animate {
|
||||
transition-delay: 2.85s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='2900'],
|
||||
body[data-aos-duration='2900'] [data-aos] {
|
||||
transition-duration: 2.9s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2900'],
|
||||
body[data-aos-delay='2900'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2900'].aos-animate,
|
||||
body[data-aos-delay='2900'] [data-aos].aos-animate {
|
||||
transition-delay: 2.9s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='2950'],
|
||||
body[data-aos-duration='2950'] [data-aos] {
|
||||
transition-duration: 2.95s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2950'],
|
||||
body[data-aos-delay='2950'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='2950'].aos-animate,
|
||||
body[data-aos-delay='2950'] [data-aos].aos-animate {
|
||||
transition-delay: 2.95s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-duration='3000'],
|
||||
body[data-aos-duration='3000'] [data-aos] {
|
||||
transition-duration: 3s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='3000'],
|
||||
body[data-aos-delay='3000'] [data-aos] {
|
||||
transition-delay: 0;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-delay='3000'].aos-animate,
|
||||
body[data-aos-delay='3000'] [data-aos].aos-animate {
|
||||
transition-delay: 3s;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-easing='linear'],
|
||||
body[data-aos-easing='linear'] [data-aos] {
|
||||
transition-timing-function: cubic-bezier(0.25, 0.25, 0.75, 0.75);
|
||||
}
|
||||
[data-aos][data-aos][data-aos-easing='ease'],
|
||||
body[data-aos-easing='ease'] [data-aos] {
|
||||
transition-timing-function: ease;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-easing='ease-in'],
|
||||
body[data-aos-easing='ease-in'] [data-aos] {
|
||||
transition-timing-function: ease-in;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-easing='ease-out'],
|
||||
body[data-aos-easing='ease-out'] [data-aos] {
|
||||
transition-timing-function: ease-out;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-easing='ease-in-out'],
|
||||
body[data-aos-easing='ease-in-out'] [data-aos] {
|
||||
transition-timing-function: ease-in-out;
|
||||
}
|
||||
[data-aos][data-aos][data-aos-easing='ease-in-back'],
|
||||
body[data-aos-easing='ease-in-back'] [data-aos] {
|
||||
transition-timing-function: cubic-bezier(0.6, -0.28, 0.735, 0.045);
|
||||
}
|
||||
[data-aos][data-aos][data-aos-easing='ease-out-back'],
|
||||
body[data-aos-easing='ease-out-back'] [data-aos] {
|
||||
transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
}
|
||||
[data-aos][data-aos][data-aos-easing='ease-in-out-back'],
|
||||
body[data-aos-easing='ease-in-out-back'] [data-aos] {
|
||||
transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
}
|
||||
[data-aos][data-aos][data-aos-easing='ease-in-sine'],
|
||||
body[data-aos-easing='ease-in-sine'] [data-aos] {
|
||||
transition-timing-function: cubic-bezier(0.47, 0, 0.745, 0.715);
|
||||
}
|
||||
[data-aos][data-aos][data-aos-easing='ease-out-sine'],
|
||||
body[data-aos-easing='ease-out-sine'] [data-aos] {
|
||||
transition-timing-function: cubic-bezier(0.39, 0.575, 0.565, 1);
|
||||
}
|
||||
[data-aos][data-aos][data-aos-easing='ease-in-out-sine'],
|
||||
body[data-aos-easing='ease-in-out-sine'] [data-aos] {
|
||||
transition-timing-function: cubic-bezier(0.445, 0.05, 0.55, 0.95);
|
||||
}
|
||||
[data-aos][data-aos][data-aos-easing='ease-in-quad'],
|
||||
body[data-aos-easing='ease-in-quad'] [data-aos] {
|
||||
transition-timing-function: cubic-bezier(0.55, 0.085, 0.68, 0.53);
|
||||
}
|
||||
[data-aos][data-aos][data-aos-easing='ease-out-quad'],
|
||||
body[data-aos-easing='ease-out-quad'] [data-aos] {
|
||||
transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
}
|
||||
[data-aos][data-aos][data-aos-easing='ease-in-out-quad'],
|
||||
body[data-aos-easing='ease-in-out-quad'] [data-aos] {
|
||||
transition-timing-function: cubic-bezier(0.455, 0.03, 0.515, 0.955);
|
||||
}
|
||||
[data-aos][data-aos][data-aos-easing='ease-in-cubic'],
|
||||
body[data-aos-easing='ease-in-cubic'] [data-aos] {
|
||||
transition-timing-function: cubic-bezier(0.55, 0.085, 0.68, 0.53);
|
||||
}
|
||||
[data-aos][data-aos][data-aos-easing='ease-out-cubic'],
|
||||
body[data-aos-easing='ease-out-cubic'] [data-aos] {
|
||||
transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
}
|
||||
[data-aos][data-aos][data-aos-easing='ease-in-out-cubic'],
|
||||
body[data-aos-easing='ease-in-out-cubic'] [data-aos] {
|
||||
transition-timing-function: cubic-bezier(0.455, 0.03, 0.515, 0.955);
|
||||
}
|
||||
[data-aos][data-aos][data-aos-easing='ease-in-quart'],
|
||||
body[data-aos-easing='ease-in-quart'] [data-aos] {
|
||||
transition-timing-function: cubic-bezier(0.55, 0.085, 0.68, 0.53);
|
||||
}
|
||||
[data-aos][data-aos][data-aos-easing='ease-out-quart'],
|
||||
body[data-aos-easing='ease-out-quart'] [data-aos] {
|
||||
transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
}
|
||||
[data-aos][data-aos][data-aos-easing='ease-in-out-quart'],
|
||||
body[data-aos-easing='ease-in-out-quart'] [data-aos] {
|
||||
transition-timing-function: cubic-bezier(0.455, 0.03, 0.515, 0.955);
|
||||
}
|
||||
[data-aos^='fade'][data-aos^='fade'] {
|
||||
opacity: 0;
|
||||
transition-property: opacity, transform;
|
||||
}
|
||||
[data-aos^='fade'][data-aos^='fade'].aos-animate {
|
||||
opacity: 1;
|
||||
transform: translateZ(0);
|
||||
}
|
||||
[data-aos='fade-up'] {
|
||||
transform: translate3d(0, 100px, 0);
|
||||
}
|
||||
[data-aos='fade-down'] {
|
||||
transform: translate3d(0, -100px, 0);
|
||||
}
|
||||
[data-aos='fade-right'] {
|
||||
transform: translate3d(-100px, 0, 0);
|
||||
}
|
||||
[data-aos='fade-left'] {
|
||||
transform: translate3d(100px, 0, 0);
|
||||
}
|
||||
[data-aos='fade-up-right'] {
|
||||
transform: translate3d(-100px, 100px, 0);
|
||||
}
|
||||
[data-aos='fade-up-left'] {
|
||||
transform: translate3d(100px, 100px, 0);
|
||||
}
|
||||
[data-aos='fade-down-right'] {
|
||||
transform: translate3d(-100px, -100px, 0);
|
||||
}
|
||||
[data-aos='fade-down-left'] {
|
||||
transform: translate3d(100px, -100px, 0);
|
||||
}
|
||||
[data-aos^='zoom'][data-aos^='zoom'] {
|
||||
opacity: 0;
|
||||
transition-property: opacity, transform;
|
||||
}
|
||||
[data-aos^='zoom'][data-aos^='zoom'].aos-animate {
|
||||
opacity: 1;
|
||||
transform: translateZ(0) scale(1);
|
||||
}
|
||||
[data-aos='zoom-in'] {
|
||||
transform: scale(0.6);
|
||||
}
|
||||
[data-aos='zoom-in-up'] {
|
||||
transform: translate3d(0, 100px, 0) scale(0.6);
|
||||
}
|
||||
[data-aos='zoom-in-down'] {
|
||||
transform: translate3d(0, -100px, 0) scale(0.6);
|
||||
}
|
||||
[data-aos='zoom-in-right'] {
|
||||
transform: translate3d(-100px, 0, 0) scale(0.6);
|
||||
}
|
||||
[data-aos='zoom-in-left'] {
|
||||
transform: translate3d(100px, 0, 0) scale(0.6);
|
||||
}
|
||||
[data-aos='zoom-out'] {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
[data-aos='zoom-out-up'] {
|
||||
transform: translate3d(0, 100px, 0) scale(1.2);
|
||||
}
|
||||
[data-aos='zoom-out-down'] {
|
||||
transform: translate3d(0, -100px, 0) scale(1.2);
|
||||
}
|
||||
[data-aos='zoom-out-right'] {
|
||||
transform: translate3d(-100px, 0, 0) scale(1.2);
|
||||
}
|
||||
[data-aos='zoom-out-left'] {
|
||||
transform: translate3d(100px, 0, 0) scale(1.2);
|
||||
}
|
||||
[data-aos^='slide'][data-aos^='slide'] {
|
||||
transition-property: transform;
|
||||
}
|
||||
[data-aos^='slide'][data-aos^='slide'].aos-animate {
|
||||
transform: translateZ(0);
|
||||
}
|
||||
[data-aos='slide-up'] {
|
||||
transform: translate3d(0, 100%, 0);
|
||||
}
|
||||
[data-aos='slide-down'] {
|
||||
transform: translate3d(0, -100%, 0);
|
||||
}
|
||||
[data-aos='slide-right'] {
|
||||
transform: translate3d(-100%, 0, 0);
|
||||
}
|
||||
[data-aos='slide-left'] {
|
||||
transform: translate3d(100%, 0, 0);
|
||||
}
|
||||
[data-aos^='flip'][data-aos^='flip'] {
|
||||
backface-visibility: hidden;
|
||||
transition-property: transform;
|
||||
}
|
||||
[data-aos='flip-left'] {
|
||||
transform: perspective(2500px) rotateY(-100deg);
|
||||
}
|
||||
[data-aos='flip-left'].aos-animate {
|
||||
transform: perspective(2500px) rotateY(0);
|
||||
}
|
||||
[data-aos='flip-right'] {
|
||||
transform: perspective(2500px) rotateY(100deg);
|
||||
}
|
||||
[data-aos='flip-right'].aos-animate {
|
||||
transform: perspective(2500px) rotateY(0);
|
||||
}
|
||||
[data-aos='flip-up'] {
|
||||
transform: perspective(2500px) rotateX(-100deg);
|
||||
}
|
||||
[data-aos='flip-up'].aos-animate {
|
||||
transform: perspective(2500px) rotateX(0);
|
||||
}
|
||||
[data-aos='flip-down'] {
|
||||
transform: perspective(2500px) rotateX(100deg);
|
||||
}
|
||||
[data-aos='flip-down'].aos-animate {
|
||||
transform: perspective(2500px) rotateX(0);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/* 图片阴影 */
|
||||
.notion-asset-wrapper-image img {
|
||||
article .notion-asset-wrapper-image img {
|
||||
box-shadow:
|
||||
rgba(50, 50, 93, 0.25) 0px 13px 27px -5px,
|
||||
rgba(0, 0, 0, 0.3) 0px 8px 16px -8px;
|
||||
|
||||
672
public/js/aos.js
Normal file
672
public/js/aos.js
Normal file
@@ -0,0 +1,672 @@
|
||||
!(function (e, t) {
|
||||
'object' == typeof exports && 'object' == typeof module
|
||||
? (module.exports = t())
|
||||
: 'function' == typeof define && define.amd
|
||||
? define([], t)
|
||||
: 'object' == typeof exports
|
||||
? (exports.AOS = t())
|
||||
: (e.AOS = t())
|
||||
})(this, function () {
|
||||
return (function (e) {
|
||||
function t(o) {
|
||||
if (n[o]) return n[o].exports
|
||||
var i = (n[o] = { exports: {}, id: o, loaded: !1 })
|
||||
return e[o].call(i.exports, i, i.exports, t), (i.loaded = !0), i.exports
|
||||
}
|
||||
var n = {}
|
||||
return (t.m = e), (t.c = n), (t.p = 'dist/'), t(0)
|
||||
})([
|
||||
function (e, t, n) {
|
||||
'use strict'
|
||||
function o(e) {
|
||||
return e && e.__esModule ? e : { default: e }
|
||||
}
|
||||
var i =
|
||||
Object.assign ||
|
||||
function (e) {
|
||||
for (var t = 1; t < arguments.length; t++) {
|
||||
var n = arguments[t]
|
||||
for (var o in n)
|
||||
Object.prototype.hasOwnProperty.call(n, o) && (e[o] = n[o])
|
||||
}
|
||||
return e
|
||||
},
|
||||
r = n(1),
|
||||
a = (o(r), n(6)),
|
||||
u = o(a),
|
||||
c = n(7),
|
||||
s = o(c),
|
||||
f = n(8),
|
||||
d = o(f),
|
||||
l = n(9),
|
||||
p = o(l),
|
||||
m = n(10),
|
||||
b = o(m),
|
||||
v = n(11),
|
||||
y = o(v),
|
||||
g = n(14),
|
||||
h = o(g),
|
||||
w = [],
|
||||
k = !1,
|
||||
x = {
|
||||
offset: 120,
|
||||
delay: 0,
|
||||
easing: 'ease',
|
||||
duration: 400,
|
||||
disable: !1,
|
||||
once: !1,
|
||||
startEvent: 'DOMContentLoaded',
|
||||
throttleDelay: 99,
|
||||
debounceDelay: 50,
|
||||
disableMutationObserver: !1
|
||||
},
|
||||
j = function () {
|
||||
var e =
|
||||
arguments.length > 0 && void 0 !== arguments[0] && arguments[0]
|
||||
if ((e && (k = !0), k))
|
||||
return (w = (0, y.default)(w, x)), (0, b.default)(w, x.once), w
|
||||
},
|
||||
O = function () {
|
||||
;(w = (0, h.default)()), j()
|
||||
},
|
||||
M = function () {
|
||||
w.forEach(function (e, t) {
|
||||
e.node.removeAttribute('data-aos'),
|
||||
e.node.removeAttribute('data-aos-easing'),
|
||||
e.node.removeAttribute('data-aos-duration'),
|
||||
e.node.removeAttribute('data-aos-delay')
|
||||
})
|
||||
},
|
||||
S = function (e) {
|
||||
return (
|
||||
e === !0 ||
|
||||
('mobile' === e && p.default.mobile()) ||
|
||||
('phone' === e && p.default.phone()) ||
|
||||
('tablet' === e && p.default.tablet()) ||
|
||||
('function' == typeof e && e() === !0)
|
||||
)
|
||||
},
|
||||
_ = function (e) {
|
||||
;(x = i(x, e)), (w = (0, h.default)())
|
||||
var t = document.all && !window.atob
|
||||
return S(x.disable) || t
|
||||
? M()
|
||||
: (x.disableMutationObserver ||
|
||||
d.default.isSupported() ||
|
||||
(console.info(
|
||||
'\n aos: MutationObserver is not supported on this browser,\n code mutations observing has been disabled.\n You may have to call "refreshHard()" by yourself.\n '
|
||||
),
|
||||
(x.disableMutationObserver = !0)),
|
||||
document
|
||||
.querySelector('body')
|
||||
.setAttribute('data-aos-easing', x.easing),
|
||||
document
|
||||
.querySelector('body')
|
||||
.setAttribute('data-aos-duration', x.duration),
|
||||
document
|
||||
.querySelector('body')
|
||||
.setAttribute('data-aos-delay', x.delay),
|
||||
'DOMContentLoaded' === x.startEvent &&
|
||||
['complete', 'interactive'].indexOf(document.readyState) > -1
|
||||
? j(!0)
|
||||
: 'load' === x.startEvent
|
||||
? window.addEventListener(x.startEvent, function () {
|
||||
j(!0)
|
||||
})
|
||||
: document.addEventListener(x.startEvent, function () {
|
||||
j(!0)
|
||||
}),
|
||||
window.addEventListener(
|
||||
'resize',
|
||||
(0, s.default)(j, x.debounceDelay, !0)
|
||||
),
|
||||
window.addEventListener(
|
||||
'orientationchange',
|
||||
(0, s.default)(j, x.debounceDelay, !0)
|
||||
),
|
||||
window.addEventListener(
|
||||
'scroll',
|
||||
(0, u.default)(function () {
|
||||
;(0, b.default)(w, x.once)
|
||||
}, x.throttleDelay)
|
||||
),
|
||||
x.disableMutationObserver || d.default.ready('[data-aos]', O),
|
||||
w)
|
||||
}
|
||||
e.exports = { init: _, refresh: j, refreshHard: O }
|
||||
},
|
||||
function (e, t) {},
|
||||
,
|
||||
,
|
||||
,
|
||||
,
|
||||
function (e, t) {
|
||||
;(function (t) {
|
||||
'use strict'
|
||||
function n(e, t, n) {
|
||||
function o(t) {
|
||||
var n = b,
|
||||
o = v
|
||||
return (b = v = void 0), (k = t), (g = e.apply(o, n))
|
||||
}
|
||||
function r(e) {
|
||||
return (k = e), (h = setTimeout(f, t)), M ? o(e) : g
|
||||
}
|
||||
function a(e) {
|
||||
var n = e - w,
|
||||
o = e - k,
|
||||
i = t - n
|
||||
return S ? j(i, y - o) : i
|
||||
}
|
||||
function c(e) {
|
||||
var n = e - w,
|
||||
o = e - k
|
||||
return void 0 === w || n >= t || n < 0 || (S && o >= y)
|
||||
}
|
||||
function f() {
|
||||
var e = O()
|
||||
return c(e) ? d(e) : void (h = setTimeout(f, a(e)))
|
||||
}
|
||||
function d(e) {
|
||||
return (h = void 0), _ && b ? o(e) : ((b = v = void 0), g)
|
||||
}
|
||||
function l() {
|
||||
void 0 !== h && clearTimeout(h), (k = 0), (b = w = v = h = void 0)
|
||||
}
|
||||
function p() {
|
||||
return void 0 === h ? g : d(O())
|
||||
}
|
||||
function m() {
|
||||
var e = O(),
|
||||
n = c(e)
|
||||
if (((b = arguments), (v = this), (w = e), n)) {
|
||||
if (void 0 === h) return r(w)
|
||||
if (S) return (h = setTimeout(f, t)), o(w)
|
||||
}
|
||||
return void 0 === h && (h = setTimeout(f, t)), g
|
||||
}
|
||||
var b,
|
||||
v,
|
||||
y,
|
||||
g,
|
||||
h,
|
||||
w,
|
||||
k = 0,
|
||||
M = !1,
|
||||
S = !1,
|
||||
_ = !0
|
||||
if ('function' != typeof e) throw new TypeError(s)
|
||||
return (
|
||||
(t = u(t) || 0),
|
||||
i(n) &&
|
||||
((M = !!n.leading),
|
||||
(S = 'maxWait' in n),
|
||||
(y = S ? x(u(n.maxWait) || 0, t) : y),
|
||||
(_ = 'trailing' in n ? !!n.trailing : _)),
|
||||
(m.cancel = l),
|
||||
(m.flush = p),
|
||||
m
|
||||
)
|
||||
}
|
||||
function o(e, t, o) {
|
||||
var r = !0,
|
||||
a = !0
|
||||
if ('function' != typeof e) throw new TypeError(s)
|
||||
return (
|
||||
i(o) &&
|
||||
((r = 'leading' in o ? !!o.leading : r),
|
||||
(a = 'trailing' in o ? !!o.trailing : a)),
|
||||
n(e, t, { leading: r, maxWait: t, trailing: a })
|
||||
)
|
||||
}
|
||||
function i(e) {
|
||||
var t = 'undefined' == typeof e ? 'undefined' : c(e)
|
||||
return !!e && ('object' == t || 'function' == t)
|
||||
}
|
||||
function r(e) {
|
||||
return (
|
||||
!!e && 'object' == ('undefined' == typeof e ? 'undefined' : c(e))
|
||||
)
|
||||
}
|
||||
function a(e) {
|
||||
return (
|
||||
'symbol' == ('undefined' == typeof e ? 'undefined' : c(e)) ||
|
||||
(r(e) && k.call(e) == d)
|
||||
)
|
||||
}
|
||||
function u(e) {
|
||||
if ('number' == typeof e) return e
|
||||
if (a(e)) return f
|
||||
if (i(e)) {
|
||||
var t = 'function' == typeof e.valueOf ? e.valueOf() : e
|
||||
e = i(t) ? t + '' : t
|
||||
}
|
||||
if ('string' != typeof e) return 0 === e ? e : +e
|
||||
e = e.replace(l, '')
|
||||
var n = m.test(e)
|
||||
return n || b.test(e) ? v(e.slice(2), n ? 2 : 8) : p.test(e) ? f : +e
|
||||
}
|
||||
var c =
|
||||
'function' == typeof Symbol && 'symbol' == typeof Symbol.iterator
|
||||
? function (e) {
|
||||
return typeof e
|
||||
}
|
||||
: function (e) {
|
||||
return e &&
|
||||
'function' == typeof Symbol &&
|
||||
e.constructor === Symbol &&
|
||||
e !== Symbol.prototype
|
||||
? 'symbol'
|
||||
: typeof e
|
||||
},
|
||||
s = 'Expected a function',
|
||||
f = NaN,
|
||||
d = '[object Symbol]',
|
||||
l = /^\s+|\s+$/g,
|
||||
p = /^[-+]0x[0-9a-f]+$/i,
|
||||
m = /^0b[01]+$/i,
|
||||
b = /^0o[0-7]+$/i,
|
||||
v = parseInt,
|
||||
y =
|
||||
'object' == ('undefined' == typeof t ? 'undefined' : c(t)) &&
|
||||
t &&
|
||||
t.Object === Object &&
|
||||
t,
|
||||
g =
|
||||
'object' == ('undefined' == typeof self ? 'undefined' : c(self)) &&
|
||||
self &&
|
||||
self.Object === Object &&
|
||||
self,
|
||||
h = y || g || Function('return this')(),
|
||||
w = Object.prototype,
|
||||
k = w.toString,
|
||||
x = Math.max,
|
||||
j = Math.min,
|
||||
O = function () {
|
||||
return h.Date.now()
|
||||
}
|
||||
e.exports = o
|
||||
}).call(
|
||||
t,
|
||||
(function () {
|
||||
return this
|
||||
})()
|
||||
)
|
||||
},
|
||||
function (e, t) {
|
||||
;(function (t) {
|
||||
'use strict'
|
||||
function n(e, t, n) {
|
||||
function i(t) {
|
||||
var n = b,
|
||||
o = v
|
||||
return (b = v = void 0), (O = t), (g = e.apply(o, n))
|
||||
}
|
||||
function r(e) {
|
||||
return (O = e), (h = setTimeout(f, t)), M ? i(e) : g
|
||||
}
|
||||
function u(e) {
|
||||
var n = e - w,
|
||||
o = e - O,
|
||||
i = t - n
|
||||
return S ? x(i, y - o) : i
|
||||
}
|
||||
function s(e) {
|
||||
var n = e - w,
|
||||
o = e - O
|
||||
return void 0 === w || n >= t || n < 0 || (S && o >= y)
|
||||
}
|
||||
function f() {
|
||||
var e = j()
|
||||
return s(e) ? d(e) : void (h = setTimeout(f, u(e)))
|
||||
}
|
||||
function d(e) {
|
||||
return (h = void 0), _ && b ? i(e) : ((b = v = void 0), g)
|
||||
}
|
||||
function l() {
|
||||
void 0 !== h && clearTimeout(h), (O = 0), (b = w = v = h = void 0)
|
||||
}
|
||||
function p() {
|
||||
return void 0 === h ? g : d(j())
|
||||
}
|
||||
function m() {
|
||||
var e = j(),
|
||||
n = s(e)
|
||||
if (((b = arguments), (v = this), (w = e), n)) {
|
||||
if (void 0 === h) return r(w)
|
||||
if (S) return (h = setTimeout(f, t)), i(w)
|
||||
}
|
||||
return void 0 === h && (h = setTimeout(f, t)), g
|
||||
}
|
||||
var b,
|
||||
v,
|
||||
y,
|
||||
g,
|
||||
h,
|
||||
w,
|
||||
O = 0,
|
||||
M = !1,
|
||||
S = !1,
|
||||
_ = !0
|
||||
if ('function' != typeof e) throw new TypeError(c)
|
||||
return (
|
||||
(t = a(t) || 0),
|
||||
o(n) &&
|
||||
((M = !!n.leading),
|
||||
(S = 'maxWait' in n),
|
||||
(y = S ? k(a(n.maxWait) || 0, t) : y),
|
||||
(_ = 'trailing' in n ? !!n.trailing : _)),
|
||||
(m.cancel = l),
|
||||
(m.flush = p),
|
||||
m
|
||||
)
|
||||
}
|
||||
function o(e) {
|
||||
var t = 'undefined' == typeof e ? 'undefined' : u(e)
|
||||
return !!e && ('object' == t || 'function' == t)
|
||||
}
|
||||
function i(e) {
|
||||
return (
|
||||
!!e && 'object' == ('undefined' == typeof e ? 'undefined' : u(e))
|
||||
)
|
||||
}
|
||||
function r(e) {
|
||||
return (
|
||||
'symbol' == ('undefined' == typeof e ? 'undefined' : u(e)) ||
|
||||
(i(e) && w.call(e) == f)
|
||||
)
|
||||
}
|
||||
function a(e) {
|
||||
if ('number' == typeof e) return e
|
||||
if (r(e)) return s
|
||||
if (o(e)) {
|
||||
var t = 'function' == typeof e.valueOf ? e.valueOf() : e
|
||||
e = o(t) ? t + '' : t
|
||||
}
|
||||
if ('string' != typeof e) return 0 === e ? e : +e
|
||||
e = e.replace(d, '')
|
||||
var n = p.test(e)
|
||||
return n || m.test(e) ? b(e.slice(2), n ? 2 : 8) : l.test(e) ? s : +e
|
||||
}
|
||||
var u =
|
||||
'function' == typeof Symbol && 'symbol' == typeof Symbol.iterator
|
||||
? function (e) {
|
||||
return typeof e
|
||||
}
|
||||
: function (e) {
|
||||
return e &&
|
||||
'function' == typeof Symbol &&
|
||||
e.constructor === Symbol &&
|
||||
e !== Symbol.prototype
|
||||
? 'symbol'
|
||||
: typeof e
|
||||
},
|
||||
c = 'Expected a function',
|
||||
s = NaN,
|
||||
f = '[object Symbol]',
|
||||
d = /^\s+|\s+$/g,
|
||||
l = /^[-+]0x[0-9a-f]+$/i,
|
||||
p = /^0b[01]+$/i,
|
||||
m = /^0o[0-7]+$/i,
|
||||
b = parseInt,
|
||||
v =
|
||||
'object' == ('undefined' == typeof t ? 'undefined' : u(t)) &&
|
||||
t &&
|
||||
t.Object === Object &&
|
||||
t,
|
||||
y =
|
||||
'object' == ('undefined' == typeof self ? 'undefined' : u(self)) &&
|
||||
self &&
|
||||
self.Object === Object &&
|
||||
self,
|
||||
g = v || y || Function('return this')(),
|
||||
h = Object.prototype,
|
||||
w = h.toString,
|
||||
k = Math.max,
|
||||
x = Math.min,
|
||||
j = function () {
|
||||
return g.Date.now()
|
||||
}
|
||||
e.exports = n
|
||||
}).call(
|
||||
t,
|
||||
(function () {
|
||||
return this
|
||||
})()
|
||||
)
|
||||
},
|
||||
function (e, t) {
|
||||
'use strict'
|
||||
function n(e) {
|
||||
var t = void 0,
|
||||
o = void 0,
|
||||
i = void 0
|
||||
for (t = 0; t < e.length; t += 1) {
|
||||
if (((o = e[t]), o.dataset && o.dataset.aos)) return !0
|
||||
if ((i = o.children && n(o.children))) return !0
|
||||
}
|
||||
return !1
|
||||
}
|
||||
function o() {
|
||||
return (
|
||||
window.MutationObserver ||
|
||||
window.WebKitMutationObserver ||
|
||||
window.MozMutationObserver
|
||||
)
|
||||
}
|
||||
function i() {
|
||||
return !!o()
|
||||
}
|
||||
function r(e, t) {
|
||||
var n = window.document,
|
||||
i = o(),
|
||||
r = new i(a)
|
||||
;(u = t),
|
||||
r.observe(n.documentElement, {
|
||||
childList: !0,
|
||||
subtree: !0,
|
||||
removedNodes: !0
|
||||
})
|
||||
}
|
||||
function a(e) {
|
||||
e &&
|
||||
e.forEach(function (e) {
|
||||
var t = Array.prototype.slice.call(e.addedNodes),
|
||||
o = Array.prototype.slice.call(e.removedNodes),
|
||||
i = t.concat(o)
|
||||
if (n(i)) return u()
|
||||
})
|
||||
}
|
||||
Object.defineProperty(t, '__esModule', { value: !0 })
|
||||
var u = function () {}
|
||||
t.default = { isSupported: i, ready: r }
|
||||
},
|
||||
function (e, t) {
|
||||
'use strict'
|
||||
function n(e, t) {
|
||||
if (!(e instanceof t))
|
||||
throw new TypeError('Cannot call a class as a function')
|
||||
}
|
||||
function o() {
|
||||
return navigator.userAgent || navigator.vendor || window.opera || ''
|
||||
}
|
||||
Object.defineProperty(t, '__esModule', { value: !0 })
|
||||
var i = (function () {
|
||||
function e(e, t) {
|
||||
for (var n = 0; n < t.length; n++) {
|
||||
var o = t[n]
|
||||
;(o.enumerable = o.enumerable || !1),
|
||||
(o.configurable = !0),
|
||||
'value' in o && (o.writable = !0),
|
||||
Object.defineProperty(e, o.key, o)
|
||||
}
|
||||
}
|
||||
return function (t, n, o) {
|
||||
return n && e(t.prototype, n), o && e(t, o), t
|
||||
}
|
||||
})(),
|
||||
r =
|
||||
/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i,
|
||||
a =
|
||||
/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i,
|
||||
u =
|
||||
/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i,
|
||||
c =
|
||||
/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i,
|
||||
s = (function () {
|
||||
function e() {
|
||||
n(this, e)
|
||||
}
|
||||
return (
|
||||
i(e, [
|
||||
{
|
||||
key: 'phone',
|
||||
value: function () {
|
||||
var e = o()
|
||||
return !(!r.test(e) && !a.test(e.substr(0, 4)))
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'mobile',
|
||||
value: function () {
|
||||
var e = o()
|
||||
return !(!u.test(e) && !c.test(e.substr(0, 4)))
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'tablet',
|
||||
value: function () {
|
||||
return this.mobile() && !this.phone()
|
||||
}
|
||||
}
|
||||
]),
|
||||
e
|
||||
)
|
||||
})()
|
||||
t.default = new s()
|
||||
},
|
||||
function (e, t) {
|
||||
'use strict'
|
||||
Object.defineProperty(t, '__esModule', { value: !0 })
|
||||
var n = function (e, t, n) {
|
||||
var o = e.node.getAttribute('data-aos-once')
|
||||
t > e.position
|
||||
? e.node.classList.add('aos-animate')
|
||||
: 'undefined' != typeof o &&
|
||||
('false' === o || (!n && 'true' !== o)) &&
|
||||
e.node.classList.remove('aos-animate')
|
||||
},
|
||||
o = function (e, t) {
|
||||
var o = window.pageYOffset,
|
||||
i = window.innerHeight
|
||||
e.forEach(function (e, r) {
|
||||
n(e, i + o, t)
|
||||
})
|
||||
}
|
||||
t.default = o
|
||||
},
|
||||
function (e, t, n) {
|
||||
'use strict'
|
||||
function o(e) {
|
||||
return e && e.__esModule ? e : { default: e }
|
||||
}
|
||||
Object.defineProperty(t, '__esModule', { value: !0 })
|
||||
var i = n(12),
|
||||
r = o(i),
|
||||
a = function (e, t) {
|
||||
return (
|
||||
e.forEach(function (e, n) {
|
||||
e.node.classList.add('aos-init'),
|
||||
(e.position = (0, r.default)(e.node, t.offset))
|
||||
}),
|
||||
e
|
||||
)
|
||||
}
|
||||
t.default = a
|
||||
},
|
||||
function (e, t, n) {
|
||||
'use strict'
|
||||
function o(e) {
|
||||
return e && e.__esModule ? e : { default: e }
|
||||
}
|
||||
Object.defineProperty(t, '__esModule', { value: !0 })
|
||||
var i = n(13),
|
||||
r = o(i),
|
||||
a = function (e, t) {
|
||||
var n = 0,
|
||||
o = 0,
|
||||
i = window.innerHeight,
|
||||
a = {
|
||||
offset: e.getAttribute('data-aos-offset'),
|
||||
anchor: e.getAttribute('data-aos-anchor'),
|
||||
anchorPlacement: e.getAttribute('data-aos-anchor-placement')
|
||||
}
|
||||
switch (
|
||||
(a.offset && !isNaN(a.offset) && (o = parseInt(a.offset)),
|
||||
a.anchor &&
|
||||
document.querySelectorAll(a.anchor) &&
|
||||
(e = document.querySelectorAll(a.anchor)[0]),
|
||||
(n = (0, r.default)(e).top),
|
||||
a.anchorPlacement)
|
||||
) {
|
||||
case 'top-bottom':
|
||||
break
|
||||
case 'center-bottom':
|
||||
n += e.offsetHeight / 2
|
||||
break
|
||||
case 'bottom-bottom':
|
||||
n += e.offsetHeight
|
||||
break
|
||||
case 'top-center':
|
||||
n += i / 2
|
||||
break
|
||||
case 'bottom-center':
|
||||
n += i / 2 + e.offsetHeight
|
||||
break
|
||||
case 'center-center':
|
||||
n += i / 2 + e.offsetHeight / 2
|
||||
break
|
||||
case 'top-top':
|
||||
n += i
|
||||
break
|
||||
case 'bottom-top':
|
||||
n += e.offsetHeight + i
|
||||
break
|
||||
case 'center-top':
|
||||
n += e.offsetHeight / 2 + i
|
||||
}
|
||||
return a.anchorPlacement || a.offset || isNaN(t) || (o = t), n + o
|
||||
}
|
||||
t.default = a
|
||||
},
|
||||
function (e, t) {
|
||||
'use strict'
|
||||
Object.defineProperty(t, '__esModule', { value: !0 })
|
||||
var n = function (e) {
|
||||
for (
|
||||
var t = 0, n = 0;
|
||||
e && !isNaN(e.offsetLeft) && !isNaN(e.offsetTop);
|
||||
|
||||
)
|
||||
(t += e.offsetLeft - ('BODY' != e.tagName ? e.scrollLeft : 0)),
|
||||
(n += e.offsetTop - ('BODY' != e.tagName ? e.scrollTop : 0)),
|
||||
(e = e.offsetParent)
|
||||
return { top: n, left: t }
|
||||
}
|
||||
t.default = n
|
||||
},
|
||||
function (e, t) {
|
||||
'use strict'
|
||||
Object.defineProperty(t, '__esModule', { value: !0 })
|
||||
var n = function (e) {
|
||||
return (
|
||||
(e = e || document.querySelectorAll('[data-aos]')),
|
||||
Array.prototype.map.call(e, function (e) {
|
||||
return { node: e }
|
||||
})
|
||||
)
|
||||
}
|
||||
t.default = n
|
||||
}
|
||||
])
|
||||
})
|
||||
@@ -3,7 +3,7 @@ const idFlutteringRibbon = 'canvasFlutteringRibbon'
|
||||
|
||||
function destroyFlutteringRibbon() {
|
||||
const ribbon = document.getElementById(idFlutteringRibbon)
|
||||
if (ribbon && ribbon.parentNode) {
|
||||
if (ribbon && ribbon.parentNode && ribbon.parentNode.contains(ribbon)) {
|
||||
ribbon.parentNode.removeChild(ribbon)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ function createNest() {
|
||||
|
||||
function destroyNest() {
|
||||
const nest = document.getElementById(idNest)
|
||||
if(nest && nest.parentNode){
|
||||
if (nest && nest.parentNode && nest.parentNode.contains(nest)) {
|
||||
nest.parentNode.removeChild(nest)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ function createRibbon() {
|
||||
|
||||
function destroyRibbon() {
|
||||
const ribbon = document.getElementById(idRibbon)
|
||||
if (ribbon && ribbon.parentNode) {
|
||||
if (ribbon && ribbon.parentNode && ribbon.parentNode.contains(ribbon)) {
|
||||
ribbon.parentNode.removeChild(ribbon)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,9 +165,11 @@ function createSakura() {
|
||||
function stopp() {
|
||||
if (staticx) {
|
||||
var child = document.getElementById(id)
|
||||
child.parentNode.removeChild(child)
|
||||
window.cancelAnimationFrame(stop)
|
||||
staticx = false
|
||||
if (child && child.parentNode && child.parentNode.contains(child)) {
|
||||
child.parentNode.removeChild(child)
|
||||
window.cancelAnimationFrame(stop)
|
||||
staticx = false
|
||||
}
|
||||
} else {
|
||||
startSakura()
|
||||
}
|
||||
@@ -177,7 +179,7 @@ function createSakura() {
|
||||
// 销毁樱花雨
|
||||
function destroySakura() {
|
||||
const sakura = document.getElementById(idSakura)
|
||||
if (sakura && sakura.parentNode) {
|
||||
if (sakura && sakura.parentNode && sakura.parentNode.contains(sakura)) {
|
||||
sakura.parentNode.removeChild(sakura)
|
||||
}
|
||||
}
|
||||
|
||||
626
public/js/typed.min.js
vendored
Normal file
626
public/js/typed.min.js
vendored
Normal file
@@ -0,0 +1,626 @@
|
||||
/*!
|
||||
*
|
||||
* typed.js - A JavaScript Typing Animation Library
|
||||
* Author: Matt Boldt <me@mattboldt.com>
|
||||
* Version: v2.0.12
|
||||
* Url: https://github.com/mattboldt/typed.js
|
||||
* License(s): MIT
|
||||
*
|
||||
*/
|
||||
;(function (t, e) {
|
||||
'object' == typeof exports && 'object' == typeof module
|
||||
? (module.exports = e())
|
||||
: 'function' == typeof define && define.amd
|
||||
? define([], e)
|
||||
: 'object' == typeof exports
|
||||
? (exports.Typed = e())
|
||||
: (t.Typed = e())
|
||||
})(this, function () {
|
||||
return (function (t) {
|
||||
function e(n) {
|
||||
if (s[n]) return s[n].exports
|
||||
var i = (s[n] = { exports: {}, id: n, loaded: !1 })
|
||||
return t[n].call(i.exports, i, i.exports, e), (i.loaded = !0), i.exports
|
||||
}
|
||||
var s = {}
|
||||
return (e.m = t), (e.c = s), (e.p = ''), e(0)
|
||||
})([
|
||||
function (t, e, s) {
|
||||
'use strict'
|
||||
function n(t, e) {
|
||||
if (!(t instanceof e))
|
||||
throw new TypeError('Cannot call a class as a function')
|
||||
}
|
||||
Object.defineProperty(e, '__esModule', { value: !0 })
|
||||
var i = (function () {
|
||||
function t(t, e) {
|
||||
for (var s = 0; s < e.length; s++) {
|
||||
var n = e[s]
|
||||
;(n.enumerable = n.enumerable || !1),
|
||||
(n.configurable = !0),
|
||||
'value' in n && (n.writable = !0),
|
||||
Object.defineProperty(t, n.key, n)
|
||||
}
|
||||
}
|
||||
return function (e, s, n) {
|
||||
return s && t(e.prototype, s), n && t(e, n), e
|
||||
}
|
||||
})(),
|
||||
r = s(1),
|
||||
o = s(3),
|
||||
a = (function () {
|
||||
function t(e, s) {
|
||||
n(this, t), r.initializer.load(this, s, e), this.begin()
|
||||
}
|
||||
return (
|
||||
i(t, [
|
||||
{
|
||||
key: 'toggle',
|
||||
value: function () {
|
||||
this.pause.status ? this.start() : this.stop()
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'stop',
|
||||
value: function () {
|
||||
this.typingComplete ||
|
||||
this.pause.status ||
|
||||
(this.toggleBlinking(!0),
|
||||
(this.pause.status = !0),
|
||||
this.options.onStop(this.arrayPos, this))
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'start',
|
||||
value: function () {
|
||||
this.typingComplete ||
|
||||
(this.pause.status &&
|
||||
((this.pause.status = !1),
|
||||
this.pause.typewrite
|
||||
? this.typewrite(
|
||||
this.pause.curString,
|
||||
this.pause.curStrPos
|
||||
)
|
||||
: this.backspace(
|
||||
this.pause.curString,
|
||||
this.pause.curStrPos
|
||||
),
|
||||
this.options.onStart(this.arrayPos, this)))
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'destroy',
|
||||
value: function () {
|
||||
this.reset(!1), this.options.onDestroy(this)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'reset',
|
||||
value: function () {
|
||||
var t =
|
||||
arguments.length <= 0 ||
|
||||
void 0 === arguments[0] ||
|
||||
arguments[0]
|
||||
clearInterval(this.timeout),
|
||||
this.replaceText(''),
|
||||
this.cursor &&
|
||||
this.cursor.parentNode &&
|
||||
(this.cursor.parentNode.removeChild(this.cursor),
|
||||
(this.cursor = null)),
|
||||
(this.strPos = 0),
|
||||
(this.arrayPos = 0),
|
||||
(this.curLoop = 0),
|
||||
t &&
|
||||
(this.insertCursor(),
|
||||
this.options.onReset(this),
|
||||
this.begin())
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'begin',
|
||||
value: function () {
|
||||
var t = this
|
||||
this.options.onBegin(this),
|
||||
(this.typingComplete = !1),
|
||||
this.shuffleStringsIfNeeded(this),
|
||||
this.insertCursor(),
|
||||
this.bindInputFocusEvents && this.bindFocusEvents(),
|
||||
(this.timeout = setTimeout(function () {
|
||||
t.currentElContent && 0 !== t.currentElContent.length
|
||||
? t.backspace(
|
||||
t.currentElContent,
|
||||
t.currentElContent.length
|
||||
)
|
||||
: t.typewrite(
|
||||
t.strings[t.sequence[t.arrayPos]],
|
||||
t.strPos
|
||||
)
|
||||
}, this.startDelay))
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'typewrite',
|
||||
value: function (t, e) {
|
||||
var s = this
|
||||
this.fadeOut &&
|
||||
this.el.classList.contains(this.fadeOutClass) &&
|
||||
(this.el.classList.remove(this.fadeOutClass),
|
||||
this.cursor &&
|
||||
this.cursor.classList.remove(this.fadeOutClass))
|
||||
var n = this.humanizer(this.typeSpeed),
|
||||
i = 1
|
||||
return this.pause.status === !0
|
||||
? void this.setPauseStatus(t, e, !0)
|
||||
: void (this.timeout = setTimeout(function () {
|
||||
e = o.htmlParser.typeHtmlChars(t, e, s)
|
||||
var n = 0,
|
||||
r = t.substr(e)
|
||||
if ('^' === r.charAt(0) && /^\^\d+/.test(r)) {
|
||||
var a = 1
|
||||
;(r = /\d+/.exec(r)[0]),
|
||||
(a += r.length),
|
||||
(n = parseInt(r)),
|
||||
(s.temporaryPause = !0),
|
||||
s.options.onTypingPaused(s.arrayPos, s),
|
||||
(t = t.substring(0, e) + t.substring(e + a)),
|
||||
s.toggleBlinking(!0)
|
||||
}
|
||||
if ('`' === r.charAt(0)) {
|
||||
for (
|
||||
;
|
||||
'`' !== t.substr(e + i).charAt(0) &&
|
||||
(i++, !(e + i > t.length));
|
||||
|
||||
);
|
||||
var u = t.substring(0, e),
|
||||
l = t.substring(u.length + 1, e + i),
|
||||
c = t.substring(e + i + 1)
|
||||
;(t = u + l + c), i--
|
||||
}
|
||||
s.timeout = setTimeout(function () {
|
||||
s.toggleBlinking(!1),
|
||||
e >= t.length
|
||||
? s.doneTyping(t, e)
|
||||
: s.keepTyping(t, e, i),
|
||||
s.temporaryPause &&
|
||||
((s.temporaryPause = !1),
|
||||
s.options.onTypingResumed(s.arrayPos, s))
|
||||
}, n)
|
||||
}, n))
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'keepTyping',
|
||||
value: function (t, e, s) {
|
||||
0 === e &&
|
||||
(this.toggleBlinking(!1),
|
||||
this.options.preStringTyped(this.arrayPos, this)),
|
||||
(e += s)
|
||||
var n = t.substr(0, e)
|
||||
this.replaceText(n), this.typewrite(t, e)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'doneTyping',
|
||||
value: function (t, e) {
|
||||
var s = this
|
||||
this.options.onStringTyped(this.arrayPos, this),
|
||||
this.toggleBlinking(!0),
|
||||
(this.arrayPos === this.strings.length - 1 &&
|
||||
(this.complete(),
|
||||
this.loop === !1 || this.curLoop === this.loopCount)) ||
|
||||
(this.timeout = setTimeout(function () {
|
||||
s.backspace(t, e)
|
||||
}, this.backDelay))
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'backspace',
|
||||
value: function (t, e) {
|
||||
var s = this
|
||||
if (this.pause.status === !0)
|
||||
return void this.setPauseStatus(t, e, !1)
|
||||
if (this.fadeOut) return this.initFadeOut()
|
||||
this.toggleBlinking(!1)
|
||||
var n = this.humanizer(this.backSpeed)
|
||||
this.timeout = setTimeout(function () {
|
||||
e = o.htmlParser.backSpaceHtmlChars(t, e, s)
|
||||
var n = t.substr(0, e)
|
||||
if ((s.replaceText(n), s.smartBackspace)) {
|
||||
var i = s.strings[s.arrayPos + 1]
|
||||
i && n === i.substr(0, e)
|
||||
? (s.stopNum = e)
|
||||
: (s.stopNum = 0)
|
||||
}
|
||||
e > s.stopNum
|
||||
? (e--, s.backspace(t, e))
|
||||
: e <= s.stopNum &&
|
||||
(s.arrayPos++,
|
||||
s.arrayPos === s.strings.length
|
||||
? ((s.arrayPos = 0),
|
||||
s.options.onLastStringBackspaced(),
|
||||
s.shuffleStringsIfNeeded(),
|
||||
s.begin())
|
||||
: s.typewrite(s.strings[s.sequence[s.arrayPos]], e))
|
||||
}, n)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'complete',
|
||||
value: function () {
|
||||
this.options.onComplete(this),
|
||||
this.loop ? this.curLoop++ : (this.typingComplete = !0)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'setPauseStatus',
|
||||
value: function (t, e, s) {
|
||||
;(this.pause.typewrite = s),
|
||||
(this.pause.curString = t),
|
||||
(this.pause.curStrPos = e)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'toggleBlinking',
|
||||
value: function (t) {
|
||||
this.cursor &&
|
||||
(this.pause.status ||
|
||||
(this.cursorBlinking !== t &&
|
||||
((this.cursorBlinking = t),
|
||||
t
|
||||
? this.cursor.classList.add('typed-cursor--blink')
|
||||
: this.cursor.classList.remove(
|
||||
'typed-cursor--blink'
|
||||
))))
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'humanizer',
|
||||
value: function (t) {
|
||||
return Math.round((Math.random() * t) / 2) + t
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'shuffleStringsIfNeeded',
|
||||
value: function () {
|
||||
this.shuffle &&
|
||||
(this.sequence = this.sequence.sort(function () {
|
||||
return Math.random() - 0.5
|
||||
}))
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'initFadeOut',
|
||||
value: function () {
|
||||
var t = this
|
||||
return (
|
||||
(this.el.className += ' ' + this.fadeOutClass),
|
||||
this.cursor &&
|
||||
(this.cursor.className += ' ' + this.fadeOutClass),
|
||||
setTimeout(function () {
|
||||
t.arrayPos++,
|
||||
t.replaceText(''),
|
||||
t.strings.length > t.arrayPos
|
||||
? t.typewrite(t.strings[t.sequence[t.arrayPos]], 0)
|
||||
: (t.typewrite(t.strings[0], 0), (t.arrayPos = 0))
|
||||
}, this.fadeOutDelay)
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'replaceText',
|
||||
value: function (t) {
|
||||
this.attr
|
||||
? this.el.setAttribute(this.attr, t)
|
||||
: this.isInput
|
||||
? (this.el.value = t)
|
||||
: 'html' === this.contentType
|
||||
? (this.el.innerHTML = t)
|
||||
: (this.el.textContent = t)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'bindFocusEvents',
|
||||
value: function () {
|
||||
var t = this
|
||||
this.isInput &&
|
||||
(this.el.addEventListener('focus', function (e) {
|
||||
t.stop()
|
||||
}),
|
||||
this.el.addEventListener('blur', function (e) {
|
||||
;(t.el.value && 0 !== t.el.value.length) || t.start()
|
||||
}))
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'insertCursor',
|
||||
value: function () {
|
||||
this.showCursor &&
|
||||
(this.cursor ||
|
||||
((this.cursor = document.createElement('span')),
|
||||
(this.cursor.className = 'typed-cursor'),
|
||||
this.cursor.setAttribute('aria-hidden', !0),
|
||||
(this.cursor.innerHTML = this.cursorChar),
|
||||
this.el.parentNode &&
|
||||
this.el.parentNode.insertBefore(
|
||||
this.cursor,
|
||||
this.el.nextSibling
|
||||
)))
|
||||
}
|
||||
}
|
||||
]),
|
||||
t
|
||||
)
|
||||
})()
|
||||
;(e['default'] = a), (t.exports = e['default'])
|
||||
},
|
||||
function (t, e, s) {
|
||||
'use strict'
|
||||
function n(t) {
|
||||
return t && t.__esModule ? t : { default: t }
|
||||
}
|
||||
function i(t, e) {
|
||||
if (!(t instanceof e))
|
||||
throw new TypeError('Cannot call a class as a function')
|
||||
}
|
||||
Object.defineProperty(e, '__esModule', { value: !0 })
|
||||
var r =
|
||||
Object.assign ||
|
||||
function (t) {
|
||||
for (var e = 1; e < arguments.length; e++) {
|
||||
var s = arguments[e]
|
||||
for (var n in s)
|
||||
Object.prototype.hasOwnProperty.call(s, n) && (t[n] = s[n])
|
||||
}
|
||||
return t
|
||||
},
|
||||
o = (function () {
|
||||
function t(t, e) {
|
||||
for (var s = 0; s < e.length; s++) {
|
||||
var n = e[s]
|
||||
;(n.enumerable = n.enumerable || !1),
|
||||
(n.configurable = !0),
|
||||
'value' in n && (n.writable = !0),
|
||||
Object.defineProperty(t, n.key, n)
|
||||
}
|
||||
}
|
||||
return function (e, s, n) {
|
||||
return s && t(e.prototype, s), n && t(e, n), e
|
||||
}
|
||||
})(),
|
||||
a = s(2),
|
||||
u = n(a),
|
||||
l = (function () {
|
||||
function t() {
|
||||
i(this, t)
|
||||
}
|
||||
return (
|
||||
o(t, [
|
||||
{
|
||||
key: 'load',
|
||||
value: function (t, e, s) {
|
||||
if (
|
||||
('string' == typeof s
|
||||
? (t.el = document.querySelector(s))
|
||||
: (t.el = s),
|
||||
(t.options = r({}, u['default'], e)),
|
||||
(t.isInput = 'input' === t.el.tagName.toLowerCase()),
|
||||
(t.attr = t.options.attr),
|
||||
(t.bindInputFocusEvents = t.options.bindInputFocusEvents),
|
||||
(t.showCursor = !t.isInput && t.options.showCursor),
|
||||
(t.cursorChar = t.options.cursorChar),
|
||||
(t.cursorBlinking = !0),
|
||||
(t.elContent = t.attr
|
||||
? t.el.getAttribute(t.attr)
|
||||
: t.el.textContent),
|
||||
(t.contentType = t.options.contentType),
|
||||
(t.typeSpeed = t.options.typeSpeed),
|
||||
(t.startDelay = t.options.startDelay),
|
||||
(t.backSpeed = t.options.backSpeed),
|
||||
(t.smartBackspace = t.options.smartBackspace),
|
||||
(t.backDelay = t.options.backDelay),
|
||||
(t.fadeOut = t.options.fadeOut),
|
||||
(t.fadeOutClass = t.options.fadeOutClass),
|
||||
(t.fadeOutDelay = t.options.fadeOutDelay),
|
||||
(t.isPaused = !1),
|
||||
(t.strings = t.options.strings.map(function (t) {
|
||||
return t.trim()
|
||||
})),
|
||||
'string' == typeof t.options.stringsElement
|
||||
? (t.stringsElement = document.querySelector(
|
||||
t.options.stringsElement
|
||||
))
|
||||
: (t.stringsElement = t.options.stringsElement),
|
||||
t.stringsElement)
|
||||
) {
|
||||
;(t.strings = []), (t.stringsElement.style.display = 'none')
|
||||
var n = Array.prototype.slice.apply(
|
||||
t.stringsElement.children
|
||||
),
|
||||
i = n.length
|
||||
if (i)
|
||||
for (var o = 0; o < i; o += 1) {
|
||||
var a = n[o]
|
||||
t.strings.push(a.innerHTML.trim())
|
||||
}
|
||||
}
|
||||
;(t.strPos = 0),
|
||||
(t.arrayPos = 0),
|
||||
(t.stopNum = 0),
|
||||
(t.loop = t.options.loop),
|
||||
(t.loopCount = t.options.loopCount),
|
||||
(t.curLoop = 0),
|
||||
(t.shuffle = t.options.shuffle),
|
||||
(t.sequence = []),
|
||||
(t.pause = {
|
||||
status: !1,
|
||||
typewrite: !0,
|
||||
curString: '',
|
||||
curStrPos: 0
|
||||
}),
|
||||
(t.typingComplete = !1)
|
||||
for (var o in t.strings) t.sequence[o] = o
|
||||
;(t.currentElContent = this.getCurrentElContent(t)),
|
||||
(t.autoInsertCss = t.options.autoInsertCss),
|
||||
this.appendAnimationCss(t)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'getCurrentElContent',
|
||||
value: function (t) {
|
||||
var e = ''
|
||||
return (e = t.attr
|
||||
? t.el.getAttribute(t.attr)
|
||||
: t.isInput
|
||||
? t.el.value
|
||||
: 'html' === t.contentType
|
||||
? t.el.innerHTML
|
||||
: t.el.textContent)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'appendAnimationCss',
|
||||
value: function (t) {
|
||||
var e = 'data-typed-js-css'
|
||||
if (
|
||||
t.autoInsertCss &&
|
||||
(t.showCursor || t.fadeOut) &&
|
||||
!document.querySelector('[' + e + ']')
|
||||
) {
|
||||
var s = document.createElement('style')
|
||||
;(s.type = 'text/css'), s.setAttribute(e, !0)
|
||||
var n = ''
|
||||
t.showCursor &&
|
||||
(n +=
|
||||
'\n .typed-cursor{\n opacity: 1;\n }\n .typed-cursor.typed-cursor--blink{\n animation: typedjsBlink 0.7s infinite;\n -webkit-animation: typedjsBlink 0.7s infinite;\n animation: typedjsBlink 0.7s infinite;\n }\n @keyframes typedjsBlink{\n 50% { opacity: 0.0; }\n }\n @-webkit-keyframes typedjsBlink{\n 0% { opacity: 1; }\n 50% { opacity: 0.0; }\n 100% { opacity: 1; }\n }\n '),
|
||||
t.fadeOut &&
|
||||
(n +=
|
||||
'\n .typed-fade-out{\n opacity: 0;\n transition: opacity .25s;\n }\n .typed-cursor.typed-cursor--blink.typed-fade-out{\n -webkit-animation: 0;\n animation: 0;\n }\n '),
|
||||
0 !== s.length &&
|
||||
((s.innerHTML = n), document.body.appendChild(s))
|
||||
}
|
||||
}
|
||||
}
|
||||
]),
|
||||
t
|
||||
)
|
||||
})()
|
||||
e['default'] = l
|
||||
var c = new l()
|
||||
e.initializer = c
|
||||
},
|
||||
function (t, e) {
|
||||
'use strict'
|
||||
Object.defineProperty(e, '__esModule', { value: !0 })
|
||||
var s = {
|
||||
strings: [
|
||||
'These are the default values...',
|
||||
'You know what you should do?',
|
||||
'Use your own!',
|
||||
'Have a great day!'
|
||||
],
|
||||
stringsElement: null,
|
||||
typeSpeed: 0,
|
||||
startDelay: 0,
|
||||
backSpeed: 0,
|
||||
smartBackspace: !0,
|
||||
shuffle: !1,
|
||||
backDelay: 700,
|
||||
fadeOut: !1,
|
||||
fadeOutClass: 'typed-fade-out',
|
||||
fadeOutDelay: 500,
|
||||
loop: !1,
|
||||
loopCount: 1 / 0,
|
||||
showCursor: !0,
|
||||
cursorChar: '|',
|
||||
autoInsertCss: !0,
|
||||
attr: null,
|
||||
bindInputFocusEvents: !1,
|
||||
contentType: 'html',
|
||||
onBegin: function (t) {},
|
||||
onComplete: function (t) {},
|
||||
preStringTyped: function (t, e) {},
|
||||
onStringTyped: function (t, e) {},
|
||||
onLastStringBackspaced: function (t) {},
|
||||
onTypingPaused: function (t, e) {},
|
||||
onTypingResumed: function (t, e) {},
|
||||
onReset: function (t) {},
|
||||
onStop: function (t, e) {},
|
||||
onStart: function (t, e) {},
|
||||
onDestroy: function (t) {}
|
||||
}
|
||||
;(e['default'] = s), (t.exports = e['default'])
|
||||
},
|
||||
function (t, e) {
|
||||
'use strict'
|
||||
function s(t, e) {
|
||||
if (!(t instanceof e))
|
||||
throw new TypeError('Cannot call a class as a function')
|
||||
}
|
||||
Object.defineProperty(e, '__esModule', { value: !0 })
|
||||
var n = (function () {
|
||||
function t(t, e) {
|
||||
for (var s = 0; s < e.length; s++) {
|
||||
var n = e[s]
|
||||
;(n.enumerable = n.enumerable || !1),
|
||||
(n.configurable = !0),
|
||||
'value' in n && (n.writable = !0),
|
||||
Object.defineProperty(t, n.key, n)
|
||||
}
|
||||
}
|
||||
return function (e, s, n) {
|
||||
return s && t(e.prototype, s), n && t(e, n), e
|
||||
}
|
||||
})(),
|
||||
i = (function () {
|
||||
function t() {
|
||||
s(this, t)
|
||||
}
|
||||
return (
|
||||
n(t, [
|
||||
{
|
||||
key: 'typeHtmlChars',
|
||||
value: function (t, e, s) {
|
||||
if ('html' !== s.contentType) return e
|
||||
var n = t.substr(e).charAt(0)
|
||||
if ('<' === n || '&' === n) {
|
||||
var i = ''
|
||||
for (
|
||||
i = '<' === n ? '>' : ';';
|
||||
t.substr(e + 1).charAt(0) !== i &&
|
||||
(e++, !(e + 1 > t.length));
|
||||
|
||||
);
|
||||
e++
|
||||
}
|
||||
return e
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'backSpaceHtmlChars',
|
||||
value: function (t, e, s) {
|
||||
if ('html' !== s.contentType) return e
|
||||
var n = t.substr(e).charAt(0)
|
||||
if ('>' === n || ';' === n) {
|
||||
var i = ''
|
||||
for (
|
||||
i = '>' === n ? '<' : '&';
|
||||
t.substr(e - 1).charAt(0) !== i && (e--, !(e < 0));
|
||||
|
||||
);
|
||||
e--
|
||||
}
|
||||
return e
|
||||
}
|
||||
}
|
||||
]),
|
||||
t
|
||||
)
|
||||
})()
|
||||
e['default'] = i
|
||||
var r = new i()
|
||||
e.htmlParser = r
|
||||
}
|
||||
])
|
||||
})
|
||||
//# sourceMappingURL=typed.min.js.map
|
||||
@@ -272,3 +272,7 @@ a.avatar-wrapper {
|
||||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
display: unset;
|
||||
}
|
||||
|
||||
@@ -179,10 +179,12 @@ const LayoutSlug = props => {
|
||||
{lock ? (
|
||||
<PostLock validPassword={validPassword} />
|
||||
) : (
|
||||
<div id='article-wrapper'>
|
||||
<div>
|
||||
<PostMeta post={post} />
|
||||
<NotionPage post={post} />
|
||||
<ShareBar post={post} />
|
||||
<div id='article-wrapper'>
|
||||
<NotionPage post={post} />
|
||||
<ShareBar post={post} />
|
||||
</div>
|
||||
<Comment frontMatter={post} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import TagItemMini from './TagItemMini'
|
||||
import Comment from '@/components/Comment'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
import ShareBar from '@/components/ShareBar'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import Link from 'next/link'
|
||||
import ArticleAround from './ArticleAround'
|
||||
import { AdSlot } from '@/components/GoogleAdsense'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import { formatDateFmt } from '@/lib/utils/formatDate'
|
||||
import WWAds from '@/components/WWAds'
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
import ShareBar from '@/components/ShareBar'
|
||||
import WWAds from '@/components/WWAds'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { formatDateFmt } from '@/lib/utils/formatDate'
|
||||
import Link from 'next/link'
|
||||
import ArticleAround from './ArticleAround'
|
||||
import TagItemMini from './TagItemMini'
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -25,66 +25,75 @@ export default function ArticleDetail(props) {
|
||||
return <></>
|
||||
}
|
||||
return (
|
||||
<div id="container" className={`${fullWidth ? 'px-10' : 'max-w-5xl '} overflow-x-auto flex-grow mx-auto w-screen md:w-full`}>
|
||||
<div
|
||||
id='container'
|
||||
className={`${fullWidth ? 'px-10' : 'max-w-5xl '} overflow-x-auto flex-grow mx-auto w-screen md:w-full`}>
|
||||
{post?.type && !post?.type !== 'Page' && post?.pageCover && (
|
||||
<div className="w-full relative md:flex-shrink-0 overflow-hidden">
|
||||
<LazyImage alt={post.title} src={post?.pageCover} className='object-cover max-h-[60vh] w-full' />
|
||||
<div className='w-full relative md:flex-shrink-0 overflow-hidden'>
|
||||
<LazyImage
|
||||
alt={post.title}
|
||||
src={post?.pageCover}
|
||||
className='object-cover max-h-[60vh] w-full'
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<article itemScope itemType="https://schema.org/Movie" className="subpixel-antialiased overflow-y-hidden py-10 px-5 lg:pt-24 md:px-32 dark:border-gray-700 bg-white dark:bg-hexo-black-gray" >
|
||||
|
||||
<article
|
||||
itemScope
|
||||
itemType='https://schema.org/Movie'
|
||||
className='subpixel-antialiased overflow-y-hidden py-10 px-5 lg:pt-24 md:px-32 dark:border-gray-700 bg-white dark:bg-hexo-black-gray'>
|
||||
<header>
|
||||
|
||||
{/* 文章Title */}
|
||||
<div className="font-bold text-4xl text-black dark:text-white">
|
||||
{siteConfig('POST_TITLE_ICON') && <NotionIcon icon={post?.pageIcon} />}{post.title}
|
||||
<div className='font-bold text-4xl text-black dark:text-white'>
|
||||
{siteConfig('POST_TITLE_ICON') && (
|
||||
<NotionIcon icon={post?.pageIcon} />
|
||||
)}
|
||||
{post.title}
|
||||
</div>
|
||||
|
||||
<section className="flex-wrap flex mt-2 text-gray-400 dark:text-gray-400 font-light leading-8">
|
||||
<section className='flex-wrap flex mt-2 text-gray-400 dark:text-gray-400 font-light leading-8'>
|
||||
<div>
|
||||
{post?.category && (<>
|
||||
{post?.category && (
|
||||
<>
|
||||
<Link
|
||||
href={`/category/${post.category}`}
|
||||
passHref
|
||||
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" />
|
||||
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}
|
||||
|
||||
</Link>
|
||||
<span className='mr-2'>|</span>
|
||||
</>)}
|
||||
<span className='mr-2'>|</span>
|
||||
</>
|
||||
)}
|
||||
|
||||
{post?.type !== 'Page' && (<>
|
||||
<Link
|
||||
href={`/archive#${formatDateFmt(post?.publishDate, 'yyyy-MM')}`}
|
||||
passHref
|
||||
className="pl-1 mr-2 cursor-pointer hover:text-gray-700 dark:hover:text-gray-200 border-b dark:border-gray-500 border-dashed">
|
||||
{post?.type !== 'Page' && (
|
||||
<>
|
||||
<Link
|
||||
href={`/archive#${formatDateFmt(post?.publishDate, 'yyyy-MM')}`}
|
||||
passHref
|
||||
className='pl-1 mr-2 cursor-pointer hover:text-gray-700 dark:hover:text-gray-200 border-b dark:border-gray-500 border-dashed'>
|
||||
{post?.publishDay}
|
||||
</Link>
|
||||
<span className='mr-2'>|</span>
|
||||
<span className='mx-2 text-gray-400 dark:text-gray-500'>
|
||||
{locale.COMMON.LAST_EDITED_TIME}: {post.lastEditedDay}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
|
||||
{post?.publishDay}
|
||||
|
||||
</Link>
|
||||
<span className='mr-2'>|</span>
|
||||
<span className='mx-2 text-gray-400 dark:text-gray-500'>
|
||||
{locale.COMMON.LAST_EDITED_TIME}: {post.lastEditedDay}
|
||||
</span>
|
||||
</>)}
|
||||
|
||||
<div className='my-2'>
|
||||
<div className='my-2'>
|
||||
{post.tagItems && (
|
||||
<div className="flex flex-nowrap overflow-x-auto">
|
||||
{post.tagItems.map(tag => (
|
||||
<TagItemMini key={tag.name} tag={tag} />
|
||||
))}
|
||||
</div>
|
||||
<div className='flex flex-nowrap overflow-x-auto'>
|
||||
{post.tagItems.map(tag => (
|
||||
<TagItemMini key={tag.name} tag={tag} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
<WWAds className='w-full' orientation='horizontal'/>
|
||||
<WWAds className='w-full' orientation='horizontal' />
|
||||
</header>
|
||||
|
||||
{/* Notion文章主体 */}
|
||||
@@ -93,17 +102,16 @@ export default function ArticleDetail(props) {
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<AdSlot type='in-article'/>
|
||||
{/* 分享 */}
|
||||
<ShareBar post={post} />
|
||||
<AdSlot type='in-article' />
|
||||
{/* 分享 */}
|
||||
<ShareBar post={post} />
|
||||
</section>
|
||||
|
||||
</article>
|
||||
|
||||
{post?.type === 'Post' && <ArticleAround prev={prev} next={next} /> }
|
||||
{post?.type === 'Post' && <ArticleAround prev={prev} next={next} />}
|
||||
|
||||
{/* 评论互动 */}
|
||||
<div className="duration-200 shadow py-6 px-12 w-screen md:w-full overflow-x-auto dark:border-gray-700 bg-white dark:bg-hexo-black-gray">
|
||||
<div className='duration-200 shadow py-6 px-12 w-screen md:w-full overflow-x-auto dark:border-gray-700 bg-white dark:bg-hexo-black-gray'>
|
||||
<Comment frontMatter={post} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { GameListIndexCombine } from './GameListIndexCombine'
|
||||
import PaginationSimple from './PaginationSimple'
|
||||
@@ -9,7 +10,8 @@ import PaginationSimple from './PaginationSimple'
|
||||
export const BlogListPage = props => {
|
||||
const { page = 1, postCount } = props
|
||||
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
|
||||
|
||||
return (
|
||||
|
||||
@@ -12,7 +12,7 @@ export default function BottomMenuBar({ post, className }) {
|
||||
return (
|
||||
<>
|
||||
{/* 移动端底部导航按钮 */}
|
||||
<div className='bottom-button-group md:hidden w-screen h-14 px-4 fixed flex items-center justify-between right-left bottom-0 z-30 bg-white border-t dark:border-gray-800'>
|
||||
<div className='dark:bg-hexo-black-gray bottom-button-group md:hidden w-screen h-14 px-4 fixed flex items-center justify-between right-left bottom-0 z-30 bg-white border-t dark:border-gray-800'>
|
||||
<div className='w-full'>
|
||||
<MobileButtonPageNav />
|
||||
</div>
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
export default function LoadingCover() {
|
||||
return <div id='cover-loading' className={'z-50 opacity-50pointer-events-none transition-all duration-300'}>
|
||||
<div className='w-full h-screen flex justify-center items-center'>
|
||||
<i className="fa-solid fa-spinner text-2xl text-black dark:text-white animate-spin"> </i>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
import Comment from '@/components/Comment'
|
||||
import { AdSlot } from '@/components/GoogleAdsense'
|
||||
import Live2D from '@/components/Live2D'
|
||||
import LoadingCover from '@/components/LoadingCover'
|
||||
import NotionIcon from '@/components/NotionIcon'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
import ShareBar from '@/components/ShareBar'
|
||||
@@ -113,6 +114,11 @@ const LayoutBase = props => {
|
||||
setFilteredNavPages(getNavPagesWithLatest(allNavPages, latestPosts, post))
|
||||
}, [router])
|
||||
|
||||
const GITBOOK_LOADING_COVER = siteConfig(
|
||||
'GITBOOK_LOADING_COVER',
|
||||
true,
|
||||
CONFIG
|
||||
)
|
||||
return (
|
||||
<ThemeGlobalGitbook.Provider
|
||||
value={{
|
||||
@@ -237,6 +243,8 @@ const LayoutBase = props => {
|
||||
)}
|
||||
</main>
|
||||
|
||||
{GITBOOK_LOADING_COVER && <LoadingCover />}
|
||||
|
||||
{/* 移动端导航抽屉 */}
|
||||
<PageNavDrawer {...props} filteredNavPages={filteredNavPages} />
|
||||
|
||||
@@ -333,8 +341,10 @@ const LayoutSlug = props => {
|
||||
|
||||
{/* Notion文章主体 */}
|
||||
{post && (
|
||||
<section id='article-wrapper' className='px-1'>
|
||||
<NotionPage post={post} />
|
||||
<section className='px-1'>
|
||||
<div id='article-wrapper'>
|
||||
<NotionPage post={post} />
|
||||
</div>
|
||||
|
||||
{/* 分享 */}
|
||||
<ShareBar post={post} />
|
||||
|
||||
@@ -4,13 +4,15 @@ const NotionPage = dynamic(() => import('@/components/NotionPage'))
|
||||
|
||||
const Announcement = ({ post, className }) => {
|
||||
if (post?.blockMap) {
|
||||
return <div >
|
||||
{post && (
|
||||
<div id="announcement-content">
|
||||
<NotionPage post={post} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
return (
|
||||
<div>
|
||||
{post && (
|
||||
<div id='announcement-content'>
|
||||
<NotionPage post={post} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return <></>
|
||||
}
|
||||
|
||||
@@ -19,18 +19,31 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
siteConfig('HEO_POST_LIST_COVER', null, CONFIG) &&
|
||||
post?.pageCoverThumbnail &&
|
||||
!showPreview
|
||||
|
||||
const POST_TWO_COLS = siteConfig('HEO_HOME_POST_TWO_COLS', true, CONFIG)
|
||||
const COVER_HOVER_ENLARGE = siteConfig(
|
||||
'HEO_POST_LIST_COVER_HOVER_ENLARGE',
|
||||
true,
|
||||
CONFIG
|
||||
)
|
||||
|
||||
return (
|
||||
<article
|
||||
className={` ${siteConfig('HEO_POST_LIST_COVER_HOVER_ENLARGE', null, CONFIG) ? ' hover:scale-110 transition-all duration-150' : ''}`}>
|
||||
className={` ${COVER_HOVER_ENLARGE} ? ' hover:scale-110 transition-all duration-150' : ''}`}>
|
||||
<div
|
||||
data-wow-delay='.2s'
|
||||
className={
|
||||
'wow fadeInUp border bg-white dark:bg-[#1e1e1e] flex mb-4 flex-col h-[23rem] md:h-52 md:flex-row 2xl:h-96 2xl:flex-col group w-full dark:border-gray-600 hover:border-indigo-600 dark:hover:border-yellow-600 duration-300 transition-colors justify-between overflow-hidden rounded-xl'
|
||||
(POST_TWO_COLS ? '2xl:h-96 2xl:flex-col' : '') +
|
||||
' wow fadeInUp border bg-white dark:bg-[#1e1e1e] flex mb-4 flex-col h-[23rem] md:h-52 md:flex-row group w-full dark:border-gray-600 hover:border-indigo-600 dark:hover:border-yellow-600 duration-300 transition-colors justify-between overflow-hidden rounded-xl'
|
||||
}>
|
||||
{/* 图片封面 */}
|
||||
{showPageCover && (
|
||||
<Link href={post?.href} passHref legacyBehavior>
|
||||
<div className='w-full md:w-5/12 2xl:w-full overflow-hidden'>
|
||||
<div
|
||||
className={
|
||||
(POST_TWO_COLS ? ' 2xl:w-full' : '') +
|
||||
' w-full md:w-5/12 overflow-hidden cursor-pointer select-none'
|
||||
}>
|
||||
<LazyImage
|
||||
priority={index === 0}
|
||||
src={post?.pageCoverThumbnail}
|
||||
@@ -44,7 +57,8 @@ const BlogPostCard = ({ index, post, showSummary, siteInfo }) => {
|
||||
{/* 文字区块 */}
|
||||
<div
|
||||
className={
|
||||
'flex p-6 2xl:p-4 flex-col justify-between h-48 md:h-full 2xl:h-48 w-full md:w-7/12 2xl:w-full'
|
||||
(POST_TWO_COLS ? '2xl:p-4 2xl:h-48 2xl:w-full' : '') +
|
||||
' flex p-6 flex-col justify-between h-48 md:h-full w-full md:w-7/12'
|
||||
}>
|
||||
<header>
|
||||
{/* 分类 */}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import CONFIG from '../config'
|
||||
import BlogPostCard from './BlogPostCard'
|
||||
import BlogPostListEmpty from './BlogPostListEmpty'
|
||||
import PaginationNumber from './PaginationNumber'
|
||||
@@ -14,16 +15,18 @@ import PaginationNumber from './PaginationNumber'
|
||||
*/
|
||||
const BlogPostListPage = ({ page = 1, posts = [], postCount, siteInfo }) => {
|
||||
const { NOTION_CONFIG } = useGlobal()
|
||||
const POSTS_PER_PAGE = siteConfig('POSTS_PER_PAGE', null, NOTION_CONFIG)
|
||||
const POSTS_PER_PAGE = siteConfig('POSTS_PER_PAGE', 12, NOTION_CONFIG)
|
||||
const totalPage = Math.ceil(postCount / POSTS_PER_PAGE)
|
||||
const showPagination = postCount >= POSTS_PER_PAGE
|
||||
const POST_TWO_COLS = siteConfig('HEO_HOME_POST_TWO_COLS', true, CONFIG)
|
||||
if (!posts || posts.length === 0 || page > totalPage) {
|
||||
return <BlogPostListEmpty />
|
||||
} else {
|
||||
return (
|
||||
<div id='container' className='w-full'>
|
||||
{/* 文章列表 */}
|
||||
<div className='2xl:grid 2xl:grid-cols-2 grid-cols-1 gap-5'>
|
||||
<div
|
||||
className={`${POST_TWO_COLS && '2xl:grid 2xl:grid-cols-2'} grid-cols-1 gap-5`}>
|
||||
{posts?.map(post => (
|
||||
<BlogPostCard
|
||||
index={posts.indexOf(post)}
|
||||
|
||||
@@ -19,7 +19,7 @@ const BlogPostListScroll = ({
|
||||
showSummary = siteConfig('HEO_POST_LIST_SUMMARY', null, CONFIG),
|
||||
siteInfo
|
||||
}) => {
|
||||
const { NOTION_CONFIG } = useGlobal()
|
||||
const { locale, NOTION_CONFIG } = useGlobal()
|
||||
const [page, updatePage] = useState(1)
|
||||
const POSTS_PER_PAGE = siteConfig('POSTS_PER_PAGE', null, NOTION_CONFIG)
|
||||
const postsToShow = getListByPage(posts, page, POSTS_PER_PAGE)
|
||||
@@ -59,15 +59,16 @@ const BlogPostListScroll = ({
|
||||
})
|
||||
|
||||
const targetRef = useRef(null)
|
||||
const { locale } = useGlobal()
|
||||
|
||||
const POST_TWO_COLS = siteConfig('HEO_HOME_POST_TWO_COLS', true, CONFIG)
|
||||
if (!postsToShow || postsToShow.length === 0) {
|
||||
return <BlogPostListEmpty currentSearch={currentSearch} />
|
||||
} else {
|
||||
return (
|
||||
<div id='container' ref={targetRef} className='w-full'>
|
||||
{/* 文章列表 */}
|
||||
<div className='2xl:grid 2xl:grid-cols-2 grid-cols-1 gap-5'>
|
||||
<div
|
||||
className={`${POST_TWO_COLS && '2xl:grid 2xl:grid-cols-2'} grid-cols-1 gap-5`}>
|
||||
{' '}
|
||||
{postsToShow.map(post => (
|
||||
<BlogPostCard
|
||||
key={post.id}
|
||||
|
||||
@@ -32,8 +32,8 @@ export default function CategoryBar(props) {
|
||||
return (
|
||||
<div
|
||||
id='category-bar'
|
||||
className={`flex flex-nowrap justify-between items-center h-12 mb-4 space-x-2 w-full lg:bg-white dark:lg:bg-[#1e1e1e]
|
||||
${border ? 'lg:border lg:hover:border dark:lg:border-gray-800 hover:border-indigo-600 dark:hover:border-yellow-600 ' : ''} py-2 lg:px-2 rounded-xl transition-colors duration-200`}>
|
||||
className={`wow fadeInUp flex flex-nowrap justify-between items-center h-12 mb-4 space-x-2 w-full lg:bg-white dark:lg:bg-[#1e1e1e]
|
||||
${border ? 'lg:border lg:hover:border dark:lg:border-gray-800 hover:border-indigo-600 dark:hover:border-yellow-600 ' : ''} py-2 lg:px-2 rounded-xl transition-colors duration-200`}>
|
||||
<div
|
||||
id='category-bar-items'
|
||||
ref={categoryBarItemsRef}
|
||||
|
||||
@@ -383,7 +383,7 @@ function TodayCard({ cRef, siteInfo }) {
|
||||
}
|
||||
/>
|
||||
<div id='more' className='select-none'>
|
||||
{locale.COMMON.MORE}
|
||||
{locale.COMMON.RECOMMEND_POSTS}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -23,11 +23,12 @@ export function InfoCard(props) {
|
||||
const url2 = siteConfig('HEO_INFO_CARD_URL2', null, CONFIG)
|
||||
const icon2 = siteConfig('HEO_INFO_CARD_ICON2', null, CONFIG)
|
||||
return (
|
||||
<Card className='bg-[#4f65f0] dark:bg-yellow-600 text-white flex flex-col w-72 overflow-hidden relative'>
|
||||
<Card className='wow fadeInUp bg-[#4f65f0] dark:bg-yellow-600 text-white flex flex-col w-72 overflow-hidden relative'>
|
||||
{/* 信息卡牌第一行 */}
|
||||
<div className='flex justify-between'>
|
||||
{/* 问候语 */}
|
||||
<GreetingsWords />
|
||||
{/* 头像 */}
|
||||
<div
|
||||
className={`${isSlugPage ? 'absolute right-0 -mt-8 -mr-6 hover:opacity-0 hover:scale-150 blur' : 'cursor-pointer'} justify-center items-center flex dark:text-gray-100 transform transitaion-all duration-200`}>
|
||||
<LazyImage
|
||||
@@ -42,9 +43,7 @@ export function InfoCard(props) {
|
||||
<h2 className='text-3xl font-extrabold mt-3'>{siteConfig('AUTHOR')}</h2>
|
||||
|
||||
{/* 公告栏 */}
|
||||
<div>
|
||||
<Announcement post={notice} style={{ color: 'white !important' }} />
|
||||
</div>
|
||||
<Announcement post={notice} style={{ color: 'white !important' }} />
|
||||
|
||||
<div className='flex justify-between'>
|
||||
<div className='flex space-x-3 hover:text-black dark:hover:text-white'>
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
export default function LoadingCover () {
|
||||
return (<div id="loading-cover" className={'md:-mt-20 flex-grow dark:text-white text-black animate__animated animate__fadeIn flex flex-col justify-center z-50 w-full h-screen container mx-auto'}>
|
||||
<div className="mx-auto">
|
||||
<i className="fas fa-spinner animate-spin"/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -34,23 +34,25 @@ export default function SideRight(props) {
|
||||
|
||||
return (
|
||||
<div id='sideRight' className='hidden xl:block w-72 space-y-4 h-full'>
|
||||
<InfoCard {...props} className='w-72' />
|
||||
<InfoCard {...props} className='w-72 wow fadeInUp' />
|
||||
|
||||
<div className='sticky top-20 space-y-4'>
|
||||
{/* 文章页显示目录 */}
|
||||
{post && post.toc && post.toc.length > 0 && (
|
||||
<Card className='bg-white dark:bg-[#1e1e1e]'>
|
||||
<Card className='bg-white dark:bg-[#1e1e1e] wow fadeInUp'>
|
||||
<Catalog toc={post.toc} />
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* 联系交流群 */}
|
||||
<TouchMeCard />
|
||||
<div className='wow fadeInUp'>
|
||||
<TouchMeCard />
|
||||
</div>
|
||||
|
||||
{/* 最新文章列表 */}
|
||||
<div
|
||||
className={
|
||||
'border hover:border-indigo-600 dark:hover:border-yellow-600 duration-200 dark:border-gray-700 dark:bg-[#1e1e1e] dark:text-white rounded-xl lg:p-6 p-4 hidden lg:block bg-white'
|
||||
'border wow fadeInUp hover:border-indigo-600 dark:hover:border-yellow-600 duration-200 dark:border-gray-700 dark:bg-[#1e1e1e] dark:text-white rounded-xl lg:p-6 p-4 hidden lg:block bg-white'
|
||||
}>
|
||||
<LatestPostsGroupMini {...props} />
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
|
||||
import FlipCard from '@/components/FlipCard'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import Link from 'next/link'
|
||||
import CONFIG from '../config'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
|
||||
/**
|
||||
* 交流频道
|
||||
@@ -13,23 +12,33 @@ export default function TouchMeCard() {
|
||||
return <></>
|
||||
}
|
||||
return (
|
||||
<div className={'relative h-28 text-white flex flex-col'}>
|
||||
|
||||
<FlipCard
|
||||
className='cursor-pointer lg:p-6 p-4 border rounded-xl bg-[#4f65f0] dark:bg-yellow-600 dark:border-gray-600'
|
||||
frontContent={
|
||||
<div className='h-full'>
|
||||
<h2 className='font-[1000] text-3xl'>{siteConfig('HEO_SOCIAL_CARD_TITLE_1', null, CONFIG)}</h2>
|
||||
<h3 className='pt-2'>{siteConfig('HEO_SOCIAL_CARD_TITLE_2', null, CONFIG)}</h3>
|
||||
<div className='absolute left-0 top-0 w-full h-full' style={{ background: 'url(https://bu.dusays.com/2023/05/16/64633c4cd36a9.png) center center no-repeat' }}></div>
|
||||
</div>}
|
||||
backContent={<Link href={siteConfig('HEO_SOCIAL_CARD_URL', null, CONFIG)}>
|
||||
<div className='font-[1000] text-xl h-full'>
|
||||
{siteConfig('HEO_SOCIAL_CARD_TITLE_3', null, CONFIG)}
|
||||
</div>
|
||||
</Link>}
|
||||
/>
|
||||
|
||||
</div>
|
||||
<div className={'relative h-28 text-white flex flex-col'}>
|
||||
<FlipCard
|
||||
className='cursor-pointer lg:p-6 p-4 border rounded-xl bg-[#4f65f0] dark:bg-yellow-600 dark:border-gray-600'
|
||||
frontContent={
|
||||
<div className='h-full'>
|
||||
<h2 className='font-[1000] text-3xl'>
|
||||
{siteConfig('HEO_SOCIAL_CARD_TITLE_1', null, CONFIG)}
|
||||
</h2>
|
||||
<h3 className='pt-2'>
|
||||
{siteConfig('HEO_SOCIAL_CARD_TITLE_2', null, CONFIG)}
|
||||
</h3>
|
||||
<div
|
||||
className='absolute left-0 top-0 w-full h-full'
|
||||
style={{
|
||||
background:
|
||||
'url(https://bu.dusays.com/2023/05/16/64633c4cd36a9.png) center center no-repeat'
|
||||
}}></div>
|
||||
</div>
|
||||
}
|
||||
backContent={
|
||||
<Link href={siteConfig('HEO_SOCIAL_CARD_URL', null, CONFIG)}>
|
||||
<div className='font-[1000] text-xl h-full'>
|
||||
{siteConfig('HEO_SOCIAL_CARD_TITLE_3', null, CONFIG)}
|
||||
</div>
|
||||
</Link>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
const CONFIG = {
|
||||
HEO_HOME_POST_TWO_COLS: true, // 首页博客两列显示,若为false则只显示一列
|
||||
HEO_LOADING_COVER: true, // 页面加载的遮罩动画
|
||||
|
||||
HEO_HOME_BANNER_ENABLE: true,
|
||||
|
||||
HEO_SITE_CREATE_TIME: '2021-09-21', // 建站日期,用于计算网站运行的第几天
|
||||
|
||||
@@ -10,6 +10,7 @@ import Comment from '@/components/Comment'
|
||||
import { AdSlot } from '@/components/GoogleAdsense'
|
||||
import { HashTag } from '@/components/HeroIcons'
|
||||
import LazyImage from '@/components/LazyImage'
|
||||
import LoadingCover from '@/components/LoadingCover'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
import ShareBar from '@/components/ShareBar'
|
||||
@@ -82,6 +83,7 @@ const LayoutBase = props => {
|
||||
false,
|
||||
CONFIG
|
||||
)
|
||||
const HEO_LOADING_COVER = siteConfig('HEO_LOADING_COVER', true, CONFIG)
|
||||
|
||||
// 加载wow动画
|
||||
useEffect(() => {
|
||||
@@ -121,6 +123,8 @@ const LayoutBase = props => {
|
||||
|
||||
{/* 页脚 */}
|
||||
<Footer title={siteConfig('TITLE')} />
|
||||
|
||||
{HEO_LOADING_COVER && <LoadingCover />}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -284,14 +288,17 @@ const LayoutSlug = props => {
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={`article h-full w-full ${fullWidth ? '' : 'xl:max-w-5xl'} ${hasCode ? 'xl:w-[73.15vw]' : ''} lg:hover:shadow lg:border rounded-2xl lg:px-2 lg:py-4 bg-white dark:bg-[#18171d] dark:border-gray-600`}>
|
||||
className={`article h-full w-full ${fullWidth ? '' : 'xl:max-w-5xl'} ${hasCode ? 'xl:w-[73.15vw]' : ''} bg-white dark:bg-[#18171d] dark:border-gray-600 lg:hover:shadow lg:border rounded-2xl lg:px-2 lg:py-4 `}>
|
||||
{/* 文章锁 */}
|
||||
{lock && <PostLock validPassword={validPassword} />}
|
||||
|
||||
{!lock && (
|
||||
<div id='article-wrapper' className='mx-auto md:w-full md:px-5'>
|
||||
<div className='mx-auto md:w-full md:px-5'>
|
||||
{/* 文章主体 */}
|
||||
<article itemScope itemType='https://schema.org/Movie'>
|
||||
<article
|
||||
id='article-wrapper'
|
||||
itemScope
|
||||
itemType='https://schema.org/Movie'>
|
||||
{/* Notion文章主体 */}
|
||||
<section
|
||||
className='wow fadeInUp p-5 justify-center mx-auto'
|
||||
|
||||
@@ -26,10 +26,7 @@ const Hero = props => {
|
||||
updateHeaderHeight()
|
||||
|
||||
if (!typed && window && document.getElementById('typed')) {
|
||||
loadExternalResource(
|
||||
'https://cdn.bootcdn.net/ajax/libs/typed.js/2.0.12/typed.min.js',
|
||||
'js'
|
||||
).then(() => {
|
||||
loadExternalResource('/js/typed.min.js', 'js').then(() => {
|
||||
if (window.Typed) {
|
||||
changeType(
|
||||
new window.Typed('#typed', {
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import Card from './Card'
|
||||
import CategoryGroup from './CategoryGroup'
|
||||
import LatestPostsGroup from './LatestPostsGroup'
|
||||
import TagGroups from './TagGroups'
|
||||
import Catalog from './Catalog'
|
||||
import { InfoCard } from './InfoCard'
|
||||
import { AnalyticsCard } from './AnalyticsCard'
|
||||
import CONFIG from '../config'
|
||||
import dynamic from 'next/dynamic'
|
||||
import Announcement from './Announcement'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import Live2D from '@/components/Live2D'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import dynamic from 'next/dynamic'
|
||||
import CONFIG from '../config'
|
||||
import { AnalyticsCard } from './AnalyticsCard'
|
||||
import Announcement from './Announcement'
|
||||
import Card from './Card'
|
||||
import Catalog from './Catalog'
|
||||
import CategoryGroup from './CategoryGroup'
|
||||
import { InfoCard } from './InfoCard'
|
||||
import LatestPostsGroup from './LatestPostsGroup'
|
||||
import TagGroups from './TagGroups'
|
||||
|
||||
const HexoRecentComments = dynamic(() => import('./HexoRecentComments'))
|
||||
const FaceBookPage = dynamic(
|
||||
@@ -33,8 +33,17 @@ const FaceBookPage = dynamic(
|
||||
*/
|
||||
export default function SideRight(props) {
|
||||
const {
|
||||
post, currentCategory, categories, latestPosts, tags,
|
||||
currentTag, showCategory, showTag, rightAreaSlot, notice, className
|
||||
post,
|
||||
currentCategory,
|
||||
categories,
|
||||
latestPosts,
|
||||
tags,
|
||||
currentTag,
|
||||
showCategory,
|
||||
showTag,
|
||||
rightAreaSlot,
|
||||
notice,
|
||||
className
|
||||
} = props
|
||||
|
||||
const { locale } = useGlobal()
|
||||
@@ -45,44 +54,54 @@ export default function SideRight(props) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div id='sideRight' className={className}>
|
||||
<InfoCard {...props} />
|
||||
{siteConfig('HEXO_WIDGET_ANALYTICS', null, CONFIG) && <AnalyticsCard {...props} />}
|
||||
<div
|
||||
id='sideRight'
|
||||
className={` lg:w-80 lg:pt-8 ${post ? 'lg:pt-0' : 'lg:pt-4'}`}>
|
||||
<div className='sticky top-8 space-y-4'>
|
||||
{post && post.toc && post.toc.length > 1 && (
|
||||
<Card>
|
||||
<Catalog toc={post.toc} />
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{showCategory && (
|
||||
<Card>
|
||||
<div className='ml-2 mb-1 '>
|
||||
<i className='fas fa-th' /> {locale.COMMON.CATEGORY}
|
||||
</div>
|
||||
<CategoryGroup
|
||||
currentCategory={currentCategory}
|
||||
categories={categories}
|
||||
/>
|
||||
</Card>
|
||||
)}
|
||||
{showTag && (
|
||||
<Card>
|
||||
<TagGroups tags={tags} currentTag={currentTag} />
|
||||
</Card>
|
||||
)}
|
||||
{siteConfig('HEXO_WIDGET_LATEST_POSTS', null, CONFIG) && latestPosts && latestPosts.length > 0 && <Card>
|
||||
<LatestPostsGroup {...props} />
|
||||
</Card>}
|
||||
<InfoCard {...props} />
|
||||
{siteConfig('HEXO_WIDGET_ANALYTICS', null, CONFIG) && (
|
||||
<AnalyticsCard {...props} />
|
||||
)}
|
||||
|
||||
<Announcement post={notice}/>
|
||||
{showCategory && (
|
||||
<Card>
|
||||
<div className='ml-2 mb-1 '>
|
||||
<i className='fas fa-th' /> {locale.COMMON.CATEGORY}
|
||||
</div>
|
||||
<CategoryGroup
|
||||
currentCategory={currentCategory}
|
||||
categories={categories}
|
||||
/>
|
||||
</Card>
|
||||
)}
|
||||
{showTag && (
|
||||
<Card>
|
||||
<TagGroups tags={tags} currentTag={currentTag} />
|
||||
</Card>
|
||||
)}
|
||||
{siteConfig('HEXO_WIDGET_LATEST_POSTS', null, CONFIG) &&
|
||||
latestPosts &&
|
||||
latestPosts.length > 0 && (
|
||||
<Card>
|
||||
<LatestPostsGroup {...props} />
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{siteConfig('COMMENT_WALINE_SERVER_URL') && siteConfig('COMMENT_WALINE_RECENT') && <HexoRecentComments/>}
|
||||
<Announcement post={notice} />
|
||||
|
||||
<div className='sticky top-20'>
|
||||
{post && post.toc && post.toc.length > 1 && <Card>
|
||||
<Catalog toc={post.toc} />
|
||||
</Card>}
|
||||
{siteConfig('COMMENT_WALINE_SERVER_URL') &&
|
||||
siteConfig('COMMENT_WALINE_RECENT') && <HexoRecentComments />}
|
||||
|
||||
{rightAreaSlot}
|
||||
<FaceBookPage/>
|
||||
<FaceBookPage />
|
||||
<Live2D />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -141,10 +141,7 @@ const LayoutBase = props => {
|
||||
</div>
|
||||
|
||||
{/* 右侧栏 */}
|
||||
<SideRight
|
||||
{...props}
|
||||
className={`space-y-4 lg:w-80 pt-4 ${post ? 'lg:pt-0' : 'lg:pt-4'}`}
|
||||
/>
|
||||
<SideRight {...props} />
|
||||
</div>
|
||||
</main>
|
||||
|
||||
@@ -290,10 +287,9 @@ const LayoutSlug = props => {
|
||||
{lock && <ArticleLock validPassword={validPassword} />}
|
||||
|
||||
{!lock && (
|
||||
<div
|
||||
id='article-wrapper'
|
||||
className='overflow-x-auto flex-grow mx-auto md:w-full md:px-5 '>
|
||||
<div className='overflow-x-auto flex-grow mx-auto md:w-full md:px-5 '>
|
||||
<article
|
||||
id='article-wrapper'
|
||||
itemScope
|
||||
itemType='https://schema.org/Movie'
|
||||
className='subpixel-antialiased overflow-y-hidden'>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
'use client'
|
||||
|
||||
/**
|
||||
@@ -7,21 +6,21 @@
|
||||
* 2. 内容大部分是在此文件中写死,notion数据从props参数中传进来
|
||||
* 3. 您可在此网站找到更多喜欢的组件 https://www.tailwind-kit.com/
|
||||
*/
|
||||
import Loading from '@/components/Loading'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
import Header from './components/Header'
|
||||
import Footer from './components/Footer'
|
||||
import Hero from './components/Hero'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useEffect } from 'react'
|
||||
import Features from './components/Features'
|
||||
import FeaturesBlocks from './components/FeaturesBlocks'
|
||||
import Testimonials from './components/Testimonials'
|
||||
import Footer from './components/Footer'
|
||||
import Header from './components/Header'
|
||||
import Hero from './components/Hero'
|
||||
import Newsletter from './components/Newsletter'
|
||||
import { useRouter } from 'next/router'
|
||||
import CONFIG from './config'
|
||||
import Loading from '@/components/Loading'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { Pricing } from './components/Pricing'
|
||||
import { useEffect } from 'react'
|
||||
import Testimonials from './components/Testimonials'
|
||||
import CONFIG from './config'
|
||||
|
||||
/**
|
||||
* 布局框架
|
||||
@@ -30,22 +29,23 @@ import { useEffect } from 'react'
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutBase = (props) => {
|
||||
const LayoutBase = props => {
|
||||
const { children } = props
|
||||
|
||||
return <div id='theme-landing' className={`${siteConfig('FONT_STYLE')} scroll-smooth overflow-hidden flex flex-col justify-between bg-white dark:bg-black`}>
|
||||
return (
|
||||
<div
|
||||
id='theme-landing'
|
||||
className={`${siteConfig('FONT_STYLE')} scroll-smooth overflow-hidden flex flex-col justify-between bg-white dark:bg-black`}>
|
||||
{/* 顶部导航栏 */}
|
||||
<Header />
|
||||
|
||||
{/* 顶部导航栏 */}
|
||||
<Header />
|
||||
{/* 内容 */}
|
||||
<div id='content-wrapper'>{children}</div>
|
||||
|
||||
{/* 内容 */}
|
||||
<div id='content-wrapper'>
|
||||
{children}
|
||||
</div>
|
||||
|
||||
{/* 底部页脚 */}
|
||||
<Footer />
|
||||
{/* 底部页脚 */}
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,16 +53,16 @@ const LayoutBase = (props) => {
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutIndex = (props) => {
|
||||
const LayoutIndex = props => {
|
||||
return (
|
||||
<>
|
||||
<Hero />
|
||||
<Features />
|
||||
<FeaturesBlocks />
|
||||
<Testimonials />
|
||||
<Pricing/>
|
||||
<Newsletter />
|
||||
</>
|
||||
<>
|
||||
<Hero />
|
||||
<Features />
|
||||
<FeaturesBlocks />
|
||||
<Testimonials />
|
||||
<Pricing />
|
||||
<Newsletter />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ const LayoutIndex = (props) => {
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutSlug = (props) => {
|
||||
const LayoutSlug = props => {
|
||||
const { post } = props
|
||||
|
||||
// 如果 是 /article/[slug] 的文章路径则进行重定向到另一个域名
|
||||
@@ -79,49 +79,90 @@ const LayoutSlug = (props) => {
|
||||
useEffect(() => {
|
||||
// 404
|
||||
if (!post) {
|
||||
setTimeout(() => {
|
||||
if (isBrowser) {
|
||||
const article = document.getElementById('notion-article')
|
||||
if (!article) {
|
||||
router.push('/404').then(() => {
|
||||
console.warn('找不到页面', router.asPath)
|
||||
})
|
||||
setTimeout(
|
||||
() => {
|
||||
if (isBrowser) {
|
||||
const article = document.getElementById('notion-article')
|
||||
if (!article) {
|
||||
router.push('/404').then(() => {
|
||||
console.warn('找不到页面', router.asPath)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}, siteConfig('POST_WAITING_TIME_FOR_404') * 1000)
|
||||
},
|
||||
siteConfig('POST_WAITING_TIME_FOR_404') * 1000
|
||||
)
|
||||
}
|
||||
}, [post])
|
||||
|
||||
if (JSON.parse(siteConfig('LANDING_POST_REDIRECT_ENABLE', null, CONFIG)) && isBrowser && router.route === '/[prefix]/[slug]') {
|
||||
const redirectUrl = siteConfig('LANDING_POST_REDIRECT_URL', null, CONFIG) + router.asPath.replace('?theme=landing', '')
|
||||
if (
|
||||
JSON.parse(siteConfig('LANDING_POST_REDIRECT_ENABLE', null, CONFIG)) &&
|
||||
isBrowser &&
|
||||
router.route === '/[prefix]/[slug]'
|
||||
) {
|
||||
const redirectUrl =
|
||||
siteConfig('LANDING_POST_REDIRECT_URL', null, CONFIG) +
|
||||
router.asPath.replace('?theme=landing', '')
|
||||
router.push(redirectUrl)
|
||||
return <div id='theme-landing'><Loading /></div>
|
||||
return (
|
||||
<div id='theme-landing'>
|
||||
<Loading />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return <>
|
||||
<div id='container-inner' className='mx-auto max-w-screen-lg p-12'>
|
||||
<NotionPage {...props} />
|
||||
return (
|
||||
<>
|
||||
<div id='container-inner' className='mx-auto max-w-screen-lg p-12'>
|
||||
<div id='article-wrapper'>
|
||||
<NotionPage {...props} />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
// 其他布局暂时留空
|
||||
const LayoutSearch = (props) => <><Hero /></>
|
||||
const LayoutArchive = (props) => <><Hero /></>
|
||||
const Layout404 = (props) => <><Hero /></>
|
||||
const LayoutCategoryIndex = (props) => <><Hero /></>
|
||||
const LayoutPostList = (props) => <><Hero /></>
|
||||
const LayoutTagIndex = (props) => <><Hero /></>
|
||||
const LayoutSearch = props => (
|
||||
<>
|
||||
<Hero />
|
||||
</>
|
||||
)
|
||||
const LayoutArchive = props => (
|
||||
<>
|
||||
<Hero />
|
||||
</>
|
||||
)
|
||||
const Layout404 = props => (
|
||||
<>
|
||||
<Hero />
|
||||
</>
|
||||
)
|
||||
const LayoutCategoryIndex = props => (
|
||||
<>
|
||||
<Hero />
|
||||
</>
|
||||
)
|
||||
const LayoutPostList = props => (
|
||||
<>
|
||||
<Hero />
|
||||
</>
|
||||
)
|
||||
const LayoutTagIndex = props => (
|
||||
<>
|
||||
<Hero />
|
||||
</>
|
||||
)
|
||||
|
||||
export {
|
||||
CONFIG as THEME_CONFIG,
|
||||
LayoutBase,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
LayoutSlug,
|
||||
Layout404,
|
||||
LayoutPostList,
|
||||
LayoutArchive,
|
||||
LayoutBase,
|
||||
LayoutCategoryIndex,
|
||||
LayoutTagIndex
|
||||
LayoutIndex,
|
||||
LayoutPostList,
|
||||
LayoutSearch,
|
||||
LayoutSlug,
|
||||
LayoutTagIndex,
|
||||
CONFIG as THEME_CONFIG
|
||||
}
|
||||
|
||||
@@ -21,10 +21,7 @@ const Hero = props => {
|
||||
useEffect(() => {
|
||||
updateHeaderHeight()
|
||||
if (!typed && window && document.getElementById('typed')) {
|
||||
loadExternalResource(
|
||||
'https://cdn.bootcdn.net/ajax/libs/typed.js/2.0.12/typed.min.js',
|
||||
'js'
|
||||
).then(() => {
|
||||
loadExternalResource('/js/typed.min.js', 'js').then(() => {
|
||||
if (window.Typed) {
|
||||
changeType(
|
||||
new window.Typed('#typed', {
|
||||
|
||||
@@ -254,9 +254,7 @@ const LayoutSlug = props => {
|
||||
{lock && <ArticleLock validPassword={validPassword} />}
|
||||
|
||||
{!lock && (
|
||||
<div
|
||||
id='article-wrapper'
|
||||
className='overflow-x-auto md:w-full px-3 '>
|
||||
<div className='overflow-x-auto md:w-full px-3 '>
|
||||
{/* 文章信息 */}
|
||||
{post?.type && post?.type === 'Post' && (
|
||||
<>
|
||||
@@ -268,7 +266,7 @@ const LayoutSlug = props => {
|
||||
)}
|
||||
|
||||
<div className='lg:px-10 subpixel-antialiased'>
|
||||
<article itemScope>
|
||||
<article id='article-wrapper' itemScope>
|
||||
{/* Notion文章主体 */}
|
||||
<section
|
||||
data-wow-delay='.1s'
|
||||
|
||||
@@ -1,18 +1,37 @@
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import CategoryItem from './CategoryItem'
|
||||
|
||||
/**
|
||||
* 分类
|
||||
* @param {*} param0
|
||||
* @returns
|
||||
*/
|
||||
const CategoryGroup = ({ currentCategory, categoryOptions }) => {
|
||||
const { locale } = useGlobal()
|
||||
if (!categoryOptions) {
|
||||
return <></>
|
||||
}
|
||||
return <div id='category-list' className='pt-4'>
|
||||
<div className='mb-2'><i className='mr-2 fas fa-th' />分类</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} />
|
||||
})}
|
||||
return (
|
||||
<div id='category-list' className='pt-4'>
|
||||
<div className='mb-2'>
|
||||
<i className='mr-2 fas fa-th' />
|
||||
{locale.COMMON.CATEGORY}
|
||||
</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>
|
||||
)
|
||||
}
|
||||
|
||||
export default CategoryGroup
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import TagItemMini from './TagItemMini'
|
||||
|
||||
/**
|
||||
@@ -8,17 +9,19 @@ import TagItemMini from './TagItemMini'
|
||||
* @constructor
|
||||
*/
|
||||
const TagGroups = ({ tagOptions, currentTag }) => {
|
||||
const { locale } = useGlobal()
|
||||
if (!tagOptions) return <></>
|
||||
return (
|
||||
<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'>
|
||||
{
|
||||
tagOptions?.map(tag => {
|
||||
const selected = tag.name === currentTag
|
||||
return <TagItemMini key={tag.name} tag={tag} selected={selected} />
|
||||
})
|
||||
}
|
||||
{tagOptions?.map(tag => {
|
||||
const selected = tag.name === currentTag
|
||||
return <TagItemMini key={tag.name} tag={tag} selected={selected} />
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
import CONFIG from './config'
|
||||
import { useState, createContext, useContext, useEffect } from 'react'
|
||||
import Footer from './components/Footer'
|
||||
import InfoCard from './components/InfoCard'
|
||||
import RevolverMaps from './components/RevolverMaps'
|
||||
import Tabs from '@/components/Tabs'
|
||||
import TopNavBar from './components/TopNavBar'
|
||||
import SearchInput from './components/SearchInput'
|
||||
import BottomMenuBar from './components/BottomMenuBar'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { useRouter } from 'next/router'
|
||||
import Comment from '@/components/Comment'
|
||||
import Live2D from '@/components/Live2D'
|
||||
import Announcement from './components/Announcement'
|
||||
import JumpToTopButton from './components/JumpToTopButton'
|
||||
import BlogPostListPage from './components/BlogPostListPage'
|
||||
import BlogPostListScroll from './components/BlogPostListScroll'
|
||||
import Catalog from './components/Catalog'
|
||||
import { ArticleLock } from './components/ArticleLock'
|
||||
import TagGroups from './components/TagGroups'
|
||||
import CategoryGroup from './components/CategoryGroup'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
import ShareBar from '@/components/ShareBar'
|
||||
import Tabs from '@/components/Tabs'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
import { Transition } from '@headlessui/react'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { createContext, useContext, useEffect, useState } from 'react'
|
||||
import Announcement from './components/Announcement'
|
||||
import ArticleAround from './components/ArticleAround'
|
||||
import ArticleInfo from './components/ArticleInfo'
|
||||
import { ArticleLock } from './components/ArticleLock'
|
||||
import BlogArchiveItem from './components/BlogArchiveItem'
|
||||
import BlogPostBar from './components/BlogPostBar'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
import Comment from '@/components/Comment'
|
||||
import ArticleAround from './components/ArticleAround'
|
||||
import TocDrawer from './components/TocDrawer'
|
||||
import BlogPostListPage from './components/BlogPostListPage'
|
||||
import BlogPostListScroll from './components/BlogPostListScroll'
|
||||
import BottomMenuBar from './components/BottomMenuBar'
|
||||
import Catalog from './components/Catalog'
|
||||
import CategoryGroup from './components/CategoryGroup'
|
||||
import CategoryItem from './components/CategoryItem'
|
||||
import Footer from './components/Footer'
|
||||
import InfoCard from './components/InfoCard'
|
||||
import JumpToTopButton from './components/JumpToTopButton'
|
||||
import RevolverMaps from './components/RevolverMaps'
|
||||
import SearchInput from './components/SearchInput'
|
||||
import TagGroups from './components/TagGroups'
|
||||
import TagItemMini from './components/TagItemMini'
|
||||
import ShareBar from '@/components/ShareBar'
|
||||
import Link from 'next/link'
|
||||
import { Transition } from '@headlessui/react'
|
||||
import TocDrawer from './components/TocDrawer'
|
||||
import TopNavBar from './components/TopNavBar'
|
||||
import CONFIG from './config'
|
||||
import { Style } from './style'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
import ArticleInfo from './components/ArticleInfo'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
|
||||
// 主题全局状态
|
||||
const ThemeGlobalMedium = createContext()
|
||||
@@ -51,86 +51,96 @@ const LayoutBase = props => {
|
||||
const router = useRouter()
|
||||
const [tocVisible, changeTocVisible] = useState(false)
|
||||
const { onLoading, fullWidth } = useGlobal()
|
||||
const [slotRight, setSlotRight] = useState(null);
|
||||
const [slotRight, setSlotRight] = useState(null)
|
||||
|
||||
useEffect(()=> {
|
||||
useEffect(() => {
|
||||
if (post?.toc?.length > 0) {
|
||||
setSlotRight(
|
||||
<div key={locale.COMMON.TABLE_OF_CONTENTS}>
|
||||
<Catalog toc={post?.toc} />
|
||||
</div>
|
||||
);
|
||||
)
|
||||
} else {
|
||||
setSlotRight(null);
|
||||
setSlotRight(null)
|
||||
}
|
||||
},[post])
|
||||
}, [post])
|
||||
|
||||
const slotTop = <BlogPostBar {...props} />
|
||||
|
||||
return (
|
||||
<ThemeGlobalMedium.Provider value={{ tocVisible, changeTocVisible }}>
|
||||
{/* CSS样式 */}
|
||||
<Style />
|
||||
<ThemeGlobalMedium.Provider value={{ tocVisible, changeTocVisible }}>
|
||||
{/* CSS样式 */}
|
||||
<Style />
|
||||
|
||||
<div id='theme-medium' className={`${siteConfig('FONT_STYLE')} bg-white dark:bg-hexo-black-gray w-full h-full min-h-screen justify-center dark:text-gray-300 scroll-smooth`}>
|
||||
<div
|
||||
id='theme-medium'
|
||||
className={`${siteConfig('FONT_STYLE')} bg-white dark:bg-hexo-black-gray w-full h-full min-h-screen justify-center dark:text-gray-300 scroll-smooth`}>
|
||||
<main
|
||||
id='wrapper'
|
||||
className={
|
||||
(JSON.parse(siteConfig('LAYOUT_SIDEBAR_REVERSE'))
|
||||
? 'flex-row-reverse'
|
||||
: '') + 'relative flex justify-between w-full h-full mx-auto'
|
||||
}>
|
||||
{/* 桌面端左侧菜单 */}
|
||||
{/* <LeftMenuBar/> */}
|
||||
|
||||
<main id='wrapper' className={(JSON.parse(siteConfig('LAYOUT_SIDEBAR_REVERSE')) ? 'flex-row-reverse' : '') + 'relative flex justify-between w-full h-full mx-auto'}>
|
||||
{/* 桌面端左侧菜单 */}
|
||||
{/* <LeftMenuBar/> */}
|
||||
{/* 主区 */}
|
||||
<div id='container-wrapper' className='w-full relative z-10'>
|
||||
{/* 顶部导航栏 */}
|
||||
<TopNavBar {...props} />
|
||||
|
||||
{/* 主区 */}
|
||||
<div id='container-wrapper' className='w-full relative z-10'>
|
||||
<div
|
||||
id='container-inner'
|
||||
className={`px-7 ${fullWidth ? '' : 'max-w-5xl'} justify-center mx-auto min-h-screen`}>
|
||||
<Transition
|
||||
show={!onLoading}
|
||||
appear={true}
|
||||
enter='transition ease-in-out duration-700 transform order-first'
|
||||
enterFrom='opacity-0 translate-y-16'
|
||||
enterTo='opacity-100'
|
||||
leave='transition ease-in-out duration-300 transform'
|
||||
leaveFrom='opacity-100'
|
||||
leaveTo='opacity-0 -translate-y-16'
|
||||
unmount={false}>
|
||||
{slotTop}
|
||||
{children}
|
||||
</Transition>
|
||||
|
||||
{/* 顶部导航栏 */}
|
||||
<TopNavBar {...props} />
|
||||
|
||||
<div id='container-inner' className={`px-7 ${fullWidth ? '' : 'max-w-5xl'} justify-center mx-auto min-h-screen`}>
|
||||
<Transition
|
||||
show={!onLoading}
|
||||
appear={true}
|
||||
enter="transition ease-in-out duration-700 transform order-first"
|
||||
enterFrom="opacity-0 translate-y-16"
|
||||
enterTo="opacity-100"
|
||||
leave="transition ease-in-out duration-300 transform"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0 -translate-y-16"
|
||||
unmount={false}
|
||||
>
|
||||
{slotTop}
|
||||
{children}
|
||||
</Transition>
|
||||
|
||||
<JumpToTopButton />
|
||||
</div>
|
||||
|
||||
{/* 底部 */}
|
||||
<Footer title={siteConfig('TITLE')} />
|
||||
</div>
|
||||
|
||||
{/* 桌面端右侧 */}
|
||||
{fullWidth
|
||||
? null
|
||||
: <div className={`hidden xl:block border-l dark:border-transparent w-80 flex-shrink-0 relative z-10 ${siteConfig('MEDIUM_RIGHT_PANEL_DARK', null, CONFIG) ? 'bg-hexo-black-gray dark' : ''}`}>
|
||||
<div className='py-14 px-6 sticky top-0'>
|
||||
<Tabs>
|
||||
{slotRight}
|
||||
<div key={locale.NAV.ABOUT}>
|
||||
{router.pathname !== '/search' && <SearchInput className='mt-6 mb-12' />}
|
||||
{showInfoCard && <InfoCard {...props} />}
|
||||
{siteConfig('MEDIUM_WIDGET_REVOLVER_MAPS', null, CONFIG) === 'true' && <RevolverMaps />}
|
||||
</div>
|
||||
</Tabs>
|
||||
<Announcement post={notice} />
|
||||
<Live2D />
|
||||
</div>
|
||||
</div>}
|
||||
|
||||
</main>
|
||||
|
||||
{/* 移动端底部导航栏 */}
|
||||
<BottomMenuBar {...props} className='block md:hidden' />
|
||||
<JumpToTopButton />
|
||||
</div>
|
||||
</ThemeGlobalMedium.Provider>
|
||||
|
||||
{/* 底部 */}
|
||||
<Footer title={siteConfig('TITLE')} />
|
||||
</div>
|
||||
|
||||
{/* 桌面端右侧 */}
|
||||
{fullWidth ? null : (
|
||||
<div
|
||||
className={`hidden xl:block border-l dark:border-transparent w-80 flex-shrink-0 relative z-10 ${siteConfig('MEDIUM_RIGHT_PANEL_DARK', null, CONFIG) ? 'bg-hexo-black-gray dark' : ''}`}>
|
||||
<div className='py-14 px-6 sticky top-0'>
|
||||
<Tabs>
|
||||
{slotRight}
|
||||
<div key={locale.NAV.ABOUT}>
|
||||
{router.pathname !== '/search' && (
|
||||
<SearchInput className='mt-6 mb-12' />
|
||||
)}
|
||||
{showInfoCard && <InfoCard {...props} />}
|
||||
{siteConfig('MEDIUM_WIDGET_REVOLVER_MAPS', null, CONFIG) ===
|
||||
'true' && <RevolverMaps />}
|
||||
</div>
|
||||
</Tabs>
|
||||
<Announcement post={notice} />
|
||||
<Live2D />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</main>
|
||||
|
||||
{/* 移动端底部导航栏 */}
|
||||
<BottomMenuBar {...props} className='block md:hidden' />
|
||||
</div>
|
||||
</ThemeGlobalMedium.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -140,7 +150,7 @@ const LayoutBase = props => {
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutIndex = (props) => {
|
||||
const LayoutIndex = props => {
|
||||
return <LayoutPostList {...props} />
|
||||
}
|
||||
|
||||
@@ -148,10 +158,16 @@ const LayoutIndex = (props) => {
|
||||
* 博客列表
|
||||
* @returns
|
||||
*/
|
||||
const LayoutPostList = (props) => {
|
||||
return <>
|
||||
{siteConfig('POST_LIST_STYLE') === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
||||
const LayoutPostList = props => {
|
||||
return (
|
||||
<>
|
||||
{siteConfig('POST_LIST_STYLE') === 'page' ? (
|
||||
<BlogPostListPage {...props} />
|
||||
) : (
|
||||
<BlogPostListScroll {...props} />
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,64 +179,72 @@ const LayoutSlug = props => {
|
||||
const { post, prev, next, lock, validPassword } = props
|
||||
const { locale } = useGlobal()
|
||||
const slotRight = post?.toc && post?.toc?.length >= 3 && (
|
||||
<div key={locale.COMMON.TABLE_OF_CONTENTS} >
|
||||
<Catalog toc={post?.toc} />
|
||||
</div>
|
||||
<div key={locale.COMMON.TABLE_OF_CONTENTS}>
|
||||
<Catalog toc={post?.toc} />
|
||||
</div>
|
||||
)
|
||||
|
||||
const router = useRouter()
|
||||
useEffect(() => {
|
||||
// 404
|
||||
if (!post) {
|
||||
setTimeout(() => {
|
||||
if (isBrowser) {
|
||||
const article = document.getElementById('notion-article')
|
||||
if (!article) {
|
||||
router.push('/404').then(() => {
|
||||
console.warn('找不到页面', router.asPath)
|
||||
})
|
||||
setTimeout(
|
||||
() => {
|
||||
if (isBrowser) {
|
||||
const article = document.getElementById('notion-article')
|
||||
if (!article) {
|
||||
router.push('/404').then(() => {
|
||||
console.warn('找不到页面', router.asPath)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}, siteConfig('POST_WAITING_TIME_FOR_404') * 1000)
|
||||
},
|
||||
siteConfig('POST_WAITING_TIME_FOR_404') * 1000
|
||||
)
|
||||
}
|
||||
}, [post])
|
||||
|
||||
return (
|
||||
<div {...props} >
|
||||
{/* 文章锁 */}
|
||||
{lock && <ArticleLock validPassword={validPassword} />}
|
||||
<div {...props}>
|
||||
{/* 文章锁 */}
|
||||
{lock && <ArticleLock validPassword={validPassword} />}
|
||||
|
||||
{!lock && <div id='article-wrapper'>
|
||||
{!lock && (
|
||||
<div>
|
||||
{/* 文章信息 */}
|
||||
<ArticleInfo {...props} />
|
||||
|
||||
{/* 文章信息 */}
|
||||
<ArticleInfo {...props} />
|
||||
{/* Notion文章主体 */}
|
||||
<article id='article-wrapper' className='px-1 max-w-4xl'>
|
||||
{post && <NotionPage post={post} />}
|
||||
</article>
|
||||
|
||||
{/* Notion文章主体 */}
|
||||
<section className="px-1 max-w-4xl">
|
||||
{post && (<NotionPage post={post} />)}
|
||||
</section>
|
||||
{/* 文章底部区域 */}
|
||||
<section>
|
||||
{/* 分享 */}
|
||||
<ShareBar post={post} />
|
||||
{/* 文章分类和标签信息 */}
|
||||
<div className='flex justify-between'>
|
||||
{siteConfig('MEDIUM_POST_DETAIL_CATEGORY', null, CONFIG) &&
|
||||
post?.category && <CategoryItem category={post?.category} />}
|
||||
<div>
|
||||
{siteConfig('MEDIUM_POST_DETAIL_TAG', null, CONFIG) &&
|
||||
post?.tagItems?.map(tag => (
|
||||
<TagItemMini key={tag.name} tag={tag} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
{/* 上一篇下一篇文章 */}
|
||||
{post?.type === 'Post' && <ArticleAround prev={prev} next={next} />}
|
||||
{/* 评论区 */}
|
||||
<Comment frontMatter={post} />
|
||||
</section>
|
||||
|
||||
{/* 文章底部区域 */}
|
||||
<section>
|
||||
{/* 分享 */}
|
||||
<ShareBar post={post} />
|
||||
{/* 文章分类和标签信息 */}
|
||||
<div className='flex justify-between'>
|
||||
{siteConfig('MEDIUM_POST_DETAIL_CATEGORY', null, CONFIG) && post?.category && <CategoryItem category={post?.category} />}
|
||||
<div>
|
||||
{siteConfig('MEDIUM_POST_DETAIL_TAG', null, CONFIG) && post?.tagItems?.map(tag => <TagItemMini key={tag.name} tag={tag} />)}
|
||||
</div>
|
||||
</div>
|
||||
{/* 上一篇下一篇文章 */}
|
||||
{post?.type === 'Post' && <ArticleAround prev={prev} next={next} />}
|
||||
{/* 评论区 */}
|
||||
<Comment frontMatter={post} />
|
||||
</section>
|
||||
|
||||
{/* 移动端目录 */}
|
||||
<TocDrawer {...props} />
|
||||
</div>}
|
||||
{/* 移动端目录 */}
|
||||
<TocDrawer {...props} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -229,7 +253,7 @@ const LayoutSlug = props => {
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutSearch = (props) => {
|
||||
const LayoutSearch = props => {
|
||||
const { locale } = useGlobal()
|
||||
const { keyword } = props
|
||||
const router = useRouter()
|
||||
@@ -248,23 +272,32 @@ const LayoutSearch = (props) => {
|
||||
}
|
||||
}, [])
|
||||
|
||||
return <>
|
||||
return (
|
||||
<>
|
||||
{/* 搜索导航栏 */}
|
||||
<div className='py-12'>
|
||||
<div className='pb-4 w-full'>{locale.NAV.SEARCH}</div>
|
||||
<SearchInput currentSearch={currentSearch} {...props} />
|
||||
{!currentSearch && (
|
||||
<>
|
||||
<TagGroups {...props} />
|
||||
<CategoryGroup {...props} />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 搜索导航栏 */}
|
||||
<div className='py-12'>
|
||||
<div className='pb-4 w-full'>{locale.NAV.SEARCH}</div>
|
||||
<SearchInput currentSearch={currentSearch} {...props} />
|
||||
{!currentSearch && <>
|
||||
<TagGroups {...props} />
|
||||
<CategoryGroup {...props} />
|
||||
</>}
|
||||
{/* 文章列表 */}
|
||||
{currentSearch && (
|
||||
<div>
|
||||
{siteConfig('POST_LIST_STYLE') === 'page' ? (
|
||||
<BlogPostListPage {...props} />
|
||||
) : (
|
||||
<BlogPostListScroll {...props} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 文章列表 */}
|
||||
{currentSearch && <div>
|
||||
{siteConfig('POST_LIST_STYLE') === 'page' ? <BlogPostListPage {...props} /> : <BlogPostListScroll {...props} />}
|
||||
</div>}
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -275,12 +308,17 @@ const LayoutSearch = (props) => {
|
||||
const LayoutArchive = props => {
|
||||
const { archivePosts } = props
|
||||
return (
|
||||
<>
|
||||
<div className="mb-10 pb-20 md:py-12 py-3 min-h-full">
|
||||
{Object.keys(archivePosts)?.map(archiveTitle => <BlogArchiveItem key={archiveTitle} archiveTitle={archiveTitle} archivePosts={archivePosts} />
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
<>
|
||||
<div className='mb-10 pb-20 md:py-12 py-3 min-h-full'>
|
||||
{Object.keys(archivePosts)?.map(archiveTitle => (
|
||||
<BlogArchiveItem
|
||||
key={archiveTitle}
|
||||
archiveTitle={archiveTitle}
|
||||
archivePosts={archivePosts}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -290,9 +328,13 @@ const LayoutArchive = props => {
|
||||
* @returns
|
||||
*/
|
||||
const Layout404 = props => {
|
||||
return <>
|
||||
<div className='w-full h-96 py-80 flex justify-center items-center'>404 Not found.</div>
|
||||
return (
|
||||
<>
|
||||
<div className='w-full h-96 py-80 flex justify-center items-center'>
|
||||
404 Not found.
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -300,33 +342,37 @@ const Layout404 = props => {
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutCategoryIndex = (props) => {
|
||||
const LayoutCategoryIndex = props => {
|
||||
const { categoryOptions } = props
|
||||
const { locale } = useGlobal()
|
||||
return (
|
||||
<>
|
||||
<div className='bg-white dark:bg-gray-700 py-10'>
|
||||
<div className='dark:text-gray-200 mb-5'>
|
||||
<i className='mr-4 fas fa-th' />{locale.COMMON.CATEGORY}:
|
||||
<>
|
||||
<div className='bg-white dark:bg-gray-700 py-10'>
|
||||
<div className='dark:text-gray-200 mb-5'>
|
||||
<i className='mr-4 fas fa-th' />
|
||||
{locale.COMMON.CATEGORY}:
|
||||
</div>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{categoryOptions?.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<div
|
||||
className={
|
||||
'hover:text-black dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'
|
||||
}>
|
||||
<i className='mr-4 fas fa-folder' />
|
||||
{category.name}({category.count})
|
||||
</div>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{categoryOptions?.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<div
|
||||
className={'hover:text-black dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'}>
|
||||
<i className='mr-4 fas fa-folder' />{category.name}({category.count})
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -339,35 +385,35 @@ const LayoutTagIndex = props => {
|
||||
const { tagOptions } = props
|
||||
const { locale } = useGlobal()
|
||||
return (
|
||||
<>
|
||||
<div className="bg-white dark:bg-gray-700 py-10">
|
||||
<div className="dark:text-gray-200 mb-5">
|
||||
<i className="mr-4 fas fa-tag" />
|
||||
{locale.COMMON.TAGS}:
|
||||
</div>
|
||||
<div id="tags-list" className="duration-200 flex flex-wrap">
|
||||
{tagOptions?.map(tag => {
|
||||
return (
|
||||
<div key={tag.name} className="p-2">
|
||||
<TagItemMini key={tag.name} tag={tag} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
<>
|
||||
<div className='bg-white dark:bg-gray-700 py-10'>
|
||||
<div className='dark:text-gray-200 mb-5'>
|
||||
<i className='mr-4 fas fa-tag' />
|
||||
{locale.COMMON.TAGS}:
|
||||
</div>
|
||||
<div id='tags-list' className='duration-200 flex flex-wrap'>
|
||||
{tagOptions?.map(tag => {
|
||||
return (
|
||||
<div key={tag.name} className='p-2'>
|
||||
<TagItemMini key={tag.name} tag={tag} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
CONFIG as THEME_CONFIG,
|
||||
Layout404,
|
||||
LayoutArchive,
|
||||
LayoutBase,
|
||||
LayoutCategoryIndex,
|
||||
LayoutIndex,
|
||||
LayoutPostList,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
LayoutSlug,
|
||||
Layout404,
|
||||
LayoutCategoryIndex,
|
||||
LayoutTagIndex
|
||||
LayoutTagIndex,
|
||||
CONFIG as THEME_CONFIG
|
||||
}
|
||||
|
||||
@@ -258,7 +258,11 @@ const LayoutSlug = props => {
|
||||
videoWrapper.appendChild(figCaptionWrapper)
|
||||
}
|
||||
// 放入页面
|
||||
notionArticle.insertBefore(videoWrapper, notionArticle.firstChild)
|
||||
if (notionArticle.firstChild && notionArticle.contains(notionArticle.firstChild)) {
|
||||
notionArticle.insertBefore(videoWrapper, notionArticle.firstChild)
|
||||
} else {
|
||||
notionArticle.appendChild(videoWrapper)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -290,8 +290,10 @@ const LayoutSlug = props => {
|
||||
|
||||
{/* Notion文章主体 */}
|
||||
{post && (
|
||||
<section id='article-wrapper' className='px-1'>
|
||||
<NotionPage post={post} />
|
||||
<section className='px-1'>
|
||||
<div id='article-wrapper'>
|
||||
<NotionPage post={post} />
|
||||
</div>
|
||||
|
||||
{/* 分享 */}
|
||||
{/* <ShareBar post={post} /> */}
|
||||
|
||||
@@ -35,9 +35,7 @@ export default function ArticleDetail(props) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
id='article-wrapper'
|
||||
className='shadow md:hover:shadow-2xl overflow-x-auto flex-grow mx-auto w-screen md:w-full '>
|
||||
<div 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'
|
||||
@@ -100,7 +98,7 @@ export default function ArticleDetail(props) {
|
||||
)}
|
||||
|
||||
{/* Notion内容主体 */}
|
||||
<article className='mx-auto'>
|
||||
<article id='article-wrapper' className='mx-auto'>
|
||||
<WWAds className='w-full' orientation='horizontal' />
|
||||
{post && <NotionPage post={post} />}
|
||||
<WWAds className='w-full' orientation='horizontal' />
|
||||
|
||||
@@ -1,34 +1,37 @@
|
||||
import CONFIG from './config'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
import dynamic from 'next/dynamic'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { createContext, useContext, useEffect, useRef, useState } from 'react'
|
||||
import Announcement from './components/Announcement'
|
||||
import ArticleDetail from './components/ArticleDetail'
|
||||
import { ArticleLock } from './components/ArticleLock'
|
||||
import BlogListBar from './components/BlogListBar'
|
||||
import BlogPostArchive from './components/BlogPostArchive'
|
||||
import BlogPostListPage from './components/BlogPostListPage'
|
||||
import BlogPostListScroll from './components/BlogPostListScroll'
|
||||
import Card from './components/Card'
|
||||
import FloatDarkModeButton from './components/FloatDarkModeButton'
|
||||
import Footer from './components/Footer'
|
||||
import JumpToBottomButton from './components/JumpToBottomButton'
|
||||
import JumpToTopButton from './components/JumpToTopButton'
|
||||
import SideAreaLeft from './components/SideAreaLeft'
|
||||
import SideAreaRight from './components/SideAreaRight'
|
||||
import TopNav from './components/TopNav'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { createContext, useContext, useEffect, useRef, useState } from 'react'
|
||||
import BlogPostListScroll from './components/BlogPostListScroll'
|
||||
import BlogPostListPage from './components/BlogPostListPage'
|
||||
import StickyBar from './components/StickyBar'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
import TocDrawerButton from './components/TocDrawerButton'
|
||||
import TocDrawer from './components/TocDrawer'
|
||||
import { ArticleLock } from './components/ArticleLock'
|
||||
import BlogPostArchive from './components/BlogPostArchive'
|
||||
import TagItem from './components/TagItem'
|
||||
import { useRouter } from 'next/router'
|
||||
import ArticleDetail from './components/ArticleDetail'
|
||||
import Link from 'next/link'
|
||||
import BlogListBar from './components/BlogListBar'
|
||||
import TocDrawer from './components/TocDrawer'
|
||||
import TocDrawerButton from './components/TocDrawerButton'
|
||||
import TopNav from './components/TopNav'
|
||||
import CONFIG from './config'
|
||||
import { Style } from './style'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import Announcement from './components/Announcement'
|
||||
import Card from './components/Card'
|
||||
import dynamic from 'next/dynamic'
|
||||
|
||||
const AlgoliaSearchModal = dynamic(() => import('@/components/AlgoliaSearchModal'), { ssr: false })
|
||||
const AlgoliaSearchModal = dynamic(
|
||||
() => import('@/components/AlgoliaSearchModal'),
|
||||
{ ssr: false }
|
||||
)
|
||||
|
||||
// 主题全局状态
|
||||
const ThemeGlobalNext = createContext()
|
||||
@@ -39,7 +42,7 @@ export const useNextGlobal = () => useContext(ThemeGlobalNext)
|
||||
* @returns {JSX.Element}
|
||||
* @constructor
|
||||
*/
|
||||
const LayoutBase = (props) => {
|
||||
const LayoutBase = props => {
|
||||
const { children, headerSlot, rightAreaSlot, post } = props
|
||||
const targetRef = useRef(null)
|
||||
const floatButtonGroup = useRef(null)
|
||||
@@ -50,7 +53,7 @@ const LayoutBase = (props) => {
|
||||
const clientHeight = targetRef?.clientHeight
|
||||
const scrollY = window.pageYOffset
|
||||
const fullHeight = clientHeight - window.outerHeight
|
||||
let per = parseFloat(((scrollY / fullHeight * 100)).toFixed(0))
|
||||
let per = parseFloat(((scrollY / fullHeight) * 100).toFixed(0))
|
||||
if (per > 100) per = 100
|
||||
const shouldShow = scrollY > 100 && per > 0
|
||||
|
||||
@@ -75,11 +78,15 @@ const LayoutBase = (props) => {
|
||||
|
||||
// 悬浮抽屉
|
||||
const drawerRight = useRef(null)
|
||||
const floatSlot = <div className='block lg:hidden'>
|
||||
<TocDrawerButton onClick={() => {
|
||||
drawerRight?.current?.handleSwitchVisible()
|
||||
}} />
|
||||
</div>
|
||||
const floatSlot = (
|
||||
<div className='block lg:hidden'>
|
||||
<TocDrawerButton
|
||||
onClick={() => {
|
||||
drawerRight?.current?.handleSwitchVisible()
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
const tocRef = isBrowser ? document.getElementById('article-wrapper') : null
|
||||
|
||||
@@ -87,53 +94,77 @@ const LayoutBase = (props) => {
|
||||
|
||||
return (
|
||||
<ThemeGlobalNext.Provider value={{ searchModal }}>
|
||||
<div id='theme-next' className={`${siteConfig('FONT_STYLE')} dark:bg-black scroll-smooth`}>
|
||||
<Style/>
|
||||
<div
|
||||
id='theme-next'
|
||||
className={`${siteConfig('FONT_STYLE')} dark:bg-black scroll-smooth`}>
|
||||
<Style />
|
||||
|
||||
{/* 移动端顶部导航栏 */}
|
||||
<TopNav {...props} />
|
||||
{/* 移动端顶部导航栏 */}
|
||||
<TopNav {...props} />
|
||||
|
||||
<AlgoliaSearchModal cRef={searchModal} {...props}/>
|
||||
<AlgoliaSearchModal cRef={searchModal} {...props} />
|
||||
|
||||
<>{headerSlot}</>
|
||||
<>{headerSlot}</>
|
||||
|
||||
{/* 顶部黑线装饰 */}
|
||||
<div className='h-0.5 w-full bg-gray-700 dark:bg-gray-600 hidden lg:block' />
|
||||
{/* 顶部黑线装饰 */}
|
||||
<div className='h-0.5 w-full bg-gray-700 dark:bg-gray-600 hidden lg:block' />
|
||||
|
||||
{/* 主区 */}
|
||||
<main id='wrapper' className={(JSON.parse(siteConfig('LAYOUT_SIDEBAR_REVERSE')) ? 'flex-row-reverse' : '') + ' next relative flex justify-center flex-1 pb-12'}>
|
||||
{/* 左侧栏样式 */}
|
||||
<SideAreaLeft targetRef={targetRef} {...props} />
|
||||
{/* 主区 */}
|
||||
<main
|
||||
id='wrapper'
|
||||
className={
|
||||
(JSON.parse(siteConfig('LAYOUT_SIDEBAR_REVERSE'))
|
||||
? 'flex-row-reverse'
|
||||
: '') + ' next relative flex justify-center flex-1 pb-12'
|
||||
}>
|
||||
{/* 左侧栏样式 */}
|
||||
<SideAreaLeft targetRef={targetRef} {...props} />
|
||||
|
||||
{/* 中央内容 */}
|
||||
<section id='container-inner' className={`${siteConfig('NEXT_NAV_TYPE', null, CONFIG) !== 'normal' ? 'mt-24' : ''} lg:max-w-3xl xl:max-w-4xl flex-grow md:mt-0 min-h-screen w-full relative z-10`} ref={targetRef}>
|
||||
{children}
|
||||
</section>
|
||||
{/* 中央内容 */}
|
||||
<section
|
||||
id='container-inner'
|
||||
className={`${siteConfig('NEXT_NAV_TYPE', null, CONFIG) !== 'normal' ? 'mt-24' : ''} lg:max-w-3xl xl:max-w-4xl flex-grow md:mt-0 min-h-screen w-full relative z-10`}
|
||||
ref={targetRef}>
|
||||
{children}
|
||||
</section>
|
||||
|
||||
{/* 右侧栏样式 */}
|
||||
{siteConfig('NEXT_RIGHT_BAR', null, CONFIG) && <SideAreaRight targetRef={targetRef} slot={rightAreaSlot} {...props} />}
|
||||
{/* 右侧栏样式 */}
|
||||
{siteConfig('NEXT_RIGHT_BAR', null, CONFIG) && (
|
||||
<SideAreaRight
|
||||
targetRef={targetRef}
|
||||
slot={rightAreaSlot}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
</main>
|
||||
|
||||
</main>
|
||||
{/* 悬浮目录按钮 */}
|
||||
{post && (
|
||||
<div className='block lg:hidden'>
|
||||
<TocDrawer post={post} cRef={drawerRight} targetRef={tocRef} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 悬浮目录按钮 */}
|
||||
{post && <div className='block lg:hidden'>
|
||||
<TocDrawer post={post} cRef={drawerRight} targetRef={tocRef} />
|
||||
</div>}
|
||||
|
||||
{/* 右下角悬浮 */}
|
||||
<div ref={floatButtonGroup} className='right-8 bottom-12 lg:right-2 fixed justify-end z-20 '>
|
||||
<div className={(showRightFloat ? 'animate__animated ' : 'hidden') + ' animate__fadeInUp rounded-md glassmorphism justify-center duration-500 animate__faster flex space-x-2 items-center cursor-pointer '}>
|
||||
<JumpToTopButton percent={percent} />
|
||||
<JumpToBottomButton />
|
||||
<FloatDarkModeButton />
|
||||
{floatSlot}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 页脚 */}
|
||||
<Footer title={siteConfig('TITLE')} />
|
||||
{/* 右下角悬浮 */}
|
||||
<div
|
||||
ref={floatButtonGroup}
|
||||
className='right-8 bottom-12 lg:right-2 fixed justify-end z-20 '>
|
||||
<div
|
||||
className={
|
||||
(showRightFloat ? 'animate__animated ' : 'hidden') +
|
||||
' animate__fadeInUp rounded-md glassmorphism justify-center duration-500 animate__faster flex space-x-2 items-center cursor-pointer '
|
||||
}>
|
||||
<JumpToTopButton percent={percent} />
|
||||
<JumpToBottomButton />
|
||||
<FloatDarkModeButton />
|
||||
{floatSlot}
|
||||
</div>
|
||||
</div>
|
||||
</ThemeGlobalNext.Provider>
|
||||
|
||||
{/* 页脚 */}
|
||||
<Footer title={siteConfig('TITLE')} />
|
||||
</div>
|
||||
</ThemeGlobalNext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -143,21 +174,24 @@ const LayoutBase = (props) => {
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutIndex = (props) => {
|
||||
const LayoutIndex = props => {
|
||||
const { notice } = props
|
||||
return <>
|
||||
{/* 首页移动端顶部显示公告 */}
|
||||
<Card className='my-2 lg:hidden'>
|
||||
<Announcement post={notice} />
|
||||
</Card>
|
||||
return (
|
||||
<>
|
||||
{/* 首页移动端顶部显示公告 */}
|
||||
<Card className='my-2 lg:hidden'>
|
||||
<Announcement post={notice} />
|
||||
</Card>
|
||||
|
||||
<BlogListBar {...props} />
|
||||
<BlogListBar {...props} />
|
||||
|
||||
{siteConfig('POST_LIST_STYLE') !== 'page'
|
||||
? <BlogPostListScroll {...props} showSummary={true} />
|
||||
: <BlogPostListPage {...props} />
|
||||
}
|
||||
{siteConfig('POST_LIST_STYLE') !== 'page' ? (
|
||||
<BlogPostListScroll {...props} showSummary={true} />
|
||||
) : (
|
||||
<BlogPostListPage {...props} />
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,16 +199,18 @@ const LayoutIndex = (props) => {
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutPostList = (props) => {
|
||||
return <>
|
||||
const LayoutPostList = props => {
|
||||
return (
|
||||
<>
|
||||
<BlogListBar {...props} />
|
||||
|
||||
<BlogListBar {...props} />
|
||||
|
||||
{siteConfig('POST_LIST_STYLE') !== 'page'
|
||||
? <BlogPostListScroll {...props} showSummary={true} />
|
||||
: <BlogPostListPage {...props} />
|
||||
}
|
||||
{siteConfig('POST_LIST_STYLE') !== 'page' ? (
|
||||
<BlogPostListScroll {...props} showSummary={true} />
|
||||
) : (
|
||||
<BlogPostListPage {...props} />
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -182,7 +218,7 @@ const LayoutPostList = (props) => {
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutSearch = (props) => {
|
||||
const LayoutSearch = props => {
|
||||
const { locale } = useGlobal()
|
||||
const { posts, keyword } = props
|
||||
|
||||
@@ -200,20 +236,21 @@ const LayoutSearch = (props) => {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
<StickyBar>
|
||||
<div className="p-4 dark:text-gray-200">
|
||||
<i className="mr-1 fas fa-search" />{' '}
|
||||
{posts?.length} {locale.COMMON.RESULT_OF_SEARCH}
|
||||
</div>
|
||||
</StickyBar>
|
||||
<div className="md:mt-5">
|
||||
{siteConfig('POST_LIST_STYLE') !== 'page'
|
||||
? <BlogPostListScroll {...props} showSummary={true} />
|
||||
: <BlogPostListPage {...props} />
|
||||
}
|
||||
</div>
|
||||
</>
|
||||
<>
|
||||
<StickyBar>
|
||||
<div className='p-4 dark:text-gray-200'>
|
||||
<i className='mr-1 fas fa-search' /> {posts?.length}{' '}
|
||||
{locale.COMMON.RESULT_OF_SEARCH}
|
||||
</div>
|
||||
</StickyBar>
|
||||
<div className='md:mt-5'>
|
||||
{siteConfig('POST_LIST_STYLE') !== 'page' ? (
|
||||
<BlogPostListScroll {...props} showSummary={true} />
|
||||
) : (
|
||||
<BlogPostListPage {...props} />
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -236,16 +273,21 @@ const Layout404 = props => {
|
||||
}, 3000)
|
||||
}, [])
|
||||
|
||||
return <>
|
||||
<div className='md:-mt-20 text-black w-full h-screen text-center justify-center content-center items-center flex flex-col'>
|
||||
<div className='dark:text-gray-200'>
|
||||
<h2 className='inline-block border-r-2 border-gray-600 mr-2 px-3 py-2 align-top'><i className='mr-2 fas fa-spinner animate-spin' />404</h2>
|
||||
<div className='inline-block text-left h-32 leading-10 items-center'>
|
||||
<h2 className='m-0 p-0'>页面无法加载,即将返回首页</h2>
|
||||
</div>
|
||||
</div>
|
||||
return (
|
||||
<>
|
||||
<div className='md:-mt-20 text-black w-full h-screen text-center justify-center content-center items-center flex flex-col'>
|
||||
<div className='dark:text-gray-200'>
|
||||
<h2 className='inline-block border-r-2 border-gray-600 mr-2 px-3 py-2 align-top'>
|
||||
<i className='mr-2 fas fa-spinner animate-spin' />
|
||||
404
|
||||
</h2>
|
||||
<div className='inline-block text-left h-32 leading-10 items-center'>
|
||||
<h2 className='m-0 p-0'>页面无法加载,即将返回首页</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -253,21 +295,21 @@ const Layout404 = props => {
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutArchive = (props) => {
|
||||
const LayoutArchive = props => {
|
||||
const { archivePosts } = props
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mb-10 pb-20 bg-white md:p-12 p-3 dark:bg-hexo-black-gray shadow-md min-h-full">
|
||||
{Object.keys(archivePosts).map(archiveTitle => (
|
||||
<BlogPostArchive
|
||||
key={archiveTitle}
|
||||
posts={archivePosts[archiveTitle]}
|
||||
archiveTitle={archiveTitle}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
<>
|
||||
<div className='mb-10 pb-20 bg-white md:p-12 p-3 dark:bg-hexo-black-gray shadow-md min-h-full'>
|
||||
{Object.keys(archivePosts).map(archiveTitle => (
|
||||
<BlogPostArchive
|
||||
key={archiveTitle}
|
||||
posts={archivePosts[archiveTitle]}
|
||||
archiveTitle={archiveTitle}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -276,33 +318,34 @@ const LayoutArchive = (props) => {
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutSlug = (props) => {
|
||||
const LayoutSlug = props => {
|
||||
const { post, lock, validPassword } = props
|
||||
|
||||
const router = useRouter()
|
||||
useEffect(() => {
|
||||
// 404
|
||||
if (!post) {
|
||||
setTimeout(() => {
|
||||
if (isBrowser) {
|
||||
const article = document.getElementById('notion-article')
|
||||
if (!article) {
|
||||
router.push('/404').then(() => {
|
||||
console.warn('找不到页面', router.asPath)
|
||||
})
|
||||
setTimeout(
|
||||
() => {
|
||||
if (isBrowser) {
|
||||
const article = document.getElementById('notion-article')
|
||||
if (!article) {
|
||||
router.push('/404').then(() => {
|
||||
console.warn('找不到页面', router.asPath)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}, siteConfig('POST_WAITING_TIME_FOR_404') * 1000)
|
||||
},
|
||||
siteConfig('POST_WAITING_TIME_FOR_404') * 1000
|
||||
)
|
||||
}
|
||||
}, [post])
|
||||
return (
|
||||
<>
|
||||
<>
|
||||
{post && !lock && <ArticleDetail {...props} />}
|
||||
|
||||
{post && !lock && <ArticleDetail {...props} />}
|
||||
|
||||
{post && lock && <ArticleLock validPassword={validPassword} />}
|
||||
|
||||
</>
|
||||
{post && lock && <ArticleLock validPassword={validPassword} />}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -311,33 +354,37 @@ const LayoutSlug = (props) => {
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutCategoryIndex = (props) => {
|
||||
const LayoutCategoryIndex = props => {
|
||||
const { allPosts, categoryOptions } = props
|
||||
const { locale } = useGlobal()
|
||||
return (
|
||||
<div totalPosts={allPosts} {...props}>
|
||||
<div className='bg-white dark:bg-hexo-black-gray px-10 py-10 shadow h-full'>
|
||||
<div className='dark:text-gray-200 mb-5'>
|
||||
<i className='mr-4 fas faTh' />{locale.COMMON.CATEGORY}:
|
||||
</div>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{categoryOptions?.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<div
|
||||
className={'hover:text-black dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'}>
|
||||
<i className='mr-4 fas fa-folder' />{category.name}({category.count})
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div totalPosts={allPosts} {...props}>
|
||||
<div className='bg-white dark:bg-hexo-black-gray px-10 py-10 shadow h-full'>
|
||||
<div className='dark:text-gray-200 mb-5'>
|
||||
<i className='mr-4 fas faTh' />
|
||||
{locale.COMMON.CATEGORY}:
|
||||
</div>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{categoryOptions?.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<div
|
||||
className={
|
||||
'hover:text-black dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'
|
||||
}>
|
||||
<i className='mr-4 fas fa-folder' />
|
||||
{category.name}({category.count})
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -346,30 +393,39 @@ const LayoutCategoryIndex = (props) => {
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutTagIndex = (props) => {
|
||||
const LayoutTagIndex = props => {
|
||||
const { tagOptions } = props
|
||||
const { locale } = useGlobal()
|
||||
return <>
|
||||
<div className='bg-white dark:bg-hexo-black-gray px-10 py-10 shadow h-full'>
|
||||
<div className='dark:text-gray-200 mb-5'><i className='fas fa-tags mr-4' />{locale.COMMON.TAGS}:</div>
|
||||
<div id='tags-list' className='duration-200 flex flex-wrap'>
|
||||
{tagOptions.map(tag => {
|
||||
return <div key={tag.name} className='p-2'><TagItem key={tag.name} tag={tag} /></div>
|
||||
})}
|
||||
</div>
|
||||
return (
|
||||
<>
|
||||
<div className='bg-white dark:bg-hexo-black-gray px-10 py-10 shadow h-full'>
|
||||
<div className='dark:text-gray-200 mb-5'>
|
||||
<i className='fas fa-tags mr-4' />
|
||||
{locale.COMMON.TAGS}:
|
||||
</div>
|
||||
<div id='tags-list' className='duration-200 flex flex-wrap'>
|
||||
{tagOptions.map(tag => {
|
||||
return (
|
||||
<div key={tag.name} className='p-2'>
|
||||
<TagItem key={tag.name} tag={tag} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
CONFIG as THEME_CONFIG,
|
||||
LayoutBase,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
LayoutSlug,
|
||||
Layout404,
|
||||
LayoutArchive,
|
||||
LayoutBase,
|
||||
LayoutCategoryIndex,
|
||||
LayoutIndex,
|
||||
LayoutPostList,
|
||||
LayoutTagIndex
|
||||
LayoutSearch,
|
||||
LayoutSlug,
|
||||
LayoutTagIndex,
|
||||
CONFIG as THEME_CONFIG
|
||||
}
|
||||
|
||||
@@ -1,32 +1,35 @@
|
||||
import CONFIG from './config'
|
||||
import { createContext, useEffect, useState, useContext, useRef } from 'react'
|
||||
import Nav from './components/Nav'
|
||||
import { Footer } from './components/Footer'
|
||||
import JumpToTopButton from './components/JumpToTopButton'
|
||||
import Comment from '@/components/Comment'
|
||||
import Live2D from '@/components/Live2D'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
import ShareBar from '@/components/ShareBar'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { deepClone, isBrowser } from '@/lib/utils'
|
||||
import { Transition } from '@headlessui/react'
|
||||
import dynamic from 'next/dynamic'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { createContext, useContext, useEffect, useRef, useState } from 'react'
|
||||
import Announcement from './components/Announcement'
|
||||
import { ArticleFooter } from './components/ArticleFooter'
|
||||
import { ArticleInfo } from './components/ArticleInfo'
|
||||
import { ArticleLock } from './components/ArticleLock'
|
||||
import BlogArchiveItem from './components/BlogArchiveItem'
|
||||
import BlogListBar from './components/BlogListBar'
|
||||
import { BlogListPage } from './components/BlogListPage'
|
||||
import { BlogListScroll } from './components/BlogListScroll'
|
||||
import { deepClone, isBrowser } from '@/lib/utils'
|
||||
import { Footer } from './components/Footer'
|
||||
import JumpToTopButton from './components/JumpToTopButton'
|
||||
import Nav from './components/Nav'
|
||||
import SearchNavBar from './components/SearchNavBar'
|
||||
import BlogArchiveItem from './components/BlogArchiveItem'
|
||||
import { ArticleLock } from './components/ArticleLock'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
import { ArticleInfo } from './components/ArticleInfo'
|
||||
import Comment from '@/components/Comment'
|
||||
import { ArticleFooter } from './components/ArticleFooter'
|
||||
import ShareBar from '@/components/ShareBar'
|
||||
import Link from 'next/link'
|
||||
import BlogListBar from './components/BlogListBar'
|
||||
import { Transition } from '@headlessui/react'
|
||||
import CONFIG from './config'
|
||||
import { Style } from './style'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { useRouter } from 'next/router'
|
||||
import dynamic from 'next/dynamic'
|
||||
|
||||
const AlgoliaSearchModal = dynamic(() => import('@/components/AlgoliaSearchModal'), { ssr: false })
|
||||
const AlgoliaSearchModal = dynamic(
|
||||
() => import('@/components/AlgoliaSearchModal'),
|
||||
{ ssr: false }
|
||||
)
|
||||
|
||||
// 主题全局状态
|
||||
const ThemeGlobalNobelium = createContext()
|
||||
@@ -45,56 +48,56 @@ const LayoutBase = props => {
|
||||
const searchModal = useRef(null)
|
||||
// 在列表中进行实时过滤
|
||||
const [filterKey, setFilterKey] = useState('')
|
||||
const topSlot = <BlogListBar {...props}/>
|
||||
const topSlot = <BlogListBar {...props} />
|
||||
|
||||
return (
|
||||
<ThemeGlobalNobelium.Provider value={{ searchModal, filterKey, setFilterKey }}>
|
||||
<div id='theme-nobelium' className={`${siteConfig('FONT_STYLE')} nobelium relative dark:text-gray-300 w-full bg-white dark:bg-black min-h-screen flex flex-col scroll-smooth`}>
|
||||
<ThemeGlobalNobelium.Provider
|
||||
value={{ searchModal, filterKey, setFilterKey }}>
|
||||
<div
|
||||
id='theme-nobelium'
|
||||
className={`${siteConfig('FONT_STYLE')} nobelium relative dark:text-gray-300 w-full bg-white dark:bg-black min-h-screen flex flex-col scroll-smooth`}>
|
||||
<Style />
|
||||
|
||||
<Style />
|
||||
{/* 顶部导航栏 */}
|
||||
<Nav {...props} />
|
||||
|
||||
{/* 顶部导航栏 */}
|
||||
<Nav {...props} />
|
||||
{/* 主区 */}
|
||||
<main
|
||||
id='out-wrapper'
|
||||
className={`relative m-auto flex-grow w-full transition-all ${!fullWidth ? 'max-w-2xl px-4' : 'px-4 md:px-24'}`}>
|
||||
<Transition
|
||||
show={!onLoading}
|
||||
appear={true}
|
||||
enter='transition ease-in-out duration-700 transform order-first'
|
||||
enterFrom='opacity-0 translate-y-16'
|
||||
enterTo='opacity-100'
|
||||
leave='transition ease-in-out duration-300 transform'
|
||||
leaveFrom='opacity-100 translate-y-0'
|
||||
leaveTo='opacity-0 -translate-y-16'
|
||||
unmount={false}>
|
||||
{/* 顶部插槽 */}
|
||||
{topSlot}
|
||||
{children}
|
||||
</Transition>
|
||||
</main>
|
||||
|
||||
{/* 主区 */}
|
||||
<main id='out-wrapper' className={`relative m-auto flex-grow w-full transition-all ${!fullWidth ? 'max-w-2xl px-4' : 'px-4 md:px-24'}`}>
|
||||
{/* 页脚 */}
|
||||
<Footer {...props} />
|
||||
|
||||
<Transition
|
||||
show={!onLoading}
|
||||
appear={true}
|
||||
enter="transition ease-in-out duration-700 transform order-first"
|
||||
enterFrom="opacity-0 translate-y-16"
|
||||
enterTo="opacity-100"
|
||||
leave="transition ease-in-out duration-300 transform"
|
||||
leaveFrom="opacity-100 translate-y-0"
|
||||
leaveTo="opacity-0 -translate-y-16"
|
||||
unmount={false}
|
||||
>
|
||||
{/* 顶部插槽 */}
|
||||
{topSlot}
|
||||
{children}
|
||||
</Transition>
|
||||
{/* 右下悬浮 */}
|
||||
<div className='fixed right-4 bottom-4'>
|
||||
<JumpToTopButton />
|
||||
</div>
|
||||
|
||||
</main>
|
||||
{/* 左下悬浮 */}
|
||||
<div className='bottom-4 -left-14 fixed justify-end z-40'>
|
||||
<Live2D />
|
||||
</div>
|
||||
|
||||
{/* 页脚 */}
|
||||
<Footer {...props} />
|
||||
|
||||
{/* 右下悬浮 */}
|
||||
<div className='fixed right-4 bottom-4'>
|
||||
<JumpToTopButton />
|
||||
</div>
|
||||
|
||||
{/* 左下悬浮 */}
|
||||
<div className="bottom-4 -left-14 fixed justify-end z-40">
|
||||
<Live2D />
|
||||
</div>
|
||||
|
||||
{/* 搜索框 */}
|
||||
<AlgoliaSearchModal cRef={searchModal} {...props}/>
|
||||
|
||||
</div>
|
||||
</ThemeGlobalNobelium.Provider>
|
||||
{/* 搜索框 */}
|
||||
<AlgoliaSearchModal cRef={searchModal} {...props} />
|
||||
</div>
|
||||
</ThemeGlobalNobelium.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -105,9 +108,7 @@ const LayoutBase = props => {
|
||||
* @returns
|
||||
*/
|
||||
const LayoutIndex = props => {
|
||||
return (
|
||||
<LayoutPostList {...props} topSlot={<Announcement {...props} />} />
|
||||
)
|
||||
return <LayoutPostList {...props} topSlot={<Announcement {...props} />} />
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,11 +131,15 @@ const LayoutPostList = props => {
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{topSlot}
|
||||
{tag && <SearchNavBar {...props} />}
|
||||
{siteConfig('POST_LIST_STYLE') === 'page' ? <BlogListPage {...props} posts={filteredBlogPosts} /> : <BlogListScroll {...props} posts={filteredBlogPosts} />}
|
||||
</>
|
||||
<>
|
||||
{topSlot}
|
||||
{tag && <SearchNavBar {...props} />}
|
||||
{siteConfig('POST_LIST_STYLE') === 'page' ? (
|
||||
<BlogListPage {...props} posts={filteredBlogPosts} />
|
||||
) : (
|
||||
<BlogListScroll {...props} posts={filteredBlogPosts} />
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -172,10 +177,16 @@ const LayoutSearch = props => {
|
||||
filteredBlogPosts = deepClone(posts)
|
||||
}
|
||||
|
||||
return <>
|
||||
<SearchNavBar {...props} />
|
||||
{siteConfig('POST_LIST_STYLE') === 'page' ? <BlogListPage {...props} posts={filteredBlogPosts} /> : <BlogListScroll {...props} posts={filteredBlogPosts} />}
|
||||
</>
|
||||
return (
|
||||
<>
|
||||
<SearchNavBar {...props} />
|
||||
{siteConfig('POST_LIST_STYLE') === 'page' ? (
|
||||
<BlogListPage {...props} posts={filteredBlogPosts} />
|
||||
) : (
|
||||
<BlogListScroll {...props} posts={filteredBlogPosts} />
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,11 +197,17 @@ const LayoutSearch = props => {
|
||||
const LayoutArchive = props => {
|
||||
const { archivePosts } = props
|
||||
return (
|
||||
<>
|
||||
<div className="mb-10 pb-20 md:py-12 p-3 min-h-screen w-full">
|
||||
{Object.keys(archivePosts).map(archiveTitle => <BlogArchiveItem key={archiveTitle} archiveTitle={archiveTitle} archivePosts={archivePosts} />)}
|
||||
</div>
|
||||
</>
|
||||
<>
|
||||
<div className='mb-10 pb-20 md:py-12 p-3 min-h-screen w-full'>
|
||||
{Object.keys(archivePosts).map(archiveTitle => (
|
||||
<BlogArchiveItem
|
||||
key={archiveTitle}
|
||||
archiveTitle={archiveTitle}
|
||||
archivePosts={archivePosts}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -205,34 +222,39 @@ const LayoutSlug = props => {
|
||||
useEffect(() => {
|
||||
// 404
|
||||
if (!post) {
|
||||
setTimeout(() => {
|
||||
if (isBrowser) {
|
||||
const article = document.getElementById('notion-article')
|
||||
if (!article) {
|
||||
router.push('/404').then(() => {
|
||||
console.warn('找不到页面', router.asPath)
|
||||
})
|
||||
setTimeout(
|
||||
() => {
|
||||
if (isBrowser) {
|
||||
const article = document.getElementById('notion-article')
|
||||
if (!article) {
|
||||
router.push('/404').then(() => {
|
||||
console.warn('找不到页面', router.asPath)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}, siteConfig('POST_WAITING_TIME_FOR_404') * 1000)
|
||||
},
|
||||
siteConfig('POST_WAITING_TIME_FOR_404') * 1000
|
||||
)
|
||||
}
|
||||
}, [post])
|
||||
return (
|
||||
<>
|
||||
<>
|
||||
{lock && <ArticleLock validPassword={validPassword} />}
|
||||
|
||||
{lock && <ArticleLock validPassword={validPassword} />}
|
||||
|
||||
{!lock && <div id="article-wrapper" className="px-2">
|
||||
<>
|
||||
<ArticleInfo post={post} />
|
||||
<NotionPage post={post} />
|
||||
<ShareBar post={post} />
|
||||
<Comment frontMatter={post} />
|
||||
<ArticleFooter />
|
||||
</>
|
||||
</div>}
|
||||
|
||||
</>
|
||||
{!lock && (
|
||||
<div className='px-2'>
|
||||
<>
|
||||
<ArticleInfo post={post} />
|
||||
<div id='article-wrapper'>
|
||||
<NotionPage post={post} />
|
||||
</div>
|
||||
<ShareBar post={post} />
|
||||
<Comment frontMatter={post} />
|
||||
<ArticleFooter />
|
||||
</>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -241,10 +263,8 @@ const LayoutSlug = props => {
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const Layout404 = (props) => {
|
||||
return <>
|
||||
404 Not found.
|
||||
</>
|
||||
const Layout404 = props => {
|
||||
return <>404 Not found.</>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -252,28 +272,31 @@ const Layout404 = (props) => {
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutCategoryIndex = (props) => {
|
||||
const LayoutCategoryIndex = props => {
|
||||
const { categoryOptions } = props
|
||||
|
||||
return (
|
||||
<>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{categoryOptions?.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<div
|
||||
className={'hover:text-black dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'}>
|
||||
<i className='mr-4 fas fa-folder' />{category.name}({category.count})
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
<>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{categoryOptions?.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<div
|
||||
className={
|
||||
'hover:text-black dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'
|
||||
}>
|
||||
<i className='mr-4 fas fa-folder' />
|
||||
{category.name}({category.count})
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -282,37 +305,43 @@ const LayoutCategoryIndex = (props) => {
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutTagIndex = (props) => {
|
||||
const LayoutTagIndex = props => {
|
||||
const { tagOptions } = props
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<div id='tags-list' className='duration-200 flex flex-wrap'>
|
||||
{tagOptions.map(tag => {
|
||||
return (
|
||||
<div key={tag.name} className='p-2'>
|
||||
<Link key={tag} href={`/tag/${encodeURIComponent(tag.name)}`} passHref
|
||||
className={`cursor-pointer inline-block rounded hover:bg-gray-500 hover:text-white duration-200 mr-2 py-1 px-2 text-xs whitespace-nowrap dark:hover:text-white text-gray-600 hover:shadow-xl dark:border-gray-400 notion-${tag.color}_background dark:bg-gray-800`}>
|
||||
<div className='font-light dark:text-gray-400'><i className='mr-1 fas fa-tag' /> {tag.name + (tag.count ? `(${tag.count})` : '')} </div>
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
<>
|
||||
<div>
|
||||
<div id='tags-list' className='duration-200 flex flex-wrap'>
|
||||
{tagOptions.map(tag => {
|
||||
return (
|
||||
<div key={tag.name} className='p-2'>
|
||||
<Link
|
||||
key={tag}
|
||||
href={`/tag/${encodeURIComponent(tag.name)}`}
|
||||
passHref
|
||||
className={`cursor-pointer inline-block rounded hover:bg-gray-500 hover:text-white duration-200 mr-2 py-1 px-2 text-xs whitespace-nowrap dark:hover:text-white text-gray-600 hover:shadow-xl dark:border-gray-400 notion-${tag.color}_background dark:bg-gray-800`}>
|
||||
<div className='font-light dark:text-gray-400'>
|
||||
<i className='mr-1 fas fa-tag' />{' '}
|
||||
{tag.name + (tag.count ? `(${tag.count})` : '')}{' '}
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
CONFIG as THEME_CONFIG,
|
||||
LayoutBase,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
LayoutSlug,
|
||||
Layout404,
|
||||
LayoutPostList,
|
||||
LayoutArchive,
|
||||
LayoutBase,
|
||||
LayoutCategoryIndex,
|
||||
LayoutTagIndex
|
||||
LayoutIndex,
|
||||
LayoutPostList,
|
||||
LayoutSearch,
|
||||
LayoutSlug,
|
||||
LayoutTagIndex,
|
||||
CONFIG as THEME_CONFIG
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
import CONFIG from './config'
|
||||
import { createContext, useContext, useEffect, useState } from 'react'
|
||||
import Header from './components/Nav'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import Comment from '@/components/Comment'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
import ShareBar from '@/components/ShareBar'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
import { Transition } from '@headlessui/react'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { createContext, useContext, useEffect, useState } from 'react'
|
||||
import { ArticleFooter } from './components/ArticleFooter'
|
||||
import { ArticleInfo } from './components/ArticleInfo'
|
||||
import { ArticleLock } from './components/ArticleLock'
|
||||
import BlogArchiveItem from './components/BlogArchiveItem'
|
||||
import { BlogListPage } from './components/BlogListPage'
|
||||
import { BlogListScroll } from './components/BlogListScroll'
|
||||
import { isBrowser } from '@/lib/utils'
|
||||
import SearchNavBar from './components/SearchNavBar'
|
||||
import BlogArchiveItem from './components/BlogArchiveItem'
|
||||
import { ArticleLock } from './components/ArticleLock'
|
||||
import NotionPage from '@/components/NotionPage'
|
||||
import { ArticleInfo } from './components/ArticleInfo'
|
||||
import Comment from '@/components/Comment'
|
||||
import { ArticleFooter } from './components/ArticleFooter'
|
||||
import ShareBar from '@/components/ShareBar'
|
||||
import Link from 'next/link'
|
||||
import { Transition } from '@headlessui/react'
|
||||
import BottomNav from './components/BottomNav'
|
||||
import Modal from './components/Modal'
|
||||
import Header from './components/Nav'
|
||||
import SearchNavBar from './components/SearchNavBar'
|
||||
import CONFIG from './config'
|
||||
import { Style } from './style'
|
||||
import replaceSearchResult from '@/components/Mark'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
// 主题全局状态
|
||||
const ThemeGlobalPlog = createContext()
|
||||
@@ -52,42 +52,45 @@ const LayoutBase = props => {
|
||||
}, [router.events])
|
||||
|
||||
return (
|
||||
<ThemeGlobalPlog.Provider value={{ showModal, setShowModal, modalContent, setModalContent }}>
|
||||
<div id='theme-plog' className={`${siteConfig('FONT_STYLE')} plog relative dark:text-gray-300 w-full dark:bg-black min-h-screen scroll-smooth`} >
|
||||
<ThemeGlobalPlog.Provider
|
||||
value={{ showModal, setShowModal, modalContent, setModalContent }}>
|
||||
<div
|
||||
id='theme-plog'
|
||||
className={`${siteConfig('FONT_STYLE')} plog relative dark:text-gray-300 w-full dark:bg-black min-h-screen scroll-smooth`}>
|
||||
<Style />
|
||||
|
||||
<Style/>
|
||||
{/* 移动端顶部导航栏 */}
|
||||
<Header {...props} />
|
||||
|
||||
{/* 移动端顶部导航栏 */}
|
||||
<Header {...props} />
|
||||
{/* 主区 */}
|
||||
<main
|
||||
id='out-wrapper'
|
||||
className={
|
||||
'relative m-auto flex-grow w-full transition-all pb-16 pt-16 md:pt-0'
|
||||
}>
|
||||
<Transition
|
||||
show={!onLoading}
|
||||
appear={true}
|
||||
enter='transition ease-in-out duration-700 transform order-first'
|
||||
enterFrom='opacity-0 translate-y-16'
|
||||
enterTo='opacity-100'
|
||||
leave='transition ease-in-out duration-300 transform'
|
||||
leaveFrom='opacity-100 translate-y-0'
|
||||
leaveTo='opacity-0 -translate-y-16'
|
||||
unmount={false}>
|
||||
{/* 顶部插槽 */}
|
||||
{topSlot}
|
||||
{children}
|
||||
</Transition>
|
||||
</main>
|
||||
|
||||
{/* 主区 */}
|
||||
<main id='out-wrapper' className={'relative m-auto flex-grow w-full transition-all pb-16 pt-16 md:pt-0'}>
|
||||
{/* 弹出框 - 用于放大显示首页图片等作用 */}
|
||||
<Modal {...props} />
|
||||
|
||||
<Transition
|
||||
show={!onLoading}
|
||||
appear={true}
|
||||
enter="transition ease-in-out duration-700 transform order-first"
|
||||
enterFrom="opacity-0 translate-y-16"
|
||||
enterTo="opacity-100"
|
||||
leave="transition ease-in-out duration-300 transform"
|
||||
leaveFrom="opacity-100 translate-y-0"
|
||||
leaveTo="opacity-0 -translate-y-16"
|
||||
unmount={false}
|
||||
>
|
||||
{/* 顶部插槽 */}
|
||||
{topSlot}
|
||||
{children}
|
||||
</Transition>
|
||||
|
||||
</main>
|
||||
|
||||
{/* 弹出框 - 用于放大显示首页图片等作用 */}
|
||||
<Modal {...props}/>
|
||||
|
||||
{/* 桌面端底部导航栏 */}
|
||||
<BottomNav {...props} />
|
||||
</div>
|
||||
</ThemeGlobalPlog.Provider >
|
||||
{/* 桌面端底部导航栏 */}
|
||||
<BottomNav {...props} />
|
||||
</div>
|
||||
</ThemeGlobalPlog.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -98,9 +101,7 @@ const LayoutBase = props => {
|
||||
* @returns
|
||||
*/
|
||||
const LayoutIndex = props => {
|
||||
return (
|
||||
<LayoutPostList {...props} />
|
||||
)
|
||||
return <LayoutPostList {...props} />
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,9 +111,13 @@ const LayoutIndex = props => {
|
||||
*/
|
||||
const LayoutPostList = props => {
|
||||
return (
|
||||
<>
|
||||
{siteConfig('POST_LIST_STYLE') === 'page' ? <BlogListPage {...props} /> : <BlogListScroll {...props} />}
|
||||
</>
|
||||
<>
|
||||
{siteConfig('POST_LIST_STYLE') === 'page' ? (
|
||||
<BlogListPage {...props} />
|
||||
) : (
|
||||
<BlogListScroll {...props} />
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -149,11 +154,17 @@ const LayoutSearch = props => {
|
||||
const LayoutArchive = props => {
|
||||
const { archivePosts } = props
|
||||
return (
|
||||
<>
|
||||
<div className="mb-10 pb-20 md:py-12 p-3 min-h-screen w-full">
|
||||
{Object.keys(archivePosts).map(archiveTitle => <BlogArchiveItem key={archiveTitle} archiveTitle={archiveTitle} archivePosts={archivePosts} />)}
|
||||
</div>
|
||||
</>
|
||||
<>
|
||||
<div className='mb-10 pb-20 md:py-12 p-3 min-h-screen w-full'>
|
||||
{Object.keys(archivePosts).map(archiveTitle => (
|
||||
<BlogArchiveItem
|
||||
key={archiveTitle}
|
||||
archiveTitle={archiveTitle}
|
||||
archivePosts={archivePosts}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -168,34 +179,39 @@ const LayoutSlug = props => {
|
||||
useEffect(() => {
|
||||
// 404
|
||||
if (!post) {
|
||||
setTimeout(() => {
|
||||
if (isBrowser) {
|
||||
const article = document.getElementById('notion-article')
|
||||
if (!article) {
|
||||
router.push('/404').then(() => {
|
||||
console.warn('找不到页面', router.asPath)
|
||||
})
|
||||
setTimeout(
|
||||
() => {
|
||||
if (isBrowser) {
|
||||
const article = document.getElementById('notion-article')
|
||||
if (!article) {
|
||||
router.push('/404').then(() => {
|
||||
console.warn('找不到页面', router.asPath)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}, siteConfig('POST_WAITING_TIME_FOR_404') * 1000)
|
||||
},
|
||||
siteConfig('POST_WAITING_TIME_FOR_404') * 1000
|
||||
)
|
||||
}
|
||||
}, [post])
|
||||
return (
|
||||
<>
|
||||
<>
|
||||
{lock && <ArticleLock validPassword={validPassword} />}
|
||||
|
||||
{lock && <ArticleLock validPassword={validPassword} />}
|
||||
|
||||
{!lock && <div id="article-wrapper" className="px-2 my-16 max-w-6xl mx-auto">
|
||||
<>
|
||||
<ArticleInfo post={post} />
|
||||
<NotionPage post={post} />
|
||||
<ShareBar post={post} />
|
||||
<Comment frontMatter={post} />
|
||||
<ArticleFooter />
|
||||
</>
|
||||
</div>}
|
||||
|
||||
</>
|
||||
{!lock && (
|
||||
<div className='px-2 my-16 max-w-6xl mx-auto'>
|
||||
<>
|
||||
<ArticleInfo post={post} />
|
||||
<div id='article-wrapper'>
|
||||
<NotionPage post={post} />
|
||||
</div>
|
||||
<ShareBar post={post} />
|
||||
<Comment frontMatter={post} />
|
||||
<ArticleFooter />
|
||||
</>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -204,10 +220,8 @@ const LayoutSlug = props => {
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const Layout404 = (props) => {
|
||||
return <>
|
||||
404 Not found.
|
||||
</>
|
||||
const Layout404 = props => {
|
||||
return <>404 Not found.</>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -215,28 +229,31 @@ const Layout404 = (props) => {
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutCategoryIndex = (props) => {
|
||||
const LayoutCategoryIndex = props => {
|
||||
const { categoryOptions } = props
|
||||
|
||||
return (
|
||||
<>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{categoryOptions?.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<div
|
||||
className={'hover:text-black dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'}>
|
||||
<i className='mr-4 fas fa-folder' />{category.name}({category.count})
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
<>
|
||||
<div id='category-list' className='duration-200 flex flex-wrap'>
|
||||
{categoryOptions?.map(category => {
|
||||
return (
|
||||
<Link
|
||||
key={category.name}
|
||||
href={`/category/${category.name}`}
|
||||
passHref
|
||||
legacyBehavior>
|
||||
<div
|
||||
className={
|
||||
'hover:text-black dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600 px-5 cursor-pointer py-2 hover:bg-gray-100'
|
||||
}>
|
||||
<i className='mr-4 fas fa-folder' />
|
||||
{category.name}({category.count})
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -245,37 +262,43 @@ const LayoutCategoryIndex = (props) => {
|
||||
* @param {*} props
|
||||
* @returns
|
||||
*/
|
||||
const LayoutTagIndex = (props) => {
|
||||
const LayoutTagIndex = props => {
|
||||
const { tagOptions } = props
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<div id='tags-list' className='duration-200 flex flex-wrap'>
|
||||
{tagOptions.map(tag => {
|
||||
return (
|
||||
<div key={tag.name} className='p-2'>
|
||||
<Link key={tag} href={`/tag/${encodeURIComponent(tag.name)}`} passHref
|
||||
className={`cursor-pointer inline-block rounded hover:bg-gray-500 hover:text-white duration-200 mr-2 py-1 px-2 text-xs whitespace-nowrap dark:hover:text-white text-gray-600 hover:shadow-xl dark:border-gray-400 notion-${tag.color}_background dark:bg-gray-800`}>
|
||||
<div className='font-light dark:text-gray-400'><i className='mr-1 fas fa-tag' /> {tag.name + (tag.count ? `(${tag.count})` : '')} </div>
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
<>
|
||||
<div>
|
||||
<div id='tags-list' className='duration-200 flex flex-wrap'>
|
||||
{tagOptions.map(tag => {
|
||||
return (
|
||||
<div key={tag.name} className='p-2'>
|
||||
<Link
|
||||
key={tag}
|
||||
href={`/tag/${encodeURIComponent(tag.name)}`}
|
||||
passHref
|
||||
className={`cursor-pointer inline-block rounded hover:bg-gray-500 hover:text-white duration-200 mr-2 py-1 px-2 text-xs whitespace-nowrap dark:hover:text-white text-gray-600 hover:shadow-xl dark:border-gray-400 notion-${tag.color}_background dark:bg-gray-800`}>
|
||||
<div className='font-light dark:text-gray-400'>
|
||||
<i className='mr-1 fas fa-tag' />{' '}
|
||||
{tag.name + (tag.count ? `(${tag.count})` : '')}{' '}
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
CONFIG as THEME_CONFIG,
|
||||
LayoutBase,
|
||||
LayoutIndex,
|
||||
LayoutSearch,
|
||||
LayoutArchive,
|
||||
LayoutSlug,
|
||||
Layout404,
|
||||
LayoutPostList,
|
||||
LayoutArchive,
|
||||
LayoutBase,
|
||||
LayoutCategoryIndex,
|
||||
LayoutTagIndex
|
||||
LayoutIndex,
|
||||
LayoutPostList,
|
||||
LayoutSearch,
|
||||
LayoutSlug,
|
||||
LayoutTagIndex,
|
||||
CONFIG as THEME_CONFIG
|
||||
}
|
||||
|
||||
@@ -224,9 +224,7 @@ const LayoutSlug = props => {
|
||||
<>
|
||||
{lock && <ArticleLock validPassword={validPassword} />}
|
||||
|
||||
<div
|
||||
id='article-wrapper'
|
||||
className={`px-2 ${fullWidth ? '' : 'xl:max-w-4xl 2xl:max-w-6xl'}`}>
|
||||
<div className={`px-2 ${fullWidth ? '' : 'xl:max-w-4xl 2xl:max-w-6xl'}`}>
|
||||
{/* 文章信息 */}
|
||||
<ArticleInfo post={post} />
|
||||
|
||||
@@ -234,8 +232,10 @@ const LayoutSlug = props => {
|
||||
{/* <AdSlot type={'in-article'} /> */}
|
||||
<WWAds orientation='horizontal' className='w-full' />
|
||||
|
||||
{/* Notion文章主体 */}
|
||||
{!lock && <NotionPage post={post} />}
|
||||
<div id='article-wrapper'>
|
||||
{/* Notion文章主体 */}
|
||||
{!lock && <NotionPage post={post} />}
|
||||
</div>
|
||||
|
||||
{/* 分享 */}
|
||||
<ShareBar post={post} />
|
||||
|
||||
@@ -143,8 +143,8 @@ const LayoutSlug = props => {
|
||||
<Banner title={post?.title} description={post?.summary} />
|
||||
<div className='container grow'>
|
||||
<div className='flex flex-wrap justify-center -mx-4'>
|
||||
<div className='w-full p-4'>
|
||||
<div id='container-inner' className='mx-auto'>
|
||||
<div id='container-inner' className='w-full p-4'>
|
||||
<div id='article-wrapper' className='mx-auto'>
|
||||
<NotionPage {...props} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -99,7 +99,9 @@ const checkThemeDOM = () => {
|
||||
elements[elements.length - 1].scrollIntoView()
|
||||
// 删除前面的元素,只保留最后一个元素
|
||||
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])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user