Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,26 +36,8 @@ jobs:
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-

- name: "Install"
run: "pnpm install --frozen-lockfile"

# 压缩图片
- name: "图片压缩"
uses: calibreapp/image-actions@main
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jpegQuality: "80"
pngQuality: "80"
webpQuality: "80"
ignorePaths: "node_modules/**"
compressOnly: true

- name: "MarkdownLint Check"
uses: DavidAnson/markdownlint-cli2-action@v17
with:
fix: true
globs: "docs*/**/*.md"

- name: "Build"
run: "pnpm run build"
4 changes: 2 additions & 2 deletions docs-java/start/connect-to-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ server-port=25565
- 在 Windows 下,CMD 执行`ipconfig /flushdns`
- 在 Linux 下,终端执行 `sudo systemd-resolve --flush-caches`

3.你的域名可能被 DNS 污染,你可以检查实际解析出来的 IP 和设置的是否一致,不一致就是被污染了,临时解决方案是更改 DNS
服务器,长远来看最好打开 DNSSEC
3.你的域名可能被 DNS 污染,你可以检查实际解析出来的 IP 和设置的是否一致,不一致就是被污染了,临时解决方案是更改 DNS
服务器,长远来看最好打开 DNSSEC

### `数据流终止`

Expand Down
21 changes: 19 additions & 2 deletions docusaurus.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Options as PresetClassicOptions } from "@docusaurus/preset-classic";
import type { Config } from "@docusaurus/types";
import path from "path";
import * as path from "path";
import { themes as prismThemes } from "prism-react-renderer";

