前言

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

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

設定 Tipue search 插件產生 static 模式需要的索引檔

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

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

改成

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 相關的資源檔案加入 Application cache

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="{{ SITEURL }}/tipuesearch_content.js"></script>, 這樣 Tipue search 才能使用 tipuesearch 這個物件內的索引資料 。 修改後的部分內容應該類似這樣 :

<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' 檔案 , 將下列片段 ,

if (getURLP('q'))
{
    $('#tipue_search_input').val(getURLP('q'));
    getTipueSearch(0, true);
}

改為

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

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

<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 + '/< 子目錄 >/search.html#' + q

結語

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