More than 1 year has passed since last update.

最近、GitLabを使い始めていますが、一言で言うと「よい」です。GitLabはGitHubを真似して作られましたが、無料機能が微妙に違います。特に大きいのは以下ですね。

  • プライベートリポジトリを使える

  • GitLab CIが使える

今までCIはリポジトリ管理とは別のサービスで使っていたひとが多いと思います。GitHub+WerckerやGitHub+Travisなど。

しかし、GitLabは例えば、GitLab Pagesをリポジトリ(master)で作り、GitLab CIを使って自動デプロイすると、即座にページを公開できます。今までCIサービスに紐付けして、リポジトリのビルドをしていたので、その辺は随分簡単になっていると思います。

https://gitlab.com/groups/pages

例えば、hugoでページを作りたいなら、以下の手順で公開できます。

$ git clone git@gitlab.com:pages/hugo.git
$ cd hugo
$ rm -rf .git

# 自分のプロジェクト(リポジトリ)にhugoを作成して以下のコマンドを実行
$ git init
$ git remote add origin git@gitlab.com:$USER/hugo.git

# baseurlを自身のものに変更する
$ vim config.toml
baseurl       = "https://$USER.gitlab.io/hugo/"

$ git add .
$ git commit -m "first"
$ git push -u origin master

# ページが出来上がるまで多少待たなくてはいけないかもしれません
$ curl -sL $USER.gitlab.io/hugo

https://syui.gitlab.io/hugo

すごく簡単ですね。.gitlab-ciを置いておくと、ソースをプッシュする度にページがビルドされ更新されます。

ここで、$user.gitlab.ioなどのプロジェクト(リポジトリ)名にすると、アドレスがトップになり、それ以外なら$user.gitlab.io/repoという形になります。

このような関係からこちらにあるサイトジェネレーターを使ってページを作成する場合、使用するアドレスによってはソースの変更が必要になります。

例えば、Octopressで$user.gitlab.ioという形でページを作るには、以下のリポジトリを参考に/octopressを削除します。ちなみに、このリポジトリをGitLabの$user.gitlab.ioリポジトリに使うと、何もしなくてもそのままページを表示できるようになっています。ただ、_config.ymlのURLはユーザーのものに変更しないといけませんが。

公式は$user.gitlab.io/octopressという形を予定しているために、コードを変更しないと適切に表示されません。具体的には、/octopressという指定をコードから削除する必要があります。トップではなく、リポジトリ名を使う場合は、/octopressをリポジトリ名に置き換える必要があります。

もちろん、グループも使えますので、$userのところは、既にGitLabで取得されていないアカウントIDでないかぎり変更可能です。

特にCIとの連携が機能すると思います。このことは、単純なWebサイト作成手順を見ても明らかです。

Hugoのアーカイブページを作成する

Hugoに全記事一覧を分かりやすく表示するページを作成します。以下の記事でだいたいわかると思います。

https://parsiya.net/blog/2016-02-14-archive-page-in-hugo/

自分の場合は、以下の様なレイアウト。

layouts/archive/single.html
{{ partial "head" . }}
{{ partial "header" . }}
<div id="container">
   <div class="outer">
        <div id="blog-archives" class="category">
          {{ .Content }}
          {{ range (where .Site.Pages "Type" "post") }}
            <h1>
        <time datetime="{{ .Date }}" itemprop="datePublished">{{ .Date.Format .Site.Params.date_format }}</time>
                <a href="{{ .Permalink }}" title="{{ .Title }}">{{ .Title }}</a>
            </h1>
          {{ end }}
        </div>
    </div>
</div>
{{ partial "footer" . }}
</body>
</html>

あまりカスタマイズしていません。

Hugoの検索システム

Hugoの検索システムを構築する方法です。

大体は下記のコードのとおりです。具体的にGrunt.jsLunr.jsでHugo用に構築します。

https://gist.github.com/sebz/efddfc8fdcb6b480f567

