플러그인

Jekyll 은 Hook 을 제공하는 플러그인 시스템을 갖추고 있어서 자신의 사이트에 꼭 맞는 컨텐츠를 생성할 수 있습니다. 따라서, Jekyll 의 소스코드를 직접 수정하지 않고도 자신의 코드가 실행되게 할 수 있습니다.

GitHub Pages 와 플러그인

GitHub Pages 는 Jekyll 을 사용합니다. 하지만 보안상의 이유로 인해, 모든 Pages 사이트는 --safe 옵션으로 사용자 플러그인이 비활성화된 상태에서 생성됩니다. 이 말은 안타깝게도, GitHub Pages 에서는 당신의 플러그인을 사용할 수 없다는 뜻입니다.

그래도 GitHub Pages 와 사용자 플러그인을 함께 사용하는 방법이 있습니다. GitHub 에 소스를 직접 올리는 대신, 로컬 시스템에서 변환을 먼저 한 후 생성된 파일을 올리면 됩니다.

플러그인 설치하기

플러그인을 설치하는 방법은 세 가지가 있습니다:

  1. Site Source 루트에 _plugins 디렉토리를 만드세요. 여기에 자신의 플러그인을 넣습니다. Jekyll 은 사이트를 생성하기 직전에 이 디렉토리의 모든 *.rb 파일을 읽어들입니다.
  2. _config.yml 파일에 gems 라는 키로 배열을 추가하고 사용하려는 플러그인들의 gem 이름을 나열하세요. 예를 들면 다음과 같습니다:

     gems: [jekyll-test-plugin, jekyll-jsonify, jekyll-assets]
     # This will require each of these gems automatically.
    

    다음 gem install jekyll-test-plugin jekyll-jsonify jekyll-assets 라고 실행하여 해당 플러그인들을 설치합니다.

  3. Gemfile 의 Bundler 그룹에 관련 플러그인을 추가합니다. 예를 들면 다음과 같습니다:

     group :jekyll_plugins do
       gem "my-jekyll-plugin"
       gem "another-jekyll-plugin"
     end
    

    이제 bundle install 명령만 한 번 실행해주면 Bundler 그룹에 있는 모든 플러그인이 설치됩니다.

_plugins_config.yml, Gemfile 은 동시에 사용할 수 있습니다

원한다면 앞서 언급한 플러그인 옵션들을 한 사이트에 동시에 사용할 수 있습니다. 어떤 옵션을 사용한다고 해서 다른 옵션을 사용하는데에 제약이 생기는 것은 아닙니다.

일반적으로, 플러그인은 네 가지 카테고리 중 하나에 속하게 됩니다:

  1. 생성기
  2. 변환기
  3. 명령어
  4. 태그

생성기

생성기를 만들어 Jekyll 로 하여금 당신이 정한 규칙에 따라 부가적인 컨텐츠를 생성하도록 할 수 있습니다.

생성기는 Jekyll::Generator 의 하위 클래스로서, Jekyll::Site 인스턴스를 전달받는 generate 메소드 가지고 있습니다. generate 메소드의 리턴값은 무시됩니다.

생성기는 Jekyll 이 컨텐츠 목록을 파악하고 난 후, 그리고 사이트가 생성되기 직전에 실행됩니다. YAML 머리말을 가진 페이지들은 Jekyll::Page 인스턴스로 저장되어 site.pages 로 사용할 수 있습니다. 정적 파일들은 Jekyll::StaticFile 인스턴스가 되어 site.static_files 로 사용할 수 있습니다. 더 자세한 내용은 변수 문서 페이지Jekyll::Site 를 살펴보세요.

예를 들어, 생성기는 빌드 시점에 계산된 값을 템플릿 변수에 주입할 수 있습니다. 다음 예제 생성기는 reading.html 템플릿의 두 변수 ongoingdone 에 값을 채워 넣습니다:

module Reading
  class Generator < Jekyll::Generator
    def generate(site)
      ongoing, done = Book.all.partition(&:ongoing?)

      reading = site.pages.detect {|page| page.name == 'reading.html'}
      reading.data['ongoing'] = ongoing
      reading.data['done'] = done
    end
  end
end

다음은 좀 더 복잡한 생성기로서, 새 페이지를 생성합니다:

