まぁ便利なのですが、growiはデータベースがmongoDBなので、心もとないという意見や、せっかく階層構造を持っているのでmarkdown単体で保存しておきたいという意見が出ています。
もともとAPI経由でやろうとしていましたが、まぁせっかくなのでbackupファイルからmarkdownを生成してみます。
記事のbackupファイルの取得
growiでは記事はrevisions
というコレクションで登録されています。
growiのwebページからbackupを作成するか、dockerで動かしている場合は次のようなコマンドでrevisonsのjsonを取得します。
$docker exec growi_mongo_1 mongoexport -d growi -c revisions --out revision_back_1013.json $docker cp growi_mongo_1:revision_back_1013.json . $docker exec growi_mongo_1 rm revision_back_1013.json
ここで取得したjsonですが、それぞれの投稿データは次のようなスキーマになっています。
{ "_id": "5ecce2e5fc19b9004a86ec47", "format": "markdown", "createdAt": "2020-05-26T09:35:33.830Z", "path": "/user/anatofuz/note/2020/05/26", "body": "ここに内容が入る", "author": "5df5ef37d744a60045dd1524", "hasDiffToPrev": true, "__v": 0 }
注目すべきはcreatedAt
はタイムスタンプになっており、author
はgrowiのuserのidとなっています。
authorが具体的に何かはrevisionsだけでは決まりませんので、とりあえず今回は放置します。
path
はgrowiのエントリのタイトルです。これはunixのファイルパスと対応してそうなので、生成したmarkdownはこのパスを利用します。
bodyはエントリの内容ですので、bodyをpathに書かれた場所に書き込む方針を取ります。
markdown自体はgit/hgなどのバージョン管理ツールで管理するのを想定するので、createdAtは最新のものを1つだけ使うようにしてみます。
Perlで軽く書く
というわけでPerlで書いてみました。
みんな大好きPath::Tiny
を使っています。
#!/usr/bin/env perl use strict; use warnings; use utf8; use Encode; use JSON; use Path::Tiny; my $json_file = shift or die 'require json file'; my $revision = decode_json(path($json_file)->slurp); my $paths; for my $elem (@$revision) { push(@{$paths->{$elem->{path}}}, $elem); } for my $path (keys %$paths) { my $elems = $paths->{$path}; print encode_utf8 "$path\n"; my @sorted_elems = sort { $b->{createdAt} cmp $a->{createdAt}} @$elems; my $latest_elem = shift @sorted_elems; my $emit_file_path = path("./emit/$path.md"); $emit_file_path->touchpath; $emit_file_path->spew_utf8($latest_elem->{body}); } __END__ { "_id": "5ecce2e5fc19b9004a86ec47", "format": "markdown", "createdAt": "2020-05-26T09:35:33.830Z", "path": "/user/anatofuz/note/2020/05/26", "body": "", "author": "5df5ef37d744a60045dd1524", "hasDiffToPrev": true, "__v": 0 }
$perl parse.pl revisons.json
の様に使います。
今回は/user/anatofuz/note/2020/05/26
の場合は./emit/user/anatofuz/note/2020/05/26.md
というファイルが生成されるようにしてみました。
実際に研究室のGrowiのbackupをもとに実行すると
$ ls emit 611/ Agda.md Christie/ FileSystem/ Haskell/ Linux/ Sandbox/ software/ user/ 611.md CbC/ Christie.md Gears/ Haskell.md Raku/ Sandbox.md software.md user.md Agda/ CbC.md Events/ Gears.md Linda.md Raku.md growi.md trash/
の様になっており、例えばRaku.mdを見ると
# Raku ちょっと前までPerl6と呼ばれていたプログラミング言語 # Docs - 公式Document - https://docs.raku.org/ - `docs.perl6.org`のものは古いので見ない # contents $lsx(/Raku)%
と無事取れていますね!!!
TODO
まぁ色々雑なのでTODOが多々あります
- 作者の情報を取得する
- Hugo等の静的サイトジェネレーターとの組み合わせを考えて、メタ情報をつける
- 生成パスがこれで良いのか問題
- できればワンバイナリかfatpackしたい
ということでversion1くらいの話です。まぁこういうの書くの楽しいですよね