Skip to content

Commit 1e76d58

Browse files
committed
mostly complete
1 parent 03f411e commit 1e76d58

File tree

26 files changed

+530
-262
lines changed

26 files changed

+530
-262
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ bun install --frozen-lockfile
2222

2323
style more
2424
a11y <https://astro.build/integrations/2/?search=&categories%5B%5D=performance%2Bseo&categories%5B%5D=accessibility>
25-
pagination https://code.vool.jp/blog/astro-pagination/
25+
pagination
26+
27+
- https://code.vool.jp/blog/astro-pagination/
28+
- https://docs.astro.build/en/guides/routing/#pagination
2629

2730
## 開発
2831

bun.lock

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@
99
"@iconify-json/feather": "^1.2.1",
1010
"@mdx-js/react": "^3.1.0",
1111
"@tailwindcss/typography": "^0.5.16",
12+
"@types/html-to-text": "^9.0.4",
1213
"astro": "^5.4.2",
1314
"astro-icon": "^1.1.5",
15+
"bits-ui": "^1.3.8",
1416
"color": "^5.0.0",
1517
"date-fns": "^4.1.0",
18+
"markdown-to-txt": "^2.0.1",
1619
"nullthrows": "^1.1.1",
1720
"prismjs": "^1.29.0",
1821
"react": "^19.0.0",
@@ -197,6 +200,8 @@
197200

198201
"@img/sharp-win32-x64": ["@img/[email protected]", "", { "os": "win32", "cpu": "x64" }, "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg=="],
199202

