summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config/_default/params.toml2
-rw-r--r--content/weekly/1.md (renamed from content/posts/weekly/1.md)0
-rw-r--r--content/weekly/10.md (renamed from content/posts/weekly/10.md)0
-rw-r--r--content/weekly/11.md (renamed from content/posts/weekly/11.md)0
-rw-r--r--content/weekly/12.md (renamed from content/posts/weekly/12.md)0
-rw-r--r--content/weekly/13.md (renamed from content/posts/weekly/13.md)0
-rw-r--r--content/weekly/14.md (renamed from content/posts/weekly/14.md)0
-rw-r--r--content/weekly/15.md (renamed from content/posts/weekly/15.md)0
-rw-r--r--content/weekly/16.md (renamed from content/posts/weekly/16.md)0
-rw-r--r--content/weekly/17.md (renamed from content/posts/weekly/17.md)0
-rw-r--r--content/weekly/18.md (renamed from content/posts/weekly/18.md)0
-rw-r--r--content/weekly/19.md (renamed from content/posts/weekly/19.md)0
-rw-r--r--content/weekly/2.md (renamed from content/posts/weekly/2.md)0
-rw-r--r--content/weekly/20.md (renamed from content/posts/weekly/20.md)0
-rw-r--r--content/weekly/21.md (renamed from content/posts/weekly/21.md)0
-rw-r--r--content/weekly/22.md (renamed from content/posts/weekly/22.md)0
-rw-r--r--content/weekly/23.md (renamed from content/posts/weekly/23.md)0
-rw-r--r--content/weekly/24.md (renamed from content/posts/weekly/24.md)0
-rw-r--r--content/weekly/25.md (renamed from content/posts/weekly/25.md)0
-rw-r--r--content/weekly/26.md (renamed from content/posts/weekly/26.md)0
-rw-r--r--content/weekly/27.md (renamed from content/posts/weekly/27.md)0
-rw-r--r--content/weekly/28.md (renamed from content/posts/weekly/28.md)0
-rw-r--r--content/weekly/29.md (renamed from content/posts/weekly/29.md)0
-rw-r--r--content/weekly/3.md (renamed from content/posts/weekly/3.md)0
-rw-r--r--content/weekly/30.md (renamed from content/posts/weekly/30.md)0
-rw-r--r--content/weekly/31.md (renamed from content/posts/weekly/31.md)0
-rw-r--r--content/weekly/32.md (renamed from content/posts/weekly/32.md)0
-rw-r--r--content/weekly/33.md (renamed from content/posts/weekly/33.md)0
-rw-r--r--content/weekly/34.md (renamed from content/posts/weekly/34.md)0
-rw-r--r--content/weekly/35.md (renamed from content/posts/weekly/35.md)0
-rw-r--r--content/weekly/36.md (renamed from content/posts/weekly/36.md)0
-rw-r--r--content/weekly/37.md (renamed from content/posts/weekly/37.md)0
-rw-r--r--content/weekly/38.md (renamed from content/posts/weekly/38.md)0
-rw-r--r--content/weekly/39.md (renamed from content/posts/weekly/39.md)0
-rw-r--r--content/weekly/4.md (renamed from content/posts/weekly/4.md)0
-rw-r--r--content/weekly/40.md (renamed from content/posts/weekly/40.md)0
-rw-r--r--content/weekly/41.md (renamed from content/posts/weekly/41.md)0
-rw-r--r--content/weekly/42.md (renamed from content/posts/weekly/42.md)0
-rw-r--r--content/weekly/43.md (renamed from content/posts/weekly/43.md)0
-rw-r--r--content/weekly/44.md (renamed from content/posts/weekly/44.md)0
-rw-r--r--content/weekly/45.md (renamed from content/posts/weekly/45.md)0
-rw-r--r--content/weekly/46.md (renamed from content/posts/weekly/46.md)0
-rw-r--r--content/weekly/47.md (renamed from content/posts/weekly/47.md)0
-rw-r--r--content/weekly/48.md (renamed from content/posts/weekly/48.md)0
-rw-r--r--content/weekly/49.md (renamed from content/posts/weekly/49.md)0
-rw-r--r--content/weekly/5.md (renamed from content/posts/weekly/5.md)0
-rw-r--r--content/weekly/50.md (renamed from content/posts/weekly/50.md)0
-rw-r--r--content/weekly/51.md (renamed from content/posts/weekly/51.md)0
-rw-r--r--content/weekly/52.md (renamed from content/posts/weekly/52.md)0
-rw-r--r--content/weekly/53.md (renamed from content/posts/weekly/53.md)0
-rw-r--r--content/weekly/54.md (renamed from content/posts/weekly/54.md)0
-rw-r--r--content/weekly/55.md (renamed from content/posts/weekly/55.md)0
-rw-r--r--content/weekly/56.md (renamed from content/posts/weekly/56.md)0
-rw-r--r--content/weekly/57.md (renamed from content/posts/weekly/57.md)0
-rw-r--r--content/weekly/58.md (renamed from content/posts/weekly/58.md)0
-rw-r--r--content/weekly/59.md (renamed from content/posts/weekly/59.md)0
-rw-r--r--content/weekly/6.md (renamed from content/posts/weekly/6.md)0
-rw-r--r--content/weekly/60.md (renamed from content/posts/weekly/60.md)0
-rw-r--r--content/weekly/61.md (renamed from content/posts/weekly/61.md)0
-rw-r--r--content/weekly/62.md (renamed from content/posts/weekly/62.md)0
-rw-r--r--content/weekly/63/index.md (renamed from content/posts/weekly/63/index.md)0
-rw-r--r--content/weekly/63/its-raining-men.jpg (renamed from content/posts/weekly/63/its-raining-men.jpg)bin80107 -> 80107 bytes
-rw-r--r--content/weekly/63/lightcast-1.png (renamed from content/posts/weekly/63/lightcast-1.png)bin223610 -> 223610 bytes
-rw-r--r--content/weekly/63/lightcast-2.png (renamed from content/posts/weekly/63/lightcast-2.png)bin228729 -> 228729 bytes
-rw-r--r--content/weekly/63/lightcast-3.png (renamed from content/posts/weekly/63/lightcast-3.png)bin80049 -> 80049 bytes
-rw-r--r--content/weekly/63/lightcast-4.png (renamed from content/posts/weekly/63/lightcast-4.png)bin129118 -> 129118 bytes
-rw-r--r--content/weekly/64/harrys-house.png (renamed from content/posts/weekly/64/harrys-house.png)bin102917 -> 102917 bytes
-rw-r--r--content/weekly/64/index.md (renamed from content/posts/weekly/64/index.md)0
-rw-r--r--content/weekly/65.md (renamed from content/posts/weekly/65.md)0
-rw-r--r--content/weekly/66.md (renamed from content/posts/weekly/66.md)0
-rw-r--r--content/weekly/67.md (renamed from content/posts/weekly/67.md)0
-rw-r--r--content/weekly/68.md (renamed from content/posts/weekly/68.md)0
-rw-r--r--content/weekly/69.md (renamed from content/posts/weekly/69.md)0
-rw-r--r--content/weekly/7.md (renamed from content/posts/weekly/7.md)0
-rw-r--r--content/weekly/70.md (renamed from content/posts/weekly/70.md)0
-rw-r--r--content/weekly/8.md (renamed from content/posts/weekly/8.md)0
-rw-r--r--content/weekly/9.md (renamed from content/posts/weekly/9.md)0
-rw-r--r--content/weekly/intro.md (renamed from content/posts/weekly/intro.md)0
-rw-r--r--layouts/section.html7
-rw-r--r--layouts/weekly/page.html3
-rw-r--r--layouts/weekly/section.html45
-rw-r--r--tag-wrangler.py330
82 files changed, 379 insertions, 8 deletions
diff --git a/config/_default/params.toml b/config/_default/params.toml
index 08c847bd..2e41a6e4 100644
--- a/config/_default/params.toml
+++ b/config/_default/params.toml
@@ -1,7 +1,7 @@
assetBaseUrl = "https://r2.eltr.ac/geedeapro"
logo = "/header.avif"
email = "hi@eltr.ac"
-mainSections = ["essays", "posts", "fictions", "library"]
+mainSections = ["essays", "posts", "weekly", "fictions", "library"]
favicon = "/favicon.png"
[author]
diff --git a/content/posts/weekly/1.md b/content/weekly/1.md
index 2547c755..2547c755 100644
--- a/content/posts/weekly/1.md
+++ b/content/weekly/1.md
diff --git a/content/posts/weekly/10.md b/content/weekly/10.md
index b2cda438..b2cda438 100644
--- a/content/posts/weekly/10.md
+++ b/content/weekly/10.md
diff --git a/content/posts/weekly/11.md b/content/weekly/11.md
index 832032b1..832032b1 100644
--- a/content/posts/weekly/11.md
+++ b/content/weekly/11.md
diff --git a/content/posts/weekly/12.md b/content/weekly/12.md
index 6f5b3bdf..6f5b3bdf 100644
--- a/content/posts/weekly/12.md
+++ b/content/weekly/12.md
diff --git a/content/posts/weekly/13.md b/content/weekly/13.md
index 759a0ea3..759a0ea3 100644
--- a/content/posts/weekly/13.md
+++ b/content/weekly/13.md
diff --git a/content/posts/weekly/14.md b/content/weekly/14.md
index 5dd3fe06..5dd3fe06 100644
--- a/content/posts/weekly/14.md
+++ b/content/weekly/14.md
diff --git a/content/posts/weekly/15.md b/content/weekly/15.md
index 0e7c6644..0e7c6644 100644
--- a/content/posts/weekly/15.md
+++ b/content/weekly/15.md
diff --git a/content/posts/weekly/16.md b/content/weekly/16.md
index 7a3e5946..7a3e5946 100644
--- a/content/posts/weekly/16.md
+++ b/content/weekly/16.md
diff --git a/content/posts/weekly/17.md b/content/weekly/17.md
index bc0ac75b..bc0ac75b 100644
--- a/content/posts/weekly/17.md
+++ b/content/weekly/17.md
diff --git a/content/posts/weekly/18.md b/content/weekly/18.md
index 6e8aa549..6e8aa549 100644
--- a/content/posts/weekly/18.md
+++ b/content/weekly/18.md
diff --git a/content/posts/weekly/19.md b/content/weekly/19.md
index e61f9f9c..e61f9f9c 100644
--- a/content/posts/weekly/19.md
+++ b/content/weekly/19.md
diff --git a/content/posts/weekly/2.md b/content/weekly/2.md
index 43b6380e..43b6380e 100644
--- a/content/posts/weekly/2.md
+++ b/content/weekly/2.md
diff --git a/content/posts/weekly/20.md b/content/weekly/20.md
index 2ea39d70..2ea39d70 100644
--- a/content/posts/weekly/20.md
+++ b/content/weekly/20.md
diff --git a/content/posts/weekly/21.md b/content/weekly/21.md
index 0e3249ac..0e3249ac 100644
--- a/content/posts/weekly/21.md
+++ b/content/weekly/21.md
diff --git a/content/posts/weekly/22.md b/content/weekly/22.md
index ba64f942..ba64f942 100644
--- a/content/posts/weekly/22.md
+++ b/content/weekly/22.md
diff --git a/content/posts/weekly/23.md b/content/weekly/23.md
index b428fd0d..b428fd0d 100644
--- a/content/posts/weekly/23.md
+++ b/content/weekly/23.md
diff --git a/content/posts/weekly/24.md b/content/weekly/24.md
index 371f2090..371f2090 100644
--- a/content/posts/weekly/24.md
+++ b/content/weekly/24.md
diff --git a/content/posts/weekly/25.md b/content/weekly/25.md
index 324d1813..324d1813 100644
--- a/content/posts/weekly/25.md
+++ b/content/weekly/25.md
diff --git a/content/posts/weekly/26.md b/content/weekly/26.md
index 728a1ce5..728a1ce5 100644
--- a/content/posts/weekly/26.md
+++ b/content/weekly/26.md
diff --git a/content/posts/weekly/27.md b/content/weekly/27.md
index 5e08d52d..5e08d52d 100644
--- a/content/posts/weekly/27.md
+++ b/content/weekly/27.md
diff --git a/content/posts/weekly/28.md b/content/weekly/28.md
index 49aa37d9..49aa37d9 100644
--- a/content/posts/weekly/28.md
+++ b/content/weekly/28.md
diff --git a/content/posts/weekly/29.md b/content/weekly/29.md
index 2b2e9eca..2b2e9eca 100644
--- a/content/posts/weekly/29.md
+++ b/content/weekly/29.md
diff --git a/content/posts/weekly/3.md b/content/weekly/3.md
index 91ce2f98..91ce2f98 100644
--- a/content/posts/weekly/3.md
+++ b/content/weekly/3.md
diff --git a/content/posts/weekly/30.md b/content/weekly/30.md
index 8d3a3fa6..8d3a3fa6 100644
--- a/content/posts/weekly/30.md
+++ b/content/weekly/30.md
diff --git a/content/posts/weekly/31.md b/content/weekly/31.md
index feff18a8..feff18a8 100644
--- a/content/posts/weekly/31.md
+++ b/content/weekly/31.md
diff --git a/content/posts/weekly/32.md b/content/weekly/32.md
index 74de563a..74de563a 100644
--- a/content/posts/weekly/32.md
+++ b/content/weekly/32.md
diff --git a/content/posts/weekly/33.md b/content/weekly/33.md
index 85bfb609..85bfb609 100644
--- a/content/posts/weekly/33.md
+++ b/content/weekly/33.md
diff --git a/content/posts/weekly/34.md b/content/weekly/34.md
index 415e6f97..415e6f97 100644
--- a/content/posts/weekly/34.md
+++ b/content/weekly/34.md
diff --git a/content/posts/weekly/35.md b/content/weekly/35.md
index cea58c6d..cea58c6d 100644
--- a/content/posts/weekly/35.md
+++ b/content/weekly/35.md
diff --git a/content/posts/weekly/36.md b/content/weekly/36.md
index 114c7dc0..114c7dc0 100644
--- a/content/posts/weekly/36.md
+++ b/content/weekly/36.md
diff --git a/content/posts/weekly/37.md b/content/weekly/37.md
index baf31a48..baf31a48 100644
--- a/content/posts/weekly/37.md
+++ b/content/weekly/37.md
diff --git a/content/posts/weekly/38.md b/content/weekly/38.md
index 0de763ba..0de763ba 100644
--- a/content/posts/weekly/38.md
+++ b/content/weekly/38.md
diff --git a/content/posts/weekly/39.md b/content/weekly/39.md
index 955e2ecc..955e2ecc 100644
--- a/content/posts/weekly/39.md
+++ b/content/weekly/39.md
diff --git a/content/posts/weekly/4.md b/content/weekly/4.md
index eafce39e..eafce39e 100644
--- a/content/posts/weekly/4.md
+++ b/content/weekly/4.md
diff --git a/content/posts/weekly/40.md b/content/weekly/40.md
index f8aae547..f8aae547 100644
--- a/content/posts/weekly/40.md
+++ b/content/weekly/40.md
diff --git a/content/posts/weekly/41.md b/content/weekly/41.md
index 6671a233..6671a233 100644
--- a/content/posts/weekly/41.md
+++ b/content/weekly/41.md
diff --git a/content/posts/weekly/42.md b/content/weekly/42.md
index 5ab3e737..5ab3e737 100644
--- a/content/posts/weekly/42.md
+++ b/content/weekly/42.md
diff --git a/content/posts/weekly/43.md b/content/weekly/43.md
index 0c5ba06e..0c5ba06e 100644
--- a/content/posts/weekly/43.md
+++ b/content/weekly/43.md
diff --git a/content/posts/weekly/44.md b/content/weekly/44.md
index e661b3b1..e661b3b1 100644
--- a/content/posts/weekly/44.md
+++ b/content/weekly/44.md
diff --git a/content/posts/weekly/45.md b/content/weekly/45.md
index a93b6a29..a93b6a29 100644
--- a/content/posts/weekly/45.md
+++ b/content/weekly/45.md
diff --git a/content/posts/weekly/46.md b/content/weekly/46.md
index 90ae1cb5..90ae1cb5 100644
--- a/content/posts/weekly/46.md
+++ b/content/weekly/46.md
diff --git a/content/posts/weekly/47.md b/content/weekly/47.md
index 480aa15f..480aa15f 100644
--- a/content/posts/weekly/47.md
+++ b/content/weekly/47.md
diff --git a/content/posts/weekly/48.md b/content/weekly/48.md
index 83082215..83082215 100644
--- a/content/posts/weekly/48.md
+++ b/content/weekly/48.md
diff --git a/content/posts/weekly/49.md b/content/weekly/49.md
index 032ef030..032ef030 100644
--- a/content/posts/weekly/49.md
+++ b/content/weekly/49.md
diff --git a/content/posts/weekly/5.md b/content/weekly/5.md
index 9f028048..9f028048 100644
--- a/content/posts/weekly/5.md
+++ b/content/weekly/5.md
diff --git a/content/posts/weekly/50.md b/content/weekly/50.md
index 8680f376..8680f376 100644
--- a/content/posts/weekly/50.md
+++ b/content/weekly/50.md
diff --git a/content/posts/weekly/51.md b/content/weekly/51.md
index 950de6e6..950de6e6 100644
--- a/content/posts/weekly/51.md
+++ b/content/weekly/51.md
diff --git a/content/posts/weekly/52.md b/content/weekly/52.md
index c9ff3c34..c9ff3c34 100644
--- a/content/posts/weekly/52.md
+++ b/content/weekly/52.md
diff --git a/content/posts/weekly/53.md b/content/weekly/53.md
index 14334ed1..14334ed1 100644
--- a/content/posts/weekly/53.md
+++ b/content/weekly/53.md
diff --git a/content/posts/weekly/54.md b/content/weekly/54.md
index 6db60094..6db60094 100644
--- a/content/posts/weekly/54.md
+++ b/content/weekly/54.md
diff --git a/content/posts/weekly/55.md b/content/weekly/55.md
index 281da4ef..281da4ef 100644
--- a/content/posts/weekly/55.md
+++ b/content/weekly/55.md
diff --git a/content/posts/weekly/56.md b/content/weekly/56.md
index 12ae0506..12ae0506 100644
--- a/content/posts/weekly/56.md
+++ b/content/weekly/56.md
diff --git a/content/posts/weekly/57.md b/content/weekly/57.md
index 5fd1f1e2..5fd1f1e2 100644
--- a/content/posts/weekly/57.md
+++ b/content/weekly/57.md
diff --git a/content/posts/weekly/58.md b/content/weekly/58.md
index 4840d503..4840d503 100644
--- a/content/posts/weekly/58.md
+++ b/content/weekly/58.md
diff --git a/content/posts/weekly/59.md b/content/weekly/59.md
index f7bcf422..f7bcf422 100644
--- a/content/posts/weekly/59.md
+++ b/content/weekly/59.md
diff --git a/content/posts/weekly/6.md b/content/weekly/6.md
index de7cafb9..de7cafb9 100644
--- a/content/posts/weekly/6.md
+++ b/content/weekly/6.md
diff --git a/content/posts/weekly/60.md b/content/weekly/60.md
index dd73797e..dd73797e 100644
--- a/content/posts/weekly/60.md
+++ b/content/weekly/60.md
diff --git a/content/posts/weekly/61.md b/content/weekly/61.md
index 9680d630..9680d630 100644
--- a/content/posts/weekly/61.md
+++ b/content/weekly/61.md
diff --git a/content/posts/weekly/62.md b/content/weekly/62.md
index 1954189e..1954189e 100644
--- a/content/posts/weekly/62.md
+++ b/content/weekly/62.md
diff --git a/content/posts/weekly/63/index.md b/content/weekly/63/index.md
index 4a1072c8..4a1072c8 100644
--- a/content/posts/weekly/63/index.md
+++ b/content/weekly/63/index.md
diff --git a/content/posts/weekly/63/its-raining-men.jpg b/content/weekly/63/its-raining-men.jpg
index a446a293..a446a293 100644
--- a/content/posts/weekly/63/its-raining-men.jpg
+++ b/content/weekly/63/its-raining-men.jpg
Binary files differ
diff --git a/content/posts/weekly/63/lightcast-1.png b/content/weekly/63/lightcast-1.png
index bf3671ba..bf3671ba 100644
--- a/content/posts/weekly/63/lightcast-1.png
+++ b/content/weekly/63/lightcast-1.png
Binary files differ
diff --git a/content/posts/weekly/63/lightcast-2.png b/content/weekly/63/lightcast-2.png
index 777280d3..777280d3 100644
--- a/content/posts/weekly/63/lightcast-2.png
+++ b/content/weekly/63/lightcast-2.png
Binary files differ
diff --git a/content/posts/weekly/63/lightcast-3.png b/content/weekly/63/lightcast-3.png
index 5a544f63..5a544f63 100644
--- a/content/posts/weekly/63/lightcast-3.png
+++ b/content/weekly/63/lightcast-3.png
Binary files differ
diff --git a/content/posts/weekly/63/lightcast-4.png b/content/weekly/63/lightcast-4.png
index b3aa621a..b3aa621a 100644
--- a/content/posts/weekly/63/lightcast-4.png
+++ b/content/weekly/63/lightcast-4.png
Binary files differ
diff --git a/content/posts/weekly/64/harrys-house.png b/content/weekly/64/harrys-house.png
index bbd59ac3..bbd59ac3 100644
--- a/content/posts/weekly/64/harrys-house.png
+++ b/content/weekly/64/harrys-house.png
Binary files differ
diff --git a/content/posts/weekly/64/index.md b/content/weekly/64/index.md
index 48c4c610..48c4c610 100644
--- a/content/posts/weekly/64/index.md
+++ b/content/weekly/64/index.md
diff --git a/content/posts/weekly/65.md b/content/weekly/65.md
index 12add3c6..12add3c6 100644
--- a/content/posts/weekly/65.md
+++ b/content/weekly/65.md
diff --git a/content/posts/weekly/66.md b/content/weekly/66.md
index d0ebd7cf..d0ebd7cf 100644
--- a/content/posts/weekly/66.md
+++ b/content/weekly/66.md
diff --git a/content/posts/weekly/67.md b/content/weekly/67.md
index c2584075..c2584075 100644
--- a/content/posts/weekly/67.md
+++ b/content/weekly/67.md
diff --git a/content/posts/weekly/68.md b/content/weekly/68.md
index 4b0269ef..4b0269ef 100644
--- a/content/posts/weekly/68.md
+++ b/content/weekly/68.md
diff --git a/content/posts/weekly/69.md b/content/weekly/69.md
index a7ee8b1c..a7ee8b1c 100644
--- a/content/posts/weekly/69.md
+++ b/content/weekly/69.md
diff --git a/content/posts/weekly/7.md b/content/weekly/7.md
index 9653bf89..9653bf89 100644
--- a/content/posts/weekly/7.md
+++ b/content/weekly/7.md
diff --git a/content/posts/weekly/70.md b/content/weekly/70.md
index f280d0f6..f280d0f6 100644
--- a/content/posts/weekly/70.md
+++ b/content/weekly/70.md
diff --git a/content/posts/weekly/8.md b/content/weekly/8.md
index de247b75..de247b75 100644
--- a/content/posts/weekly/8.md
+++ b/content/weekly/8.md
diff --git a/content/posts/weekly/9.md b/content/weekly/9.md
index 5e760525..5e760525 100644
--- a/content/posts/weekly/9.md
+++ b/content/weekly/9.md
diff --git a/content/posts/weekly/intro.md b/content/weekly/intro.md
index d8abac25..d8abac25 100644
--- a/content/posts/weekly/intro.md
+++ b/content/weekly/intro.md
diff --git a/layouts/section.html b/layouts/section.html
index 7497a217..5b5cb33a 100644
--- a/layouts/section.html
+++ b/layouts/section.html
@@ -11,10 +11,6 @@
{{ partial "section-categories" $pages }}
- {{ if eq .Site.Language.Lang "zh" }}
- <p class="text-secondary text-sm">*稻草人周刊也属于散文集,但为了方便查阅,周刊没有列在下面,请到<a href="/categories/稻草人周刊/">分类页面</a>查看周刊。</p>
- {{ end }}
-
<!-- Post Archive List -->
{{ $remainingMonthsToOpen := 3 }}
{{ range $pages.GroupByDate "2006" -}}
@@ -32,8 +28,6 @@
</h2>
<ul class="ps-0 flex flex-col gap-2 list-none leading-relaxed">
{{ range .Pages }}
- {{ $isWeekly := (eq .Params.categories "稻草人周刊") }}
- {{ if not (eq .Params.categories "稻草人周刊") }}
<li class="flex gap-4 text-size-lg">
<span class="text-size-xs h-5 font-mono text-secondary flex-shrink-0
inline-block border-1 border-solid border-t-5 px-1
@@ -46,7 +40,6 @@
</a>
</li>
{{ end }}
- {{ end }}
</ul>
</div>
{{ $remainingMonthsToOpen = sub $remainingMonthsToOpen 1 }}
diff --git a/layouts/weekly/page.html b/layouts/weekly/page.html
new file mode 100644
index 00000000..e093e810
--- /dev/null
+++ b/layouts/weekly/page.html
@@ -0,0 +1,3 @@
+{{ define "main" }}
+ {{ partial "template/post-page" . }}
+{{ end }}
diff --git a/layouts/weekly/section.html b/layouts/weekly/section.html
new file mode 100644
index 00000000..14bb4db4
--- /dev/null
+++ b/layouts/weekly/section.html
@@ -0,0 +1,45 @@
+{{ define "main" }}
+
+ {{ $pages := .Pages }}
+ {{ $categories := slice }}
+
+ <article>
+ {{ partial "header.html" . }}
+ {{ partial "home/home-nav" . }}
+ <div class="posts-list pagefind-exclude">
+ <div class="markdown-body">{{ .Content }}</div>
+
+ <!-- Post Archive List -->
+ {{ $remainingMonthsToOpen := 3 }}
+ {{ range $pages.GroupByDate "2006" -}}
+ <section class="w-full">
+ {{ partial "components/section-title" (dict
+ "Left" .Key
+ "Right" (T "archivePage.postCountAnnual" (len .Pages))
+ )}}
+
+ {{ range .Pages.GroupByDate "January" }}
+ <div class="lazy-render"{{ if gt $remainingMonthsToOpen 0 }} open{{ end }}>
+ <h2 class="text-size-lg inline-block w-full m-0
+ flex justify-between items-center">
+ {{ .Key }}
+ </h2>
+ <ul class="ps-0 flex flex-col gap-2 list-none leading-relaxed">
+ {{ range .Pages }}
+ <li class="text-size-lg">
+ <a href="{{ .RelPermalink }}">
+ {{ .Title }}{{ with .Params.subtitle }}:<span class="text-secondary">{{. }}</span>
+ {{ end }}
+ </a>
+ </li>
+ {{ end }}
+ </ul>
+ </div>
+ {{ $remainingMonthsToOpen = sub $remainingMonthsToOpen 1 }}
+ {{ end }}
+ </section>
+ {{ end }}
+ </div>
+ </article>
+ {{ partial "footer.html" . }}
+{{ end }}
diff --git a/tag-wrangler.py b/tag-wrangler.py
new file mode 100644
index 00000000..1ac896d1
--- /dev/null
+++ b/tag-wrangler.py
@@ -0,0 +1,330 @@
+#!/usr/bin/env python3
+"""
+Hugo 分类管理脚本
+支持删除或重命名 categories
+"""
+
+import re
+import sys
+from pathlib import Path
+from typing import Tuple, List, Optional
+
+import yaml
+import tomli
+import tomli_w
+
+
+class FrontmatterParser:
+ """解析和修改 frontmatter"""
+
+ YAML_PATTERN = re.compile(r'^---\s*\n(.*?)\n---\s*\n', re.DOTALL)
+ TOML_PATTERN = re.compile(r'^\+\+\+\s*\n(.*?)\n\+\+\+\s*\n', re.DOTALL)
+
+ @staticmethod
+ def parse(content: str) -> Tuple[Optional[dict], str, str, str]:
+ """
+ 解析 frontmatter
+ 返回: (data, body, format, raw_frontmatter)
+ format: 'yaml', 'toml', or 'none'
+ """
+ # 检测 YAML frontmatter (---)
+ if content.startswith('---'):
+ match = FrontmatterParser.YAML_PATTERN.match(content)
+ if match:
+ yaml_content = match.group(1)
+ body = content[match.end():]
+ try:
+ data = yaml.safe_load(yaml_content) or {}
+ return data, body, 'yaml', yaml_content
+ except yaml.YAMLError as e:
+ raise ValueError(f"YAML 解析错误: {e}")
+
+ # 检测 TOML frontmatter (+++)
+ if content.startswith('+++'):
+ match = FrontmatterParser.TOML_PATTERN.match(content)
+ if match:
+ toml_content = match.group(1)
+ body = content[match.end():]
+ try:
+ data = tomli.loads(toml_content.encode('utf-8'))
+ return data, body, 'toml', toml_content
+ except Exception as e:
+ raise ValueError(f"TOML 解析错误: {e}")
+
+ # 没有 frontmatter
+ return None, content, 'none', ''
+
+ @staticmethod
+ def serialize(data: dict, body: str, format_type: str) -> str:
+ """将 data 和 body 序列化为字符串"""
+ if format_type == 'yaml':
+ # 清理 None 值
+ clean_data = {k: v for k, v in data.items() if v is not None}
+ if not clean_data:
+ return body
+ yaml_content = yaml.dump(clean_data, allow_unicode=True, sort_keys=False, default_flow_style=False)
+ return f"---\n{yaml_content}---\n{body}"
+
+ elif format_type == 'toml':
+ # 清理 None 值,TOML 不支持 null
+ def clean_for_toml(obj):
+ if isinstance(obj, dict):
+ return {k: clean_for_toml(v) for k, v in obj.items() if v is not None}
+ elif isinstance(obj, list):
+ return [clean_for_toml(item) for item in obj if item is not None]
+ elif obj is None:
+ return ""
+ return obj
+
+ clean_data = clean_for_toml(data)
+ if not clean_data:
+ return body
+ try:
+ toml_bytes = tomli_w.dumps(clean_data)
+ toml_str = toml_bytes.decode('utf-8') if isinstance(toml_bytes, bytes) else toml_bytes
+ return f"+++\n{toml_str}+++\n{body}"
+ except Exception as e:
+ raise ValueError(f"TOML 序列化错误: {e}")
+
+ else:
+ return body
+
+
+class CategoryManager:
+ def __init__(self, content_dir: Path, dry_run: bool = True):
+ self.content_dir = Path(content_dir)
+ self.dry_run = dry_run
+ self.parser = FrontmatterParser()
+ self.stats = {
+ 'processed': 0,
+ 'modified': 0,
+ 'skipped': 0,
+ 'errors': 0
+ }
+
+ def get_categories(self, data: dict) -> List[str]:
+ """
+ 获取 categories,支持多种格式:
+ - categories: "single"
+ - categories: ["array", "of", "cats"]
+ - category: "single" (别名)
+ """
+ if not data:
+ return []
+
+ # 优先检查 categories
+ cats = data.get('categories')
+ if cats is None:
+ # 尝试 category(单数形式)
+ cats = data.get('category')
+
+ if cats is None:
+ return []
+
+ # 统一转换为列表
+ if isinstance(cats, str):
+ return [cats]
+ elif isinstance(cats, list):
+ return cats
+ else:
+ return [str(cats)]
+
+ def set_categories(self, data: dict, categories: List[str]):
+ """设置 categories,如果为空则删除该字段"""
+ if 'category' in data:
+ del data['category']
+
+ if not categories:
+ if 'categories' in data:
+ del data['categories']
+ else:
+ data['categories'] = categories
+
+ def delete_category(self, file_path: Path, target_cat: str) -> bool:
+ """从文件中删除指定的 category"""
+ try:
+ content = file_path.read_text(encoding='utf-8')
+ data, body, fmt, _ = self.parser.parse(content)
+
+ if data is None:
+ return False
+
+ categories = self.get_categories(data)
+ if target_cat not in categories:
+ return False
+
+ # 删除目标 category
+ new_categories = [c for c in categories if c != target_cat]
+ self.set_categories(data, new_categories)
+
+ # 生成新内容
+ new_content = self.parser.serialize(data, body, fmt)
+
+ if not self.dry_run:
+ file_path.write_text(new_content, encoding='utf-8')
+ print(f"✅ 删除 '{target_cat}' from {file_path.relative_to(self.content_dir)}")
+ else:
+ print(f"[DRY-RUN] 将删除 '{target_cat}' from {file_path.relative_to(self.content_dir)}")
+ if not new_categories:
+ print(f" categories 字段将被删除")
+ else:
+ print(f" 新 categories: {new_categories}")
+
+ return True
+
+ except Exception as e:
+ print(f"❌ 错误处理 {file_path}: {e}")
+ self.stats['errors'] += 1
+ return False
+
+ def rename_category(self, file_path: Path, old_cat: str, new_cat: str) -> bool:
+ """重命名文件中的 category"""
+ try:
+ content = file_path.read_text(encoding='utf-8')
+ data, body, fmt, _ = self.parser.parse(content)
+
+ if data is None:
+ return False
+
+ categories = self.get_categories(data)
+ if old_cat not in categories:
+ return False
+
+ # 替换 category
+ new_categories = [new_cat if c == old_cat else c for c in categories]
+ self.set_categories(data, new_categories)
+
+ # 生成新内容
+ new_content = self.parser.serialize(data, body, fmt)
+
+ if not self.dry_run:
+ file_path.write_text(new_content, encoding='utf-8')
+ print(f"✅ 重命名 '{old_cat}' -> '{new_cat}' in {file_path.relative_to(self.content_dir)}")
+ else:
+ print(f"[DRY-RUN] 将重命名 '{old_cat}' -> '{new_cat}' in {file_path.relative_to(self.content_dir)}")
+ print(f" 新 categories: {new_categories}")
+
+ return True
+
+ except Exception as e:
+ print(f"❌ 错误处理 {file_path}: {e}")
+ self.stats['errors'] += 1
+ return False
+
+ def scan_files(self) -> List[Path]:
+ """扫描所有 markdown 文件"""
+ md_files = []
+ for ext in ['*.md', '*.markdown', '*.mdown']:
+ md_files.extend(self.content_dir.rglob(ext))
+ return md_files
+
+ def run_delete(self, target_cat: str):
+ """执行删除操作"""
+ print(f"\n{'='*60}")
+ print(f"🗑️ 删除分类: '{target_cat}'")
+ print(f"{'='*60}")
+ print(f"模式: {'预览 (dry-run)' if self.dry_run else '实际执行'}")
+ print()
+
+ files = self.scan_files()
+ found_count = 0
+
+ for file_path in files:
+ self.stats['processed'] += 1
+ if self.delete_category(file_path, target_cat):
+ found_count += 1
+ self.stats['modified'] += 1
+
+ print(f"\n{'='*60}")
+ print(f"处理完成: 扫描 {self.stats['processed']} 个文件")
+ print(f"找到并处理: {found_count} 个文件包含 '{target_cat}'")
+ print(f"错误: {self.stats['errors']}")
+
+ if self.dry_run:
+ print(f"\n💡 预览模式,未实际修改。使用 --execute 执行实际操作")
+
+ def run_rename(self, old_cat: str, new_cat: str):
+ """执行重命名操作"""
+ print(f"\n{'='*60}")
+ print(f"✏️ 重命名分类: '{old_cat}' -> '{new_cat}'")
+ print(f"{'='*60}")
+ print(f"模式: {'预览 (dry-run)' if self.dry_run else '实际执行'}")
+ print()
+
+ files = self.scan_files()
+ found_count = 0
+
+ for file_path in files:
+ self.stats['processed'] += 1
+ if self.rename_category(file_path, old_cat, new_cat):
+ found_count += 1
+ self.stats['modified'] += 1
+
+ print(f"\n{'='*60}")
+ print(f"处理完成: 扫描 {self.stats['processed']} 个文件")
+ print(f"找到并处理: {found_count} 个文件包含 '{old_cat}'")
+ print(f"错误: {self.stats['errors']}")
+
+ if self.dry_run:
+ print(f"\n💡 预览模式,未实际修改。使用 --execute 执行实际操作")
+
+
+def print_usage():
+ print("""Hugo 分类管理脚本
+
+用法:
+ python category_manager.py --delete <分类名> [--execute]
+ python category_manager.py --rename <旧分类名> <新分类名> [--execute]
+
+选项:
+ --execute, -e 实际执行修改(默认是预览模式)
+
+示例:
+ # 预览删除 "旧文章" 分类
+ python category_manager.py --delete "旧文章"
+
+ # 实际删除 "旧文章" 分类
+ python category_manager.py --delete "旧文章" --execute
+
+ # 预览重命名 "日记" 为 "生活"
+ python category_manager.py --rename "日记" "生活"
+
+ # 实际重命名
+ python category_manager.py --rename "日记" "生活" --execute
+""")
+
+
+def main():
+ args = sys.argv[1:]
+
+ if not args or '--help' in args or '-h' in args:
+ print_usage()
+ sys.exit(0)
+
+ # 检查是否有 --execute
+ dry_run = '--execute' not in args and '-e' not in args
+
+ # 移除 --execute 参数
+ args = [a for a in args if a not in ['--execute', '-e']]
+
+ content_dir = Path("content")
+
+ if len(args) >= 2 and args[0] == '--delete':
+ target_cat = args[1]
+ manager = CategoryManager(content_dir, dry_run)
+ manager.run_delete(target_cat)
+
+ elif len(args) >= 3 and args[0] == '--rename':
+ old_cat = args[1]
+ new_cat = args[2]
+ manager = CategoryManager(content_dir, dry_run)
+ manager.run_rename(old_cat, new_cat)
+
+ else:
+ print("❌ 参数错误")
+ print_usage()
+ sys.exit(1)
+
+
+if __name__ == "__main__":
+ main()