LearnApplyShare

jekyll 블로그 tag 기능 추가

August 10, 2018 - [jekyll, tags]

Intro

얼마 전에 추가했던 카테고리 기능만으로는 왠지 아쉬움이 있어 태그 기능을 추가하기로 했다. 지킬블로그는 모 하나 기능 붙이려면 여간 귀찮은 게 아니다. 관련하여 여러가지 글들을 읽어 보았지만 johngrib 님의 아래 글이 따라하기 가장 쉬웠던 것 같다.

https://johngrib.github.io/blog/2017/01/22/jekyll-category-tag

위 내용을 토대로 태그 기능을 추가한 과정을 공유한다


포스트에 태그 입력방법

글 작성시 front-matter 영역에 아래와 같이 tags 항목을 추가하면 된다

---
layout: post
title:  "[jekyll] tag 기능 추가"
date:   2018-08-11 01:00:00 +0900
categories: jekyll
tags: [jekyll, tags]
---

태그목록을 보여줄 화면 만들기

아래와 같은 모습으로 태그목록을 보여주는 화면을 만들 것이다


/tag.md

먼저 링크를 새로 따기 위해서 루트 경로에 tag.md 파일을 만들었다. layout으로 tag를 지정했기 때문에 /layout/tag.html 파일을 끌어올 것이다.

---
layout: tag
permalink: /tags/
title: Tags
---

/layout/tag.html

tag.html 에서는 전체 포스트에서 사용된 모든 태그의 목록을 보여줄 것이다. 11~13라인에서 땡겨오는 tag_cloud.html 은 필수요소는 아니지만. 태그클라우드를 이쁘게 보여주고 싶은 욕심에 추가해 보았다. 원치 않으면 제거해도 된다.

---
layout: default
---
<article class="tag">
<div>
<header class="post-header">
<h1 class="page-heading">Tag cloud</h1>
</header>
<div>
{% include tag_cloud.html %}
</div>
<div>
{% for tag in site.tags %}
<!-- tag_name 변수 지정: 태그명은 소문자화(slugize) 한다 -->
{% capture tag_name %}{{tag|first|slugize}}{% endcapture %}
<!-- tag_size 변수 지정-->
{% capture tag_size %}{{tag|last|size}}{% endcapture %}
<!-- font_size 변수 지정: 태그숫자/전체태그숫자 * 100 + 50 -->
{% capture font_size %}{{tag_size | times: site.tags.size | divided_by:site.tags.size | plus: 14 }}{% endcapture %}
<div class="tagname">
<a href="/tags/archives#{{tag_name}}" style="font-size:{{font_size}}px">{{ tag_name }}</a>
</div>
{% endfor %}
</div>
</div>
</article>
view raw tag.html hosted with ❤ by GitHub

/includes/tag_cloud.html

태그클라우드 렌더링은 jasondavies 의 tag-cloud 소스를 이용했다. 아래 소스는 태그클라우드 demo화면의 소스를 일부 수정한 것이다.

