working download and blog
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import Footer from "@/components/Footer";
|
||||
import Header from "@/components/Header";
|
||||
import listNews from "@/lib/news";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
|
||||
export default function Download() {
|
||||
return (
|
||||
<div className="flex-1 flex flex-col h-screen">
|
||||
<div className="flex flex-col bg-[url('/background.png')] bg-center bg-no-repeat h-52">
|
||||
<Header />
|
||||
|
||||
<h1 className="text-5xl font-black m-auto w-max font-['Panton']">
|
||||
DOWNLOAD
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div className="w-full h-full flex flex-col items-center pt-6">
|
||||
Release downloads aren't available yet :(
|
||||
<Link
|
||||
href="https://github.com/saturnclientmc/saturnclient/releases/"
|
||||
target="_blank"
|
||||
className="hover:cursor-pointer mt-10 relative bg-red border text-white py-4 px-6 rounded-xl backdrop-blur-xs w-max group transition-colors duration-300 hover:text-[#e2bf7d] animate-fadeIn"
|
||||
>
|
||||
Download on GitHub
|
||||
</Link>
|
||||
<div className="flex flex-col items-center mt-4 gap-2">
|
||||
<p>Step 1: Download the latest release from GitHub</p>
|
||||
<p>Step 2: Locate your Minecraft mods folder (fabric required)</p>
|
||||
<p>Step 3: Place the downloaded release into the mods folder</p>
|
||||
<p>
|
||||
Step 4: Launch the game on the official minecraft launcher (fabric)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
h1 {
|
||||
font-size: xx-large;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: x-large;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: medium;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: disc;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
ol {
|
||||
list-style-type: decimal;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
img {
|
||||
border-radius: 10px;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import Markdown from "react-markdown";
|
||||
import "./Markdown.css";
|
||||
|
||||
export default function Md({ children }: { children: string }) {
|
||||
return <Markdown>{children}</Markdown>;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import { readFileSync } from "fs";
|
||||
import smartSplit from "@/lib/smartSplit";
|
||||
import { parseNews } from "@/lib/news";
|
||||
import Header from "@/components/Header";
|
||||
import Footer from "@/components/Footer";
|
||||
import Md from "./Markdown";
|
||||
|
||||
export default async function News({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ id: string }>;
|
||||
}) {
|
||||
const contents = readFileSync(`news/${(await params).id}.md`, "utf-8");
|
||||
|
||||
const { authors, title, description, image, date } = parseNews(
|
||||
contents,
|
||||
(await params).id
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
className="bg-[url('/background.png')] bg-center bg-no-repeat h-96"
|
||||
style={{ backgroundImage: `url(${image})` }}
|
||||
>
|
||||
<Header />
|
||||
|
||||
<h1 className="font-black m-auto w-max font-['Panton'] !text-5xl mt-14">
|
||||
{title}
|
||||
</h1>
|
||||
|
||||
<p className="m-auto w-max font-['Panton'] !text-2xl mt-5">
|
||||
{description}
|
||||
</p>
|
||||
<p className="m-auto w-max font-['Panton'] !text-xl">
|
||||
written by {authors.join(", ")}
|
||||
</p>
|
||||
</div>
|
||||
<div className="w-[54rem] mx-auto mt-10">
|
||||
<div className="rounded-2xl bg-[#111] p-5 markdown">
|
||||
<Md>{smartSplit(contents, "---", 3)[2]}</Md>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+11
-8
@@ -1,5 +1,6 @@
|
||||
import Footer from "@/components/Footer";
|
||||
import Header from "@/components/Header";
|
||||
import listNews from "@/lib/news";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
|
||||
@@ -14,14 +15,16 @@ import Link from "next/link";
|
||||
// },
|
||||
// ];
|
||||
|
||||
const newsList = Array(3 * 6).fill({
|
||||
authors: [],
|
||||
title: "Hello World",
|
||||
description: "lorem ipsum ipsum lorem",
|
||||
image: "/background.png",
|
||||
date: "2025-04-16",
|
||||
id: "",
|
||||
});
|
||||
// const newsList = Array(3 * 6).fill({
|
||||
// authors: [],
|
||||
// title: "Hello World",
|
||||
// description: "lorem ipsum ipsum lorem",
|
||||
// image: "/background.png",
|
||||
// date: "2025-04-16",
|
||||
// id: "",
|
||||
// });
|
||||
|
||||
const newsList = listNews();
|
||||
|
||||
export default function News() {
|
||||
return (
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import { readdirSync, readFileSync } from "fs";
|
||||
|
||||
export interface News {
|
||||
authors: string[];
|
||||
title: string;
|
||||
description: string;
|
||||
image: string;
|
||||
date: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export function parseNews(news: string, id: string): News {
|
||||
const content = news.split("---", 2)[1];
|
||||
|
||||
const params: News = {
|
||||
authors: [],
|
||||
title: "Undefined title",
|
||||
description: "",
|
||||
image: "/background.png",
|
||||
date: "Undefined date",
|
||||
id,
|
||||
};
|
||||
|
||||
content.split("\n").forEach((v) => {
|
||||
const [key, value] = v.split(":").map((v) => v.trim());
|
||||
if (key === "authors") {
|
||||
params.authors = value.split(",").map((v) => v.trim());
|
||||
} else if (
|
||||
key === "title" ||
|
||||
key === "description" ||
|
||||
key === "image" ||
|
||||
key === "date"
|
||||
) {
|
||||
params[key] = value;
|
||||
}
|
||||
});
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
export default function listNews(): News[] {
|
||||
const newsIdList = readdirSync("news");
|
||||
|
||||
if (newsIdList === null) return [];
|
||||
|
||||
return newsIdList.map((v) => {
|
||||
return parseNews(
|
||||
readFileSync(`news/${v}`, "utf-8"),
|
||||
v.replaceAll(".md", "")
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
export default function smartSplit(
|
||||
str: string,
|
||||
separator: string,
|
||||
limit: number
|
||||
) {
|
||||
const parts = str.split(separator);
|
||||
if (parts.length <= limit) return parts;
|
||||
|
||||
const head = parts.slice(0, limit - 1);
|
||||
const tail = parts.slice(limit - 1).join(separator);
|
||||
return [...head, tail];
|
||||
}
|
||||
Reference in New Issue
Block a user