203+
"@internationalized/date": ["@internationalized/[email protected]", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-VJ5WS3fcVx0bejE/YHfbDKR/yawZgKqn/if+oEeLqNwBtPzVB06olkfcnojTmEMX+gTpH+FlQ69SHNitJ8/erQ=="],
204+
200205
"@jridgewell/gen-mapping": ["@jridgewell/[email protected]", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="],
201206

202207
"@jridgewell/resolve-uri": ["@jridgewell/[email protected]", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
@@ -345,6 +350,8 @@
345350

346351
"@types/hast": ["@types/[email protected]", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="],
347352

353+
"@types/html-to-text": ["@types/[email protected]", "", {}, "sha512-pUY3cKH/Nm2yYrEmDlPR1mR7yszjGx4DrwPjQ702C4/D5CwHuZTgZdIdwPkRbcuhs7BAh2L5rg3CL5cbRiGTCQ=="],
354+
348355
"@types/mdast": ["@types/[email protected]", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="],
349356

350357
"@types/mdx": ["@types/[email protected]", "", {}, "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw=="],
@@ -419,6 +426,8 @@
419426

420427
"base-64": ["[email protected]", "", {}, "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg=="],
421428

429+
"bits-ui": ["[email protected]", "", { "dependencies": { "@floating-ui/core": "^1.6.4", "@floating-ui/dom": "^1.6.7", "@internationalized/date": "^3.5.6", "esm-env": "^1.1.2", "runed": "^0.23.2", "svelte-toolbelt": "^0.7.1", "tabbable": "^6.2.0" }, "peerDependencies": { "svelte": "^5.11.0" } }, "sha512-vmj0uQQqh7sEw5La4CXKjMszcDHeEwjUX5Q4/cX3UZ2aTY/HTEaMK5cJyCfA+2yMO7YNCx5mIM/THgFvphHt2w=="],
430+
422431
"boolbase": ["[email protected]", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="],
423432

424433
"boxen": ["[email protected]", "", { "dependencies": { "ansi-align": "^3.0.1", "camelcase": "^8.0.0", "chalk": "^5.3.0", "cli-boxes": "^3.0.0", "string-width": "^7.2.0", "type-fest": "^4.21.0", "widest-line": "^5.0.0", "wrap-ansi": "^9.0.0" } }, "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw=="],
@@ -795,10 +804,14 @@
795804

796805
"lodash.castarray": ["[email protected]", "", {}, "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q=="],
797806

807+
"lodash.escape": ["[email protected]", "", {}, "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw=="],
808+
798809
"lodash.isplainobject": ["[email protected]", "", {}, "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="],
799810

800811
"lodash.merge": ["[email protected]", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
801812

813+
"lodash.unescape": ["[email protected]", "", {}, "sha512-DhhGRshNS1aX6s5YdBE3njCCouPgnG29ebyHvImlZzXZf2SHgt+J08DHgytTPnpywNbO1Y8mNUFyQuIDBq2JZg=="],
814+
802815
"longest-streak": ["[email protected]", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
803816

804817
"lru-cache": ["[email protected]", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
@@ -811,6 +824,10 @@
811824

812825
"markdown-table": ["[email protected]", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="],
813826

827+
"markdown-to-txt": ["[email protected]", "", { "dependencies": { "lodash.escape": "^4.0.1", "lodash.unescape": "^4.0.1", "marked": "^4.0.14" } }, "sha512-Hsj7KTN8k1gutlLum3vosHwVZGnv8/cbYKWVkUyo/D1rzOYddbDesILebRfOsaVfjIBJank/AVOySBlHAYqfZw=="],
828+
829+
"marked": ["[email protected]", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A=="],
830+
814831
"math-intrinsics": ["[email protected]", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
815832

816833
"mdast-util-definitions": ["[email protected]", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ=="],
@@ -1101,6 +1118,8 @@
11011118

11021119
"run-parallel": ["[email protected]", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
11031120

1121+
"runed": ["[email protected]", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-9q8oUiBYeXIDLWNK5DfCWlkL0EW3oGbk845VdKlPeia28l751VpfesaB/+7pI6rnbx1I6rqoZ2fZxptOJLxILA=="],
1122+
11041123
"s.color": ["[email protected]", "", {}, "sha512-AUNrbEUHeKY8XsYr/DYpl+qk5+aM+DChopnWOPEzn8YKzOhv4l2zH6LzZms3tOZP3wwdOyc0RmTciyi46HLIuA=="],
11051124

11061125
"safer-buffer": ["[email protected]", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
@@ -1147,6 +1166,8 @@
11471166

11481167
"svelte": ["[email protected]", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", "acorn": "^8.12.1", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "esm-env": "^1.2.1", "esrap": "^1.4.3", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-dxHyh3USJyayafSt5I5QD7KuoCM5ZGdIOtLQiKHEro7tymdh0jMcNkiSBVHW+LOA2jEqZEHhyfwN6/pCjx0Fug=="],
11491168

1169+
"svelte-toolbelt": ["[email protected]", "", { "dependencies": { "clsx": "^2.1.1", "runed": "^0.23.2", "style-to-object": "^1.0.8" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-HcBOcR17Vx9bjaOceUvxkY3nGmbBmCBBbuWLLEWO6jtmWH8f/QoWmbyUfQZrpDINH39en1b8mptfPQT9VKQ1xQ=="],
1170+
11501171
"svgo": ["[email protected]", "", { "dependencies": { "@trysound/sax": "0.2.0", "commander": "^7.2.0", "css-select": "^5.1.0", "css-tree": "^2.3.1", "css-what": "^6.1.0", "csso": "^5.0.5", "picocolors": "^1.0.0" }, "bin": "./bin/svgo" }, "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw=="],
11511172

11521173
"tabbable": ["[email protected]", "", {}, "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="],

contents/articles/2025-02-20_2025-spring-camp/index.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
---
22
title: 2025 年度春合宿を開催しました
3-
date: 2025-03-01T20:00:00+09:00
3+
date: 2025-03-01
44
image: ./image.jpg
55
slug: 2025-spring-camp
6-
author: tyasumura
6+
author: "tyasumura"
77
---
88

99
ut.code(); では 2 月 20 日から 22 日まで、東京大学山中寮内藤セミナーハウスにて春合宿を実施しました。

contents/banner.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
type Banner = {
2+
shown: boolean;
3+
kind: "notify" | "error";
4+
long: string;
5+
short: string;
6+
link: string;
7+
linkText?: string;
8+
};
9+
const banner: Banner = {
10+
shown: true,
11+
kind: "error",
12+
long: "開発中の Website V3 を見ています",
13+
short: "ハッカソンを開催します",
14+
link: "https://utcode.net",
15+
linkText: "リリース版に戻る",
16+
};
17+
18+
export default banner;

contents/members/kshibayama/index.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ description: サークルいっぱい入ってる多趣味な人。
77
faceImage: ./face.jpg
88
upperBodyImage: ./upper-body.jpg
99
github: Tsurubara-UTcode
10+
theme-light: "#CEDDF2"
1011
---
1112

1213
## 自己紹介

contents/members/ykobayashi/index.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ date: 2023-04-03
77
description: Helix と NixOS を使います。
88
faceImage: ./face.jpg
99
upperBodyImage: ./upper-body.jpg
10+
theme-light: "#FEFCE8"
1011
---
1112

1213
## 自己紹介

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@
2424
"@iconify-json/feather": "^1.2.1",
2525
"@mdx-js/react": "^3.1.0",
2626
"@tailwindcss/typography": "^0.5.16",
27+
"@types/html-to-text": "^9.0.4",
2728
"astro": "^5.4.2",
2829
"astro-icon": "^1.1.5",
2930
"color": "^5.0.0",
3031
"date-fns": "^4.1.0",
32+
"markdown-to-txt": "^2.0.1",
3133
"nullthrows": "^1.1.1",
3234
"prismjs": "^1.29.0",
3335
"react": "^19.0.0",

src/components/ActionButton.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const { to, variant = "dark" } = props;
1515
href={to}
1616
{...!to.startsWith("/") ? { target: "_blank", rel: "noreferrer" } : {}}
1717
class:list={[
18-
"not-prose relative flex w-max items-center gap-4 rounded-full bg-white px-6 py-3 font-bold text-black hover:brightness-95 active:top-0.75",
18+
"not-prose relative flex w-max items-center gap-4 rounded-full bg-white px-6 py-3 font-bold text-black hover:brightness-95 active:top-0.25",
1919
variant === "dark" && "border border-black",
2020
!props["no-motion"] && "motion",
2121
Astro.props.class,

src/components/ArticleList.astro

Lines changed: 56 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,102 @@
11
---
22
import { format } from "date-fns";
3-
import noImage from "../images/no-image.svg";
4-
import type { Article } from "../schema";
53
import { Image } from "astro:assets";
4+
import { getCollection } from "astro:content";
5+
import { markdownToTxt } from "markdown-to-txt";
66
77
interface Props {
8-
variant?: "normal" | "compact";
9-
articles: { data: Article; body?: string }[];
8+
variant?: "full" | "compact";
109
class?: string;
1110
}
1211
const props = Astro.props;
13-
const { variant = "normal", articles } = props;
12+
const { variant = "full" } = props;
13+
14+
const articles = (await getCollection("articles")).sort(
15+
(a, b) => b.data.date.getTime() - a.data.date.getTime(),
16+
);
17+
if (variant === "compact") {
18+
articles.splice(3);
19+
}
20+
21+
const MDXSpecialSyntax = /^import ActionButton from ".+";/;
22+
23+
const articlesWithExcerpts = await Promise.all(
24+
articles.map(async (article) => {
25+
if (!article.body) throw new Error("article doesn't have body!");
26+
// 😇 performance
27+
const text = markdownToTxt(article.body);
28+
return {
29+
article,
30+
text: text.replace(MDXSpecialSyntax, ""),
31+
};
32+
}),
33+
);
1434
---
1535

16-
<!--
17-
fragment ArticleListArticle on Mdx {
18-
id
19-
frontmatter {
20-
date
21-
slug
22-
title
23-
image {
24-
childImageSharp {
25-
gatsbyImageData(
26-
width: 600
27-
height: 400
28-
transformOptions: { fit: INSIDE }
29-
)
30-
largeGatsbyImageData: gatsbyImageData(
31-
width: 1200
32-
height: 800
33-
transformOptions: { fit: INSIDE }
34-
)
35-
}
36-
}
37-
}
38-
excerpt(pruneLength: 60)
39-
longExcerpt: excerpt(pruneLength: 200)
40-
}
41-
-->
4236
<ul
4337
class:list={[
4438
"grid grid-flow-dense gap-9 md:grid-cols-2 lg:grid-cols-3",
45-
variant === "normal" && "xl:grid-cols-4",
39+
variant === "full" ? "variant-full xl:grid-cols-4" : "variant-compact",
4640
props.class,
4741
]}
4842
>
4943
{
50-
articles.map((article, i) => {
51-
const isFeatured = variant === "normal" && i % 11 === 0; // 11 記事ごとに大きく表示する
44+
articlesWithExcerpts.map(({ article, text }, i) => {
45+
const isFeatured = variant === "full" && i % 11 === 0; // 11 記事ごとに大きく表示する
5246
const additionalProps = isFeatured
5347
? {
5448
cellClassName: "md:col-span-2 md:row-span-2",
55-
imageClassName: "h-[350px] md:h-[450px]",
56-
excerpt: article.body?.slice(0, 120),
49+
imageClassName: "max-h-[350px] md:max-h-[450px]",
50+
excerpt: text.slice(0, 300),
5751
}
5852
: {
5953
cellClassName: "",
60-
imageClassName: "h-[200px]",
61-
excerpt: article.body?.slice(0, 120),
54+
imageClassName: "max-h-[200px]",
55+
excerpt: text.slice(0, 80),
6256
};
6357
return (
6458
<li class="contents">
6559
<a
66-
href={`/articles/${article.data.slug}`}
60+
href={`/articles/${article.id}`}
6761
class:list={[
68-
"block hover:opacity-80",
62+
"relative rounded-xl p-1 shadow-md hover:brightness-110 active:top-0.5",
6963
additionalProps.cellClassName,
7064
]}
7165
>
72-
<div
66+
<Image
67+
loading={i < 5 ? "eager" : "lazy"}
68+
alt="カバー画像"
69+
height={48 * 4 * 4}
70+
width={48 * 4 * 4}
71+
src={article.data.image}
7372
class:list={[
74-
"isolate h-48 w-full overflow-clip rounded-xl object-cover",
73+
"animate-move w-full rounded-xl object-contain object-top",
7574
additionalProps.imageClassName,
7675
]}
77-
>
78-
<Image
79-
alt="カバー画像"
80-
height={48 * 4 * 4}
81-
width={48 * 4 * 4}
82-
src={article.data.image}
83-
class="h-full w-full object-cover"
84-
/>
85-
</div>
76+
/>
8677
<div class="mt-4">
8778
<time class="block text-sm text-gray-500">
8879
{format(article.data.date, "yyyy/MM/dd HH:mm")}
8980
</time>
9081
<h3 class="text-lg font-bold">{article.data.title}</h3>
91-
<p class="prose mt-2 max-w-none">{additionalProps.excerpt}</p>
82+
<p class="prose mt-2 max-w-none">{additionalProps.excerpt}...</p>
9283
</div>
9384
</a>
9485
</li>
9586
);
9687
})
9788
}
9889
</ul>
90+
<style>
91+
@import "tailwindcss";
92+
@media (max-width: 64rem) {
93+
.variant-compact :nth-child(n + 3) a {
94+
@apply hidden;
95+
}
96+
}
97+
@media (max-width: 80rem) {
98+
.variant-compact :nth-child(n + 4) a {
99+
@apply hidden;
100+
}
101+
}
102+
</style>

src/components/Footer.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const props = Astro.props;
1212
<footer
1313
class:list={["mt-auto mb-0 w-full bg-black text-gray-200", props.class]}
1414
>
15-
<div class="container mx-auto px-8 py-12">
15+
<div class="relative bottom-0 mx-auto px-8 py-12">
1616
<div
1717
class="grid gap-x-16 gap-y-8 md:grid-cols-2 md:grid-rows-2 lg:grid-cols-3 lg:grid-rows-1"
1818
>

0 commit comments

Comments
 (0)