最近、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
すごく簡単ですね。.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に全記事一覧を分かりやすく表示するページを作成します。以下の記事でだいたいわかると思います。
自分の場合は、以下の様なレイアウト。
{{ 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.jsとLunr.jsでHugo用に構築します。
自分の場合の構築方法です。書いてあるとおりだとconfig
のparmalink
を設定しない場合の出力が得られますが、設定している場合は使えません。したがって、急遽無理やり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
に置くこととします。
<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>
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です。