欲しいものリスト

phoenix-powerHugoの検索システムを構築する方法

大体は下記のコードのとおりです。具体的にGrunt.jsLunr.jsでHugo用に構築します。

https://gist.github.com/sebz/efddfc8fdcb6b480f567

自分の場合の構築方法です。書いてあるとおりだとconfigparmalinkを設定しない場合の出力が得られますが、設定している場合は使えません。したがって、急遽無理やりShellScriptで書き直します。これはGruntfile.jsを直せばいいのですが、正直、面倒くさかった…。

bin/lunrjs.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/bin/zsh
d=${0:a:h:h}
# backup
h=${0:a:h}
if cat $j|jq . ;then
  cp $j $h
fi
h=$h/PagesIndex.json
j=$d/static/bower_components/lunr.js/PagesIndex.json
t=`cat $j |jq '.[]'|sed -e 's#/post##g'`
a=`cat $j | sed -e 's#/post##g'`
echo $a >! $j
t=`echo $t|jq -r '.href'|cut -d - -f 1-4`

for (( i=1;i<=`echo "$t"|wc -l`;i++ ))
do
  f=`echo "$t"|awk "NR==$i"`
  c=`echo $f|tr '-' '/'`
  sed -i "" "s#${f}#${c}#g" $j
done

cat $j

diff $j $h

とりあえず記事にあるGrntfile.jsを適時修正し作成し、ビルド後にスクリプトを実行するという手順。

出力ファイルは/bower_components/lunr.js/PagesIndex.jsonに置くこととします。

layouts/partials/widgets/search.html
1
2
3
4
5
6
7
<div class="widget-wrap">
<input id="search" type="text" placeholder="search">
<ul id="results">
</ul>
<script type="text/javascript" src="/js/search.js"></script>
<script type="text/javascript" src="/bower_components/lunr.js/lunr.min.js"></script>
</div>
js/search.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
var lunrIndex,
    $results,
    pagesIndex;

// Initialize lunrjs using our generated index file
function initLunr() {
    // First retrieve the index file
    $.getJSON("/bower_components/lunr.js/PagesIndex.json")
        .done(function(index) {
            pagesIndex = index;
            console.log("index:", pagesIndex);

            // Set up lunrjs by declaring the fields we use
            // Also provide their boost level for the ranking
            lunrIndex = lunr(function() {
                this.field("title", {
                    boost: 10
                });
                this.field("tags", {
                    boost: 5
                });
                this.field("content");

                // ref is the result item identifier (I chose the page URL)
                this.ref("href");
            });

            // Feed lunr with each file and let lunr actually index them
            pagesIndex.forEach(function(page) {
                lunrIndex.add(page);
            });
        })
        .fail(function(jqxhr, textStatus, error) {
            var err = textStatus + ", " + error;
            console.error("Error getting Hugo index flie:", err);
        });
}

// Nothing crazy here, just hook up a listener on the input field
function initUI() {
    $results = $("#results");
    $("#search").keyup(function() {
        $results.empty();

        // Only trigger a search when 2 chars. at least have been provided
        var query = $(this).val();
        if (query.length < 2) {
            return;
        }

        var results = search(query);

        renderResults(results);
    });
}

/**
 * Trigger a search in lunr and transform the result
 *
 * @param  {String} query
 * @return {Array}  results
 */
function search(query) {
    // Find the item in our index corresponding to the lunr one to have more info
    // Lunr result:
    //  {ref: "/section/page1", score: 0.2725657778206127}
    // Our result:
    //  {title:"Page1", href:"/section/page1", ...}
    return lunrIndex.search(query).map(function(result) {
            return pagesIndex.filter(function(page) {
                return page.href === result.ref;
            })[0];
        });
}

/**
 * Display the 10 first results
 *
 * @param  {Array} results to display
 */
function renderResults(results) {
    if (!results.length) {
        return;
    }

    // Only show the ten first results
    results.slice(0, 10).forEach(function(result) {
        var $result = $("<li>");
        $result.append($("<a>", {
            href: result.href,
            text: "» " + result.title
        }));
        $results.append($result);
    });
}

// Let's get started
initLunr();

$(document).ready(function() {
    initUI();
});

これで検索システムの完成です。Hugo Buildで同時にPagesIndexを作成するようにしておけばOKです。