module Jekyll

  class CategoryPage < Page
    def initialize(site, base, dir, category)
      @site = site
      @base = base
      @dir = dir
      @name = 'index.html'

      self.process(@name)
      self.read_yaml(File.join(base, '_layouts'), 'category_index.html')
      self.data['category'] = category

      category_title_prefix = site.config['category_title_prefix'] || 'Category: '
      self.data['title'] = "#{category_title_prefix}#{category}"
    end
  end

  class CategoryPageGenerator < Generator
    safe true

    def generate(site)
      if site.layouts.key? 'category_index'
        dir = site.config['category_dir'] || 'categories'
        site.categories.each_key do |category|
          site.pages << CategoryPage.new(site, site.source, File.join(dir, category), category)
        end
      end
    end
  end

end

이 생성기는 categories 안에 각 카테고리 별로 파일을 생성하고, category_index.html 레이아웃을 사용하여 각 카테고리 별 포스트 목록을 만듭니다.

생성기가 필수로 구현해야 할 메소드는 딱 하나입니다:

메소드 설명

generate

컨텐츠를 생성합니다.

변환기

당신의 사이트에 사용하고자 하는 다른 마크업 언어가 있다면, 해당 언어를 처리할 수 있는 변환기를 직접 구현하면 됩니다. Markdown 과 Textile 마크업 언어도 이 메소드 사용해서 구현한 것입니다.

YAML 머리말을 잊지 마세요

Jekyll 은 오직 YAML 머리말로 시작하는 파일만 변환합니다. 변환기 플러그인을 추가해서 사용할때도 마찬가지 입니다.

아래 예제는 .upcase 로 끝나는 모든 포스트를 읽어서 UpcaseConverter 로 처리하는 변환기입니다:

module Jekyll
  class UpcaseConverter < Converter
    safe true
    priority :low

    def matches(ext)
      ext =~ /^\.upcase$/i
    end

    def output_ext(ext)
      ".html"
    end

    def convert(content)
      content.upcase
    end
  end
end

변환기는 최소한 아래 3 가지 메소드를 구현해야 합니다:

메소드 설명

matches

주어진 확장자가 이 변환기가 처리할 수 있는 확장자 목록에 포함되어 있는가? 전달인자가 하나 필요합니다: 파일의 확장자 (점 포함). 포함되어 있다면 true 를, 그렇지 않다면 false 를 반환해야 합니다.

output_ext

출력할 파일의 확장자 (점 포함). 일반적으로 ".html" 가 될 것입니다.

convert

컨텐츠를 변환하는 로직. 전달인자가 하나 필요합니다: 변환되지 않은 파일 내용 (YAML 머리말 제외). 반드시 문자열을 반환해야 합니다.

위 예제에서는, UpcaseConverter#matches 는 확장자가 .upcase 인지 확인하고, 만약 그렇다면 내용을 변환하기 위해 UpcaseConverter#convert 를 호출합니다. 이 예제에서 변환기는 단순히 전체 내용을 대문자로 변환합니다. 마지막으로, 변환된 내용을 페이지로 저장할 때 .html 확장자를 사용합니다.

명령어

버전 2.5.0 부터, Jekyll 은 jekyll 실행파일에 하위명령어를 추가로 제공하는 플러그인들로 확장될 수 있습니다. Gemfile:jekyll_plugins 라는 그룹에 관련 플러그인을 추가하면 됩니다:

group :jekyll_plugins do
  gem "my_fancy_jekyll_plugin"
end

명령어 는 반드시 Jekyll::Command 클래스의 하위 클래스이어야 하고 init_with_program 이라는 하나의 클래스 메소드를 가져야 합니다. 예를 들면 다음과 같습니다:

class MyNewCommand < Jekyll::Command
  class << self
    def init_with_program(prog)
      prog.command(:new) do |c|
        c.syntax "new [options]"
        c.description 'Create a new Jekyll site.'

        c.option 'dest', '-d DEST', 'Where the site should go.'

        c.action do |args, options|
          Jekyll::Site.new_site_at(options['dest'])
        end
      end
    end
  end
end

명령어는 반드시 이 클래스 메소드를 구현해야 합니다:

메소드 설명

init_with_program

이 메소드의 파라메터는 단 하나, Mercenary::Program 인스턴스인데 이는 바로 Jekyll 프로그램 그 자체입니다. 프로그램에 따라, 명령어는 위 문법을 사용해서 생성될 것입니다. 더 자세한 내용은, GitHub.com 의 Mercenary 저장소를 방문하세요.

태그

사이트에 자신의 Liquid 태그를 사용하고 싶다면, 태그 시스템의 Hook 을 사용하면 됩니다. Jekyll 에 내장된 highlightinclude 가 바로 그 예입니다. 다음 예제는 페이지가 생성된 시간을 출력해주는 Liquid 태그입니다:

