Boostnote

Evernote から Boostnote へ

注: 下記スクリプトの実行結果には責任をもてませんので、せめて実行前にはバックアップを取った上で実行・結果確認をしてください。

Evernote から Boostnote へデータを移行するのに試行錯誤して、1日くらいかけてやっとできたっぽいのでメモ。

Boostnote には、 Ever2boost という移行用ツールが用意されていますが、残念ながらこのために必要な Evernote の Developer Token が "Update: the creation of developer tokens is temporarily disabled." となっていて、半年くらいずーっとこのままです。

そのため、次のような手順で移行を試みました。

  1. Evernote から html でエクスポートする
  2. pandoc を使って html を markdown に変換
  3. Boostnote から markdown をインポート
  4. インポートしてできた .cson を一部書き換え

1. Evernote から html でエクスポートする

Evernote にはノートを html ファイルにエクスポートする機能があるため、これを使ってエクスポートします。
このとき、エクスポートしたファイルにはフォルダ(ノートブック)に関する情報が欠落しているため、面倒ですがフォルダ単位にエクスポートをします(タグの情報はエクスポートされます)。ノートブックの分類なんてどうでもいいや、という方は全部まとめてエクスポートしてOKです。
私の場合は、30くらいのフォルダに分かれてました。面倒。

2. pandoc を使って html を markdown に変換

boostnote は html ファイルをインポートすることができないため、 pandoc を使ってエクスポートしたファイルを markdown に変換します。
フォルダごとに pandoc を実行するのが面倒だったので、以下のようなPHPのスクリプトで変換しました。このスクリプトファイルを置いたところにノートブックのスタックのフォルダが有り、その中にさらにノートブックのフォルダが有る、という想定です。

convert.php
notebookstack_1
 - notebook_a
    -- fileA.html
    -- fileB.html
 - notebook_b
    -- fileC.html
notebookstack_2
 - notebook_c
    -- fileD.html
 - notebook_d
convert.php
<?php

$inpath = __DIR__;

$dirs = glob($inpath. '/*');
foreach ($dirs as $dir) {
    if (is_dir($dir) === false) {
        continue;
    }
    $subdirs = glob($dir . '/*');

    foreach ($subdirs as $subdir) {
        if (! is_dir($subdir.'/output')) {
            mkdir($subdir.'/output');
        }

        if (is_dir($subdir) === false) {
            continue;
        }
        $files = glob($subdir . "/*.html");

        foreach ($files as $file) {
            $fileNameArray = explode('.', basename($file));

            $outputFileName = $fileNameArray[0].'.md';
            system ('pandoc "'.$file.'" -s -o "'. $subdir .'/output/'. $outputFileName. '"');
        }
    }
}

3. Boostnote から markdown をインポート

Boostnote を起動して、2. で変換した markdown をインポートします。Mac の場合は、「ファイル」ー「Import From」からインポートできます。
フォルダを指定してインポートするため、Boostnote で予め対応するフォルダを作っておきましょう。

4. インポートしてできた .cson を一部書き換え

インポートしたデータには、作成日、更新日、タグがセットされていない(本文中に書かれている)ため、プログラムを書いてセットします。
例えば、次のようなスクリプトを書いて実行します。

csonUpdate.php
<?php

$path = __DIR__;

$files = glob($path . "/*.cson");

foreach ($files as $infile) {
    // initialize
    $evernoteMeta = false;
    $output = "";
    $matches = [];

    $createdAt = "";
    $updatedAt = "";
    $tags = [];

    $content = file_get_contents($infile);
    preg_match("/  ---\n(.*)\n  \.\.\./s", $content, $matches);
    if (! ($metas = $matches[1])) {echo basename($infile);
        continue;
    }
    foreach (explode("\n", $metas) as $meta) {
        if (substr($meta, 2, 9) == "created: ") {
            $createdAt = 'createdAt: "'. substr_replace(substr($meta, 12, 19), 'T', 10, 1) . '.000Z"';
        }
        if (substr($meta, 2, 9) == "updated: ") {
            $updateAt = 'updatedAt: "'. substr_replace(substr($meta, 12, 19), 'T', 10, 1) . '.000Z"';
        }
        if (substr($meta, 2, 10) == "keywords: ") {
            $tags = explode(',', substr($meta, 12));
        }
    }

    foreach (explode("\n", $content) as $line) {
        if ($line == "  ---") {
            $evernoteMeta = true;
            continue;
        }

        if (substr($line, 0, 11) == "createdAt: ") {
            if ($createdAt) {
                $output .= $createdAt."\n";
            }
            else {
                $output .= $line."\n";
            }
            continue;
        }
        if (substr($line, 0, 11) == "updatedAt: ") {
            if ($updateddAt) {
                $output .= $updatedAt."\n";
            }
            else {
                $output .= $line."\n";
            }
            continue;
        }
        if (substr($line, 0, 6) == "tags: ") {
            $output .= 'tags: ['. (count($tags)>0 ? implode(',', array_map(function($tag){return '"'. $tag .'"';}, $tags)) : "") .']' . "\n";
            continue;
        }
        if ($evernoteMeta === true) {
            if (substr($line, 0, 5) == "  ...") {
                $evernoteMeta = false;
                continue;
            }
            continue;
        }
        else {
            $output .= $line . "\n";
        }
    }
    $result = file_put_contents($infile, $output);
    if ($result === false) {
      echo $infile;
    }
}

試行錯誤して疲れたので手抜きスクリプトですが、 .cson と同じフォルダにおいて実行します。で、そのままこのスクリプトを放置して Boostnote を起動すると、どうもファイルを読み込んでくれません。そのため、変換が終わったらこのスクリプトはフォルダから取り除いてください。