hexoのように、手元に記事のファイルがあると便利だった。

これまで書いてきた記事にタグを付ける時に、本文に何かが含まれていたらタグに追加する、とかが Perl で簡単にできるようになった。

これまでは過去記事にタグを追加しよう、とか思ったこともないけど、こういうことをやろうと思えるようになったのは良いね。

紆余曲折あって、変換スクリプトはこんな感じになっている。

二重管理になるけど、今のところは大きく問題はない感じ。

tools/rename_posts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#!/usr/bin/env perl
use utf8;
use strict;
use warnings;
use Path::Tiny qw(path);
use YAML ();
use Time::Moment ();

my $root = path(__FILE__)->absolute->parent(2);

# 記事を取得
my $posts_dir = path($root, 'source', '_posts');
my $iterator = $posts_dir->iterator(+{recurse => 1});

# タイムゾーンを取得
my $tm = Time::Moment->now;
my $offset = $tm->offset;
my $jp_offset = 540;

# 記事から時間を取得して、名称変更
while (my $post = $iterator->()) {
next unless $post->is_file;
my ($yaml, $after) = split /\n---/, $post->slurp_utf8;
my $info = YAML::Load($yaml);

my $modified;

# ISO8601を持っていない場合はdateからISOを作成
unless (exists $info->{iso8601}) {

# 存在しなければ今書いたことにする
if (!exists $info->{date}) {
$info->{iso8601} = Time::Moment->now->to_string;
}

# すでに変換済みであればそのまま渡す
elsif (-1 < index($info->{date}, 'T')) {
$info->{iso8601} = $info->{date};
}

# date があれば iso8601 を作成
else {
my $date = join('T', split(/\s/, $info->{date})) . 'Z';
my $tm = Time::Moment->from_string($date);
my $new_date = $tm->with_offset_same_local($offset);
$info->{iso8601} = $new_date->to_string;
}

# date はURLのために日本時間へ統一
my $tm = Time::Moment->from_string($info->{iso8601});
my $url_date = $tm->with_offset_same_instant($jp_offset);
$info->{date} = $url_date->strftime('%F %T');
$modified = 1;
}

# 本文に文字列が含まれていたらタグを追加
my $tag = 'perl';
if ($after =~ /$tag\b/i) {
my $tags = $info->{tags};

# undef が含まれていたら削除する
$tags = +[grep { $_ ne 'undef' and $_ ne $tag } @{$tags}];
push @{$tags}, $tag;
$info->{tags} = +[sort @{$tags}];
$modified = 1;
}

# 変更されていたら保存する
if ($modified) {

# 結合して出力
my $dump_yaml = YAML::Dump($info);
my $body = join qq{\n---}, $dump_yaml, $after;
$post->spew_utf8($body);
}

# 時間でファイル名を変更
my $tm = Time::Moment->from_string($info->{iso8601})->with_offset_same_instant($jp_offset);
my $path = $tm->strftime('%Y/%m/%d/%H%M%S');
my $new_post = path($posts_dir, qq{$path.md})->absolute;
$new_post->parent->mkpath;
$post->move($new_post->stringify);
}