module Jekyll
  class RenderTimeTag < Liquid::Tag

    def initialize(tag_name, text, tokens)
      super
      @text = text
    end

    def render(context)
      "#{@text} #{Time.now}"
    end
  end
end

Liquid::Template.register_tag('render_time', Jekyll::RenderTimeTag)

Liquid 태그는 최소한 다음 메소드는 구현해야 합니다:

메소드 설명

render

태그 컨텐츠를 출력합니다.

그리고 다음과 같이 Liquid 템플릿 엔진에 태그를 등록해야 합니다:

Liquid::Template.register_tag('render_time', Jekyll::RenderTimeTag)

이렇게 하면, 페이지의 어느 곳에서나 다음과 같이 태그를 사용할 수 있습니다:

<p>{% render_time page rendered at: %}</p>

그러면 다음과 같은 결과를 얻을 수 있습니다:

<p>page rendered at: Tue June 22 23:38:47 –0500 2010</p>

Liquid 필터

Liquid 템플릿 시스템에 필터를 추가하는 것은 위에 설명한 태그 추가 방법과 상당히 유사합니다. 필터는 단지 자신의 메소드를 Liquid 로 보내는 모듈일 뿐입니다. 모든 메소드에는 최소한 하나의 매개변수가 있어야 하며, 이것은 바로 필터의 입력입니다. 반환 값이 필터의 출력이 됩니다.

module Jekyll
  module AssetFilter
    def asset_url(input)
      "http://www.example.com/#{input}?#{Time.now.to_i}"
    end
  end
end

Liquid::Template.register_filter(Jekyll::AssetFilter)
ProTip™: Liquid 를 사용해서 site 객체에 접근할 수 있습니다

Jekyll 은 context.registers[:site] 와 같이 Liquid 의 context.registers 기능을 통해서 site 객체에 접근할 수 있게 해줍니다. 예를 들어, context.registers[:site].config 라고 입력하여 전역 환경설정 파일 _config.yml 에 접근할 수 있습니다.

플래그

플러그인을 만들 때는 다음 두 플래그를 알아두어야 합니다:

플래그 설명

safe

이 플러그인이 임의의 코드가 실행되는 것이 금지된 환경에서도 안전하게 실행될 수 있다는 것을 알려주는 boolean 플래그입니다. GitHub Pages 는 실행해도 안전한 Core 플러그인을 골라내기 위해 이 플래그를 사용합니다. 플러그인이 임의의 코드 실행이 없는 환경에서 사용되어야 한다면, 이 플래그를 true 로 설정하세요. GitHub Pages 는 여전히 당신의 플러그인을 사용하지 않을 것입니다. 하지만, Jekyll 프로젝트에 포함시키려는 경우에는 이게 제일 좋은 방법입니다!

priority

플러그인을 읽어들이는 순서를 결정하는 플래그입니다. 사용할 수 있는 값은 :lowest:low, :normal, :high, :highest 입니다. 우선순위가 높은 플러그인이 먼저 적용되고, 우선순위가 낮은 플러그인이 나중에 적용됩니다.

앞서 설명한 플러그인 예제를 사용하려면, 다음과 같이 플래그를 설정해야 합니다:

module Jekyll
  class UpcaseConverter < Converter
    safe true
    priority :low
    ...
  end
end

Hook

Hook 을 사용하면, 당신의 플러그인이 사이트 빌드에 다방면으로 정교한 작업을 수행할 수 있습니다. 당신의 플러그인에 Hook 이 포함되어 있으면, Jekyll 은 정해진 시점에 해당 Hook 을 호출합니다.

Hook 은 이벤트 이름과 컨테이너에 등록됩니다. 등록하는 방법은, Jekyll::Hooks.register 를 호출하고 컨테이너, 이벤트 이름과 Hook 이 실행될 때 호출할 코드를 연결하는 것입니다. 예를 들어, Jekyll 이 포스트를 생성할 때마다 특정 코드를 실행하도록 하려면, 다음과 같이 Hook 을 등록하면 됩니다:

Jekyll::Hooks.register :posts, :post_render do |post|
  # Jekyll 이 포스트를 생성한 뒤 호출할 코드
end

