블로그 꾸미다 검색기능이 있으면 좋을꺼 같다 생각했는데 오픈소스 라이브러리가 있어 사용하기로 했습니다.
일단 깃헙에서 설명문을 보며 필요한 부분만 찾아보도록 합시다.
search.json 파일을 만들어 블로그의 루트파일에 넣어주어야 합니다.
이 파일을 통해 정렬에 사용할 객체를 생성해줍니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
---
layout: none
---
[
{% for post in site.posts %}
{
"title" : "{{ post.title | escape }}",
"category" : "{{ post.category }}",
"tags" : "{{ post.tags | join: ', ' }}",
"url" : "{{ site.baseurl }}{{ post.url }}",
"date" : "{{ post.date | date: '%m/%d/%Y' }}"
} {% unless forloop.last %},{% endunless %}
{% endfor %}
]
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
---
layout: none
---
[
{% for post in site.posts %}
{
"title" : "{{ post.title | escape }}",
"category" : "{{ post.category }}",
"tags" : "{{ post.tags | join: ', ' }}",
"url" : "{{ site.baseurl }}{{ post.url }}",
"date" : "{{ post.date }}",
"content" : "{{ post.content | remove_chars | escape | strip_html | strip_newlines | remove: '\' }}"
} {% unless forloop.last %},{% endunless %}
{% endfor %}
,
{% for page in site.pages %}
{
{% if page.title != nil %}
"title" : "{{ page.title | escape }}",
"category" : "{{ page.category }}",
"tags" : "{{ page.tags | join: ', ' }}",
"url" : "{{ site.baseurl }}{{ page.url }}",
"date" : "{{ page.date }}",
"content" : "{{ page.content | remove_chars | escape | strip_html | strip_newlines | remove: '\' }}"
{% endif %}
} {% unless forloop.last %},{% endunless %}
{% endfor %}
]
모든 텍스트에서 찾기위해서 처음에는 두번째처럼 설정했었는데 검색 결과가 만족스럽지 않아 첫번째 코드를 사용하려합니다.
두번째 코드에서 remove: ‘\‘를 추가한 이유는 content 텍스트에 해당 단어가 포함되어 있으면 json파일이 깨지기 때문입니다.
또한 Mac 환경과 Windows 환경을 왔다갔다해서 그런지 일부 텍스트 중 Tab과 스페이스가 혼합되어 json을 제대로 못 만드는 경우가 있어 Tab을 모두 space로 변경해주었습니다.
다음으로 해줄 일은 플러그인에 필요한 DOM(문서 객체 모델)을 만들어주어야 합니다.
필요한 DOM은
입니다.
직접 구현해줄 수도 있고 라이브러리에서 제공하는 js파일을 사용할 수 있습니다.
1
2
3
4
5
6
<!-- HTML elements for search -->
<input type="text" id="search-input" placeholder="Search blog posts..">
<ul id="results-container"></ul>
<!-- or without installing anything -->
<script src="https://unpkg.com/simple-jekyll-search@latest/dest/simple-jekyll-search.min.js"></script>
저는 기본으로 제공하는 스타일보다 다른 스타일을 적용하도록 하겠습니다.
https://material.io/components/text-fields를 적용해보려 합니다.
cdn을 이용해서 다음과 같이 빠르게 적용해볼 수 있습니다.
link를 해주고
1
2
3
<link href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css" rel="stylesheet">
<script src="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js"></script>
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
자신이 원하는 모양을 적용해줍니다.
1
2
3
4
5
<label class="mdc-text-field mdc-text-field--filled">
<span class="mdc-text-field__ripple"></span>
<input class="mdc-text-field__input" type="text" id="search-input" placeholder="Search Keyword" size="120" aria-label="Label"></textarea>
<span class="mdc-line-ripple"></span>
</label>
결과 리스트도 통일성을 위해 material을 적용하도록 하겠습니다.
저는 https://material.io/components/lists를 사용하려 합니다.
1
<ul class="mdc-list mdc-list--two-line" id="results-container"></ul>
리스트를 담을 컨테이너만 선언해주고 템플릿은 이후 과정에서 추가해줍니다.
SimpleJekyllSearch
함수의 옵션들을 살펴보면서 사용해 봅니다.
searchInput
위에서 원하는 엘리먼트에 id="search-input"
를 지정하고 document.getElementById('search-input')
와 같이 선언하여 매칭합니다.
resultsContainer
일반적으로 <ul>
을 사용합니다. searchInput처럼 document.getElementById('results-container')
와 같이 선언하여 매칭합니다.
json
search.json로 설정해줍니다.
searchResultTemplate
이 부분이 위에서 설명한 results-container에 담을 리스트 형태를 지정해줍니다.
저는 이런식으로 사용하려합니다.
1
2
3
4
5
6
7
8
9
`
<li class="mdc-list-item">
<span class="mdc-list-item__ripple"></span>
<span class="mdc-list-item__text">
<a href="{url}"><span class="mdc-list-item__primary-text">{title}</span></a>
<span class="mdc-list-item__secondary-text"><i class="fa fa-tag"></i> {tags}</span>
</span>
</li><hr>
`
templateMiddleware
템플릿에서 일치하는 항목이 발견될 때 호출하는 함수를 정의할 수 있습니다.
해당 속성의 이름, 값과 템플릿이 전달됩니다.
함수가 정의하지 않은 값을 반환하면 해당 값으로 템플릿에서 반환됩니다.
주로 URL 조작등에 사용한다고 합니다.
sortMiddleware
필터링된 결과를 정렬하는데 사용할 수 있는 함수입니다. 아마 우선순위를 세팅하는 것 같은데 정말 간단하게 날짜로 해봅니다.
noResultsText
결과가 없을때 출력할 텍스트입니다. 샘플과 동일하게 ‘No results found’ 를 추가하였습니다.
limit
결과 개수 제한입니다. 넉넉하게 30으로 하였습니다.
fuzzy
좀더 유연한 검색을 가능하게 해줍니다. 저는 false로 세팅하여 엄격하게 제한하도록 하려합니다.
exclude
제외하고 싶은 문구를 추가할 수 있습니다. 굳이 필요없어 보여 넘어가도록 하겠습니다.
success
데이터가 로드되었을 때 호출해주고 싶은 함수를 추가할 수 있습니다.
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
<script src="/js/simple-jekyll-search.js"></script>
<script type="text/javascript">
SimpleJekyllSearch({
searchInput: document.getElementById('search-input'),
resultsContainer: document.getElementById('results-container'),
json: '/search.json',
searchResultTemplate: `
<li class="mdc-list-item">
<span class="mdc-list-item__ripple"></span>
<span class="mdc-list-item__text">
<a href="{url}"><span class="mdc-list-item__primary-text">{title}</span></a>
<span class="mdc-list-item__secondary-text">{date}, <i class="fa fa-tag"></i>{tags}</span>
</span>
</li><hr>
`,
sortMiddleware: function(a, b) {
var adate = String(a.date);
var bdate = String(b.date);
return adate.localeCompare(bdate)
},
noResultsText: 'No results found',
limit: 30,
fuzzy: false
})
</script>
제가 만들고 싶은대로 필요한부분만 채워보았습니다.
simple-jekyll-search.js는 샘플 프로젝트에서 그대로 가져왔습니다.
날짜순으로 정렬된 것도 확인하였고 결과가 그럭저럭 괜찮게 나왔습니다.