const IS_CHINA_SITE = process.env.CHINA === "true";
Expand Down Expand Up @@ -65,7 +65,7 @@ const config: Config = {
clientModules: [
require.resolve("./src/clientModules/routeModules.js"),
require.resolve("./src/clientModules/adsModules.js"),
require.resolve("./src/clientModules/githubIconModule.js")
require.resolve("./src/clientModules/themeModules.ts")
],

presets: [
Expand Down Expand Up @@ -99,6 +99,7 @@ const config: Config = {
plugins: [
"docusaurus-plugin-image-zoom",
"docusaurus-plugin-sass",
path.resolve(__dirname, "src/plugins/remote-gh-viewer-plugin.ts"),
["@gracefullight/docusaurus-plugin-microsoft-clarity", { projectId: "oyfswsvfpc" }],
[
"@docusaurus/plugin-content-docs",
Expand Down Expand Up @@ -172,13 +173,29 @@ const config: Config = {
href: "/favicon.ico"
}
},
{
tagName: "link",
attributes: {
rel: "preconnect",
href: "https://fontsapi.zeoseven.com",
crossOrigin: "anonymous"
}
},
{
tagName: "link",
attributes: {
rel: "preconnect",
href: "https://D1KV1BYF3B-dsn.algolia.net",
crossOrigin: "anonymous"
}
},
{
tagName: "link",
attributes: {
rel: "preconnect",
href: "https://giscus.app",
crossOrigin: "anonymous"
}
}
],

Expand Down
9 changes: 8 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,13 @@
"prism-react-renderer": "^2.4.1",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"sass": "^1.94.0"
"rehype-raw": "^7.0.0",
"rehype-stringify": "^10.0.1",
"remark-gfm": "^4.0.1",
"remark-parse": "^11.0.0",
"remark-rehype": "^11.1.2",
"sass": "^1.94.0",
"unified": "^11.0.5"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "^3.9.2",
Expand All @@ -59,6 +65,7 @@
"autoprefixer": "^10.4.22",
"markdownlint-cli2": "^0.18.1",
"postcss": "^8.5.6",
"prettier": "^3.6.2",
"swc-loader": "^0.2.6",
"tailwind-merge": "^3.4.0",
"tailwindcss": "^4.1.17",
Expand Down
47,898 changes: 27,341 additions & 20,557 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

69 changes: 0 additions & 69 deletions src/clientModules/githubIconModule.js

This file was deleted.

95 changes: 95 additions & 0 deletions src/clientModules/themeModules.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
$ripple-duration: 600ms;
$cascade-duration: 400ms;
$cascade-delay: 40ms;
$card-wave-duration: 400ms;

// 涟漪元素样式
.theme-ripple {
position: fixed;
width: 0;
height: 0;
border-radius: 50%;
transform: scale(0);
pointer-events: none;
z-index: 9999;
animation: themeRippleExpand $ripple-duration cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

// 涟漪展开动画
@keyframes themeRippleExpand {
0% {
transform: scale(0);
opacity: 1;
}
50% {
opacity: 0.8;
}
100% {
transform: scale(1);
opacity: 0;
}
}

// 瀑布流过渡动画
@keyframes themeCascade {
0% {
filter: brightness(1);
}
30% {
filter: brightness(1.05);
}
100% {
filter: brightness(1);
}
}

// 卡片波浪动画
@keyframes cardWave {
0% {
transform: translateY(0) scale(1);
}
40% {
transform: translateY(-2px) scale(1.005);
}
100% {
transform: translateY(0) scale(1);
}
}

// 瀑布流过渡增强效果
.theme-transitioning {
.navbar {
animation: themeCascade $cascade-duration ease-out;
}

.main-wrapper {
animation: themeCascade $cascade-duration ease-out $cascade-delay backwards;
}

article {
animation: themeCascade $cascade-duration ease-out ($cascade-delay * 2) backwards;
}

.footer {
animation: themeCascade $cascade-duration ease-out ($cascade-delay * 5) backwards;
}

// 卡片波浪效果
.card {
animation: cardWave $card-wave-duration ease-out backwards;

@for $i from 1 through 6 {
&:nth-child(#{$i}) {
animation-delay: (100ms + ($i - 1) * 40ms);
}
}
}
}

// 尊重减少动画偏好
@media (prefers-reduced-motion: reduce) {
.theme-ripple,
.theme-transitioning * {
animation: none !important;
}
}
115 changes: 115 additions & 0 deletions src/clientModules/themeModules.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/**
* NitWikit 主题切换动画模块
* 实现瀑布流涟漪效果
*/
import ExecutionEnvironment from "@docusaurus/ExecutionEnvironment";
import "./themeModules.scss";

if (ExecutionEnvironment.canUseDOM) {
// 常量定义
const TRANSITION_DURATION = 600;
const TRANSITION_CLASS = "theme-transitioning";
const THEME_LISTENER_ATTR = "data-theme-listener";
const SELECTOR = 'button[class*="colorModeToggle"]';

let isAnimating = false;
let transitionTimeout: ReturnType<typeof setTimeout> | null = null;

// 等待 DOM 加载完成
const init = (): void => {
const colorModeToggle = document.querySelector(SELECTOR) as HTMLButtonElement | null;

if (colorModeToggle) {
colorModeToggle.addEventListener("click", handleThemeToggle);
}

// 监听 DOM 变化,处理动态加载的按钮
const observer = new MutationObserver((): void => {
const toggle = document.querySelector(SELECTOR) as HTMLButtonElement | null;
if (toggle && !toggle.hasAttribute(THEME_LISTENER_ATTR)) {
toggle.setAttribute(THEME_LISTENER_ATTR, "true");
toggle.addEventListener("click", handleThemeToggle);
}
});

observer.observe(document.body, { childList: true, subtree: true });
};

function handleThemeToggle(e: Event): void {
// 防抖
if (isAnimating) return;

isAnimating = true;
const button = e.currentTarget as HTMLButtonElement;
const rect = button.getBoundingClientRect();

// 创建涟漪效果
createRipple(rect.left + rect.width / 2, rect.top + rect.height / 2);

// 添加瀑布流过渡标记
document.documentElement.classList.add(TRANSITION_CLASS);

// 清除之前的超时
if (transitionTimeout) {
clearTimeout(transitionTimeout);
}

// 过渡完成后移除标记和重置状态
transitionTimeout = setTimeout((): void => {
document.documentElement.classList.remove(TRANSITION_CLASS);
isAnimating = false;
transitionTimeout = null;
}, TRANSITION_DURATION);
}

function createRipple(x: number, y: number): void {
const ripple = document.createElement("div");
ripple.className = "theme-ripple";

const maxDimension = Math.max(window.innerWidth, window.innerHeight) * 2;
const halfDimension = maxDimension / 2;

// 主题涟漪颜色
const isDark = document.documentElement.getAttribute("data-theme") === "dark";
const bgColor = isDark ? "rgba(248, 250, 252, 0.08)" : "rgba(2, 6, 23, 0.06)";

// 动态样式
ripple.style.left = `${x}px`;
ripple.style.top = `${y}px`;
ripple.style.width = `${maxDimension}px`;
ripple.style.height = `${maxDimension}px`;
ripple.style.marginLeft = `-${halfDimension}px`;
ripple.style.marginTop = `-${halfDimension}px`;
ripple.style.background = bgColor;

document.body.appendChild(ripple);

// 清理
const removeRipple = (): void => {
ripple.removeEventListener("animationend", removeRipple);
ripple.remove();
};
ripple.addEventListener("animationend", removeRipple);
}

// 注入样式
function injectStyles(): void {
if (document.getElementById("theme-ripple-styles")) return;

const style = document.createElement("style");
style.id = "theme-ripple-styles";
document.head.appendChild(style);
}

// 初始化
const setupThemeAnimation = (): void => {
injectStyles();
init();
};

if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", setupThemeAnimation);
} else {
setupThemeAnimation();
}
}
Loading