Jekyllブログへ検索バーを入れる

2023-03-18 hit count image

特にプラグインを入れなくて、Jekyllブログへ検索バーを入れる方法について説明します。

概要

私はJekyllとGitHubを使ってブログを運営しています。ブログの運営目的は、情報の共有もありますが、自分がよく忘れる部分を残して、必要な時探して見るためもあります。

しかしブログポストが多くなって、必要な時、早くブログを探すことが大変になりました。それで、今回Jekyllブログへ検索バーを入れることにしました。

Jekyllブログへ検索バーを入れる - 検索バー

今回のブログポストではJekyllブログへプラグインを使わなく、検索バーを作る方法について紹介します。

データの準備

検索結果を表示するためには検索へ使うデータが必要です。そのデータを作る方法について説明します。

データレイアウト

検索結果を表示するデータをJekyllのLiquid文法を使ってJSON形で作成する予定です。

データを生成するためにはまず、レイアウトを作る必要があります。データ用のレイアウトを作るため、_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 }}",
      "url": "{{ site.url }}/{{subPost.lang}}{{ subPost.url }}",
      "date": "{{ subPost.last_modified_at | date_to_xmlschema }}",
      "category": "{{ subPost.categories }}"
  }
  {%- unless forloop.last -%},{%- endunless -%}
  {%- endfor -%}
]

上のソースコードは実際私がこのブログで使ってるソースコードです。皆さんは皆さんのブログに合わせて、カスタマイズして使ってください。

ソースコードを詳しく見てみます。


{% if page.target == "home" %}
  {%- assign posts = site.posts -%}
{% else %}
  {%- assign posts = site.posts | where_exp:"item", "item.categories contains page.target" -%}
{% endif %}

上のコードはJSONデータで吐き出すブログポストたちを持ってくるソースコードです。page.targethomeの場合、全てのブログポストを、homeじゃない場合はpage.targetがブログポストのカテゴリー(item.categories)に含まれたポストだけを用意します。ここで使ったpage.targetはJekyllga提供する基本変数ではなく、JSONデータを作るため作った変数です。


{%- for subPost in posts -%}
{
    "title": "{{ subPost.title | xml_escape }}",
    "description": "{{ subPost.description | xml_escape }}",
    "url": "{{ site.url }}/{{subPost.lang}}{{ subPost.url }}",
    "date": "{{ subPost.last_modified_at | date_to_xmlschema }}",
    "category": "{{ subPost.categories }}"
}
{%- unless forloop.last -%},{%- endunless -%}
{%- endfor -%}

このように準備したデータを持って、単純にループをしながら、JSONの形のデータを作ります。

デーアを作る

上で作ったレイアウトを使って実際データを作って見ます。普通のJekyllブログなら、_postsフォルダの下にブログポストを作成します。

|- _posts
  |- react-native
    |- 2020-01-01-new-blog.md
    |- 2020-01-02-new-blog.md
    |- 2020-01-03-new-blog.md

ここに分かりやすい名前でJSONデータ用のファイルを1個生成します。(ex> posts.md, api.md…)

|- _posts
  |- react-native
    |- posts.md
    |- 2020-01-01-new-blog.md
    |- 2020-01-02-new-blog.md
    |- 2020-01-03-new-blog.md

そしてそのファイルを開いて下記のように修正します。

---
layout: 'posts'
permalink: '/api/react-native/posts.json'
target: 'react-native'
---

上で生成したレイアウトを使うためlayout: 'posts'を指定しました。そして、データが配布されるURLを指定するためpermalinkへ特定なURLを適用しました。

最後に最も重要なtarget変数です。現在の例題ではreact-nativeを指定してます。上で作ったレイアウトを覚えてみると、ブログポストのcategoriesへこのように指定したtargetが含まれたポストだけJSONデータで生成されるようにしましあ。つまり、react-nativeと言うカテゴリーを持ってるポストだけJSONデータで生成されます。

全てのポストを持ってるJSONデータを生成したい場合、このtargethomeと指定します。このhomeもJekyllのルールではないので、他の名前を使っても大丈夫です。(ex> all)もちろん、他の名前を使った場合は上で作った_layouts/posts.jsonファイルのif文も修正しなきゃならないです。

検索バーを作る

ここからは単純なデザインコーディングです。HTMLとCSSで検索バーをデザインして、jQueryを使って上で作ったJSONデータを撮ってくる予定です。

HTMLを作る

画面へ検索バーを表示するため_includes/search_bar.htmlを作って下記のように修正します。単純なデザインなので、このコードは参考だけして皆さんが直接作ることをおすすめします。

<div class="container">
  <div class="row">
    <div class="col-12">
      <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>
  </div>
</div>

SCSS/CSSを作る

