ブログというのをどうして書いてるのかというと、過去やったことを記録しておきたいからなのだが、後で見返したいというのが一番大きい。
Wordpressを使っていた頃はテンプレートについていた検索機能をそのまま使っていたから、何も苦労はなかったのだけど、これからは必要な機能は自前で用意しないといけないのだ…というわけで作った話。
実際には検索してヒットしたものを使わせてもらったのだが、まぁ自分でどうしたのかというところも含めて、記録しておく。
参考:Jekyll製ウェブサイトに簡易検索機能を実装する
— Genji App Blog
まずはjsonを出力するようなレイアウトを作成する。
$ cat _layouts/posts.json
[
{% if page.target == "home" %}
{%- assign posts = site.posts -%}
{% else %}
{%- assign posts = site.posts | where_exp:"item", "item.categories contains page.target" -%}
{% endif %}
{%- for subPost in posts -%}
{
"title": "{{ subPost.title | xml_escape }}",
"description": "{{ subPost.description | xml_escape }}",
"text": {{ subPost.content | jsonify }},
"url": "{{ site.url }}/{{subPost.lang}}{{ subPost.url }}",
"date": "{{ subPost.last_modified_at | date_to_xmlschema }}",
"category": "{{ subPost.categories }}"
}
{%- unless forloop.last -%},{%- endunless -%}
{%- endfor -%}
]
実際にjsonファイルを作ってもらえるようにpostを作成する。
$ cat _posts/2000-01-01-posts.md
---
layout: 'posts'
permalink: '/api/posts.json'
target: 'home'
---
実際にアクセスして、それっぽいjsonファイルが取得できることを確認しておく。
検索キーワードの入力を受ける箱、検索結果を表示する場所を作成する。
$ cat _includes/search_bar.html
<div class="container">
<div id="search-bar">
<i class="fa fa-search" aria-hidden="true"></i>
<input id="search" type="text" placeholder="Search..." />
<div id="search-result"></div>
</div>
</div>
あとはてきとうなレイアウトに{% include search_bar.html %}
とかして表示するようにしておく。
<script type="text/javascript">
let posts = [];
$(window).on('load', () => {
$.get('/api/posts.json', {}, (data) => {
posts = data;
});
$('#search').on('keyup', () => {
const keyword = document.getElementById('search').value.toLowerCase();
const searchResult = [];
if (keyword.length > 0) {
$('#search-result').show();
} else {
$('#search-result').hide();
}
$('.result-item').remove();
for (let post of posts) {
if (
post.title.toLowerCase().indexOf(keyword) >= 0 ||
post.text.toLowerCase().indexOf(keyword) >= 0
) {
searchResult.push(post);
}
}
if (searchResult.length === 0) {
$('#search-result').append(
'<div class="result-item"><div class="description">There is no search result.</div></div>'
);
} else {
for (let result of searchResult) {
$('#search-result').append(
'<a class="result-item" href="' + result.url + '"><di class="title"> 【' + result.category + '】' + result.title + '</div><div class="description">' + result.description + '</div></a>'
);
}
}
});
});
</script>
以上でいけるでしょう。
事前にJSONファイルを作成しておいて、検索処理自体はクライアントサイドで全部実施するという仕組み。単純にキーワードを全文探索しているので、記事数量と本文の物量が増えれば重くなるのかもしれないが、今のところ特に問題なさそうなので、暫くこれでいこう。