Hugo Shortcode 實現可折疊區塊
Hugo Shortcode 實現可折疊區塊
方案 2:在專案
問題背景
在撰寫技術文章時,我們會在文章中加入程式碼範例。但是 blog 的目標是分享我處理問題的思路,而不是提供解決方案,所以我希望預設把程式碼隱藏。
最初的解決方案
使用 HTML5 的 <details> 和 <summary> 標籤:
1<details>
2<summary>點擊查看程式碼</summary>
3
4\```javascript
5console.log('Hello World');
6\```
7
8</details>這個方案雖然功能正常,但會觸發 MD033 Markdown Linter 警告:
1MD033/no-inline-html: Inline HTML [Element: details]為什麼會有這個警告?
Markdown 設計哲學
Markdown 的設計理念是:
- 保持純文字的可讀性
- 避免直接使用 HTML 標籤
- 使用語義化的標記語法
MD033 規則的目的
MD033 規則旨在:
- 維持 Markdown 的純淨性:避免 HTML 與 Markdown 混用
- 提升可維護性:純 Markdown 更容易閱讀和維護
- 確保相容性:不同的 Markdown 渲染器對 HTML 的支援程度不同
Hugo Shortcode 解決方案
什麼是 Shortcode?
Hugo Shortcode 是 Hugo 靜態網站生成器提供的一個強大功能,允許你:
- 在 Markdown 中使用自定義的簡短標記
- 封裝複雜的 HTML 結構
- 保持 Markdown 文件的整潔
優勢分析
| 特性 | HTML 標籤 | Hugo Shortcode |
|---|---|---|
| Markdown Linter | 觸發警告 | 無警告 |
| 可維護性 | 分散在各處 | 集中管理 |
| 可讀性 | 較差 | 優秀 |
| 彈性 | 固定結構 | 可自定義 |
| Hugo 最佳實踐 | 不推薦 | 官方推薦 |
實現步驟
步驟 1:創建 Shortcode 檔案
在專案根目錄創建 layouts/shortcodes/details.html:
點擊查看 Shortcode 程式碼
1{{/*
2 Details shortcode - 用於創建可折疊的內容區塊
3
4 使用方式:
5
6
7<details>
8 <summary>點擊展開</summary>
9
10 內容...
11
12</details>
13
14 參數:
15 - summary: 摘要文字(可選,預設為 "點擊展開")
16*/}}
17<details>
18 <summary>{{ .Get "summary" | default "點擊展開" }}</summary>
19 {{ .Inner | markdownify }}
20</details>程式碼說明:
- 註解區塊:
{{/* ... */}}用於說明 shortcode 的用途和使用方式 - 參數獲取:
.Get "summary"獲取 summary 參數 - 預設值:
default "點擊展開"提供預設文字 - 內容處理:
.Inner獲取標籤內的內容 - Markdown 渲染:
markdownify將內容中的 Markdown 語法轉換為 HTML
步驟 2:在 Markdown 中使用
舊方式(會觸發 MD033)
1<details>
2<summary>點擊查看程式碼</summary>
3
4\```toml
5[markup]
6 [markup.tableOfContents]
7 startLevel = 2
8\```
9
10</details>新方式(符合 Markdown 規範)
1
點擊查看程式碼
\```toml
[markup]
[markup.tableOfContents]
startLevel = 2
\```
步驟 3:添加 CSS 樣式
在 layouts/partials/custom_head.html 中添加樣式:
點擊查看 CSS 樣式程式碼
1/* 可折疊程式碼區塊樣式 */
2details {
3 margin: 1.5rem 0;
4 padding: 1rem;
5 background: rgba(0, 0, 0, 0.05);
6 border-radius: 8px;
7 border: 1px solid rgba(0, 0, 0, 0.1);
8 transition: all 0.3s ease;
9}
10
11details:hover {
12 background: rgba(0, 0, 0, 0.08);
13 border-color: rgba(0, 0, 0, 0.15);
14}
15
16details[open] {
17 background: rgba(0, 0, 0, 0.03);
18 border-color: rgba(0, 0, 0, 0.2);
19}
20
21summary {
22 cursor: pointer;
23 font-weight: 600;
24 font-size: 0.95rem;
25 padding: 0.5rem;
26 margin: -1rem -1rem 0 -1rem;
27 border-radius: 8px 8px 0 0;
28 background: rgba(0, 0, 0, 0.05);
29 transition: all 0.2s ease;
30 user-select: none;
31 list-style: none;
32}
33
34summary::-webkit-details-marker {
35 display: none;
36}
37
38summary::before {
39 content: '▶';
40 display: inline-block;
41 margin-right: 0.5rem;
42 transition: transform 0.3s ease;
43 font-size: 0.8rem;
44}
45
46details[open] summary::before {
47 transform: rotate(90deg);
48}
49
50summary:hover {
51 background: rgba(0, 0, 0, 0.1);
52}
53
54details[open] summary {
55 margin-bottom: 1rem;
56 border-bottom: 1px solid rgba(0, 0, 0, 0.1);
57 border-radius: 8px 8px 0 0;
58}
59
60/* 確保 details 內的程式碼區塊樣式正常 */
61details pre {
62 margin: 1rem 0 0 0;
63}
64
65details > *:not(summary) {
66 animation: fadeIn 0.3s ease;
67}
68
69@keyframes fadeIn {
70 from {
71 opacity: 0;
72 transform: translateY(-10px);
73 }
74 to {
75 opacity: 1;
76 transform: translateY(0);
77 }
78}
79
80/* 響應式設計 */
81@media (max-width: 768px) {
82 details {
83 margin: 1rem 0;
84 padding: 0.8rem;
85 }
86
87 summary {
88 font-size: 0.9rem;
89 padding: 0.4rem;
90 margin: -0.8rem -0.8rem 0 -0.8rem;
91 }
92}進階功能
自定義參數
你可以擴展 shortcode 支援更多參數:
點擊查看進階 Shortcode 程式碼
1{{/*
2 進階 Details shortcode
3
4 參數:
5 - summary: 摘要文字
6 - open: 是否預設展開(true/false)
7 - class: 自定義 CSS 類別
8*/}}
9<details {{ if .Get "open" }}open{{ end }} {{ with .Get "class" }}class="{{ . }}"{{ end }}>
10 <summary>{{ .Get "summary" | default "點擊展開" }}</summary>
11 {{ .Inner | markdownify }}
12</details>使用範例:
1
重要提示
這個區塊預設是展開的
巢狀使用
Shortcode 支援巢狀使用:
1
外層標題
這是外層內容
內層標題
這是內層內容
遷移指南
批量替換
如果你已經有很多使用 HTML 標籤的文章,可以使用以下步驟批量替換:
步驟 1:備份檔案
1git commit -am "備份:準備遷移到 shortcode"步驟 2:使用 sed 批量替換(macOS)
點擊查看批量替換腳本
1# 替換開始標籤
2find content -name "*.md" -type f -exec sed -i '' \
3 's/<details>$/{{< details summary="點擊查看程式碼" >}}/g' {} +
4
5# 替換帶 summary 的開始標籤
6find content -name "*.md" -type f -exec sed -i '' \
7 's/<details>.*<summary>\(.*\)<\/summary>/{{< details summary="\1" >}}/g' {} +
8
9# 替換結束標籤
10find content -name "*.md" -type f -exec sed -i '' \
11 's/<\/details>/{{< \/details >}}/g' {} +步驟 3:驗證結果
1# 檢查是否還有 HTML 標籤
2grep -r "<details>" content/
3grep -r "</details>" content/步驟 4:測試並提交
1hugo server -D
2# 確認無誤後提交
3git add .
4git commit -m "遷移到 shortcode:移除 HTML 標籤"常見問題
Q1: Shortcode 不生效?
可能原因:
- 檔案路徑錯誤:確認檔案在
layouts/shortcodes/目錄 - 檔案名稱錯誤:檔案名稱應該是
details.html - Hugo 版本過舊:確認 Hugo 版本 >= 0.55
解決方案:
1# 檢查 Hugo 版本
2hugo version
3
4# 重新啟動 Hugo server
5hugo server -D --disableFastRenderQ2: Markdown 內容沒有被渲染?
問題:shortcode 內的 Markdown 語法沒有被轉換為 HTML
解決方案:
確認使用了 markdownify 函數:
1{{ .Inner | markdownify }}Q3: 如何處理全域 gitignore 規則?
如果你的專案需要追蹤 .claude/settings.local.json,但被全域 gitignore 排除:
方案 1:強制添加
1git add -f .claude/settings.local.json方案 2:在專案 .gitignore 中覆蓋
# 允許追蹤 .claude/settings.local.json
!.claude/settings.local.jsonQ4: CSS 樣式沒有生效?
檢查清單:
- 確認 CSS 是否正確載入到
custom_head.html - 確認瀏覽器快取是否清除(Ctrl+Shift+R 強制重新整理)
- 確認 CSS 選擇器是否正確
- 確認是否有其他 CSS 覆蓋了樣式
效能考量
Shortcode vs HTML 標籤
| 項目 | HTML 標籤 | Shortcode |
|---|---|---|
| 建置時間 | 快 | 稍慢(需處理) |
| 執行時效能 | 相同 | 相同 |
| 快取效果 | 相同 | 相同 |
| 維護成本 | 高 | 低 |