各テーマへデザインを担当するSCSSCSSファイルがあると思います。私が使ってるテーマの場合、_sass/styles.scssのファイルがデザインを担当してます。このようなファイルを開いて下記のように修正します。

#search-bar {
  margin: 32px auto;
  border: 1px solid #ccc;
  border-radius: 20px;
  padding: 0 20px;

  & #search {
    width: calc(100% - 30px);
    border: none;
    line-height: 44px;
    outline: none;
    border-style: none;
  }
  & #search-result {
    display: none;
    position: absolute;
    top: 80px;
    width: calc(100% - 70px);
    max-height: 325px;
    overflow-y: auto;
    background-color: white;
    box-shadow: 0px 4px 8px 0 #ccc;
    z-index: 99999;
    & .result-item {
      display: block;
      padding: 8px 16px;
      text-decoration: none;
      & .title,
      .description {
        width: 100%;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
      & .title {
        color: #f74094;
        padding-bottom: 4px;
        font-size: 16px;
      }
      & .description {
        color: #757575;
        font-size: 16px;
      }
    }
  }
}

私が使ってるテーマはSCSSを使ってますので、SCSSの形で作成しました。CSSの形を使ってるテーマの場合はCSS形式に合わせてコードを作成してください。

Javascriptを作成

次は、上で作ったJSONデータを読んでくるJavascriptを作成してみます。私が使ってるテーマは基本的jQueryを使ってるので、ここにはjQueryで作成されたソースコードを紹介します。

$(function () {
  var posts = [];
  $.get(lang + '/api/jekyll/posts.json', function (data) {
    posts = data;
  });
  $('#search').on('keyup', function () {
    var keyword = this.value.toLowerCase();
    var searchResult = [];

    if (keyword.length > 0) {
      $('#search-result').show();
    } else {
      $('#search-result').hide();
    }
    $('.result-item').remove();

    for (var i = 0; i < posts.length; i++) {
      var post = posts[i];
      if (
        post.title.toLowerCase().indexOf(keyword) >= 0 ||
        post.description.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 (var i = 0; i < searchResult.length; i++) {
        $('#search-result').append(
          '<a class="result-item" href="' +
            searchResult[i].url +
            '"><div class="title">【' + searchResult[i].category + '' +
            searchResult[i].title +
            '</div><div class="description">' +
            searchResult[i].description +
            '</div></a>'
        );
      }
    }
  });
});

ソースコードを詳しく見ます。

var posts = [];
$.get('/api/jekyll/posts.json', function (data) {
  posts = data;
});

データを保管する変数postsと上で作ったJSONデータをajaxを使って取ってきた後、postsへ保存しました。ajaxのURLは皆さんの状況に合わせて変更してください。私は1つのブログポストは1つのカテゴリーだけ使ってるので上のように使いました。

$('#search').on('keyup', function () {
  var keyword = this.value.toLowerCase();
  var searchResult = [];

  if (keyword.length > 0) {
    $('#search-result').show();
  } else {
    $('#search-result').hide();
  }
  $('.result-item').remove();
  ...
});

検索バーへ検索語を入力すると、検索語を小文字にして、検索結果を画面へ表示するためのHTMLを画面に表示させます。

$('#search').on('keyup', function () {
  ...
  for (var i = 0; i < posts.length; i++) {
    var post = posts[i];
    if (
      post.title.toLowerCase().indexOf(keyword) >= 0 ||
      post.description.toLowerCase().indexOf(keyword) >= 0
    ) {
      searchResult.push(post);
    }
  }
  ...
});

その後、検索結果のデータをループしながら、タイトルと説明文へ一致する項目を探します。

$('#search').on('keyup', function () {
 ...
  if (searchResult.length === 0) {
    ...
  } else {
    ...
  }
});

最後は検索結果がない場合は検索結果がありません。を表示して、検索結果がある場合は、ループをしながらリストを表示します。

検索バーを表示

下記のコードを使って検索バーを表示したい場所へ表示することができます。


{% include search_bar.html %}

完了

私が作ったソースコードを紹介したので、内容が考えたより多くなりました。このブログポストで最も重要なことはJSONデータを作ることです。他のものは皆さんの素敵なデザインで検索バーを作って、簡単なJavascriptコードを作ったJSONデータを検索します。

皆さんも皆さんのJekyllブログへ素敵な検索バーを入れてみてください!

私のブログが役に立ちましたか?下にコメントを残してください。それは私にとって大きな大きな力になります!

アプリ広報

今見てるブログを作成たDekuが開発したアプリを使ってみてください。
Dekuが開発したアプリはFlutterで開発されています。

興味がある方はアプリをダウンロードしてアプリを使ってくれると本当に助かります。

Posts