mirror of
https://github.com/ClovertaTheTrilobita/SanYeCao-blog.git
synced 2026-07-03 23:51:26 +00:00
Compare commits
11 commits
7566503db7
...
c95b9c978a
| Author | SHA1 | Date | |
|---|---|---|---|
| c95b9c978a | |||
| 4b1726ac00 | |||
| 983ef3bfb5 | |||
| 9b1e1f6b93 | |||
| 0a239f53c2 | |||
| f44d976330 | |||
|
|
e3b38c20f0 | ||
|
|
8168e1fed2 | ||
| 69e0e4e666 | |||
| 07a42ea123 | |||
| fc005b4944 |
23 changed files with 137 additions and 3175 deletions
|
|
@ -1,95 +0,0 @@
|
|||
import fs from "fs";
|
||||
import path from "path";
|
||||
import Fontmin from "fontmin";
|
||||
|
||||
function getFiles(dir) {
|
||||
const results = [];
|
||||
const list = fs.readdirSync(dir);
|
||||
|
||||
for (const file of list) {
|
||||
const filePath = path.join(dir, file);
|
||||
const stat = fs.statSync(filePath);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
results.push(...getFiles(filePath));
|
||||
} else {
|
||||
results.push(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
function scanDirectory(dir) {
|
||||
let set = new Set();
|
||||
const files = getFiles(dir);
|
||||
|
||||
for (const file of files) {
|
||||
const ignoredExtensions = [
|
||||
".ttf",
|
||||
".otf",
|
||||
".woff",
|
||||
".woff2",
|
||||
".eot",
|
||||
".png",
|
||||
".jpg",
|
||||
".jpeg",
|
||||
".webp",
|
||||
".gif",
|
||||
".ico",
|
||||
".pdf",
|
||||
];
|
||||
|
||||
if (ignoredExtensions.some((ext) => file.endsWith(ext))) continue;
|
||||
|
||||
try {
|
||||
const content = fs.readFileSync(file, "utf8");
|
||||
const currentSet = new Set(content);
|
||||
set = new Set([...set, ...currentSet]);
|
||||
} catch {
|
||||
// 跳过二进制等不可读文件
|
||||
}
|
||||
}
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
function subsetFont(src, text) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const fontmin = new Fontmin()
|
||||
.src(src)
|
||||
.use(
|
||||
Fontmin.glyph({
|
||||
text,
|
||||
hinting: false,
|
||||
})
|
||||
)
|
||||
.use(Fontmin.ttf2woff2())
|
||||
.dest("public/fonts/subset");
|
||||
|
||||
fontmin.run((err) => {
|
||||
if (err) return reject(err);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const baseChars =
|
||||
"首页文章标签关于作者评论发布于切换主题,。!?:“”‘’()《》【】、—…·-_/\\'\"()[]{}<>:;.!? ";
|
||||
const scanned = Array.from(scanDirectory("src")).join("");
|
||||
const chars = Array.from(new Set((scanned + baseChars).split(""))).join("");
|
||||
|
||||
await Promise.all([
|
||||
subsetFont("public/fonts/MapleMono-CN-Regular.ttf", chars),
|
||||
subsetFont("public/fonts/MapleMono-CN-Bold.ttf", chars),
|
||||
subsetFont("public/fonts/MapleMono-CN-Italic.ttf", chars),
|
||||
]);
|
||||
|
||||
console.log(`中文子集字体生成完成,共收集 ${chars.length} 个字符`);
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
3018
package-lock.json
generated
3018
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -9,8 +9,7 @@
|
|||
"dev": "astro dev",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro",
|
||||
"subset-font": "node build/fontmin.js",
|
||||
"build": "npm run subset-font && astro build"
|
||||
"build": "astro build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/rss": "^4.0.17",
|
||||
|
|
@ -18,11 +17,9 @@
|
|||
"@astrojs/svelte": "^8.0.4",
|
||||
"astro": "^6.0.8",
|
||||
"playwright": "^1.59.1",
|
||||
"rehype-mermaid": "^3.0.0",
|
||||
"url": "^0.11.4"
|
||||
"rehype-mermaid": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.5.0",
|
||||
"fontmin": "^1.1.1"
|
||||
"@types/node": "^25.5.0"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -12,14 +12,14 @@ const tags = data.tags;
|
|||
<div class="post-link">
|
||||
<div class="post-text">
|
||||
<a href={data.url} class="post-title-link">
|
||||
<h2 class="post-title" transition:name={`post-title-${data.slug}`}>
|
||||
<h2 class="post-title" transition:name={`post-title-${data.postId}`}>
|
||||
{data.title}
|
||||
</h2>
|
||||
</a>
|
||||
<a href={data.url} class="post-description">
|
||||
{data.description}
|
||||
</a>
|
||||
<div class="tags">
|
||||
<div class="tags" transition:name={`post-tags-${data.postId}`}>
|
||||
{
|
||||
tags.map((tag: string) => (
|
||||
<p class="tag">
|
||||
|
|
@ -40,7 +40,13 @@ const tags = data.tags;
|
|||
</div>
|
||||
|
||||
<a href={data.url} class="post-image-link">
|
||||
<img src={data.img} alt={data.title} class="post-image" loading="lazy" />
|
||||
<img
|
||||
src={data.img}
|
||||
alt={data.title}
|
||||
class="post-image"
|
||||
loading="lazy"
|
||||
transition:name={`post-image-${data.postId}`}
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
|
|
@ -167,7 +173,7 @@ const tags = data.tags;
|
|||
text-decoration: none;
|
||||
font-weight: 400;
|
||||
font-size: 0.92rem;
|
||||
font-style: italic;
|
||||
/* font-style: italic; */
|
||||
}
|
||||
|
||||
.post-meta-row {
|
||||
|
|
@ -206,7 +212,7 @@ const tags = data.tags;
|
|||
aspect-ratio: 16 / 10;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
border: 2px #94a0ab dashed;
|
||||
border: 1.5px #94a0ab dashed;
|
||||
flex-shrink: 0;
|
||||
display: block;
|
||||
}
|
||||
|
|
@ -256,7 +262,7 @@ const tags = data.tags;
|
|||
}
|
||||
|
||||
.post-image {
|
||||
border: none;
|
||||
/* border: none; */
|
||||
grid-area: image;
|
||||
width: 100%;
|
||||
height: calc(145px * 10 / 16);
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ const latestPosts = filteredPosts.slice(0, 7);
|
|||
img={post.data.image.url}
|
||||
tags={post.data.tags}
|
||||
slug={slug}
|
||||
postId={post.id}
|
||||
/>
|
||||
);
|
||||
})
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ const groupedPosts = filteredPosts.reduce((acc: any[], post: any) => {
|
|||
>
|
||||
<h2
|
||||
class="post-title"
|
||||
transition:name={`post-title-${slug}`}
|
||||
transition:name={`post-title-${post.id}`}
|
||||
>
|
||||
{post.data.title}
|
||||
</h2>
|
||||
|
|
@ -147,7 +147,8 @@ const groupedPosts = filteredPosts.reduce((acc: any[], post: any) => {
|
|||
margin: 0;
|
||||
font-size: 0.88rem;
|
||||
color: #555;
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
/* font-style: italic; */
|
||||
line-height: 1.5;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-word;
|
||||
|
|
|
|||
|
|
@ -70,15 +70,15 @@ const switchHref = "/" + segments.join("/");
|
|||
}
|
||||
|
||||
.lang-switch {
|
||||
color: black; !important
|
||||
font-weight: 700; !important
|
||||
font-size: 0.95rem; !important
|
||||
text-decoration: none; !important
|
||||
line-height: 1; !important
|
||||
color: black;
|
||||
font-weight: 700;
|
||||
font-size: 0.95rem;
|
||||
text-decoration: none;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.lang-switch:hover {
|
||||
text-decoration: underline; !important
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.sun {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
---
|
||||
import BaseLayout from "./BaseLayout.astro";
|
||||
import Remark42Embed from "@/components/Remark42Embed.astro";
|
||||
import { fade } from "astro:transitions";
|
||||
import { getLangFromUrl, getTranslations } from "@/i18n";
|
||||
import "@/styles/global.css";
|
||||
|
||||
const { frontmatter, lang, postId } = Astro.props;
|
||||
const { frontmatter, lang, slug, postId } = Astro.props;
|
||||
const comments = lang === "zh" ? "评论区" : "comments";
|
||||
const t = getTranslations(lang);
|
||||
---
|
||||
|
|
@ -39,14 +40,18 @@ const t = getTranslations(lang);
|
|||
<article class="post-article">
|
||||
<div class="post-header">
|
||||
<div class="post-meta">
|
||||
<h1 class="post-title" transition:name={`post-title-${postId}`} >{frontmatter.title}</h1>
|
||||
<p class="description"><em>{frontmatter.description}</em></p>
|
||||
<h1 class="post-title" transition:name={`post-title-${postId}`}>
|
||||
{frontmatter.title}
|
||||
</h1>
|
||||
<p class="description">
|
||||
<em>{frontmatter.description}</em>
|
||||
</p>
|
||||
<p class="meta-line">
|
||||
{t.post.publishedOn}: {frontmatter.pubDate.toLocaleDateString()}
|
||||
</p>
|
||||
<p class="meta-line">{t.post.writtenBy}: {frontmatter.author}</p>
|
||||
|
||||
<div class="tags">
|
||||
<div class="tags" transition:name={`post-tags-${postId}`}>
|
||||
{
|
||||
frontmatter.tags.map((tag: string) => (
|
||||
<p class="tag">
|
||||
|
|
@ -61,17 +66,18 @@ const t = getTranslations(lang);
|
|||
src={frontmatter.image.url}
|
||||
alt={frontmatter.image.alt}
|
||||
class="post-cover"
|
||||
transition:name={`post-image-${postId}`}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="post-divider"></div>
|
||||
|
||||
<div class="post-content">
|
||||
<div class="post-content" transition:animate={fade({ duration: "0.2s" })}>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<h2>{comments}</h2>
|
||||
<Remark42Embed slug={postId} />
|
||||
<Remark42Embed slug={slug} />
|
||||
</article>
|
||||
</BaseLayout>
|
||||
|
||||
|
|
@ -187,7 +193,7 @@ const t = getTranslations(lang);
|
|||
transition:
|
||||
opacity 0.2s ease,
|
||||
transform 0.27s ease,
|
||||
visibility 0.2s ease;
|
||||
visibility 0.2s ease,
|
||||
box-shadow 0.2s ease,
|
||||
background 0.2s ease,
|
||||
color 0.2s ease;
|
||||
|
|
@ -284,10 +290,11 @@ const t = getTranslations(lang);
|
|||
.post-cover {
|
||||
width: 300px;
|
||||
height: auto;
|
||||
aspect-ratio: 16 / 9;
|
||||
aspect-ratio: 16 / 10;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
border-radius: 0.4rem;
|
||||
/* border-radius: 0.4rem; */
|
||||
border: 1.5px #94a0ab dashed;
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
|
@ -346,6 +353,7 @@ const t = getTranslations(lang);
|
|||
.post-cover {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
aspect-ratio: 16 / 9;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ const pageTitle = t.home.title;
|
|||
width="33"
|
||||
height="33"
|
||||
aria-hidden="true"
|
||||
style="margin-left: -15px; margin-bottom: -5px; color:#3f50e5"
|
||||
style="margin-left: 0px; margin-bottom: -5px; color:#3f50e5"
|
||||
>
|
||||
<path
|
||||
d="M6.18 17.82a1.64 1.64 0 1 1 0 3.28 1.64 1.64 0 0 1 0-3.28ZM3 10.44v2.25c4.56 0 8.27 3.71 8.27 8.27h2.25C13.52 15.16 8.84 10.44 3 10.44Zm0-4.54v2.25c7.06 0 12.81 5.75 12.81 12.81h2.25C18.06 12.66 11.3 5.9 3 5.9Z"
|
||||
|
|
@ -66,4 +66,8 @@ const pageTitle = t.home.title;
|
|||
:global(.dark) .section-divider {
|
||||
background: #7f8b97;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-weight: 700;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -28,6 +28,11 @@ const [postLang, ...slugParts] = post.id.split("/");
|
|||
const slug = slugParts.join("/");
|
||||
---
|
||||
|
||||
<MarkdownPostLayout frontmatter={post.data} lang={lang} postId={slug}>
|
||||
<MarkdownPostLayout
|
||||
frontmatter={post.data}
|
||||
lang={lang}
|
||||
slug={slug}
|
||||
postId={post.id}
|
||||
>
|
||||
<Content />
|
||||
</MarkdownPostLayout>
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ const t = getTranslations(lang);
|
|||
<BaseLayout pageTitle={String(tag)}>
|
||||
<p class="tag-heading">
|
||||
{lang === "zh" ? "带有标签" : "Posts tagged with"}{" "}
|
||||
<span class="tag-chip">{tag}</span>
|
||||
<span class="tag-chip" transition:name={`post-tags-${tag}`}>{tag}</span>
|
||||
{lang === "zh" ? "的文章" : ""}
|
||||
</p>
|
||||
<ul>
|
||||
|
|
@ -54,6 +54,7 @@ const t = getTranslations(lang);
|
|||
date={formattedDate}
|
||||
img={post.data.image.url}
|
||||
tags={post.data.tags}
|
||||
postId={post.id}
|
||||
/>
|
||||
);
|
||||
})
|
||||
|
|
|
|||
|
|
@ -15,14 +15,14 @@ const tags = [...new Set(allPosts.map((post: any) => post.data.tags).flat())];
|
|||
const pageTitle = lang === "zh" ? "标签索引" : "Tag Index";
|
||||
---
|
||||
|
||||
<BaseLayout pageTitle=`${pageTitle} - ${t.banner.title}` `>
|
||||
<BaseLayout pageTitle=`${pageTitle} - ${t.banner.title}`>
|
||||
<h1>{t.tags.title}</h1>
|
||||
<p>{t.tags.description}</p>
|
||||
|
||||
<div class="tags">
|
||||
{
|
||||
tags.map((tag) => (
|
||||
<p class="tag">
|
||||
<p class="tag" transition:name={`post-tags-${tag}`}>
|
||||
<a href={`/${lang}/tags/${tag}`}>{tag}</a>
|
||||
</p>
|
||||
))
|
||||
|
|
|
|||
|
|
@ -2,30 +2,6 @@
|
|||
@import url("https://unpkg.com/@fontsource/maple-mono@5.2.6/400-italic.css");
|
||||
@import url("https://unpkg.com/@fontsource/maple-mono@5.2.6/700.css");
|
||||
|
||||
@font-face {
|
||||
font-family: "Maple Mono CN";
|
||||
src: url("/fonts/subset/MapleMono-CN-Regular.woff2") format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Maple Mono CN";
|
||||
src: url("/fonts/subset/MapleMono-CN-Italic.woff2") format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Maple Mono CN";
|
||||
src: url("/fonts/subset/MapleMono-CN-Bold.woff2") format("woff2");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 1rem;
|
||||
border-radius: 0.5rem;
|
||||
|
|
@ -57,7 +33,19 @@ article svg[id^="mermaid-"] {
|
|||
}
|
||||
|
||||
html {
|
||||
font-family: "Maple Mono", "Maple Mono CN", monospace;
|
||||
/* font-family: "Maple Mono", "Maple Mono CN", monospace; */
|
||||
font-family:
|
||||
system-ui,
|
||||
-apple-system,
|
||||
BlinkMacSystemFont,
|
||||
"Segoe UI",
|
||||
Roboto,
|
||||
Oxygen,
|
||||
Ubuntu,
|
||||
Cantarell,
|
||||
"Open Sans",
|
||||
"Helvetica Neue",
|
||||
sans-serif;
|
||||
background-color: #ffffff;
|
||||
color: #1f2328;
|
||||
}
|
||||
|
|
@ -101,7 +89,7 @@ html.dark body::after {
|
|||
|
||||
@media (max-width: 900px) {
|
||||
body::after {
|
||||
opacity: 0.1;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -113,10 +101,6 @@ html.dark body::after {
|
|||
body {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
body::after {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue