のんびりSEの議事録

プログラミング系のポストからアプリに関してのポストなどをしていきます。まれにアニメ・マンガなど

個人用wikiをJekyllに移行したときにやったこと2 [カスタマイズ編]

前回に引き続き、Jekyllについての記事です。 今回はカスタマイズした内容について記載してます。

carefree-se.hatenablog.com

デザインのカスタマイズ

レスポンシブデザインにしたかったので、Bulma を一部使用することにしました。

  • Bulmaの公式から最新バージョンをassetsに保存
  • 保存したsassを読み込む

  • _sass/main.scss

@charset "utf-8";
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+JP&family=Roboto&display=swap');

/* Bulmaの変数をセット */
$family-sans-serif: 'Noto Sans JP','Roboto', sans-serif;

$body-background-color: #faf0e6;
$body-color: #000;
$footer-background-color: #faf0e6;

$pre-background: #272822;
$pre: #f2f2f2;

$code-background: #303030;
$code: #f2f2f2;

/* 必要最低限なファイルをimport */
@import 'bulma-0.9.0/utilities/_all';
@import 'bulma-0.9.0/base/_all';
@import 'bulma-0.9.0/layout/_all';
@import 'bulma-0.9.0/elements/_all';
@import 'bulma-0.9.0/helpers/_all';
@import 'bulma-0.9.0/components/breadcrumb';
@import 'bulma-0.9.0/components/pagination';
@import 'bulma-0.9.0/grid/columns';

コードハイライトライブラリ(highlight.js)の導入

https://highlightjs.org/

  • CDNからソースを読み込む
  • layoutに指定し、テンプレートに適用
<link rel="stylesheet"
          href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/monokai.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js"></script>

Styleについては以下のページで確認が出来る

https://highlightjs.org/static/demo/

アーカイブページのカスタマイズ

jekyll-archives:
  enabled:  # 年、月、カテゴリー、タグのアーカイブを有効
    - year
    - month
    - categories
    - tags
  layout: archive # アーカイブページのレイアウトを指定
  permalinks:  # アーカイブのリンクを以下のように指定
    year: '/:year/'
    month: '/:year/:month/'
    day: '/:year/:month/:day/'
    tag: '/tags/:name/'
    category: '/categories/:name/'

アーカイブ用のlayout作成

jekyll-archives/layouts.md at master · jekyll/jekyll-archives · GitHub

  {% assign title = page.title %}
  {% if title == nil %} <!-- ページのタイトルがなければ、urlのパスからタイトルを取得する -->
  {% assign title = page.url | split: '/' | shift | compact | join: '-' %}
  {% endif %}
  <article class="section article">
    <div class="container">
      <h1 class="title">{{ title }}</h1>
      <div class="box">
        <div class="content">
          <ul>
            {% for post in page.posts %}  <!-- アーカイブページのPostsが各アーカイブ毎に格納されてくるのでその中のPostsから情報を取得する -->
            <li>
              <a class="post-link" href="{{ post.url | relative_url }}"><span
                  class="post-date">{{ post.date | date: "%Y-%m-%d" }}</span> - {{ post.title }}
                {% for tag in post.tags %}
                <span class="tag is-primary ml-2">{{ tag }}</span>
                {% endfor %}
              </a>
            </li>
            {% endfor %}
          </ul>
        </div>
      </div>
    </div>
  </article>

目次の自動挿入

目次のカスタマイズ等を検討していたため、今回はこちらのソースを参考にしました。

github.com

  • 最新のtoc.html_includes ディレクトリにダウンロード
  • index以外のページに目次を挿入
  {% unless page.path contains 'index' %}
  <div class="container toc box">
    <div class="content">
      {% include toc.html html=content %}
    </div>
  </div>
  {% endunless %}

パンくずリストの自動挿入

PageのURLからパンくずリストを自動生成

{% assign url_paths = page.url | split: '/' %}  <!-- URLを分割 -->
{% assign url = '/' %}

<div class="container">
  <nav class="breadcrumb has-succeeds-separator" aria-label="breadcrumbs">
    <ul>
      {% for path in url_paths %}
      {% if path == '' %}
      <li>
        <a href="/" title="Top">Top</a>
      </li>
      {% elsif url_paths.last == path %} <!-- 最後のpathはactiveにしてリンクはさせない -->
      <li class="is-active">
        <a href="" title="{{ path }}">{{ path | replace: '.html', '' | url_decode | capitalize }}</a>
      </li>
      {% elsif path contains 'categories' %} <!-- カテゴリーのアーカイブページは `/categories/:names` に遷移させる -->
      <li class="">
        <a href="/categories/"
          title="{{ path | capitalize }}">{{ path | replace: '.html', '' | url_decode | capitalize }}</a>
      </li>
      {% elsif path contains 'tags' %} <!-- タグのアーカイブページは `/tags/:names` に遷移させる -->
      <li class="">
        <a href="/tags/" title="{{ path | capitalize }}">{{ path | replace: '.html', '' | url_decode | capitalize }}</a>
      </li>
      {% elsif page.type == 'month' or page.type == 'year' %}
      <li class="">
        <a href="/{{ path }}/"
          title="{{ path | capitalize }}">{{ path | replace: '.html', '' | url_decode | capitalize }}</a>
      </li>
      {% else %}
      <li class="">
        <a href="/categories/{{ path }}/"
          title="{{ path | capitalize }}">{{ path | replace: '.html', '' | url_decode | capitalize }}</a>
      </li>
      {% endif %}
      {% endfor %}
    </ul>
  </nav>
</div>

ページネーションの挿入

jekyllrb-ja.github.io

jekyll-paginateプラグインを利用してページネーションを挿入

今回、次のページと前のページのみ利用し、カテゴリーをまたいだページングは拒否したかったので、以下のようにページネーションを作成しました。

<div class="container">
  {% assign page_category = page.categories | last %}
  <nav class="pagination is-centered" role="navigation" aria-label="pagination">
    {% if page.previous %}
      {% assign previous_category = page.previous.categories | last %}
      {% if previous_category == page_category %}
      <a class="pagination-previous pagination-exists" href="{{ page.previous.url }}" title="{{ page.previous.title }}">
        <span class="icon"><i class="fas fa-angle-left"></i></span>{{ page.previous.title }}</a>
      {% else %}
      <a class="pagination-previous" href="#">
        <span class="icon"><i class="fas fa-angle-left"></i></span>
      </a>
      {% endif %}
    {% endif %}

    {% if page.next %}
      {% assign next_category = page.next.categories | last %}
      {% if next_category == page_category %}
      <a class="pagination-next pagination-exists" href="{{ page.next.url }}" title="{{ page.next.title }}">
        {{ page.next.title }}<span class="icon"><i class="fas fa-angle-right"></i></span>
      </a>
      {% else %}
      <a class="pagination-previous" href="#">
        <span class="icon"><i class="fas fa-angle-right"></i></span>
      </a>
      {% endif %}
    {% endif %}
  </nav>
</div>
  • page.next : 次のページ
  • page.previous : 前のページ

タグの自動挿入

各種ページの先頭にタグを自動挿入

{% if page.tags %}
<div class="container page-tags">
  <div class="tags are-medium">
    {% for tag in page.tags %}
    <a href="/tags/{{ tag }}/" class="mr-2">
      <span class="tag is-primary">{{ tag }}</span>
    </a>
    {% endfor %}
  </div>
</div>
{% endif %}

最近の記事の自動挿入

<div class="box">
  <div class="content">
    <ul>
      {% for page in site.posts limit: 10 %}
      <li>
        <a href="{{ page.url }}" title="{{ page.title }}">{{ page.date | date: '%Y-%m-%d' }} -
          {{ page.title }}</a>
        <span class="are-small ml-4">
          {% for tag in page.tags %}
          <a href="/tags/{{ tag }}/">
            <span class="tag is-primary">{{ tag }}</span>
          </a>
          {% endfor %}
        </span>
      </li>
      {% endfor %}
    </ul>
  </div>
</div>

SiteのPostsはデフォルトではdateの降順になっており、limit で件数を指定してループさせてます。 Postsの順番を変えたい場合、sortreverseのFilterを利用することで順番を変えれます。

Github Actionsを利用したDeploy

今回、Github Pageでは利用できないpluginや、最新のバージョンを使用したかったため、Jekyll ビルド成果物をS3にuploaeするようにスクリプトを作成し、Github Actionsにてdeployするように変更しました。

S3にアップロードするスクリプト (_script/deploy.sh)

#!/usr/bin/env bash

deploy_dir="_site"
html_files=`find $deploy_dir -name '*.html' -type f`
s3_bucket="s3://bucket-name"


for file in $html_files; do
  if [[ ! $file =~ 'index.html' ]]; then
    reprace_name=`echo $file | sed -r 's/\.html//'`
    mv $file $reprace_name
  fi
done

aws s3 sync $deploy_dir $s3_bucket --exclude "*.md" --exclude "*.js" --exclude "*.css" --exclude "*.xml" --exclude ".DS_Store" --acl public-read --content-type "text/html"
aws s3 sync $deploy_dir $s3_bucket --exclude "*.md" --include "*.js" --include "*.css" --include "*.xml" --exclude ".DS_Store" --acl public-read

S3ではindex.html以外のファイルは拡張子つきでアクセスする必要があるため、パスのみであくせすさせるには、Content-Typeをtext/htmlにして、*.html 拡張子を削除してアップロードする必要があります。

amazon web services - S3 static pages without .html extension - Stack Overflow

Github Actions 定義

.github/workflows/ruby.yml

name: Ruby

on:
  push:
    branches: [ master ]

jobs:
  deploy:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - uses: chrislennon/action-aws-cli@v1.1 # aws-cliコマンドを利用するために必要
    - name: Cache bundler
      uses: actions/cache@v2 # bundlerをキャッシュさせる
      with:
        path: vendor/bundle
        key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
        restore-keys: |
          ${{ runner.os }}-gems-
    - name: Set up Ruby
      uses: ruby/setup-ruby@ec106b438a1ff6ff109590de34ddc62c540232e0
      with:
        ruby-version: 2.6
    - name: Install dependencies
      run: |
        bundle config path vendor/bundle
        bundle install --jobs 4 --retry 3
    - name: jekyll build
      run: bundle exec jekyll build  # _site ディレクトリにbuild成果物が保存される
    - name: deploy s3
      run: ./_script/deploy.sh
      shell: bash # 実行shellをbashに
      env: # AWSのキーを指定 (Secretsにて保存)
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

完成品

www.tanish-kr.com

ソース

github.com

所感

何と言っても記事をマークダウンでかけて、特にDBもいらないのはいいですね。
Liquidテンプレートに関しては、ERBほどやれることは多くは無い印象ですが、必要に応じて自作でLiquidのフィルターをRubyで作成も可能なので、慣れれば困ることは無いのかと思いました。

Liquid for Programmers · Shopify/liquid Wiki · GitHub