aboutsummaryrefslogtreecommitdiff
path: root/www-2/src
diff options
context:
space:
mode:
authorYuqian Yang <crupest@crupest.life>2026-01-23 23:16:45 +0800
committerYuqian Yang <crupest@crupest.life>2026-01-23 23:16:45 +0800
commit78e3e234877cb10ca1088df31e831b36fa4a12c0 (patch)
treea4b86275895b33d47df4686e5ce8f98b57016f90 /www-2/src
parent3af5ef00b38c6962c6e3f63add0312fa6537b74b (diff)
downloadcrupest-78e3e234877cb10ca1088df31e831b36fa4a12c0.tar.gz
crupest-78e3e234877cb10ca1088df31e831b36fa4a12c0.tar.bz2
crupest-78e3e234877cb10ca1088df31e831b36fa4a12c0.zip
HALF WORK!
Diffstat (limited to 'www-2/src')
-rw-r--r--www-2/src/assets/css/todos.css17
-rw-r--r--www-2/src/assets/img/github.pngbin0 -> 6393 bytes
-rw-r--r--www-2/src/components/ArticlePreview.astro68
-rw-r--r--www-2/src/components/Friend.astro49
-rw-r--r--www-2/src/components/Nav.astro23
-rw-r--r--www-2/src/content.config.ts17
-rw-r--r--www-2/src/layouts/ArticlePage.astro50
-rw-r--r--www-2/src/layouts/PageBase.astro181
-rw-r--r--www-2/src/pages/[...id].astro18
-rw-r--r--www-2/src/pages/index.astro124
10 files changed, 547 insertions, 0 deletions
diff --git a/www-2/src/assets/css/todos.css b/www-2/src/assets/css/todos.css
new file mode 100644
index 0000000..f9aa23b
--- /dev/null
+++ b/www-2/src/assets/css/todos.css
@@ -0,0 +1,17 @@
+h3.todo {
+ &::before {
+ font-size: small;
+ }
+
+ &.working::before {
+ content: "(working) ";
+ }
+
+ &.done::before {
+ content: "(done) ";
+ }
+
+ &.give-up::before {
+ content: "(give up) ";
+ }
+}
diff --git a/www-2/src/assets/img/github.png b/www-2/src/assets/img/github.png
new file mode 100644
index 0000000..6cb3b70
--- /dev/null
+++ b/www-2/src/assets/img/github.png
Binary files differ
diff --git a/www-2/src/components/ArticlePreview.astro b/www-2/src/components/ArticlePreview.astro
new file mode 100644
index 0000000..3301ad2
--- /dev/null
+++ b/www-2/src/components/ArticlePreview.astro
@@ -0,0 +1,68 @@
+---
+interface Props {
+ title: string;
+ date: string;
+ url: string;
+ content: string;
+ headerElement?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "h7";
+}
+
+const { title, date, url, content, headerElement = "h2" } = Astro.props;
+const H = headerElement;
+---
+
+<section class="article-preview">
+ <span class="date">{date}</span>
+ <H class="title"><a href={url}>{title}</a></H>
+ <p class="content">
+ {content}
+ </p>
+ <p>... <a class="mono-link" href="{{ .link }}">Read more</a></p>
+</section>
+
+<style>
+ .article-preview {
+ font-size: 0.95em;
+ padding-inline: 0.5em;
+ padding-block: 0.5em;
+
+ & > p {
+ font-size: 0.9em;
+ line-height: 1.4;
+ margin-inline-start: 0.3em;
+ margin-block: 0;
+ }
+
+ & > .title {
+ margin-block-start: 0;
+ margin-block-end: 0.3em;
+ }
+
+ & > .date {
+ font-size: small;
+ margin-top: 0.25em;
+ float: right;
+ color: hsl(0, 0%, 25%);
+ }
+
+ & > .content {
+ overflow: hidden;
+ height: 3lh;
+ }
+ }
+
+ html[data-theme="dark"] {
+ & .article-preview {
+ background-color: hsl(0, 0%, 3%);
+
+ & > .date {
+ color: hsl(0, 0%, 75%);
+ }
+ }
+ }
+
+ hr.article-preview-hr {
+ border: none;
+ border-top: 1.5px dashed currentColor;
+ }
+</style>
diff --git a/www-2/src/components/Friend.astro b/www-2/src/components/Friend.astro
new file mode 100644
index 0000000..d0de0ab
--- /dev/null
+++ b/www-2/src/components/Friend.astro
@@ -0,0 +1,49 @@
+---
+import githubIcon from "../assets/img/github.png";
+
+interface Props {
+ name: string;
+ url?: string;
+ githubUrl: string;
+ avatarUrl: string;
+ tag?: string;
+}
+
+const { name, githubUrl, url = githubUrl, avatarUrl, tag } = Astro.props;
+---
+
+<div class="friend">
+ <a rel="noopener noreferrer" href={url}>
+ <img
+ class="friend-avatar"
+ alt={`Friend ${name}'s avatar`}
+ src={avatarUrl}
+ width="80"
+ height="80"
+ /><br />{name}</a
+ >
+ <a rel="noopener noreferrer" href={githubUrl}>
+ <img class="friend-github" src={githubIcon.src} />
+ </a><br />
+ {tag && <span class="friend-tag">{tag}</span>}
+</div>
+
+<style>
+.friend a {
+ font-family: unset;
+}
+
+.friend-avatar {
+ object-fit: cover;
+}
+
+.friend-github {
+ width: 1em;
+ vertical-align: middle;
+ margin-right: -0.5em;
+}
+
+.friend-tag {
+ font-size: 0.8em;
+}
+</style> \ No newline at end of file
diff --git a/www-2/src/components/Nav.astro b/www-2/src/components/Nav.astro
new file mode 100644
index 0000000..f62a9dc
--- /dev/null
+++ b/www-2/src/components/Nav.astro
@@ -0,0 +1,23 @@
+---
+
+let path = Astro.url.pathname
+if (path.startsWith("/")) { path = path.slice(1)}
+if (path.endsWith("/")) { path = path.slice(0, -1)}
+const segments = path.split("/").slice(0, -1);
+const sections: {name: string; link: string;}[] = []
+let current = "/"
+for (const segment of segments) {
+ current += segment + "/";
+ sections.push({
+ name: segment,
+ link: current
+ })
+}
+
+---
+<nav class="mono">
+ { sections.map(s =>
+ <><a class="mono-link" href={s.link}>{s.name}</a> ></>)
+ }
+ this
+</nav>
diff --git a/www-2/src/content.config.ts b/www-2/src/content.config.ts
new file mode 100644
index 0000000..f309aa5
--- /dev/null
+++ b/www-2/src/content.config.ts
@@ -0,0 +1,17 @@
+import { defineCollection } from "astro:content";
+import { glob } from "astro/loaders";
+import { z } from "astro/zod";
+
+const blogs = defineCollection({
+ loader: glob({ pattern: "**/*.md", base: "./content" }),
+ schema: z.object({
+ title: z.string(),
+ description: z.string().optional(),
+ date: z.coerce.date(),
+ lastmod: z.coerce.date().optional(),
+ categories: z.string().optional(),
+ tags: z.array(z.string()).optional(),
+ }),
+});
+
+export const collections = { blogs };
diff --git a/www-2/src/layouts/ArticlePage.astro b/www-2/src/layouts/ArticlePage.astro
new file mode 100644
index 0000000..b6ea5d0
--- /dev/null
+++ b/www-2/src/layouts/ArticlePage.astro
@@ -0,0 +1,50 @@
+---
+import PageBase from "./PageBase.astro";
+import Nav from "../components/Nav.astro";
+
+interface Props {
+ id: string;
+ data: {
+ title: string;
+ date: Date;
+ lastmod?: Date;
+ };
+}
+
+const {
+ id,
+ data: { title, date, lastmod },
+} = Astro.props;
+---
+
+<PageBase>
+ <Nav />
+ <h1 class="post-title">{title}</h1>
+ <hr />
+ <p class="post-info">
+ <span class="created">{date.toLocaleString()}</span> |
+ {
+ lastmod && (
+ <span class="last-updated">
+ Last updated: {lastmod.toLocaleString()}
+ </span>
+ )
+ }
+ </p>
+ <slot />
+</PageBase>
+
+<style>
+ .post-info {
+ margin-block: 0;
+ font-family: monospace;
+ font-size: 0.95em;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 1em;
+
+ & > .created {
+ margin-inline-end: auto;
+ }
+ }
+</style>
diff --git a/www-2/src/layouts/PageBase.astro b/www-2/src/layouts/PageBase.astro
new file mode 100644
index 0000000..e6e0e1e
--- /dev/null
+++ b/www-2/src/layouts/PageBase.astro
@@ -0,0 +1,181 @@
+<!doctype html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="viewport" content="width=device-width" />
+ <link rel="icon" href="/favicon.ico" />
+ <meta name="generator" content={Astro.generator} />
+ <title>Astro Basics</title>
+ </head>
+ <body>
+ <article id="main-article">
+ <slot />
+ <hr />
+ <footer class="mono-link">
+ <p id="license">
+ <small
+ >This work is licensed under
+ <a
+ rel="license noopener noreferrer"
+ href="https://creativecommons.org/licenses/by-nc/4.0/"
+ target="_blank"
+ >
+ <span id="license-text">CC BY-NC 4.0</span>
+ <span id="license-img-container">
+ <img
+ src="https://mirrors.creativecommons.org/presskit/icons/cc.svg"
+ />
+ <img
+ src="https://mirrors.creativecommons.org/presskit/icons/by.svg"
+ />
+ <img
+ src="https://mirrors.creativecommons.org/presskit/icons/nc.svg"
+ />
+ </span>
+ </a>
+ </small>
+ </p>
+ </footer>
+ </article>
+ </body>
+</html>
+
+<style is:global>
+html {
+ width: 100%;
+ --body-fg-color: unset;
+ --body-bg-color: unset;
+ --table-border-color: black;
+ --toast-fg-color: white;
+ --toast-bg-color: black;
+ --code-fg-color: var(--body-fg-color);
+ --code-bg-color: #eff1f5;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+body {
+ width: 100%;
+ margin: 0;
+ color: var(--body-fg-color);
+ background-color: var(--body-bg-color);
+}
+
+/* https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/Heading_Elements#specifying_a_uniform_font_size_for_h1 */
+h1 {
+ margin-block: 0.67em;
+ font-size: 2em;
+}
+
+.mono {
+ font-family: monospace;
+}
+
+a.mono-link,
+.mono-link a,
+.mono-link .fake-link {
+ font-family: monospace;
+}
+
+div.mono-container {
+ font-family: monospace;
+ margin-block: 1rem;
+}
+
+table {
+ border-collapse: collapse;
+
+ &, :is(td,th) {
+ padding: 0.2em 0.4em;
+ border: 1px solid var(--table-border-color);
+ }
+}
+
+.toast {
+ font-size: large;
+ font-family: monospace;
+ color: var(--toast-fg-color);
+ background-color: var(--toast-bg-color);
+ padding: 0.5em 0.3em;
+ border-radius: 6px;
+
+ position: fixed;
+ z-index: 1;
+ top: 4px;
+ left: 50vw;
+ transform: translateX(-50%);
+}
+
+.chroma {
+ overflow-x: auto;
+ padding-left: 1px;
+ padding-right: 4px;
+ border-radius: 6px;
+}
+
+nav {
+ font-size: large;
+}
+
+#main-article {
+ position: relative;
+ left: 50%;
+ transform: translateX(-50%);
+ max-width: 880px;
+ padding: 0 1em;
+ margin-top: 1em;
+}
+
+#license a {
+ font-family: initial;
+ text-decoration: none;
+}
+
+#license-text {
+ font-family: monospace;
+ text-decoration: initial;
+}
+
+#license-img-container img {
+ height: 1em;
+ vertical-align: middle;
+}
+
+.link-group {
+ margin-block-end: 1em;
+
+ > .link-group-title {
+ font-size: 1.1em;
+ margin-block-end: 5px;
+ }
+
+ > .link-group-list {
+ border-inline-start: solid 1px hsl(0, 0%, 25%);
+ padding-inline-start: 8px;
+
+ > .link-group-item::before {
+ content: "- ";
+ }
+ }
+}
+
+html[data-theme="dark"] {
+ --body-fg-color: white;
+ --body-bg-color: black;
+ --table-border-color: hsl(0, 0%, 25%);
+ --toast-fg-color: var(--body-bg-color);
+ --toast-bg-color: var(--body-fg-color);
+ --code-bg-color: #1e1e2e;
+
+ & a:link {
+ color:#34ffd9;
+ }
+
+ & a:visited {
+ color:#abcac4;
+ }
+}
+
+</style>
diff --git a/www-2/src/pages/[...id].astro b/www-2/src/pages/[...id].astro
new file mode 100644
index 0000000..b3c5b40
--- /dev/null
+++ b/www-2/src/pages/[...id].astro
@@ -0,0 +1,18 @@
+---
+import { getCollection, render } from "astro:content";
+
+import ArticlePage from "../layouts/ArticlePage.astro";
+
+export async function getStaticPaths() {
+ const posts = await getCollection("blogs");
+ return posts.map((post) => ({
+ params: { id: post.id },
+ props: { post },
+ }));
+}
+
+const { post } = Astro.props;
+const { Content } = await render(post);
+---
+
+<ArticlePage id={post.id} data={post.data}><Content /></ArticlePage>
diff --git a/www-2/src/pages/index.astro b/www-2/src/pages/index.astro
new file mode 100644
index 0000000..4007037
--- /dev/null
+++ b/www-2/src/pages/index.astro
@@ -0,0 +1,124 @@
+---
+import { getCollection, render } from "astro:content";
+
+import PageBase from "../layouts/PageBase.astro";
+import Friend from "../components/Friend.astro";
+import ArticlePreview from "../components/ArticlePreview.astro";
+
+const posts = (
+ await getCollection("blogs", ({ id }) => id.startsWith("posts/"))
+).slice(0, 3);
+---
+
+<PageBase>
+ <img id="avatar" src="/avatar.png" alt="My avatar" width="80" height="80" />
+ <h1 id="title">Hello! This is <code>crupest</code> !</h1>
+ <hr />
+ <section>
+ <p>Welcome to my home page! Nice to meet you here! 🥰</p>
+ <p>
+ Feel free to contact me via my email address <a
+ href="mailto:crupest@crupest.life">crupest@crupest.life</a
+ >, or just create an issue in any of my <a
+ rel="noopener noreferrer"
+ href="https://github.com/crupest">GitHub</a
+ >
+ repos. I love talking with people a lot.
+ </p>
+ <div id="links" class="mono-link">
+ goto:
+ <ul>
+ <li><a href="/git/">git</a></li>
+ <li><a href="/notes/">notes</a></li>
+ <li><a href="/notes/hurd">hurd</a></li>
+ <li><a href="/notes/cheat-sheet">cheat-sheet</a></li>
+ </ul>
+ </div>
+ </section>
+ <hr />
+ <section id="recent-posts">
+ <h2>Recent Posts <a class="mono-link" href="/posts">(all)</a></h2>
+ {
+ posts.map((post) => (
+ <ArticlePreview
+ title={post.data.title}
+ date={post.data.date.toLocaleString()}
+ url={"/posts/" + post.id}
+ content=""
+ />
+ ))
+ }
+ </section>
+ <hr />
+ <section>
+ <h2 id="friends">
+ My Friends <small>(more links are being collected ...)</small>
+ </h2>
+ <div id="friends-container">
+ <Friend
+ name="wsm"
+ avatarUrl="https://avatars.githubusercontent.com/u/74699943?v=4"
+ githubUrl="wushuming666"
+ />
+ <Friend
+ name="hsz"
+ url="https://www.hszsoft.com"
+ avatarUrl="https://avatars.githubusercontent.com/u/63097618?v=4"
+ githubUrl="hszSoft"
+ tag="随性の程序员"
+ />
+ </div>
+ </section>
+</PageBase>
+
+<style>
+ #avatar {
+ float: right;
+ }
+
+ #links {
+ font-family: monospace;
+
+ margin-block-end: 1rem;
+
+ > ul {
+ display: inline;
+ padding-inline-start: 0.5em;
+ > li {
+ display: inline;
+
+ &::after {
+ content: " | ";
+ }
+ }
+ }
+ }
+
+ #recent-posts {
+ margin-block-end: 1.5em;
+ }
+
+ #friends-container {
+ display: flex;
+ gap: 1em;
+ }
+
+ .friend {
+ flex-grow: 0;
+ text-align: center;
+ }
+
+ .citation {
+ margin: auto;
+ }
+
+ .citation figcaption {
+ text-align: right;
+ }
+
+ html[data-theme="dark"] {
+ & .friend-github {
+ filter: invert(1);
+ }
+ }
+</style>