mirror of
https://github.com/hamster1963/nezha-dash.git
synced 2025-04-24 21:10:45 +08:00
Merge branch 'main' into cloudflare-dev
This commit is contained in:
commit
74dbba7881
10
.env.example
10
.env.example
@ -1,6 +1,6 @@
|
|||||||
NezhaBaseUrl=http://1.1.1.1:8008
|
NezhaBaseUrl=http://124.XX.XX.XX:8008
|
||||||
NezhaAuth=nezha-token
|
NezhaAuth=your-nezha-api-token
|
||||||
ServerDisablePrefetch=false
|
DefaultLocale=zh
|
||||||
NEXT_PUBLIC_NezhaFetchInterval=2000
|
NEXT_PUBLIC_NezhaFetchInterval=5000
|
||||||
NEXT_PUBLIC_ShowFlag=true
|
NEXT_PUBLIC_ShowFlag=true
|
||||||
NEXT_PUBLIC_DisableCartoon=false
|
NEXT_PUBLIC_DisableCartoon=true
|
36
.github/workflows/Deploy.yml
vendored
36
.github/workflows/Deploy.yml
vendored
@ -5,8 +5,40 @@ on:
|
|||||||
tags:
|
tags:
|
||||||
- "v*"
|
- "v*"
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY_IMAGE: hamster1963/nezha-dash
|
||||||
|
ALIYUN_REGISTRY_IMAGE: registry.cn-guangzhou.aliyuncs.com/hamster-home/nezha-dash
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
changelog:
|
||||||
|
name: Generate Changelog
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
release_body: ${{ steps.git-cliff.outputs.content }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Generate a changelog
|
||||||
|
uses: orhun/git-cliff-action@v4
|
||||||
|
id: git-cliff
|
||||||
|
with:
|
||||||
|
config: git-cliff-config/cliff.toml
|
||||||
|
args: -vv --latest --strip 'footer'
|
||||||
|
env:
|
||||||
|
OUTPUT: CHANGES.md
|
||||||
|
- name: Release
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
|
with:
|
||||||
|
body: ${{ steps.git-cliff.outputs.content }}
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
env:
|
||||||
|
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||||
|
|
||||||
build-and-push:
|
build-and-push:
|
||||||
|
name: Build and push Docker image
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
environment: Production
|
environment: Production
|
||||||
steps:
|
steps:
|
||||||
@ -37,8 +69,8 @@ jobs:
|
|||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v5
|
||||||
with:
|
with:
|
||||||
images: |
|
images: |
|
||||||
hamster1963/nezha-dash
|
${{ env.REGISTRY_IMAGE }}
|
||||||
registry.cn-guangzhou.aliyuncs.com/hamster-home/nezha-dash
|
${{ env.ALIYUN_REGISTRY_IMAGE }}
|
||||||
tags: |
|
tags: |
|
||||||
type=raw,value=latest
|
type=raw,value=latest
|
||||||
type=ref,event=tag
|
type=ref,event=tag
|
||||||
|
@ -13,10 +13,10 @@
|
|||||||
#### 环境变量
|
#### 环境变量
|
||||||
|
|
||||||
| 变量名 | 含义 | 示例 |
|
| 变量名 | 含义 | 示例 |
|
||||||
| ------------------------------ | -------------------- | -------------------------------- |
|
| ------------------------------ | -------------------------------- | -------------------------------- |
|
||||||
| NezhaBaseUrl | nezha 面板地址 | http://120.x.x.x:8008 |
|
| NezhaBaseUrl | nezha 面板地址 | http://120.x.x.x:8008 |
|
||||||
| NezhaAuth | nezha 面板 API Token | 5hAY3QX6Nl9B3Uxxxx26KMvOMyXS1Udi |
|
| NezhaAuth | nezha 面板 API Token | 5hAY3QX6Nl9B3Uxxxx26KMvOMyXS1Udi |
|
||||||
| ServerDisablePrefetch | 是否禁用预加载 | **默认**:false |
|
| DefaultLocale | 面板默认显示语言(代码参考下表) | **默认**:en |
|
||||||
| NEXT_PUBLIC_NezhaFetchInterval | 获取数据间隔(毫秒) | **默认**:2000 |
|
| NEXT_PUBLIC_NezhaFetchInterval | 获取数据间隔(毫秒) | **默认**:2000 |
|
||||||
| NEXT_PUBLIC_ShowFlag | 是否显示旗帜 | **默认**:false |
|
| NEXT_PUBLIC_ShowFlag | 是否显示旗帜 | **默认**:false |
|
||||||
| NEXT_PUBLIC_DisableCartoon | 是否禁用卡通人物 | **默认**:false |
|
| NEXT_PUBLIC_DisableCartoon | 是否禁用卡通人物 | **默认**:false |
|
||||||
|
@ -6,18 +6,29 @@ import { nezhaFetcher } from "../../../../lib/utils";
|
|||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import getEnv from "../../../../lib/env-entry";
|
import getEnv from "../../../../lib/env-entry";
|
||||||
export default function ServerListClient() {
|
export default function ServerListClient() {
|
||||||
const { data } = useSWR<ServerApi>("/api/server", nezhaFetcher, {
|
const { data, error } = useSWR<ServerApi>("/api/server", nezhaFetcher, {
|
||||||
refreshInterval: Number(getEnv("NEXT_PUBLIC_NezhaFetchInterval")) || 2000,
|
refreshInterval: Number(getEnv("NEXT_PUBLIC_NezhaFetchInterval")) || 2000,
|
||||||
});
|
});
|
||||||
|
if (error)
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col items-center justify-center">
|
||||||
|
<p className="text-sm font-medium opacity-40">{error.message}</p>
|
||||||
|
<p className="text-sm font-medium opacity-40">
|
||||||
|
Please check your environment variables and review the server console
|
||||||
|
logs for more details.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
if (!data) return null;
|
if (!data) return null;
|
||||||
const sortedServers = data.result.sort((a, b) => {
|
|
||||||
if (a.display_index && b.display_index) {
|
const { result } = data;
|
||||||
return b.display_index - a.display_index;
|
|
||||||
}
|
const sortedServers = result.sort((a, b) => {
|
||||||
if (a.display_index) return -1;
|
const displayIndexDiff = (b.display_index || 0) - (a.display_index || 0);
|
||||||
if (b.display_index) return 1;
|
if (displayIndexDiff !== 0) return displayIndexDiff;
|
||||||
return a.id - b.id;
|
return a.id - b.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="grid grid-cols-1 gap-2 md:grid-cols-2">
|
<section className="grid grid-cols-1 gap-2 md:grid-cols-2">
|
||||||
{sortedServers.map((serverInfo) => (
|
{sortedServers.map((serverInfo) => (
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
|
import { unstable_setRequestLocale } from "next-intl/server";
|
||||||
import ServerList from "../../../components/ServerList";
|
import ServerList from "../../../components/ServerList";
|
||||||
import ServerOverview from "../../../components/ServerOverview";
|
import ServerOverview from "../../../components/ServerOverview";
|
||||||
|
|
||||||
export const runtime = 'edge';
|
export const runtime = 'edge';
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home({
|
||||||
|
params: { locale },
|
||||||
|
}: {
|
||||||
|
params: { locale: string };
|
||||||
|
}) {
|
||||||
|
unstable_setRequestLocale(locale);
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto grid w-full max-w-5xl gap-4 md:gap-6">
|
<div className="mx-auto grid w-full max-w-5xl gap-4 md:gap-6">
|
||||||
<ServerOverview />
|
<ServerOverview />
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// @auto-i18n-check. Please do not delete the line.
|
// @auto-i18n-check. Please do not delete the line.
|
||||||
|
|
||||||
import "@/styles/globals.css";
|
import "@/styles/globals.css";
|
||||||
|
import "/node_modules/flag-icons/css/flag-icons.min.css";
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { NextIntlClientProvider, useMessages } from "next-intl";
|
import { NextIntlClientProvider, useMessages } from "next-intl";
|
||||||
import { PublicEnvScript } from "next-runtime-env";
|
import { PublicEnvScript } from "next-runtime-env";
|
||||||
@ -10,6 +12,7 @@ import { ThemeProvider } from "next-themes";
|
|||||||
import { Viewport } from "next";
|
import { Viewport } from "next";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { locales } from "@/i18n-metadata";
|
import { locales } from "@/i18n-metadata";
|
||||||
|
import { unstable_setRequestLocale } from "next-intl/server";
|
||||||
|
|
||||||
const fontSans = FontSans({
|
const fontSans = FontSans({
|
||||||
subsets: ["latin"],
|
subsets: ["latin"],
|
||||||
@ -34,11 +37,12 @@ export const viewport: Viewport = {
|
|||||||
userScalable: false,
|
userScalable: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function generateStaticParams() {
|
export const dynamic = "force-static";
|
||||||
|
|
||||||
|
export async function generateStaticParams() {
|
||||||
return locales.map((locale) => ({ locale }));
|
return locales.map((locale) => ({ locale }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default function LocaleLayout({
|
export default function LocaleLayout({
|
||||||
children,
|
children,
|
||||||
params: { locale },
|
params: { locale },
|
||||||
@ -46,6 +50,8 @@ export default function LocaleLayout({
|
|||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
params: { locale: string };
|
params: { locale: string };
|
||||||
}) {
|
}) {
|
||||||
|
unstable_setRequestLocale(locale);
|
||||||
|
|
||||||
const messages = useMessages();
|
const messages = useMessages();
|
||||||
return (
|
return (
|
||||||
<html lang={locale} suppressHydrationWarning>
|
<html lang={locale} suppressHydrationWarning>
|
||||||
|
@ -8,17 +8,18 @@ export const dynamic = "force-dynamic";
|
|||||||
|
|
||||||
export const runtime = 'edge';
|
export const runtime = 'edge';
|
||||||
|
|
||||||
|
interface NezhaDataResponse {
|
||||||
|
error?: string;
|
||||||
|
data?: ServerApi;
|
||||||
|
}
|
||||||
|
|
||||||
export async function GET(_: Request) {
|
export async function GET(_: Request) {
|
||||||
try {
|
const response = (await GetNezhaData()) as NezhaDataResponse;
|
||||||
const response = await GetNezhaData();
|
if (response.error) {
|
||||||
return NextResponse.json(response, { status: 200 });
|
console.log(response.error);
|
||||||
} catch (error) {
|
return NextResponse.json({ error: response.error }, { status: 400 });
|
||||||
console.error(error);
|
|
||||||
return NextResponse.json(
|
|
||||||
{ error: "fetch nezha data failed" },
|
|
||||||
{ status: 400 },
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
return NextResponse.json(response, { status: 200 });
|
||||||
}
|
}
|
||||||
|
|
||||||
async function GetNezhaData() {
|
async function GetNezhaData() {
|
||||||
|
@ -9,8 +9,9 @@ import {
|
|||||||
} from "@/components/ui/popover";
|
} from "@/components/ui/popover";
|
||||||
import { cn, formatNezhaInfo } from "@/lib/utils";
|
import { cn, formatNezhaInfo } from "@/lib/utils";
|
||||||
import ServerCardPopover from "./ServerCardPopover";
|
import ServerCardPopover from "./ServerCardPopover";
|
||||||
import getUnicodeFlagIcon from "country-flag-icons/unicode";
|
|
||||||
import { env } from "next-runtime-env";
|
import { env } from "next-runtime-env";
|
||||||
|
import ServerFlag from "./ServerFlag";
|
||||||
|
|
||||||
export default function ServerCard({
|
export default function ServerCard({
|
||||||
serverInfo,
|
serverInfo,
|
||||||
@ -32,15 +33,7 @@ export default function ServerCard({
|
|||||||
<Popover>
|
<Popover>
|
||||||
<PopoverTrigger asChild>
|
<PopoverTrigger asChild>
|
||||||
<section className={"flex items-center justify-start gap-2 lg:w-28"}>
|
<section className={"flex items-center justify-start gap-2 lg:w-28"}>
|
||||||
{showFlag ? (
|
{showFlag ? <ServerFlag country_code={country_code} /> : null}
|
||||||
country_code ? (
|
|
||||||
<span className="text-[12px] text-muted-foreground">
|
|
||||||
{getUnicodeFlagIcon(country_code)}
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<span className="text-[12px] text-muted-foreground">🏁</span>
|
|
||||||
)
|
|
||||||
) : null}
|
|
||||||
<p
|
<p
|
||||||
className={cn(
|
className={cn(
|
||||||
"break-all font-bold tracking-tight",
|
"break-all font-bold tracking-tight",
|
||||||
@ -58,8 +51,6 @@ export default function ServerCard({
|
|||||||
</Popover>
|
</Popover>
|
||||||
<section className={"grid grid-cols-5 items-center gap-3"}>
|
<section className={"grid grid-cols-5 items-center gap-3"}>
|
||||||
<div className={"flex w-14 flex-col"}>
|
<div className={"flex w-14 flex-col"}>
|
||||||
{" "}
|
|
||||||
{/* 设置固定宽度 */}
|
|
||||||
<p className="text-xs text-muted-foreground">{t("CPU")}</p>
|
<p className="text-xs text-muted-foreground">{t("CPU")}</p>
|
||||||
<div className="flex items-center text-xs font-semibold">
|
<div className="flex items-center text-xs font-semibold">
|
||||||
{cpu.toFixed(2)}%
|
{cpu.toFixed(2)}%
|
||||||
@ -67,8 +58,6 @@ export default function ServerCard({
|
|||||||
<ServerUsageBar value={cpu} />
|
<ServerUsageBar value={cpu} />
|
||||||
</div>
|
</div>
|
||||||
<div className={"flex w-14 flex-col"}>
|
<div className={"flex w-14 flex-col"}>
|
||||||
{" "}
|
|
||||||
{/* 设置固定宽度 */}
|
|
||||||
<p className="text-xs text-muted-foreground">{t("Mem")}</p>
|
<p className="text-xs text-muted-foreground">{t("Mem")}</p>
|
||||||
<div className="flex items-center text-xs font-semibold">
|
<div className="flex items-center text-xs font-semibold">
|
||||||
{mem.toFixed(2)}%
|
{mem.toFixed(2)}%
|
||||||
@ -76,8 +65,6 @@ export default function ServerCard({
|
|||||||
<ServerUsageBar value={mem} />
|
<ServerUsageBar value={mem} />
|
||||||
</div>
|
</div>
|
||||||
<div className={"flex w-14 flex-col"}>
|
<div className={"flex w-14 flex-col"}>
|
||||||
{" "}
|
|
||||||
{/* 设置固定宽度 */}
|
|
||||||
<p className="text-xs text-muted-foreground">{t("STG")}</p>
|
<p className="text-xs text-muted-foreground">{t("STG")}</p>
|
||||||
<div className="flex items-center text-xs font-semibold">
|
<div className="flex items-center text-xs font-semibold">
|
||||||
{stg.toFixed(2)}%
|
{stg.toFixed(2)}%
|
||||||
@ -85,8 +72,6 @@ export default function ServerCard({
|
|||||||
<ServerUsageBar value={stg} />
|
<ServerUsageBar value={stg} />
|
||||||
</div>
|
</div>
|
||||||
<div className={"flex w-14 flex-col"}>
|
<div className={"flex w-14 flex-col"}>
|
||||||
{" "}
|
|
||||||
{/* 设置固定宽度 */}
|
|
||||||
<p className="text-xs text-muted-foreground">{t("Upload")}</p>
|
<p className="text-xs text-muted-foreground">{t("Upload")}</p>
|
||||||
<div className="flex items-center text-xs font-semibold">
|
<div className="flex items-center text-xs font-semibold">
|
||||||
{up.toFixed(2)}
|
{up.toFixed(2)}
|
||||||
@ -94,8 +79,6 @@ export default function ServerCard({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={"flex w-14 flex-col"}>
|
<div className={"flex w-14 flex-col"}>
|
||||||
{" "}
|
|
||||||
{/* 设置固定宽度 */}
|
|
||||||
<p className="text-xs text-muted-foreground">{t("Download")}</p>
|
<p className="text-xs text-muted-foreground">{t("Download")}</p>
|
||||||
<div className="flex items-center text-xs font-semibold">
|
<div className="flex items-center text-xs font-semibold">
|
||||||
{down.toFixed(2)}
|
{down.toFixed(2)}
|
||||||
@ -113,15 +96,7 @@ export default function ServerCard({
|
|||||||
<Popover>
|
<Popover>
|
||||||
<PopoverTrigger asChild>
|
<PopoverTrigger asChild>
|
||||||
<section className={"flex items-center justify-start gap-2 lg:w-28"}>
|
<section className={"flex items-center justify-start gap-2 lg:w-28"}>
|
||||||
{showFlag ? (
|
{showFlag ? <ServerFlag country_code={country_code} /> : null}
|
||||||
country_code ? (
|
|
||||||
<span className="text-[12px] text-muted-foreground">
|
|
||||||
{getUnicodeFlagIcon(country_code)}
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<span className="text-[12px] text-muted-foreground">🏁</span>
|
|
||||||
)
|
|
||||||
) : null}
|
|
||||||
<p
|
<p
|
||||||
className={cn(
|
className={cn(
|
||||||
"break-all font-bold tracking-tight",
|
"break-all font-bold tracking-tight",
|
||||||
|
36
components/ServerFlag.tsx
Normal file
36
components/ServerFlag.tsx
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import getUnicodeFlagIcon from "country-flag-icons/unicode";
|
||||||
|
|
||||||
|
export default function ServerFlag({ country_code }: { country_code: string }) {
|
||||||
|
const [supportsEmojiFlags, setSupportsEmojiFlags] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const checkEmojiSupport = () => {
|
||||||
|
const canvas = document.createElement("canvas");
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
const emojiFlag = "🇺🇸"; // 使用美国国旗作为测试
|
||||||
|
if (!ctx) return;
|
||||||
|
ctx.fillStyle = "#000";
|
||||||
|
ctx.textBaseline = "top";
|
||||||
|
ctx.font = "32px Arial";
|
||||||
|
ctx.fillText(emojiFlag, 0, 0);
|
||||||
|
|
||||||
|
const support = ctx.getImageData(16, 16, 1, 1).data[3] !== 0;
|
||||||
|
setSupportsEmojiFlags(support);
|
||||||
|
};
|
||||||
|
|
||||||
|
checkEmojiSupport();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (!country_code) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span className="text-[12px] text-muted-foreground">
|
||||||
|
{!supportsEmojiFlags ? (
|
||||||
|
<span className={`fi fi-${country_code}`}></span>
|
||||||
|
) : (
|
||||||
|
getUnicodeFlagIcon(country_code)
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
NezhaBaseUrl=http://0.0.0.0:8008
|
NezhaBaseUrl=http://124.XX.XX.XX:8008
|
||||||
NezhaAuth=5hAY3QX6Nl9B3UOQgB26KdsdS1dsdUdM
|
NezhaAuth=your-nezha-api-token
|
||||||
ServerDisablePrefetch=false
|
DefaultLocale=zh
|
||||||
NEXT_PUBLIC_NezhaFetchInterval=5000
|
NEXT_PUBLIC_NezhaFetchInterval=5000
|
||||||
NEXT_PUBLIC_ShowFlag=true
|
NEXT_PUBLIC_ShowFlag=true
|
||||||
NEXT_PUBLIC_DisableCartoon=true
|
NEXT_PUBLIC_DisableCartoon=true
|
83
git-cliff-config/cliff.toml
Normal file
83
git-cliff-config/cliff.toml
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
# git-cliff ~ configuration file
|
||||||
|
# https://git-cliff.org/docs/configuration
|
||||||
|
#
|
||||||
|
# Lines starting with "#" are comments.
|
||||||
|
# Configuration options are organized into tables and keys.
|
||||||
|
# See documentation for more information on available options.
|
||||||
|
|
||||||
|
[changelog]
|
||||||
|
# changelog header
|
||||||
|
header = """
|
||||||
|
# Changelog\n
|
||||||
|
"""
|
||||||
|
# template for the changelog body
|
||||||
|
# https://tera.netlify.app/docs/
|
||||||
|
body = """
|
||||||
|
{% if version %}\
|
||||||
|
## Release {{ version | trim_start_matches(pat="v") }} - {{ timestamp | date(format="%Y-%m-%d") }}
|
||||||
|
{% else %}\
|
||||||
|
## [unreleased]
|
||||||
|
{% endif %}\
|
||||||
|
|
||||||
|
{% for group, commits in commits | group_by(attribute="group") %}
|
||||||
|
### {{ group | upper_first }}
|
||||||
|
{% for commit in commits %}
|
||||||
|
* {{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}]($REPO/commit/{{ commit.id }})) by [@{{ commit.author.name }}](https://github.com/{{ commit.author.name }})\
|
||||||
|
{% for footer in commit.footers -%}
|
||||||
|
, {{ footer.token }}{{ footer.separator }}{{ footer.value }}\
|
||||||
|
{% endfor %}\
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}\n
|
||||||
|
"""
|
||||||
|
# remove the leading and trailing whitespace from the template
|
||||||
|
trim = true
|
||||||
|
postprocessors = [
|
||||||
|
{ pattern = '\$REPO', replace = "https://github.com/hamster1963/nezha-dash" }, # replace repository URL
|
||||||
|
]
|
||||||
|
# changelog footer
|
||||||
|
footer = """
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
[git]
|
||||||
|
# parse the commits based on https://www.conventionalcommits.org
|
||||||
|
conventional_commits = true
|
||||||
|
# filter out the commits that are not conventional
|
||||||
|
filter_unconventional = true
|
||||||
|
# process each line of a commit as an individual commit
|
||||||
|
split_commits = true
|
||||||
|
# regex for preprocessing the commit messages
|
||||||
|
commit_preprocessors = [
|
||||||
|
{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](https://github.com/orhun/git-cliff/issues/${2}))" },
|
||||||
|
]
|
||||||
|
# regex for parsing and grouping commits
|
||||||
|
commit_parsers = [
|
||||||
|
{ message = "^feat", group = "<!-- 0 -->⛰️ Features" },
|
||||||
|
{ message = "^fix", group = "<!-- 1 -->🐛 Bug Fixes" },
|
||||||
|
{ message = "^doc", group = "<!-- 3 -->📚 Documentation" },
|
||||||
|
{ message = "^perf", group = "<!-- 4 -->⚡ Performance" },
|
||||||
|
{ message = "^refactor", group = "<!-- 2 -->🚜 Refactor" },
|
||||||
|
{ message = "^style", group = "<!-- 5 -->🎨 Styling" },
|
||||||
|
{ message = "^test", group = "<!-- 6 -->🧪 Testing" },
|
||||||
|
{ message = "^chore\\(release\\): prepare for", skip = true },
|
||||||
|
{ message = "^chore\\(pr\\)", skip = true },
|
||||||
|
{ message = "^chore\\(pull\\)", skip = true },
|
||||||
|
{ message = "^chore", group = "<!-- 7 -->⚙️ Miscellaneous Tasks" },
|
||||||
|
{ body = ".*security", group = "<!-- 8 -->🛡️ Security" },
|
||||||
|
{ message = "^update", group = "<!-- 9 -->🔼 Updates" },
|
||||||
|
{ message = "^delete", group = "<!-- 10 -->🔞 Delete" },
|
||||||
|
]
|
||||||
|
# protect breaking changes from being skipped due to matching a skipping commit_parser
|
||||||
|
protect_breaking_commits = false
|
||||||
|
# filter out the commits that are not matched by commit parsers
|
||||||
|
filter_commits = false
|
||||||
|
# glob pattern for matching git tags
|
||||||
|
tag_pattern = "v[0-20]*"
|
||||||
|
# regex for skipping tags
|
||||||
|
skip_tags = ""
|
||||||
|
# regex for ignoring tags
|
||||||
|
ignore_tags = "v.*-beta.*"
|
||||||
|
# sort the tags topologically
|
||||||
|
topo_order = false
|
||||||
|
# sort the commits inside sections by oldest/newest order
|
||||||
|
sort_commits = "oldest"
|
@ -1,5 +1,7 @@
|
|||||||
// @auto-i18n-check. Please do not delete the line.
|
// @auto-i18n-check. Please do not delete the line.
|
||||||
|
|
||||||
|
import getEnv from "./lib/env-entry";
|
||||||
|
|
||||||
export const localeItems = [
|
export const localeItems = [
|
||||||
{ code: "en", name: "English" },
|
{ code: "en", name: "English" },
|
||||||
{ code: "ja", name: "日本語" },
|
{ code: "ja", name: "日本語" },
|
||||||
@ -21,4 +23,4 @@ export const localeItems = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const locales = localeItems.map((item) => item.code);
|
export const locales = localeItems.map((item) => item.code);
|
||||||
export const defaultLocale = "en";
|
export const defaultLocale = getEnv("DefaultLocale") || "en";
|
||||||
|
@ -10,8 +10,8 @@ export async function GetNezhaData() {
|
|||||||
|
|
||||||
var nezhaBaseUrl = getEnv("NezhaBaseUrl");
|
var nezhaBaseUrl = getEnv("NezhaBaseUrl");
|
||||||
if (!nezhaBaseUrl) {
|
if (!nezhaBaseUrl) {
|
||||||
console.error("NezhaBaseUrl is not set");
|
console.log("NezhaBaseUrl is not set");
|
||||||
throw new Error("NezhaBaseUrl is not set");
|
return { error: "NezhaBaseUrl is not set" };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove trailing slash
|
// Remove trailing slash
|
||||||
@ -27,7 +27,12 @@ export async function GetNezhaData() {
|
|||||||
revalidate: 0,
|
revalidate: 0,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const nezhaData = (await response.json()).result as NezhaAPI[];
|
const resData = await response.json();
|
||||||
|
const nezhaData = resData.result as NezhaAPI[];
|
||||||
|
if (!nezhaData) {
|
||||||
|
console.log(resData);
|
||||||
|
return { error: "NezhaData fetch failed" };
|
||||||
|
}
|
||||||
const data: ServerApi = {
|
const data: ServerApi = {
|
||||||
live_servers: 0,
|
live_servers: 0,
|
||||||
offline_servers: 0,
|
offline_servers: 0,
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
// @auto-i18n-check. Please do not delete the line.
|
// @auto-i18n-check. Please do not delete the line.
|
||||||
|
|
||||||
import createMiddleware from "next-intl/middleware";
|
import createMiddleware from "next-intl/middleware";
|
||||||
import { locales } from "./i18n-metadata";
|
import { defaultLocale, locales } from "./i18n-metadata";
|
||||||
|
|
||||||
export default createMiddleware({
|
export default createMiddleware({
|
||||||
// A list of all locales that are supported
|
// A list of all locales that are supported
|
||||||
locales: locales,
|
locales: locales,
|
||||||
|
|
||||||
// Used when no locale matches
|
// Used when no locale matches
|
||||||
defaultLocale: "en",
|
defaultLocale: defaultLocale,
|
||||||
|
|
||||||
// 'always': This is the default, The home page will also be redirected to the default language, such as www.abc.com to www.abc.com/en
|
// 'always': This is the default, The home page will also be redirected to the default language, such as www.abc.com to www.abc.com/en
|
||||||
// 'as-needed': The default page is not redirected. For example, if you open www.abc.com, it is still www.abc.com
|
// 'as-needed': The default page is not redirected. For example, if you open www.abc.com, it is still www.abc.com
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
import withBundleAnalyzer from "@next/bundle-analyzer";
|
||||||
|
|
||||||
|
const bundleAnalyzer = withBundleAnalyzer({
|
||||||
|
enabled: process.env.ANALYZE === "true",
|
||||||
|
});
|
||||||
|
|
||||||
import createNextIntlPlugin from "next-intl/plugin";
|
import createNextIntlPlugin from "next-intl/plugin";
|
||||||
const withNextIntl = createNextIntlPlugin();
|
const withNextIntl = createNextIntlPlugin();
|
||||||
import withPWAInit from "@ducanh2912/next-pwa";
|
import withPWAInit from "@ducanh2912/next-pwa";
|
||||||
@ -16,5 +22,10 @@ const withPWA = withPWAInit({
|
|||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
output: "standalone",
|
output: "standalone",
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
|
logging: {
|
||||||
|
fetches: {
|
||||||
|
fullUrl: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
export default withPWA(withNextIntl(nextConfig));
|
export default bundleAnalyzer(withPWA(withNextIntl(nextConfig)));
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"country-flag-icons": "^1.5.13",
|
"country-flag-icons": "^1.5.13",
|
||||||
"eslint-plugin-simple-import-sort": "^12.1.1",
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
||||||
|
"flag-icons": "^7.2.3",
|
||||||
"lucide-react": "^0.414.0",
|
"lucide-react": "^0.414.0",
|
||||||
"luxon": "^3.5.0",
|
"luxon": "^3.5.0",
|
||||||
"next": "^14.2.13",
|
"next": "^14.2.13",
|
||||||
@ -47,8 +48,8 @@
|
|||||||
"eslint-plugin-turbo": "^2.1.2",
|
"eslint-plugin-turbo": "^2.1.2",
|
||||||
"eslint-plugin-unused-imports": "^4.1.4",
|
"eslint-plugin-unused-imports": "^4.1.4",
|
||||||
"@next/bundle-analyzer": "^14.2.13",
|
"@next/bundle-analyzer": "^14.2.13",
|
||||||
"@types/node": "^22.7.2",
|
"@types/node": "^22.7.4",
|
||||||
"@types/react": "^18.3.9",
|
"@types/react": "^18.3.10",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"eslint": "^9.11.1",
|
"eslint": "^9.11.1",
|
||||||
|
Loading…
Reference in New Issue
Block a user