気付いたらHexoのパーマリンクが変わっていたので自動生成+固定にできるよう対応
気付いたら、過去記事のURLが変わっていた
超びっくりした。Twitterに張ってあったリンク踏んだらなんもねーの。
HexoにはランダムなIDを生成する機能があり(Permalinks | Hexo)、これをパーマリンクに組み込んでいたのですが、どうやらこのIDがどこかのタイミングで再生成されているようです。
というわけで再現条件を検証してみましたところ、hexo clean
で生成されたコンテンツを削除し、再度生成するとIDが変わることが分かりました。
シェルのログ
|
|
記事ファイルを作成しておく。
|
|
上記のように_config.ymlで指定して、パーマリンクにランダム生成されるIDが含まれるようにしておく。
|
|
hexo clean
を行う前後でIDが変わっている。
テーマを変えるときとか、間違って作ってしまったタグをタグ一覧から削除するときなど、けっこう頻繁にhexo clean
するのに、そのたびにパーマリンクが変わってしまうのはひどすぎます。即刻やめることにしました。
用意されているパーマリンク用変数を検証する
上記ページより変数表を引用します。
変数名 | 説明 |
---|---|
:year | Published year of posts (4-digit) |
:month | Published month of posts (2-digit) |
:i_month | Published month of posts (Without leading zeros) |
:day | Published day of posts (2-digit) |
:i_day | Published day of posts (Without leading zeros) |
:title | Filename |
:id | Post ID |
:category | Categories. If the post is uncategorized, it’ll be category_dir setting. |
後述しますが、実はslug
という変数もあります。内容はtitle
と同じです。
基本的には日付だけでいいのですが、それだと同日複数更新に対応できません。(全部最初の記事にリンクされる)
となると:title
を使うしかないのですが、個人的に日本語URLが嫌いなので、できれば使いたくありません。
title
変数の詳細
まず、これはファイル名であってフロントマターのtitle:
の内容ではないことに注意することがあります。
もっとも、hexo new
での生成時には同じ内容が挿入されるのですが、どちらかを変更すれば当然互いに異なる内容になります。つまり、hexo new
での記事生成の際にパーマリンクにする内容を入力し、その後ファイル内のtitle:
項目を修正すればいい、という話ではあります。
しかし、いわゆるスラッグを考えるのは大嫌いだし、title:
項目を毎回削除して書き直すのもごめん被りたいところです。
どうでもいいですが、ファイル名が2014-09-15-タイトル
とかの場合、なぜかtitle
変数の内容はタイトル
になるようです。日付っぽいのをエスケープするのかな…?
hexo new
コマンドを使わずAlfred Workflowで対応してみる
だったらhexo自体をカスタマイズすればいいわけですが、そこまでの知識はないので、とりあえずAlfred Workflowで対応することにしました。ターミナルコマンドを利用します。
ランダムな文字列を生成する
ユニークなURLを生成するために、ランダムな文字列を生成してみます。
上記を参考にしました。
|
|
完全にランダムなので、かぶる可能性がなくはないですが、同じ日付でかぶらなければいいので、そんな天文学的確率は気にしなくていいでしょう。
ユーザ定義変数を利用して任意にスラッグをつける
Hexoでは、各記事のフロントマターに適当な項目を入力すると、変数として参照することができます。
この際、Hexoに定義されている変数名は上書きできないため避けなければなりません。実は、slug
が使えなかったので定義されていることに気付いたのだったり。
記事ファイルのフロントマターに、以下のような記述を追加するとします。
|
|
_config.yml
で以下のように記述すると、パーマリンクで参照できます。
|
|
結果として生成された記事のURLは、以下のようになります。
http://wbtmiu.herokuapp.com/2014/09/15/hoge/
後は、pid:
項目をランダム生成してしまえばいいわけです。
完成したAlfred Workflow用シェルスクリプト
Alfred Workflowでこういうのを作ります。
上記を参考に、ターミナルコマンドを作成しました。
|
|
これで、以下の処理が行われます。
- Hexoソースフォルダに記事ファイルを作成
- ファイル名を生成
- クエリをファイル名として適正にする
- 日付を挿入
- フロントマターを生成
- クエリを素のまま
title
に挿入 - 日付を
date
に挿入 pid
をランダムに生成
- クエリを素のまま
- ファイル名を生成
- FoldingTextで記事ファイルを開く
過去記事をこの形式に修正
当然、過去記事も修正する必要があります。
もともとのフロントマター形式は以下の通りです。
|
|
これを、以下のように修正します。
|
|
基本的には、sedによる置換で、tags:
行の上にpid:
行を挿入していくことになります。
sed内部で文字列生成(失敗)
|
|
一見よさそうですが、生成される文字が全部同じなので意味ないです。
for文でループ処理(成功)
上記を参考にしました。
|
|
内容としては、
ls
でファイル一覧を取得してfile
変数に格納- ファイルごとにループ処理
- 文字列生成して
key
変数に格納 key
変数込みで置換
- 文字列生成して
この場合、1ループごとに文字列生成されるためファイルごとに違う文字列が挿入されます。
というか、「ファイルごとの複数処理」ってこんなんでよかったのか。もっと早くわかってればあれもこれも……うっ頭が……