Jekyll 은 :site, :pages, :posts:documents 에 관련된 Hook 을 제공합니다. 어떤 상황에서든, Jekyll 은 Hook 을 호출하며 첫 번째 매개변수로 컨테이너 객체를 넘겨줍니다. 하지만 :pre_render 의 경우에는 두 번째 매개변수로 페이로드 해시도 제공하는데, 이로 인해 렌더링 중 사용할 수 있는 변수들에 대해 완벽한 관리 권한을 얻을 수 있습니다.

사용 가능한 Hook 들의 전체 목록은 다음과 같습니다:

컨테이너 이벤트 호출 시점

:site

:after_reset

사이트가 초기화된 후

:site

:post_read

디스크로부터 사이트 데이터를 읽어들인 후

:site

:pre_render

전체 사이트를 렌더링하기 직전

:site

:post_render

전체 사이트를 렌더링한 직후 (파일 생성 전)

:site

:post_write

전체 사이트 파일을 디스크에 생성한 직후

:pages

:post_init

페이지가 초기화될 때마다

:pages

:pre_render

페이지 렌더링 직전

:pages

:post_render

페이지 렌더링 직후 (디스크에 생성 전)

:pages

:post_write

페이지를 디스크에 생성한 후

:posts

:post_init

포스트가 초기화될 때마다

:posts

:pre_render

포스트를 렌더링하기 직전

:posts

:post_render

포스트 렌더링 후 (디스크에 쓰기 전)

:posts

:post_write

포스트를 디스크에 생성한 후

:documents

:post_init

문서가 초기화될 때마다

:documents

:pre_render

문서 렌더링 직후

:documents

:post_render

문서를 렌더링한 후 (디스크에 쓰기 전)

:documents

:post_write

문서를 디스크에 생성한 후

사용가능한 플러그인

유용한 플러그인들을 모아두었습니다:

생성기

변환기

필터

  • Truncate HTML by Matt Hall: A Jekyll filter that truncates HTML while preserving markup structure.
  • Domain Name Filter by Lawrence Woodman: Filters the input text so that just the domain name is left.
  • Summarize Filter by Mathieu Arnold: Remove markup after a <div id="extended"> tag.
  • i18n_filter: Liquid filter to use I18n localization.
  • Smilify by SaswatPadhi: Convert text emoticons in your content to themeable smiley pics.
  • Read in X Minutes by zachleat: Estimates the reading time of a string (for blog post content).
  • Jekyll-timeago: Converts a time value to the time ago in words.
  • pluralize: Easily combine a number and a word into a grammatically-correct amount like “1 minute” or “2 minutes”.
  • reading_time: Count words and estimate reading time for a piece of text, ignoring HTML elements that are unlikely to contain running text.
  • Table of Content Generator: Generate the HTML code containing a table of content (TOC), the TOC can be customized in many way, for example you can decide which pages can be without TOC.
  • jekyll-humanize: This is a port of the Django app humanize which adds a “human touch” to data. Each method represents a Fluid type filter that can be used in your Jekyll site templates. Given that Jekyll produces static sites, some of the original methods do not make logical sense to port (e.g. naturaltime).
  • Jekyll-Ordinal: Jekyll liquid filter to output a date ordinal such as “st”, “nd”, “rd”, or “th”.
  • Deprecated articles keeper by Kazuya Kobayashi: A simple Jekyll filter which monitor how old an article is.
  • Jekyll-jalali by Mehdi Sadeghi: A simple Gregorian to Jalali date converter filter.
  • Jekyll Thumbnail Filter: Related posts thumbnail filter.
  • Jekyll-Smartify: SmartyPants filter. Make "quotes" “curly”
  • liquid-md5: Returns an MD5 hash. Helpful for generating Gravatars in templates.
  • jekyll-roman: A liquid filter for Jekyll that converts numbers into Roman numerals.
  • jekyll-typogrify: A Jekyll plugin that brings the functions of typogruby.
  • Jekyll Email Protect: Email protection liquid filter for Jekyll

태그

콜렉션

기타

편집기

  • sublime-jekyll: A Sublime Text package for Jekyll static sites. This package should help creating Jekyll sites and posts easier by providing access to key template tags and filters, as well as common completions and a current date/datetime command (for dating posts). You can install this package manually via GitHub, or via Package Control.
  • vim-jekyll: A vim plugin to generate new posts and run jekyll build all without leaving vim.
  • markdown-writer: An Atom package for Jekyll. It can create new posts/drafts, manage tags/categories, insert link/images and add many useful key mappings.
Jekyll 플러그인을 수배합니다

자신의 플러그인을 이 목록에 포함시키고 싶다면, 기여하기 페이지를 읽어보세요.