那天幫文章做了點更新,卻想到文章沒辦法顯示最後修改時間,因此來研究一下該如何處理。
這整個計畫嚴格來說在最後一步失敗了,但還是記錄下…畢竟我都搞這久了,不騙一篇網誌留下一點紀錄,我實在不甘心 QAQ(附上傳送門給想先看看失敗地方的人)。但也不算完全失敗,最後用了點 tricy 的作法,也算是符合要求?
顯示修改時間
好了,就按部就班、一步一步來吧,先來試試如何顯示修改時間。
雖然在 Jekyll-NextT 的使用文件中,沒有看到關於顯示最後修改時間的說明,不過我在程式碼中發現了些端倪。
-
在
_config.yml
的post_meta
中有個updated_at
字段,將這個參數打開(即設為true
)。1
2
3
4
5
6# Post meta display settings post_meta: item_text: true created_at: true updated_at: true categories: true
-
並在每篇文章的 yaml 區域中加上
updated
與時間:1
2
3
4
5
6
7
8
9
10
11
12
13--- title: 文章標題 date: 2013-12-24 updated: 2020-07-28 categories: - Foo tags: - Foo - Bar - Baz --- // 以下開始撰寫你的文章
出來的效果如下圖。但是我不是很喜歡這效果,原因有二:
-
陳列的資訊太多的
這有違我選這個主題的初衷,當初選擇這個主題很大的原因是因為簡潔,為了更簡潔我還把原先資訊列上的說明文字全拿掉了。現在變這麼長,實在讓我感到很阿雜 -
排序問題
另一個原因是,當來到首頁與其他出現時間軸頁面時,會發現它們的排序還是照著發布時間來,與我原先預期不同,我期望最後修改的文章會在最前面的說。
時間擇一顯示
雖然沒有符合預期的原生結果,但還好身為一個工程師,我可以自己動手做,至於失敗就是另外一回事了。
巡視了下網站,發現時間戳會出現在網站的三處:文章本身、首頁 以及 時間軸 三處。不過實際翻看程式碼,會注意到文章與首頁的時間戳其實共用一個 HTML 的,所以需要修改的地方只有兩處。
updated
,我更喜歡用 modified
這個單字。所以在我修改後的程式碼當中,都使用了 post.modified
取代了 post.updated
。若不想隨我更改,請將下列中的 modified
取代掉。
限制條件
先提提一個限制條件。
在每篇文章的 yaml 區中一定要同時存在 date
與 modified
兩個字段,即便文章沒有更新過,也必須在 modified
字段中填入發布的時間(這也是我喜歡用 modified
取代 updated
的原因)。否則下面程式碼在執行的時候,會因為 modified
為空值,導致時間顯示空白;或依照 modified
排序時,因為空值,而導致順序掉到最後面去。
為了解決這問題,我有試著找過並詢問過 Liquid 中是否可以像 python 一樣能自定義 sort 功能,讓未修改過的文章不必填寫兩個相同時間,但很不幸的 Liquid 沒有支援這個功能。
所以…還是乖乖填兩個字段吧
文章 & 首頁
回到顯示時間的部分,我們來看看如何修改顯示結果。
在文章與首頁這兩個部分時間戳是共用 _includes/_macro/post.html
這份程式碼的,而時間戳則是定義在 <span class="post-time">...</span>
的區塊中。
觀察下原先的程式碼會發現,顯示發布時間與最後修改時間的結構非常的相像,兩者相異之處也只有相對應的參數不同。按這概念先試著做了一次變數抽取,可以將原先顯示發布時間程式碼改寫成:
1 |
|
確認要提取的變數後,就可以開始進行修改:
-
移除原始程式碼
這邊顯示的邏輯與原本的程式碼不同,因此方便起見我把之前原先顯示兩個時間,也就是<span class="post-time">...</span>
的部分全部移掉。 -
確認顯示邏輯
兩個變數互相搭配的情況下,會有 4 種可能:created_at updated_at 顯示邏輯 true false 顯示發布時間 true true 這個比較麻煩,必須再進一步判斷,如果發布時間與修改時間一致,則顯示發布時間;若相異,則顯示修改時間。 false true …雖然我覺得應該不會有人這樣設,不過這狀況應該是顯示修改時間? false false 整個區塊不顯示。 -
程式撰寫
按照上面的真值表邏輯,就可以開始撰寫了。-
format_modified
考慮到如果 updated_at 為false
的情況, yaml 中可能不會存在該字段,所以先判斷它是否存在,再來套用 Filter。 -
show
另外用了一個名為show
的變數來當 flag。一來是因為想盡可能遵守程式碼不重複的原則,二來是因為 Liquid 的流程控制真的超難寫,有些 Ruby 的語法我在這邊都找不到。
-
修改後的程式碼如下:
1 |
|
時間軸
時間軸這邊改起來算快,因為之前為了在時間軸上顯示完整日期,其實已經改過一次了。
一樣到 _includes/_macro/post-collapse.html
中,修改時間軸上的 Item 物件。可以看到程式碼中原本是讀取 post.date
顯示時間,這邊加個流程控制來決定讀取的變數。
1 |
|
另外在時間軸上也藏了一個小小需要改的地方,就是在 archives 頁面上那個年份的分隔。
這邊是定義在 _includes/archive.html
中,還滿好找的,上方剛好有一個註解寫 Show year。一樣幫那行加上個流程控制:
1 |
|
按修改時間排序
搞定時間顯示後,我還希望文章可以按照最後修改的日期來排序,不然我辛苦改完了不就沒人知道嗎?
而與排序有關的有時間軸以及首頁的部分。
時間軸
剛剛頁面都停在了時間軸附近了,所以排序我就從這裡改起了!
跟前面不太一樣,前面顯示時間是時間軸中的 Item 實作的。這邊則是牽扯所有文章的排序,必須在 Item 外就完成,因此會在出現時間軸的頁面,分別是 Categories、 Tags、 Archives ,中各自實作。但三者個改法其實都是相同的。
分別在 _includes/category.html
、_includes/archive.html
與 _includes/tag.html
中找到 for 迴圈的位置,並將原先傳入的變數,先用另一個變數暫存,再判斷是否需要按修改時間排序,最後再將結果傳入迴圈中:
1 |
|
首頁
最後是首頁的部分,這邊也是我唯一改不動的部分。也不能說改不動,如果你沒有啟動分頁器功能,其實是可以順利完成,但一旦啟動分頁器就 GG 了。
打開 _includes/index.html
,會看到原先兩行程式碼分別對應兩種狀況:有無使用分頁器。原本不打算動這邊的邏輯,直接在最後套上判斷式就好,結果如下:
1 |
|
但,越看越不對勁。在分頁器啟動的情況下,它其實是先從分頁器取出了一頁假設 10 篇的文章,而我排序僅僅是這 10 篇文章,而不是對著全部文章排序阿…。這樣子,如果是修改某篇很舊的文中,它還是不會被排到頂端阿!
只好用關鍵字 jekyll-paginate sort by modified date 之類的,下去找找有無相關資訊。但並沒有看到任何有用的建議,倒是發現了這個 Pull request。這個 request 的目的是想要按照更新日期來排序,但很明顯地它還沒有被合併阿阿阿阿…。
tricy 的作法
因為搞不定在開起分頁器後,全部文章的排序問題,這個計畫原本該宣告失敗的。但我實在不甘心,超想要那個打勾的日曆 icon 阿阿阿阿!
我想到既然它只能照 date
這個字段來排,那我就讓它照這個來排吧!但我直接來告訴它何時要顯示 modified 的 icon。 基於這個想法,我把上面寫的程式碼全部 rollback 回去,砍掉重練。
所以現在文章的 yaml 變成了這樣,一旦文章有修改,則更改時間,並把 is_modified
設置為 true
:
1 |
|
接下來去改 _includes/_macro/post.html
,一樣動 <span class="post-time">...</span>
中間的程式碼,程式碼跟之前的章節類似,唯一的區別就是我把 timestamp
變數抽掉了,全部都只讀 date
這個字段,如此我就不參與排序的處理了。
1 |
|
是說,別忘了 _config.yml
中,該開的還是要開。
後記
說實話,這個功能開發時程拉了好長一陣子,原本我都已經把它部署到 github page 上了,結果在寫網誌的時候發現有 bug,只好先把功能給 rollback 掉,爾後來回嘗試了些方法,最後只先這樣了。雖然 yaml 的可讀性看起來怪怪的,不過 UI 上顯示一切正常,也算是也成功?
不過說真的,寫網誌真的會促進思考,為了順利寫完網誌,還重新理了理程式邏輯,把原本懶得處理的例外狀況都補上,還順便發了自己好幾條 issue …
更新紀錄
最後更新日期:2020-09-07
- 2020-09-07 發布
- 2020-09-01 完稿
- 2020-07-22 起稿