Jekyll-Potion

navigation

navigation 는 디렉토리로 구조화된 메뉴 트리를 표현하는 tag 로서 layout 에서 사용됩니다.

기본적인 선언은 다음과 같습니다.

복사성공!
1
{% navigation %}

navigationproto theme 의 기본 template, javascript, stylesheet 는 다음과 같습니다.

이 값은 새로운 theme 작성시 용도에 맞게 변경이 가능합니다.

  • template
  • javascript
  • stylesheet
navigation.liquid
복사성공!
1
2
3
4
5
<ul class="nav-menu">
    {% for potion in navigation %}
        {% navigation-page %}
    {% endfor %}
</ul>

template 작성 항목

변수명 필수여부 설명
navigation Y markdown 페이지 목록
navigation-page Y markdown 페이지 링크 tag
navigation-page.liquid
복사성공!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<li data-nav-link-id="{{ potion.url }}">
    <div class="nav-link fold{% if potion.has_child? %} has-child {% endif %}" data-fold-target-id="{{ potion.url }}">
        <a href="{{ potion.url }}" class="nav-href" data-nav-link>{{ potion.title }}</a>
        <span class="nav-unfold" data-unfold-id="{{ potion.url }}"> </span>
        <span class="nav-fold" data-fold-id="{{ potion.url }}"> </span>
    </div>
    {% if potion.has_child? %}
        <ul class="nav-menu">
            {% for potion in potion.children %}
                {% navigation-page %}
            {% endfor %}
        </ul>
    {% endif %}
</li>

template 작성 항목

변수명 필수여부 설명
potion.url Y 분석된 페이지의 url
potion.has_child? Y 페이지의 하위 페이지 유무
data-fold-target-id   하위 페이지가 있을 경우 접고 펼치는 기능에 대한 target id
만일 접고 펼치는 기능이 필요하지 않을 경우 제외 가능
data-nav-link Y javascript 를 통한 제어를 위한 key
potion.title Y 분석된 페이지의 title
data-unfold-id Y 하위 페이지 목록을 접기 위한 key
만일 접고 펼치는 기능이 필요하지 않을 경우 제외 가능
data-fold-id Y 하위 페이지 목록을 펼치기 위한 key
만일 접고 펼치는 기능이 필요하지 않을 경우 제외 가능
potion.children Y 하위 페이지 목록
navigation-page Y 하위 페이지 markdown 페이지 링크 tag
navigation.js
복사성공!
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
29
30
31
32
33
34
35
36
37
38
39
40
(($) => {
  class Navigation {
    constructor(options) {
      this.options = options
    }

    static matchPath(path, requestPath) {
      return new RegExp(path + '(/|/?#([^/]*))?$').test(requestPath)
    }

    init(pathname) {
      $('[data-unfold-id]:not([data-potion-handled])')
        .attr('data-potion-handled', 'true')
        .on('click', e => {
          $('[data-fold-target-id=\'' + $(e.currentTarget).attr('data-unfold-id') + '\']').removeClass('{{ fold_class }}')
        })

      $('[data-fold-id]:not([data-potion-handled])')
        .attr('data-potion-handled', 'true')
        .on('click', e => {
          $('[data-fold-target-id=\'' + $(e.currentTarget).attr('data-fold-id') + '\']').addClass('{{ fold_class }}')
        })

      let all_links = $('[data-nav-link-id]')
      all_links.removeClass('{{ active_class }}')

      let $selected = all_links.filter((_, nav_link) => Navigation.matchPath($(nav_link).attr('data-nav-link-id'), pathname))

      $selected.addClass('{{ active_class }}')
      $('[data-fold-target-id=\'' + pathname + '\']').removeClass('{{ fold_class }}')

      $selected.parents('[data-nav-link-id]').filter((_, p) => $(p).has($selected).length)
        .each((_, nav_link) => $('[data-fold-target-id=\'' + $(nav_link).attr('data-nav-link-id') + '\']').removeClass('{{ fold_class }}'))
    }
  }

  $.navigation = (options) => {
    return new Navigation(options)
  }
})(jQuery)

jekyll-potionjquery 를 사용합니다.

javascript 는 {{ ~ }} 을 포함한 template 이며, 설정에서 결정한 값을 매핑하여 javascript 파일을 생성합니다.

{{ ~ }} 구문은 태그 설정theme[].tags.navigation 항목을 참고해 주세요.

함수 설명

함수명 설명
init HTML 요소 내 data-unfold-id, data-fold-id, data-nav-link-id 로 설정한 attribute 를 찾고, data-nav-link-id 로 설정된 메뉴 링크에 대한 동작, 하위 메뉴에 대한 접기, 펼치기에 대한 event 처리를 초기화 합니다. event 를 추가한 다음 data-potion-handled attribute 를 추가하며, data-potion-handled attribute 가 추가된 HTML 요소에 대해서는 더 이상 event 를 추가하지 않습니다.

사용법

복사성공!
1
2
3
let navigation = $.navigation()

navigation.init() // 문서의 load, 갱신 시 호출해줍니다.
복사성공!
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
& > nav {
  flex: 0 0 300px;
  
  height: calc(100% - 5em);
  overflow-y: scroll;
  overflow-x: hidden;
  padding-block-start: 1em;
  @include border(border-right);
  
  & > div.nav-container {
    width: 100%;
    height: 100%;
    margin-inline-end: 0.8em;
  
    ul {
      display: block;
      list-style-type: none;
      margin-block: 0;
      margin-inline: 0;
      padding-inline-start: 0;
    }
  
    li {
      display: block;
      padding-inline-start: 1em;
  
      & > div.nav-link {
        display: flex;
        padding-block-start: 0.2em;
        padding-block-end: 0.5em;
        padding-inline-start: 0.3em;
        color: black;
  
        &:hover {
          background-color: gray;
          color: white;
        }
  
        & > a.nav-href {
          flex: auto;
          width: 90%;
          color: inherit;
          text-decoration: none;
        }
  
        %span-nav {
          width: 1em;
          flex: auto;
          display: none;
          color: inherit;
  
          &:hover {
            cursor: pointer;
          }
        }
  
        & > span.nav-unfold {
          @include unfold("black", 50%);
          @extend %span-nav;
        }
  
        & > span.nav-fold {
          @include fold("black", 50%);
          @extend %span-nav;
        }
  
        &.has-child {
          & > span.nav-unfold {
            display: none;
          }
  
          & > span.nav-fold {
            display: block;
          }
  
          & + ul.nav-menu {
            display: block;
          }
  
          &.fold {
            & > span.nav-unfold {
              display: block;
            }
  
            & > span.nav-fold {
              display: none;
            }
  
            + ul.nav-menu {
              display: none;
            }
          }
        }
      }
  
      &.active {
        & > div.nav-link {
          background-color: lightgray;
          @include border(border);
          border-inline: none;
          color: blue;
        }
      }
    }
  }
}