<!--
태그 클라우드
https://github.com/jasondavies/d3-cloud
-->
<div id="vis"></div>
<form id="form" style="display:none;">
<p style="position: absolute; right: 0; top: 0" id="status"></p>
<div style="text-align: center">
<div id="presets"></div>
<div id="custom-area">
<p><label for="text">Paste your text below!</label>
<p><textarea id="text">
{% for tag in site.tags %}
{% capture tag_name %}{{tag|first|slugize}}{% endcapture %}
{% capture tag_size %}{{tag|last|size|times:5}}{% endcapture %}
{% for i in (1..tag_size) %}
{{ tag_name }}
{% endfor %}
{% endfor %}
</textarea>
<button id="go" type="submit">Go!</button>
</div>
</div>
<hr>
<div style="float: right; text-align: right">
<p><label for="max">Number of words:</label> <input type="number" value="250" min="1" id="max">
<p><label for="per-line"><input type="checkbox" id="per-line"> One word per line</label>
<!--<p><label for="colours">Colours:</label> <a href="#" id="random-palette">get random palette</a>-->
<p><label>Download:</label>
<button id="download-svg">SVG</button><!-- |
<a id="download-png" href="#">PNG</a>-->
</div>
<div style="float: left">
<p><label>Spiral:</label>
<label for="archimedean"><input type="radio" name="spiral" id="archimedean" value="archimedean" checked="checked"> Archimedean</label>
<label for="rectangular"><input type="radio" name="spiral" id="rectangular" value="rectangular"> Rectangular</label>
<p><label for="scale">Scale:</label>
<label for="scale-log"><input type="radio" name="scale" id="scale-log" value="log" checked="checked"> log n</label>
<label for="scale-sqrt"><input type="radio" name="scale" id="scale-sqrt" value="sqrt"> √n</label>
<label for="scale-linear"><input type="radio" name="scale" id="scale-linear" value="linear"> n</label>
<p><label for="font">Font:</label> <input type="text" id="font" value="Impact">
</div>
<div id="angles">
<p><input type="number" id="angle-count" value="5" min="1"> <label for="angle-count">orientations</label>
<label for="angle-from">from</label> <input type="number" id="angle-from" value="-60" min="-90" max="90"> °
<label for="angle-to">to</label> <input type="number" id="angle-to" value="60" min="-90" max="90"> °
</div>
<hr style="clear: both">
<p style="float: right"><a href="about/">How the Word Cloud Generator Works</a>.
<p style="float: left">Copyright &copy; <a href="http://www.jasondavies.com/">Jason Davies</a> | <a href="../privacy/">Privacy Policy</a>. The generated word clouds may be used for any purpose.
</form>
<script src="https://www.jasondavies.com/d3.min.js"></script>
<script src="https://www.jasondavies.com/wordcloud/cloud.min.js"></script>
<script>
// tag-cloud 크기를 스크린 사이즈에 따라 보정 18.08.11
function resizeTagCloud(){
if(document.body.offsetWidth < 800){
document.getElementById("vis").style.zoom = 0.8 * (document.body.offsetWidth/800)
}
}
window.onload = window.onresize = resizeTagCloud;
</script>
view raw tag_cloud.html hosted with ❤ by GitHub

/_sass/whiteglass/_layout.scss

태그클라우드와 태그목록의 스타일을 추가한다. 이 내용은 사용하는 블로그 스킨에 따라 추가하는 경로가 다를 수 있으니 적절한 곳에 추가하도록 한다.

/**
 * tag_cloud
 */
#presets a {
  border-left: solid #666 1px;
  padding: 0 10px;
}
#presets a.first {
  border-left: none;
}
#keyword {
  width: 300px;
}
#fetcher {
  width: 500px;
}
#keyword,
#go {
  font-size: 1.5em;
}
#text {
  width: 100%;
  height: 100px;
}
p.copy {
  font-size: small;
}
#form {
  font-size: small;
  position: relative;
}
hr {
  border: none;
  border-bottom: solid #ccc 1px;
}
a.active {
  text-decoration: none;
  color: #000;
  font-weight: bold;
  cursor: text;
}
#angles line,
#angles path,
#angles circle {
  stroke: #666;
}
#angles text {
  fill: #333;
}
#angles path.drag {
  fill: #666;
  cursor: move;
}
#angles {
  text-align: center;
  margin: 0 auto;
  width: 350px;
}
#angles input,
#max {
  width: 42px;
}

#vis {
  zoom: 0.8;
}

/**
 * tag_list
 */
.tag {
  .tagname {
    transition: all 0.1s ease-in-out;
    display: inline-block;
    margin-left: 10px;
    &:hover {
      transform: scale(1.1);
      -webkit-transform: scale(1.1);
    }
    a {
      color: $grey-color;
    }
  }
}

여기까지 작업이 완료되었으면 `http://localhost:4000/tags` 로 접근할 때 태그클라우드&태그목록 화면을 볼 수 있을 것이다. 이제 태그목록에서 태그명을 클릭하면 해당 태그를 가진 포스트 목록을 보여줄 화면을 만들 것이다. 위쪽의 태그클라우드(svg)에서도 태그를 클릭할 수 있으면 더 없이 좋겠지만 d3를 만질 수 있는 실력이 되지 않아 포기했다. OTL

태그에 해당하는 포스트목록 화면

이제 아래와 같이 사이트의 전체 태그 별 포스트목록을 보여주는 화면을 만들 것이다.


/tag_archives.md

태그당 포스트목록 화면의 링크는 /tags/archives 로 정한다(물론 본인이 원하는데로 parmalink 값을 정해도 무관한다)

---
layout: tag_archives
permalink: /tags/archives
title: Tags
---

/layouts/tag_archives.html

태그목록 화면에서(~/tags) 태그 클릭시 링크에 따라 해당 태그의 글목을 바로 보여주기 위하여 13라인의 div태그에 id를 태그명으로 각각 지정했음을 주목 해주기 바란다.

