Tipue search 是一個 Javascript 程式庫,可以在客戶端進行資料搜尋,對於像本站一樣的靜態網站,是一個可行的選擇。 山姆鍋為了讓網站內容可以快取在客戶端,使用了 HTML5 application cache 的技術。透過這樣的技術,網站大部份內容都可以離線觀看,但是卻發現 Tipue search 無法在離線狀態下運作。

對於像 Tipue search 這種 Javascript 搜尋引擎,要離線運作理應不難。根據文件建議,採用它的 static 模式作為離線搜尋的基礎。 Pelican 有個 Tipue search 的插件,可以用來產生所需要的索引檔案,但它只支援 Tipue search 的 JSON 模式。 先不考慮過程遇到的問題,大致上,只要按照下列步驟即可:

修改 Tipue search Pelican 插件,找到 generate_output 方法,將其中 ‘tipuesearch_content.json’ 改為 ’tipuesearch_content.js’,以及

1
2
with open(path, 'w', encoding='utf-8') as fd:
json.dump(root_node, fd, separators=(',', ':'), ensure_ascii=False)

改成

1
2
3
4
5
with open(path, 'w', encoding='utf-8') as fd:
search_text = json.dumps(root_node, separators=(',', ':'), ensure_ascii=False)
fd.write('var tipuesearch =')
fd.write(search_text)
fd.write(';')

這樣的修改目的在使用索引資料建立 tipuesearch JavaScript 物件。這個物件是 Tipue search 的 static 模式下所需要的。

Tipue search 自帶的檔案有下列這些:

  • tipuesearch.css
  • tipuesearch.min.js
  • tipuesearch_set.js
  • img/search.png

這些檔案放置的位置跟如何設定 Tipue search 與使用的主題有關。像山姆鍋使用的 Pelican 插件所產生的索引檔放在 /tipuesearch_content.js, 其他檔案則放在 /theme/tipuesearch/ 目錄中。 您也可以參考 本站的快取描述檔

修改搜尋網頁樣板

山姆鍋的網站使用的樣板,需要修改的檔案名稱是 search.html ,讀者需要根據使用的樣板調整。將模式從’json’改為’static’。 把’contentLocation’的值改為 ‘tipuesearch_content.js’(這是插件產生的索引檔)。 在原先的 JavaScript 之前,加入 <script type=\"text/javascript\" src=\"/tipuesearch\_content.js\"\>\</script\>,這樣 Tipue search 才能使用 tipuesearch 這個物件內的索引資料。修改後的部分內容應該類似這樣:

1
2
3
<script type="text/javascript" src="{{ SITEURL }}/tipuesearch_content.js"></script>
<script type="text/javascript" src="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/tipuesearch/tipuesearch_set.js"></script>
<script type="text/javascript" src="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/tipuesearch/tipuesearch.js"></script>

完成以上步驟,Tipue search 已經可以支援 static 模式,Pelican 也可以產生所需要的索引檔,該快取的檔案也都指定在描述檔中了。 直覺上,應該算是大功告成了!

可惜,事情往往沒有想像中的單純。實際測試,發現還是無法在離線模式下運作,膜拜 Google 大神的結果,發現只要網址中出現查詢字串 (query string), 也就是 ? 之後的那部分,瀏覽器便會試圖從網路上重新抓取 search.html 檔案。但因為在離線模式下,這個動作一定會失敗。 Tipue search 運作的方式便是從查詢字串中找到 q 這個參數作爲搜尋關鍵字。

要讓 Tipue search 可以在離線模式下正常運作,看來只能讓它使用網址中的 hashtag(#) 來獲取搜尋關鍵字。按照規格,這樣的網址變更,瀏覽器不會試圖從網路重新下載網頁。 這部分的修改需要改到 Tipue search 的程式碼,對於後續更新會有些麻煩。

在 Tipue search 的 ‘tipuesearch.js’ 檔案,將下列片段,

1
2
3
4
5
if (getURLP('q'))
{
$('#tipue_search_input').val(getURLP('q'));
getTipueSearch(0, true);
}

改為

1
2
3
4
5
6
if (window.location.hash)
{
q = window.location.hash.substr(1)
$('#tipue_search_input').val(q);
getTipueSearch(0, true);
}

這樣的修改是要讓 Tipue search 從網址的 hashtag 取得參數,並去掉’#'字元。 樣板中跟搜尋相關的界面,會在網址後面加上 ?q = 關鍵字 , 要修改這樣的行為,需要用到 JavaScript 了。底下是本站使用的代碼:

1
2
3
4
5
6
7
8
9
10
11
12
<script type="text/javascript">
$('#tipue_search_bar').submit(function(ev) {
ev.preventDefault();
q = $('#tipue_search_input').val()
url = window.location.href
pathArray = location.href.split( '/' );
protocol = pathArray[0];
host = pathArray[2];
url = protocol + '//' + host;
window.location = url + '/search.html#' + q
});
</script>

山姆鍋假設網頁放在根目錄,如果放在子目錄,請將 url + '/search.html#' + q 改為 url + '/< 子目錄 & gt;/search.html#' + q

結語

山姆鍋手癢試著讓部落格可以快取在客戶端,衍生出離線搜尋的需求。拼拼湊湊下,也完成了一個可行的方案。在一般情況下,山姆鍋不建議直接修改程式, 因為會造成後續維護的困難。不管如何,一個可以離線搜尋內容的部落格,就這樣完成了!

參考資料