2022 年,怀着持续输出的愿望,我折腾了一个博客。为了彰显决心,我斥资购入了一个简短的双字母域名:gu.ink。这个域名第一年的费用并不算高,但由于 NameSilo 糟糕的用户体验,我当时并未注意到续费价格会大幅上涨。博客的意义,无论是过去还是今天,我都希望它是我探索、记录的自留地,一个属于我自己的 kingdom。
TOC
Open TOC
hexo 与 Astro paper
最初的博客采用了 Hexo 框架搭配 Butterfly 主题。不得不说,Hexo 在博客搭建方面确实很完备,Butterfly 主题的视觉效果也相当精美。而现在选择的 Astro Paper,与 Hexo 默认提供的功能相比显得非常简陋,很多功能都需要通过修改源码来实现,甚至连默认字体都不支持中文。
那么为什么还要换呢?主要原因是 Hexo + Butterfly 的组合过于重量级。每篇文章都需要配图,这不仅耗费时间,还会占用大量存储空间(无论是托管服务的免费额度还是本地硬盘)。相比之下,Astro Paper 的极简风格符合我希望的写作体验——简单、专注、高效。
还有一个原因,前端变化太快了,Astro 相对而言比 Hexo 是一个更现代化的框架。可以理解为,我只是在折腾。
2025 年
每年也许总是会在年初充满 passion,渐渐颓废,等到年末想起来还有目标没有完成,再经过一段 passion 时期,试图挽救年初的 flags,一年又过去了。
大除夕回想到新年里所决定的计划时,我们发现我们只做到了三分之一,另外三分之一不曾发现,还有三分之一则已经忘却了。人生之美便在这里。 —— 林语堂,《生活的艺术》
去年(2024 年)年末,我反思了一下,我觉得问题出在计划本身。一个理想的计划不应该只是一行空泛的 TODO 式的句子,也许我们应该借鉴项目管理现有经验,将计划分解为一系列的小目标,达到符合 SMART 原则。
- S:具体的(Specific)
- M:可衡量的(Measurable)
- A:可达到的(Attainable)
- R:相关的(Relevant)
- T:有截止期限的(Time-bound)
计划如果达到了 SMART 原则,剩下的大概就是精力和执行力的问题了。我年末的时候写了一份计划书,相对而言比较具体,所以我不打算在这里立 flags 了。
写作,仍然是重要的。
我依旧觉得 AI 时代,人类还是不能放弃思考,我认同维特根斯坦所说的「我语言的界限意味着我的世界的界限」。
pre-commit hook
可以考虑将下面的 Python 脚本加入到 .git/hooks
目录下,命名为 pre-commit
,从而实现添加文件自动添加发布时间 pubDatetime
,修改时,自动增加修改时间 modDatetime
。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import sys
import re
from datetime import datetime, timezone
import subprocess
from typing import List, Tuple
def get_staged_markdown_files() -> List[str]:
"""获取暂存区中的所有 Markdown 文件"""
cmd = ["git", "diff", "--cached", "--name-only", "--diff-filter=ACM"]
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
print(f"Error getting staged files: {result.stderr}")
sys.exit(1)
return [f for f in result.stdout.splitlines() if f.endswith('.md')]
def is_new_file(file_path: str) -> bool:
"""判断文件是否为新增文件"""
cmd = ["git", "diff", "--cached", "--diff-filter=A", file_path]
result = subprocess.run(cmd, capture_output=True, text=True)
return bool(result.stdout.strip())
def get_current_time() -> str:
"""获取当前 UTC 时间,格式化为 ISO 8601 格式"""
return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
def update_frontmatter(content: str, is_new: bool) -> Tuple[str, bool]:
"""更新文件的 Frontmatter
Args:
content: 文件内容
is_new: 是否为新文件
Returns:
tuple: (更新后的内容, 是否进行了修改)
"""
current_time = get_current_time()
frontmatter_pattern = re.compile(r"(---\n.*?\n---)", re.DOTALL)
if not frontmatter_pattern.search(content):
return content, False
def update_datetime(frontmatter: str) -> str:
if is_new:
if "pubDatetime:" not in frontmatter:
lines = frontmatter.splitlines()
lines.insert(3, f"pubDatetime: {current_time}")
frontmatter = "\n".join(lines)
else:
pass
else:
# 对于修改的文件,确保存在 pubDatetime
if "pubDatetime:" not in frontmatter:
# 在 frontmatter 的第二行添加
lines = frontmatter.splitlines()
lines.insert(1, f"pubDatetime: {current_time}")
frontmatter = "\n".join(lines)
if "modDatetime:" in frontmatter:
# 更新已存在的 modDatetime
frontmatter = re.sub(
r"modDatetime:.*?\n",
f"modDatetime: {current_time}\n",
frontmatter
)
else:
# 添加新的 modDatetime
frontmatter = re.sub(
r"(pubDatetime:.*?\n)",
f"\\1modDatetime: {current_time}\n",
frontmatter
)
return frontmatter
new_content = frontmatter_pattern.sub(
lambda m: update_datetime(m.group(1)),
content
)
return new_content, new_content != content
def main():
"""主函数"""
try:
files = get_staged_markdown_files()
for file_path in files:
if not os.path.exists(file_path):
continue
# 读取文件内容
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
# 更新 Frontmatter
new_content, was_modified = update_frontmatter(
content,
is_new_file(file_path)
)
if was_modified:
# 写入更新后的内容
with open(file_path, 'w', encoding='utf-8') as f:
f.write(new_content)
# 将修改后的文件重新添加到暂存区
subprocess.run(["git", "add", file_path], check=True)
sys.exit(0)
except Exception as e:
print(f"Error: {str(e)}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()