---
layout: default
---
<article class="home">
<div>
<header class="post-header">
<h1 class="page-heading">Archives by tag</h1>
</header>
<div>
{% for tag in site.tags%}
<div style="margin-bottom: 50px;">
{% capture tag_name %}{{tag|first|slugize}}{% endcapture %}
<div id="{{ tag_name }}"></div>
<h4 class="category-head">* {{ tag_name }}</h4>
<ul class="post-archives">
{% for post in site.tags[tag_name] %}
<li style="margin-left: 20px;">
<span class="post-meta">
{{ post.date | date: "%b %-d, %Y" }}
{% if post.categories != empty or post.tags != empty %}
{% include category_links.html categories=post.categories tags=post.tags %}
{% endif %}
{% if post.external-url %}
• <a href="{{ post.url | relative_url }}">Permalink</a>
{% endif %}
</span>
<h2>
{% if post.external-url %}
<a class="post-link" href="{{ post.external-url }}">{{ post.title | escape }} &rarr;</a>
{% else %}
<a class="post-link" href="{{ post.url | relative_url }}"{% if lang != empty %} lang="{{ lang }}"{% endif %}>{{ post.title | escape }}</a>
{% endif %}
</h2>
</li>
{% endfor %}
</ul>
</div>
{% endfor %}
</div>
</div>
{% if true or site.disqus.comments == true and jekyll.environment == "production" %}
<div class="post-comments" itemprop="comment">
{% include custom_comments_provider.html %}
</div>
{% endif %}
</article>

또는 아래와 같이 해당하는 태그의 글목록만 보여주는 것도 가능하다.

위와 같이 처리하려면 각 태그별 글항목 div를 모두 display: none; 으로 처리하되(아래 소스 12라인) 마지막에 스크립트를 이용하여(53라인) 현재 태그에 해당하는 항목만 display: block; 으로 처리한다.

---
layout: default
---
<article class="home">
<div>
<header class="post-header">
<h1 class="page-heading">Archives by tag</h1>
</header>
<div>
{% for tag in site.tags%}
{% capture tag_name %}{{tag|first|slugize}}{% endcapture %}
<div style="margin-bottom: 50px; display: none;" id="{{ tag_name }}">
<h4 class="category-head">* {{ tag_name }}</h4>
<ul class="post-archives">
{% for post in site.tags[tag_name] %}
<li style="margin-left: 20px;">
<span class="post-meta">
{{ post.date | date: "%b %-d, %Y" }}
{% if post.categories != empty or post.tags != empty %}
{% include category_links.html categories=post.categories tags=post.tags %}
{% endif %}
{% if post.external-url %}
• <a href="{{ post.url | relative_url }}">Permalink</a>
{% endif %}
</span>
<h2>
{% if post.external-url %}
<a class="post-link" href="{{ post.external-url }}">{{ post.title | escape }} &rarr;</a>
{% else %}
<a class="post-link" href="{{ post.url | relative_url }}"{% if lang != empty %} lang="{{ lang }}"{% endif %}>{{ post.title | escape }}</a>
{% endif %}
</h2>
</li>
{% endfor %}
</ul>
</div>
{% endfor %}
</div>
</div>
{% if true or site.disqus.comments == true and jekyll.environment == "production" %}
<div class="post-comments" itemprop="comment">
{% include custom_comments_provider.html %}
</div>
{% endif %}
</article>
<script>
document.getElementById(decodeURIComponent(location.hash.substr(1)+"_")).style.display = "block";
</script>

글 내용에 태그 보여주기

앞서 front-matter에 지정한 tag를 글보기 화면에서 보여줄 필요가 있는데. 글보기 화면에서 필요한 부분에 아래 소스를 삽입한다

<div>
** 태그표시 시작 **
<br>
{% if page.tags != empty %}
[{% for tag in page.tags %}
<a href="/tags/archives#{{ tag | escape }}">{{tag}}</a>
{% if forloop.index != page.tags.size %},{% endif %}
{% endfor %}]
{% endif %}
<br>
** 태그표시 끝 **
</div>
view raw renderTag.html hosted with ❤ by GitHub

실행결과

** 태그표시 시작 **
{% if page.tags != empty %} [{% for tag in page.tags %} {{tag}} {% if forloop.index != page.tags.size %},{% endif %} {% endfor %}] {% endif %}
** 태그표시 끝 **

Tags 메뉴 추가

새롭게 추가되는 Tags 메뉴는

/_config.yml 설정에서 navigation 항목에 적절하게 추가한다

navigation:
- title: About
url: /about
- title: Category
url: /category
- title: Tags
url: /tags
- title: Archives
url: /archives
view raw _config.yml hosted with ❤ by GitHub