Hexo Icarus 顯示瀏覽量(三):Hack Icarus 頁面,串接瀏覽量 API
上一講透過 Google Analytics 加上 AWS Lambda,我們完成了透過 Page Path 來取得 View Count 的 API,接下來便是將瀏覽量顯示在 Hexo Icarus 主題中的預覽及內文了。
由於 Icarus 本身提供的設定檔支援的是不蒜子,和我使用 Google Analytics 作為瀏覽量資料庫的方式不同,只能另尋他法。
在瀏覽一些其他的實作方法後,發現有些方式能夠透過修改 Icarus 的模板來加上自訂內容,然而在當下專案我所使用的 hexo 5.4 和 icarus 4.3 並沒有發現類似的模板可供修改,直接進入 node_modules
修改 Icarus 產出的頁面顯然會在重新安裝時被覆蓋,不是個太好的辦法。
因為我想加入的自訂內容僅僅是「瀏覽數」而已,所以在不變更 Hexo、Icarus 的版本前提下,我選擇了一個可能也不太「乾淨」的方法來達成目的,Hack Hexo Icarus 的頁面的 HTML 來插入內容。
方案選擇及其原理
在我開發前端以及撰寫爬蟲的經驗中,時常會需要在頁面上透過 XPath 或 CSS Selector 等方式定位某個元件的內容,然後做樣式的修改或是模擬點擊等操作。
那麼,只要有方法可以讓我取得 HTML 的 DOM,或是插入一段 JavaScript 的程式碼即可達成目的。
剛好在 Hexo 5.0.0 版本之後有一個新功能稱作 Injector,讓我們可以將程式碼塞入 HTML 的 <head>
或 <body>
當中。
如此一來,我們只要準備好一段 JavaScript 的程式碼,在裡面產生瀏覽數的 HTML Element,然後塞入適當的位置,這個功能便算是完成了。
注入 JavaScript File
透過 Hexo 的 Injector,我們可以在專案目錄的 source/
下新增一個資料夾叫做 js
,來存放要被注入的檔案。
所以我新增了一個獲取瀏覽數並產生 HTML 元件的檔案,存成 source/js/view-count.js
,裡面可以先很簡單的寫一段 console.log
來驗證功能是否成功。
接著新增一個 scripts/
的資料夾在專案目錄下(如果不存在的話),在裡面新增叫做 inject-view-count.js
的檔案,裡面寫入 hexo.extend.injector.register('body_end', '<script src="/js/view-count.js"></script>');
。
Hexo 會讀取 scripts/
下的內容並執行。
當我們將 Hexo 跑起來時,便能看到 view-count.js
被塞入 HTML 中,並且裡面的內容被成功執行!
撰寫 view-count.js
:串接 API 及產生瀏覽數 Element
成功 Hack 進頁面的 HTML 後,再來就是將功能完成,第一步是定位需要顯示瀏覽數的元件。
在觀察 Icarus 的頁面呈現後,我發現有兩個地方會顯示發表及更新時間、字數等資訊,也就是在這些元件後方,是我預計加上瀏覽數的位置。
這兩個地方都是以卡片呈現,差別在於第一個地方是瀏覽多篇文章的分頁,另一個則是點選文章後的內文。
兩處位置的共通點,在 Icarus 中都是以卡片的形式呈現,也都可以透過 .card:has(h1.title)
的 Selector 語法來找到這些卡片,在文章內文中可以選取到一張卡片,而分頁中則能選取到多張。
選擇到卡片之後,再來就是定位要插入瀏覽量的位置,可以透過卡片下的 .level-left
class 來取得這個區塊,在建立好瀏覽量元素後 .appendChild
在此區塊的後面。
最後,我們需要獲取這篇文章的 Page Path 當成參數送往我們所撰寫的 View Count API。這在瀏覽單篇文章的時候沒有什麼問題,只要透過 window.location.pathname
獲取當前頁面的 Path 即可。
然而在文章分頁的地方需要換種做法,我們知道文章卡片的標題有超連結可以前往內文,因此使用 .title a
來定位標題的超連結內容,就能取得我們所需 Path。
如此一來,無論在分頁或內文,都能夠在文章資訊的區塊看到瀏覽量了。
附錄:完整 view-count.js
1 | document.addEventListener('DOMContentLoaded', async () => { |