自分の場合の構築方法です。書いてあるとおりだとconfigparmalinkを設定しない場合の出力が得られますが、設定している場合は使えません。したがって、急遽無理やりShellScriptで書き直します。これはGruntfile.jsを直せばいいのですが、正直、面倒くさかった...。

#!/bin/zsh
d=${0:a:h:h}
# backup
h=${0:a:h}
if cat $j|jq . ;then
    cp $j $h
fi
h=$h/PagesIndex.json
j=$d/static/bower_components/lunr.js/PagesIndex.json
t=`cat $j |jq '.[]'|sed -e 's#/post##g'`
a=`cat $j | sed -e 's#/post##g'`
echo $a >! $j
t=`echo $t|jq -r '.href'|cut -d - -f 1-4`

for (( i=1;i<=`echo "$t"|wc -l`;i++ ))
do
    f=`echo "$t"|awk "NR==$i"`
    c=`echo $f|tr '-' '/'`
    sed -i "" "s#${f}#${c}#g" $j
done

cat $j

diff $j $h

とりあえず記事にあるGrntfile.jsを適時修正し作成し、ビルド後にスクリプトを実行するという手順。

出力ファイルは/bower_components/lunr.js/PagesIndex.jsonに置くこととします。

layouts/partials/widgets/search.html
<div class="widget-wrap">
<input id="search" type="text" placeholder="search">
<ul id="results">
</ul>
<script type="text/javascript" src="/js/search.js"></script>
<script type="text/javascript" src="/bower_components/lunr.js/lunr.min.js"></script>
</div>
js/search.html
var lunrIndex,
    $results,
    pagesIndex;

// Initialize lunrjs using our generated index file
function initLunr() {
    // First retrieve the index file
    $.getJSON("/bower_components/lunr.js/PagesIndex.json")
        .done(function(index) {
            pagesIndex = index;
            console.log("index:", pagesIndex);

            // Set up lunrjs by declaring the fields we use
            // Also provide their boost level for the ranking
            lunrIndex = lunr(function() {
                this.field("title", {
                    boost: 10
                });
                this.field("tags", {
                    boost: 5
                });
                this.field("content");

                // ref is the result item identifier (I chose the page URL)
                this.ref("href");
            });

            // Feed lunr with each file and let lunr actually index them
            pagesIndex.forEach(function(page) {
                lunrIndex.add(page);
            });
        })
        .fail(function(jqxhr, textStatus, error) {
            var err = textStatus + ", " + error;
            console.error("Error getting Hugo index flie:", err);
        });
}

// Nothing crazy here, just hook up a listener on the input field
function initUI() {
    $results = $("#results");
    $("#search").keyup(function() {
        $results.empty();

        // Only trigger a search when 2 chars. at least have been provided
        var query = $(this).val();
        if (query.length < 2) {
            return;
        }

        var results = search(query);

        renderResults(results);
    });
}

/**
 * Trigger a search in lunr and transform the result
 *
 * @param  {String} query
 * @return {Array}  results
 */
function search(query) {
    // Find the item in our index corresponding to the lunr one to have more info
    // Lunr result: 
    //  {ref: "/section/page1", score: 0.2725657778206127}
    // Our result:
    //  {title:"Page1", href:"/section/page1", ...}
    return lunrIndex.search(query).map(function(result) {
            return pagesIndex.filter(function(page) {
                return page.href === result.ref;
            })[0];
        });
}

/**
 * Display the 10 first results
 *
 * @param  {Array} results to display
 */
function renderResults(results) {
    if (!results.length) {
        return;
    }

    // Only show the ten first results
    results.slice(0, 10).forEach(function(result) {
        var $result = $("<li>");
        $result.append($("<a>", {
            href: result.href,
            text: "» " + result.title
        }));
        $results.append($result);
    });
}

// Let's get started
initLunr();

$(document).ready(function() {
    initUI();
});

これで検索システムの完成です。Hugo Buildで同時にPagesIndexを作成するようにしておけばOKです。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.