(Photo by Christin Hume on Unsplash)
高中時曾任校刊社社長,也許對於出版不會太陌生。從 2017 年開始轉換使用 Hugo,逐步打造相對應的工作流程與工具,在這裡做個紀錄。不論入門或活用,希望大家能從中獲得能為自己提升工作效率的片段 :)
內容大綱
優缺點比較
當時採用以及現今繼續採用 Hugo 作為 blog 基礎系統的幾個優點:
- 開放原始碼 - https://github.com/gohugoio/hugo
- 開放格式
- 從筆記整理、草稿撰寫、到 Hugo 內容產出、甚至整理投影片,全程得以使用共通的開放格式 Markdown,節省許多資料轉換時間。
- 內容檔案格式為純文字 (Front Matter + Markdown),未來若需要轉換格式有出路
- 內容檔案格式為純文字,搭配版本控制或檔案同步機制,可以自己跨平台、任選編輯器
- 原始內容可以放進版本控制、同時達成異地備份
- 當時觀察了好一陣子,Hugo 使用人數夠多且呈現增加趨勢,不會太快變成孤兒(不會太快再轉換一次)
- 產出為靜態檔案,不需要維護特定規格的主機,找個 GitHub Pages 或 Amazon S3 丟上去後設定 DNS 指向即可
- 快(各種意義上的節省時間)(例如在 Macbook Air (M1, 2020)build 343 pages 只需要 1077 ms,平均每頁花費 3.14 ms)
- 有指令列工具 (CLI),方便進行自動化
- 擴充套件偏少(我覺得是優點,不會犧牲「快」)
缺點:
- 一起參與協作的同伴,有學習門檻。學習 Markdown 等語法和作業流程
編輯器
Visual Studio Code (VSCode)
Hugo 對各種編輯器都有社群貢獻的一些擴充套件。
我主要在 macOS 上使用 Visual Studio Code 來編輯 Hugo 的內容檔案。沒特地安裝 Hugo 控制相關套件(啊就 CLI 控),倒是安裝了些 Hugo、Markdown 語法周邊:
- Hugo Language and Syntax Support
- Hugo Shortcode Syntax Highlighting
- Hugo Snippets
- Markdown All in One
- Mermaid Markdown Syntax Highlighting
- Markdown Preview Mermaid Support
- Marp for VS Code - 做 Marp Markdown 簡報的套件(範例)
- Path Intellisense - 選擇圖檔路徑時節省時間
關於輸入圖檔路徑以及預覽,還在找尋其他有效率的做法,目前是盡量固定檔名命名規則,然後大量複製貼上 ![](/img/2021/2021-06-19-hugo-workflow/filename_here.png)
,接著到 Hugo 在地預覽(瀏覽器)上查看,希望未來有機會直接在編輯器內預覽。
Joplin
在某些場合不方便開啟電腦、或來不及開啟電腦時,我會使用跨平台的 Joplin 來編輯 Markdown,或是先快速做筆記片段暫存。等到整理文章時再來剪貼統整。之後再另外準備一些文章來討論 Joplin。
Joplin 也是開源軟體,可以達成跨平台,所以我在 Android phone、iPhone、iPad、Macbook Pro/Air、Windows 都可以同步筆記,繼續下一個階段的編輯整理動作。
Byword
在開始使用 Joplin 之前,使用過一小段時間的 Byword。目的相同,需要跨平台、任何裝置順手抓來就要可以快速進入做筆記的狀態,然後不用擔心跨裝置之間筆記同步掉資料的問題。且 Byword 無法運作在 Android 裝置上,這有時候有點困擾,因為出差時的主力機是 Android。
Obsidian
身邊陸續越來越多朋友跟我推薦 Obsidian,果然一開起來玩就停不下來。雖然不是開源軟體,但我的底線是開放的資料格式。我很期待運用 Obsidian 插入圖片後可以立即預覽的功能來編輯 Hugo 內容檔案,但至少食譜類的筆記已經往這邊移動了。但目前無法成為主力,因為只能在電腦上操作,行動裝置上還未有公開的版本。再觀察看看。
Hugo
環境設定 config.toml
設定檔可以多爬 Hugo 官方文件,以及 Hugo 官方 Discourse 討論區。
一開始搞不清楚要在哪裡設定,但多看幾個文件後,可以鎖定幾個目錄位置,每個都動手設定看看,會比較快上手。
因為想練習英文寫作,所以很貪心地從一開始就將手上的 Hugo 往多國語系方向做設定(也為後來的某些客服系統打下基礎)。多國語系的架構、對應、翻譯、片段更新與維護,還是個值得研究的題目。
|
|
內容分類 content
目前使用了兩種內容:post
與 note
。前者紀錄隨著時間順序而興起撰文者,後者嘗試相互連結形成網狀結構,也許會往 Digital Garden 方向整理(從清理蜘蛛網,到種花種草?!)。
我也建立了個別的 archetypes 檔案、以及個別的 create new shell scripts 對應到 post
與 note
兩種內容格式。
以下是 create new post 的 shell 範例:(若你沒有將圖檔依照各篇文章用目錄區隔開的需求,可以忽略這個範例,直接 hugo new 即可)
|
|
最後更新 lastmod
我是將 blog 當作筆記系統的延伸,所以常常有個想法、或想到之間的關聯性等等,就會回頭做些修改或調整,因此希望能呈現出該文章建立與最後一次修改的日期。參考了這幾篇文章,實作了 lastmod 這個功能。
- Docs: Configure Front Matter: Configure Dates
- Last Modified Date in Hugo, by Mert Bakır
- Hugo Blog 進化筆記 - 八墨寫信, by Will Liu
- Docs: Function: .Format
自定義 shell aliases and functions
參考自 Christian Mohn 的工作流程,稍作修改成為自己的版本。
若大家有興趣,之後我會更新在我的 dotfiles 的 .aliases.local.example
裡頭(現在 dotfiles 裡頭因為 Apple Silicon 而一片混亂中,敬請小心服用 XDD)。
|
|
因為在編輯文章時,有時需要大量螢幕截圖(例如每年年底 AWS re:Invent Keynote 筆記),每次螢幕截圖後還需要手動搬移檔案到 Hugo 專案的 static/img/年份/該篇文章專屬目錄
底下,加上有時還要做轉檔與壓縮優化等步驟,實在頗累人。後來索性將 Dropbox Screenshots 關閉,但沿用 ~/Dropbox/Screenshots
目錄路徑為預設值,同時新增一個小工具,當我在編輯某篇文章時,將預設儲存螢幕截圖的目錄,改成我的 Hugo 靜態檔案存放的對應路徑,用完再切回預設目錄。
Script 中使用的 info/success,大家替換成 echo 即可。
|
|
圖片 Images
使用 ImageOptim 讓圖片載入加速。
圖片來源主要是 Unsplash 或是個人出差出遊累積的大量照片(早期出門一天平均產生一兩千張照片,近年有比較收斂些)(好啦,都是拍吃的或是拍飛機居多,哈哈)。每篇文章會特地做 ogimage 以及 twitter card 處理,都在 Front Matter 搞定。你說偷懶、沒空的時候怎麼辦?身為一位負責任的工程師,凡走過必留下預設值 :p
Favicon
參考 Add Favicon to Hugo-Based Website | Igor Baiborodine。
- 新增一個
layouts/partials/favicon.html
- 修改
layouts/partials/head.html
引入 favicon partials。
- 修改
- Step 1: Add Favicon Using favicon.io
- 快速簡單先做一個基底 favicon。
- 然後再丟給下一步做更完整的描述檔案。
- Step 2: Add Favicon Using realfavicongenerator.net
- 上傳前一步產生的
android-chrome-512x512.png
進去產生完整檔案包。 - 我在
Favicon Generator Options
這個段落,加上使用分頁Compression
做壓縮。 - 下載檔案包,全部放到 hugo site
static/
目錄下。 - 產生的 HTML code 放進
layouts/partials/favicon.html
裡頭。
- 上傳前一步產生的
Footnotes and Citations
參考 Hugo Footnotes and Citations - GeekThis
在 Hugo 設定檔案中開啟 Footnotes 參數:
現在新的 Hugo 版本都使用 Goldmark。
[markup]
defaultMarkdownHandler = "goldmark"
[markup.goldmark]
[markup.goldmark.extensions]
footnote = true
Footnotes 語法格式:
That's some text with a footnote.[^1]
[^1]: And that's the footnote.
CSS 調整使之長相老派:
a.footnote-ref::before {
content: '[';
}
a.footnote-ref::after {
content: ']';
}
Paginator
(新增於 2023-09-19)
這陣子嘗試提早在 hugo 建立未來想要使用的草稿文章 (draft post),有將 front matter 設定 draft = true
。但我使用的 hugo theme 頗為老舊,上游已經停止更新,我自己也做了滿多改動,暫時沒有心力套用近代剛發行的其他 hugo theme,也因此累積了超過一定數量之後的草稿文章後,我的首頁文章清單會因為 paginator 計算分母出錯(誤將草稿文章也計入分母)而出現空白的情況。在 GPT-4 的協助、以及交叉檢查文件作確認之下,完成了修改,現在 paginator 可以正確計算分子分母、正確顯示頁面內容了。
layouts/index.html
:
|
|
layouts/partials/pagination.html
:
|
|
以下是 GPT-4 修改 paginator 的步驟說明
感謝你提供的詳細內容。現在讓我們來解決這個問題。
首先,我們需要在 layouts/index.html
的開頭正確設置分頁(paginator
)。
在
layouts/index.html
中的最上方,加入以下程式碼:{{ $pages := where (where .Site.RegularPages "Params.hidden" "ne" "true") "Draft" "!=" true }} {{ $paginator := .Paginate $pages }}
這將會建立一個名為
$paginator
的新分頁物件,該物件已經過濾掉設為隱藏和草稿的頁面。現在,在你的
layouts/index.html
的range
循環中,替換原本的.Paginator.Pages
參照為$paginator.Pages
:從:
{{ range where .Paginator.Pages "Params.hidden" "ne" "true" }}
改為:
{{ range $paginator.Pages }}
因為我們已經過濾掉設為隱藏的頁面,所以現在不再需要進一步的
where
條件。修改
layouts/partials/pagination.html
:將:
{{ $pag := $.Paginator }}
改為:
{{ $pag := $.Site.Paginator }}
但考慮到我們已經在
layouts/index.html
中建立了$paginator
,因此我們實際上應該在pagination.html
中使用$paginator
。為了達到這個目的,你應該傳遞
$paginator
到pagination.html
partial。這是如何做的:在
layouts/index.html
中,將:{{ partial "pagination.html" . }}
改為:
{{ partial "pagination.html" $paginator }}
然後,在
layouts/partials/pagination.html
中,你可以直接使用$pag
(因為它現在指向你傳遞的$paginator
)。請試著進行這些修改,然後重新生成你的網站。如果你遇到其他問題或有疑慮,請隨時讓我知道!
工作流程
(2016 拍攝於西班牙馬德里一家書店,那天會議下班後原本想去的圖書館沒開放。)
前置作業
- 閱讀,大量閱讀 ,這部份另開一局做拆解。基本流程設計是從閱讀後的筆記與總結中,抽取出可以轉寫成文的靈感,放入待辦清單中。
筆記,剛才有提過,目前主力使用 Joplin 搭配 Dropbox 同步,有在考慮 Joplin Server。- 筆記系統的主力在 2021Q4 逐步改用 視覺系筆記 Heptabase。
- 筆記,另外還有使用 Instapaper 等工具,待另開一文分享。可以先參考 我的 個人知識系統 工作流程。
- 紙本筆記本,從小學開始我身邊一定都會帶或大或小的紙本筆記本,也曾一度用便條紙做實驗,直到遇到 FIELD NOTES 之後就沒換過了。對我來說大小適中,我通常使用 Original Dot-Graph 或是 Original Graph Paper 方便書寫時對齊。通常都趁著 Black Friday 或 Prime Day 進一些庫存。
- 待辦清單,之前使用 OmniFocus ,但後來為了完整跨平台與協作改用另一套,未來一併整理到 我的 個人知識系統 工作流程 做介紹。
作業中
- 從待辦清單中安排一個時段,撰寫一個寫作主題,例如本篇。
- 接著在 CLI 中開始建立 Hugo 內容檔案,並將對應該篇文章的靜態圖檔目錄建立起來。未來若覺得 slug 想要修改,直接在 Front Matter 中修改即可,檔名和目錄名稱就不做更動,例如本篇我就從
hugo-workflow
修改成my-hugo-workflow
。 - 或是想要回頭修改既有內容檔案,則快速切換到 Hugo 專案目錄。
|
|
- 開啟本地端預覽,
|
|
- 因為這個 terminal 已被 hugo server 使用中,所以使用 iTerm2
Cmd
+Shift
+T
開啟同一路徑在另一個分頁。
- 切換到 Hugo 專案中的靜態圖檔目錄後,
|
|
- 暫離、或是完成編輯,不再需要將螢幕截圖傳送到靜態圖檔目錄:
|
|
- 書寫時,從前述各個筆記系統搜尋相關材料,盡力讓相關的資訊或知識藉由 URL 關聯起來,方便自己或讀者交叉參照。
- 相比於 WordPress 之類的系統,Hugo 讓我專注在內容寫作。
- 完成草稿後,使用 Hugo 在地預覽模式閱讀個幾遍,若內容有值得標記畫底線之處,使用 自定義的 Hugo Shortcode 來畫底線,範例可以參考這一篇 AWS re:Invent Keynote 筆記。
後製作業
- 初版內容整理完成後,會再抽空多看幾次。檢查中英文版本是否能正確切換、檢查站內相對應連結能否順利抵達、回顧寫作過程中有沒有觀察到新的需求,要來更新這個 Hugo 工作流程,讓未來的自己更有效率(效率偏執但應該還不到狂,我有導入適量的偷懶來做平衡(炸 XDD)。
- Blog 主要是寫給自己(以及未來的家人?!)看的,倒也不追求發表速度(Hugo 很快,但不急),對於內容的查證相對比較在意。
- 抽空批次讓 ImageOptim 整理一下圖檔們。
- 版本控制、備份與部署。
- 目前是部署到 GitHub Pages 然後搭配自己的 domain name。未來也許會試試看 Amazon S3 + CloudFront 玩些變化。
- GitHub Pages Docs 提到:可以在發布的根目錄加入
.nojekyll
檔案,可以跳過預設的 Jekyll build 流程步驟,節省一些時間。
- GitHub Pages Docs 提到:可以在發布的根目錄加入
後記
Hugo 以及這套個人知識系統 工作流程,不一定適合每一個人(倒是,這個句型幾乎適合每一個場景)。若您對其中哪個環節感興趣,歡迎一起交流討論,一起增進效率 :)
如果這個分享對你有幫助,歡迎拍打餵食一杯咖啡 ☕ 😍