この記事はチュートリアルとしても考えられ、hugo ウェブサイトに検索機能を追加し、ホットリロードを実現して、より良い体験を提供します。
他のプログラムの場合、特定のテンプレートに従って以下の形式のファイルを生成するだけで済みます。主なコードは第 2 部から始まり、最初の章では hugo を使って記事リストの json ファイルを出力する方法について説明しています。
title
は記事のタイトル、permalink
は記事のリンクです。
[{
"permalink": "",
"title": ""
}, {
"permalink": "",
"title": ""
}]
1. hugo テンプレートで記事リストの json ファイルを生成する#
layouts
フォルダ内にindex.json
ファイルを新規作成し、テンプレート内容は以下の通りです:
2 行目の最後の "blog"
はあなたの記事フォルダの名前です。大部分は posts などですが、ここは私個人の名前です。
{{- $.Scratch.Set "posts" slice -}}
{{- range where .Site.RegularPages "Type" "blog" -}}
{{- $.Scratch.Add "posts" (dict "title" .Title "permalink" .Permalink) -}}
{{- end -}}
{{- $.Scratch.Get "posts" | jsonify -}}
このテンプレートに従って、hugo のローカルプレビューを開くと、http://localhost:1313/index.json
で確認できます。以下のようなデータが出力された場合、成功を意味します。
2. js コード#
/layouts/_default
に新しいテンプレートファイルsearch.html
を作成し、他のテンプレートファイルを参考に大まかな構造を作成し、必要な内容を書き込みます。
まずはシンプルな html 構造を作成し、input にイベントをバインドします。
<form class="search">
<input type="text" id="searchTerm" name="searchTerm" autocomplete="off" oninput="initiateSearch()">
</form>
<div id="resultsContainer">キーワードを入力して検索...</div>
次に、get リクエストを通じて json ファイルを取得し、キーワードパラメータを渡して検索リストを生成します。
<script>
function search(jsonData, searchTerm) {
let results = [];
for (let i = 0; i < jsonData.length; i++) {
for (let property in jsonData[i]) {
if (jsonData[i].hasOwnProperty(property) && jsonData[i][property].toString().indexOf(searchTerm) > -1) {
results.push(jsonData[i]);
break;
}
}
}
return results;
}
function displayResults(searchResults) {
let container = document.getElementById("resultsContainer");
container.innerHTML = "";
if (searchResults.length > 0) {
for (let i = 0; i < searchResults.length; i++) {
let resultDiv = document.createElement("div");
let resultTitle = document.createElement("a");
resultTitle.innerText = searchResults[i].title;
resultTitle.setAttribute('href', searchResults[i].permalink)
resultDiv.appendChild(resultTitle);
container.appendChild(resultDiv);
}
} else {
let noResultsMessage = document.createElement("p");
noResultsMessage.innerText = "検索結果が見つかりませんでした。";
container.appendChild(noResultsMessage);
}
}
function initiateSearch() {
let searchTerm = document.getElementById("searchTerm").value;
let xhr = new XMLHttpRequest();
xhr.open('GET', '/index.json', true);
xhr.onreadystatechange = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
let jsonData = JSON.parse(xhr.responseText);
let searchResults = search(jsonData, searchTerm);
displayResults(searchResults);
}
};
xhr.send();
}
</script>
次に、/content
に新しいsearch.md
ファイルを作成し、このテンプレートを呼び出します。
---
slug: search
title: 検索
layout: search
---
基本的なスタイルを書きましたので、そのまま使用できます。
.search {
width: 100%;
display: flex;
align-items: center;
height: 36px;
}
.search #searchTerm {
width: 100%;
height: 100%;
outline: none;
border: none;
padding: 0 15px;
box-shadow: 1px 2px 10px rgba(0, 0, 0, 0.1);
}
#resultsContainer {
margin-top: 20px;
}
#resultsContainer div {
margin-bottom: 10px;
margin: 0;
}
#resultsContainer div a {
display: block;
width: 100%;
padding: 6px 10px;
transition: all 0.1s linear;
border-radius: 4px;
}
#resultsContainer div a:hover {
background: #f3f3f3;
}