修改网站的favicon,并将favicon迁移到site.ts中

This commit is contained in:
2026-09-20 20:59:26 +08:00
parent eca2ad599f
commit 081d5fa65f
18 changed files with 120 additions and 11 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 919 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 554 B

-3
View File
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 41 KiB

+2 -1
View File
@@ -4,7 +4,7 @@
* pnpm new-post "文章标题" * pnpm new-post "文章标题"
* pnpm new-post "树莓派装 Docker" --category 教程 --tags Docker,树莓派 * pnpm new-post "树莓派装 Docker" --category 教程 --tags Docker,树莓派
* pnpm new-post "读《XX》有感" --category 思考 --description "摘要" --pinned * pnpm new-post "读《XX》有感" --category 思考 --description "摘要" --pinned
* pnpm new-post "标题" --file my-custom-slug --category 建站 * pnpm new-post "标题" --file 文件名 --slug my-custom-slug --category 建站
* *
* 不加 --category 时文件放在 src/content/posts/ 根目录; * 不加 --category 时文件放在 src/content/posts/ 根目录;
* 加了则同时写进 frontmatter 的 category 并放进同名子目录,和现有文章结构一致。 * 加了则同时写进 frontmatter 的 category 并放进同名子目录,和现有文章结构一致。
@@ -38,6 +38,7 @@ if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
--category <分类> 分类名,同时决定存放的子目录 --category <分类> 分类名,同时决定存放的子目录
--file <文件名> 自定义文件名(默认用标题) --file <文件名> 自定义文件名(默认用标题)
--tags <标签,标签> 标签,逗号分隔 --tags <标签,标签> 标签,逗号分隔
--slug <英文主题> 通常使用文章标题的英文缩写,Astro博客自带的属性
--description <摘要> 摘要,用于 SEO 和列表卡片 --description <摘要> 摘要,用于 SEO 和列表卡片
--image <路径> 封面图,public 下的绝对路径 --image <路径> 封面图,public 下的绝对路径
--pinned 置顶 --pinned 置顶
+1 -1
View File
@@ -47,7 +47,7 @@ if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
--title <标题> 可选标题 --title <标题> 可选标题
--location <地点> 地点,显示在日期旁 --location <地点> 地点,显示在日期旁
--weather <天气> 天气,与地点一起显示 --weather <天气> 天气,与地点一起显示
--images <路径,路径> 配图,public 下的绝对路径,逗号分隔 --images <路径,路径> 配图,public 下的绝对路径,逗号分隔,或者使用图床url链接
--tags <标签,标签> 标签,逗号分隔 --tags <标签,标签> 标签,逗号分隔
--pinned 置顶 --pinned 置顶
+1 -1
View File
@@ -142,7 +142,7 @@ const statCells = [
rel="noreferrer" rel="noreferrer"
class="flex items-center gap-2 text-muted-foreground text-xs hover:text-foreground transition-colors duration-200 group md:justify-end md:pr-4" class="flex items-center gap-2 text-muted-foreground text-xs hover:text-foreground transition-colors duration-200 group md:justify-end md:pr-4"
> >
<Github class="w-3.5 h-3.5" /> <Github className="w-3.5 h-3.5" />
<span>博客主题:朱墨留白 | VermilionVoid</span> <span>博客主题:朱墨留白 | VermilionVoid</span>
</a> </a>
</div> </div>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 481 KiB

@@ -0,0 +1,10 @@
---
title: "工作效率的提升"
published: 2026-09-20
description: "我们这个时代为什么越来越繁忙,人工智能带来的增效仍然是一把双刃剑"
slug: Improving-work-efficiency
tags: [工作,人的异化]
category: "思考"
---
在这里写正文。
+42
View File
@@ -48,6 +48,48 @@ export const siteTitleSuffix = site.name
/** 站点头像/站点图标的绝对地址,供友链页等对外展示用 */ /** 站点头像/站点图标的绝对地址,供友链页等对外展示用 */
export const siteAvatarUrl = `${site.url}/avatar.webp` export const siteAvatarUrl = `${site.url}/avatar.webp`
/**
* 站点图标(favicon)配置。
*
* 换图标有两种做法:
* 1. 图省事:直接覆盖 public/favicon/ 下的同名文件,本文件一个字都不用改;
* 2. 换了文件名或目录:只改下面这些值,页面里的 <link> 和 Web App Manifest 会一起跟上。
*
* dir 对应 public/ 下的目录,在线上就是站根下的绝对路径。
*/
export const favicon = {
/** 图标目录。改了要同步把 src/pages/favicon/ 这个路由目录挪到同名位置 */
dir: "/favicon",
/** 标签页图标:老的 .ico 兜底,内含 16/32/48 三档 */
ico: "favicon.ico",
/** 标签页主图标 32x32 —— 浏览器最常取的就是它 */
png32: "favicon-32x32.png",
/** 标签页小图标 16x16 */
png16: "favicon-16x16.png",
/** iOS「添加到主屏幕」图标,180x180 */
appleTouchIcon: "apple-touch-icon.png",
/**
* Web App Manifest:只在「添加到主屏幕 / 装成 App」时被浏览器取用。
* 文件不在 public/ 里,而是由 src/pages/favicon/[manifest].ts 按本配置生成,
* 所以站名、图标路径不会和这里对不上。
*/
manifest: {
/** 生成的文件名。改这里,<link rel="manifest"> 和产物文件名一起变 */
file: "site.webmanifest",
/** Android「添加到主屏幕」用的两档图标 */
android192: "android-chrome-192x192.png",
android512: "android-chrome-512x512.png",
/** 移动端状态栏与启动屏配色 */
themeColor: "#ffffff",
backgroundColor: "#ffffff",
},
} as const
/** 把 favicon 里的文件名拼成站内绝对路径,例如 /favicon/favicon.ico */
export const faviconUrl = (file: string) => `${favicon.dir}/${file}`
/** /**
* 统计分析。每一项留空即不加载对应的脚本。 * 统计分析。每一项留空即不加载对应的脚本。
*/ */
+6 -5
View File
@@ -5,7 +5,7 @@
import "katex/dist/katex.min.css" import "katex/dist/katex.min.css"
import "@/styles/global.css" import "@/styles/global.css"
import { ClientRouter } from "astro:transitions" import { ClientRouter } from "astro:transitions"
import { analytics, homeTitle, site } from "@/data/site" import { analytics, favicon, faviconUrl, homeTitle, site } from "@/data/site"
import ImageLightbox from "@/components/ImageLightbox.astro" import ImageLightbox from "@/components/ImageLightbox.astro"
interface Props { interface Props {
@@ -91,10 +91,11 @@ const resolvedTwitterDescription = twitterDescription || description
? "https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400..700;1,400..700&family=Noto+Serif+SC:wght@400..900&display=swap" ? "https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400..700;1,400..700&family=Noto+Serif+SC:wght@400..900&display=swap"
: "https://fonts.googleapis.com/css2?family=Inter:wght@400..700&family=Noto+Sans+SC:wght@400..700&family=Playfair+Display:ital,wght@0,400..700;1,400..700&family=Noto+Serif+SC:wght@400..900&display=swap"} : "https://fonts.googleapis.com/css2?family=Inter:wght@400..700&family=Noto+Sans+SC:wght@400..700&family=Playfair+Display:ital,wght@0,400..700;1,400..700&family=Noto+Serif+SC:wght@400..900&display=swap"}
/> />
<link rel="icon" href="/icon-light-32x32.png" media="(prefers-color-scheme: light)" /> <link rel="icon" href={faviconUrl(favicon.ico)} sizes="16x16 32x32 48x48" />
<link rel="icon" href="/icon-dark-32x32.png" media="(prefers-color-scheme: dark)" /> <link rel="icon" href={faviconUrl(favicon.png32)} type="image/png" sizes="32x32" />
<link rel="icon" href="/icon.svg" type="image/svg+xml" /> <link rel="icon" href={faviconUrl(favicon.png16)} type="image/png" sizes="16x16" />
<link rel="apple-touch-icon" href="/apple-icon.png" /> <link rel="apple-touch-icon" href={faviconUrl(favicon.appleTouchIcon)} />
<link rel="manifest" href={faviconUrl(favicon.manifest.file)} />
<script is:inline define:vars={{ analytics }}> <script is:inline define:vars={{ analytics }}>
;(() => { ;(() => {
// ClientRouter 切页时 head 里的内联脚本可能再次执行,用全局标记兜底 // ClientRouter 切页时 head 里的内联脚本可能再次执行,用全局标记兜底
+58
View File
@@ -0,0 +1,58 @@
import fs from "node:fs"
import path from "node:path"
import type { APIRoute } from "astro"
import { favicon, faviconUrl, site } from "@/data/site"
/**
* Web App Manifest 由路由生成而非放在 public/,这样站名、图标路径都跟随
* src/data/site.ts —— 换 favicon 只需要改那一个文件,不会出现"manifest 没跟上"。
* 同样的思路见 src/pages/robots.txt.ts。
*
* 产物文件名取自 favicon.manifest.file,所以改名也在 site.ts 里做。
*/
/** 本路由所在目录,必须和 favicon.dir 一致 —— 改了一个就得改名另一个 */
const ROUTE_DIR = "/favicon"
export function getStaticPaths() {
if (favicon.dir !== ROUTE_DIR) {
throw new Error(
`favicon.dir 是 "${favicon.dir}",但 manifest 路由在 src/pages${ROUTE_DIR}/ 下。` +
`请把该目录一并改名为 src/pages${favicon.dir}/,否则 manifest 会被生成到错误的路径上。`,
)
}
// public/ 里的同名文件会在构建时胜出(Astro 只打一行 WARN 就跳过本路由),
// manifest 会静默停在旧内容。宁可构建失败,也不要默默把旧 manifest 推上线。
const shadow = path.join(process.cwd(), "public", favicon.dir, favicon.manifest.file)
if (fs.existsSync(shadow)) {
throw new Error(
`public${favicon.dir}/${favicon.manifest.file} 与本路由重名,构建时 public 里的那个会胜出,` +
`manifest 将不再跟随 site.ts。请删掉它 —— manifest 是自动生成的,不需要手写。`,
)
}
return [{ params: { manifest: favicon.manifest.file } }]
}
export const GET: APIRoute = () => {
const { manifest } = favicon
const body = {
name: site.name,
description: site.description,
lang: site.lang,
start_url: "/",
display: "standalone",
background_color: manifest.backgroundColor,
theme_color: manifest.themeColor,
icons: [
{ src: faviconUrl(manifest.android192), sizes: "192x192", type: "image/png" },
{ src: faviconUrl(manifest.android512), sizes: "512x512", type: "image/png" },
],
}
return new Response(JSON.stringify(body, null, 2), {
headers: { "Content-Type": "application/manifest+json; charset=utf-8" },
})
}