風柳メモ

ソフトウェア・プログラミング関連の覚書が中心。

Twitterのカユイところに手が届くブラウザ拡張/スクリプト

覚え書きを兼ねて、今後も更新される可能性のある自作のTwitter用ブラウザ拡張機能/スクリプト類をまとめてみました。

はてなブログの記事に更新日付を表示&古い記事に警告を出す試み

はてなブログが配信しているサイトマップの仕様が変わっていることに、今更ながら気が付きました
変化したのが2020/04/01からなので、何ヶ月気が付かなかったのか、という話ですが。
sitemap.xml の中身を覗いてみたら、クエリで年月を指定することにより、指定月に作成した記事の更新日付を取得できるようです。

これを利用して、フッタなどに貼り付けることで

  • 個別記事に更新日付を表示
  • 更新日付が古い場合には、警告を表示

するようなスクリプトを試作してみました。

f:id:furyu-tei:20200818053148p:plain
はてなブログの記事に更新日付を入れてみる&古い記事には警告を表示する



更新日付の取得方法について

はてなブログの記事には作成日付は最初から入っており、例えば

var entry_date = new Date( document.querySelector( 'time[datetime][pubdate].updated' ).getAttribute( 'datetime' ) );

のようにすることで、簡単に取得することができます。
これを用いて記事が古いかどうかを判断して表示するスクリプトは以前から存在します。
sprint-life.hatenablog.com

しかし、実際には記事は更新されることもよくあり、その記事の情報が古いかどうかは更新日付を元に判断したいところです。

2020/04/01より前のサイトマップ仕様

2020/03/31まで、サイトマップの仕様は

/sitemap.xml?page=<ページ番号>

のような形式で、1ページ毎に作成日付の新しいものから順に100件ずつ、記事のURLと更新日付が含まれる仕様になっていました。
なお、当概仕様のサイトマップには現在でもアクセス可能です。
これだと、特定記事の更新日付を取得するためには、当該記事のURLが現れるまでひたすらページ番号を増やしてアクセスする必要があります。
上記の記事やコメント中でも、サイトマップから更新日を取得することは可能ではあるものの、記事と一致させることが手間なので実用的ではない旨書かれています。

このサイトマップを使った更新日付表示の実装例は
www.tsubasa-note.blog

等があるようです。
また、サイトマップの場合には何度もアクセスが発生してしまう問題を解消するため、AMP(更新日付が埋め込まれている)を利用した実装もあるようです。
psn.hatenablog.jp

2020/04/01 以降のサイトマップ仕様

2020/04/01から配信されるようになったサイトマップの仕様では、

/sitemap_periodical.xml?year=<作成年>&month=<作成月>

のようにすると、

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    <url>
        <loc>https://memo.furyutei.work/entry/20161015/1476495230</loc>
        <lastmod>2016-12-06T09:08:18+09:00</lastmod>
    </url>
    <url>
        <loc>https://memo.furyutei.work/entry/20161008/1475863694</loc>
        <lastmod>2016-12-06T09:08:56+09:00</lastmod>
    </url>
    <url>
        <loc>https://memo.furyutei.work/entry/20161008/1475860031</loc>
        <lastmod>2017-11-14T07:08:24+09:00</lastmod>
    </url>
    <url>
        <loc>https://memo.furyutei.work/entry/20161007/1475839249</loc>
        <lastmod>2020-03-07T03:29:59+09:00</lastmod>
    </url>
</urlset>

のように、指定した年月に作成した記事のURLと更新日の一覧を取得することが出来るようになっていました。
これならアクセスが1回だけで済むので、実用的だと思われます。

個別記事に更新日付を表示&古い記事に警告を表示するスクリプトとCSSのサンプル

注意事項
  • スクリプトをブログのフッタなどに貼り付ける場合、<script>~</script>で囲むのを忘れないこと
  • サンプルソースコードはGist上にあります。なお、残念ながら Gist 上のコードは外部スクリプトとしては読み込めません(Content-Type: text/plain; charset=utf-8 のため)
  • async/await とか使っているので、モダンブラウザじゃないと動きません(笑)
    それじゃ嫌だというかたはこちらの記事等を参考にして、新しいサイトマップ仕様に対応させてみてください

余談

記事の更新時刻が例えば

2017-11-14T07:08:24+09:00

という文字列で与えられたとき、閲覧者のタイムゾーンによらずに日本標準時の年月日で

2017-11-14

という文字列に変換するためにはどうするのがスマートなんですかね……?
いや、上記サンプル中ではT以降の文字を消す、という手抜き実装ですが……

また、同様に

2017-11-13T22:08:24Z

で与えられた場合には?

var modified_date = new Date( '2017-11-13T22:08:24Z' );
modified_date.setHours( modified_date.getHours()+9 );
var jst_date_string = modified_date.toISOString().replace( /T.*$/, '' );

のようにすれば一応できるけれど、正攻法ではないですね……。

Git for WindowsのGit BASHでウィンドウタイトルだけが文字化けする現象(winptyが原因)と対処方法

[2020.10.27追記] Git for Windows 2.29.1-64-bit(mintty 3.4.0 / winpty 0.4.3 の組み合わせ)では、exec winpty bash した後も Git Bash のウィンドウタイトルが文字化けしなくなった模様。以下は古いバージョンについての記述であり、新バージョンでは環境変数 PS1 を書き換えるとかえって文字化けしてしまうので、注意。



Git BASHで、たまたま日本語を含むフォルダ下で作業していたら、ウィンドウのタイトルだけが文字化けしていることに気がついた(ウィンドウ内については正常に表示されている)。
Windows 10 Pro バージョン 1909 (OS ビルド 18363.959)、Git for Windows 2.28.0-64-bit、mintty 3.2.0 (x86_64-pc-msys) [Windows 18363]

f:id:furyu-tei:20200812030339p:plain
Git BASHでウィンドウタイトルだけが文字化けしている様子

この現象の原因と、対処方法についての覚え書きを残しておく。




原因

どうやら、~/.bash_profile にて

exec winpty bash

を記述していたためらしい。

試しにこの記述を外すと、ウィンドウタイトルは化けなくなる。
ただし当然ながら、対話型コマンドがそのままではうまく動作しなくなる。

f:id:furyu-tei:20200812040929p:plain
exec winpy bash の記述を外した場合


Python なんかの Windows ネイティブな対話型コマンドを呼び出すのに、いちいち

$ winpty python

としたり、あるいは ~/.bashrc で対話型コマンド毎に

alias python="winpty python.exe"

のように alias 定義するのが面倒だったので bash 自体を winpty で呼び出していたのだけれど、これが原因でウィンドウタイトルが化けてしまうのは想定外……。

対処方法

A. 必要なコマンド毎に個別に winpty を付けて呼び出す alias を定義しておく

bash そのものを winpty 経由で呼び出しているのが原因なのでこれを止め、個別のコマンド毎に winpty 付き呼び出しを行うようにすれば問題はなくなる。
その場合、標準では /etc/profile.d/aliases.sh にて

    for name in node ipython php php5 psql python2.7
    do
        case "$(type -p "$name".exe 2>/dev/null)" in
        ''|/usr/bin/*) continue;;
        esac
        alias $name="winpty $name.exe"
    done

のように、いくつかのコマンドについて対応されているのを参考にして ~/.bashrc に必要なコマンドについて同様の記述を追記するというのが一つの方法。

B. 環境変数 PS1 を書き換える

A. のようにすると、対話型コマンドの種類が増えるごとにメンテナンスしなければならないため、面倒なのが難点。
そこで、bash を winpty で呼び出したときにウィンドウタイトルのみが化けている点に着目し、プロンプト定義用の環境変数(PS1)を書き換えてやれば良いのではないか? と考えた。
状況的に、bash を winpty 経由にした際には、mintty はウィンドウタイトル文字列としては Shift-JIS(CP932) で渡されることを期待しているのではないかと推測、$PS1 中に含まれる $PWD の文字コードを変換するように定義してみると、

export PS1=`echo "$PS1" | sed "s~\\$PWD~\\\`echo \\$PWD | iconv -f utf-8 -t cp932 2>/dev/null\\\`~"`

これでうまくいった。
ウィンドウタイトルに関してだけはなんとかなったということで、winpty bash したときに出る潜在的な問題は他にもあるかも知れない。

f:id:furyu-tei:20200812042525p:plain
ウィンドウタイトルも文字化けせず、対話型コマンドも正常に起動できている

覚え書きを兼ねて、現状の ~/.bash_profile および ~/.bashrc を残しておく。

~/.bash_profile

#【覚書】
# ※参考:[bashの.profileや.bashrc等を実行する動作仕様 - sgryjp.log](https://blog.sgry.jp/entry/2019/11/09/232927)
#===============================================================================
# ・ ~/.bash_profile はログインシェルで一度だけ実行される
#   このため、主に
#
#   - ログイン時に一度だけ実行したい処理
#   - 対話操作では必要のない(対話操作以外のコマンド実行に必要な)設定(環境変数 LANG 定義等)
#   - ログインシェル/サブシェルに関わらず基本変更不要な設定(環境変数 PATH 定義等)
#
#   を記述するのに向く
#
# ・ ~/.bashrc はサブシェルでは自動的に呼ばれる(ログインシェルでは自動では呼ばれない)
#   このため、~/.bash_profile からも呼び出されるよう設定の上で (^1)
#
#   - alias や関数等、暗黙的に引き継がれない設定
#   - 対話操作のみで必要となる設定(環境変数 PS1、EDITOR 等)
#
#   を記述するのに向く
#
#   (^1) ~/.bashrc があるのに ~/.bash_profile, ~/.bash_login or ~/.profile が無い環境は推奨されず、
#        例えば Git for Windows においては、その場合、/etc/profile.d/bash_profile.sh により
#        ~/.bashrc を呼び出す記述が入った ~/.bash_profile が生成される
#===============================================================================

# ■ ~/.bashrc 実行
#   ※ログインシェルでは ~/.bashrc は自動的には実行されないため、この設定が必要
#test -f ~/.profile && . ~/.profile
test -f ~/.bashrc && . ~/.bashrc

# ■ 各種定義
export PYTHONUTF8=1
export PYTHONSTARTUP=~/.pythonstartup

# ■ bash を winpty 経由で起動
#   ※ Windows ネイティブな対話型コマンド(Python 等の、interactive mode が mintty に対応していないもの)に対応
exec winpty bash
#   ※ exec によりシェルプロセス自体を置換しているため、これ以降に書いた内容は反映されないことに注意

~/.bashrc

if [[ $TERM_PROGRAM = "mintty" ]]; then
    # ■ mintty 専用設定
    case `tty` in
        /dev/cons*) # winpty
            # winpty 経由だと $PWD が日本語を含む場合ウィンドウタイトルが文字化けする(mintty 3.2.0)問題に対処
            # → mintty 3.4.0 / winpty 0.4.3 の組み合わせでは発生しなくなったため、必要がなくなった
            # export PS1=`echo "$PS1" | sed "s~\\$PWD~\\\`echo \\$PWD | iconv -f utf-8 -t cp932 2>/dev/null\\\`~"`
            ;;
        /dev/pty*) # (default)
            ;;
    esac
fi


# ■ 暗黙的にサブシェルに引き継がれない設定(alias・関数定義)
# ※サブシェルでは、
#   - profile系スクリプト(/etc/profile、/etc/profile.d/*、~/.bash_profile等)は実行されない
#   - ログインシェルで定義された alias や関数は引き継がれない
#   ことに注意
shopt -q login_shell || {
    # サブシェル専用設定
    # ※必要に応じて /etc/profile や /etc/profile.d/* (aliases.sh等)で定義されている alias 等をコピーしておく
    alias ls='ls -F --color=auto --show-control-chars'
    alias ll='ls -l'
}

# ~/.bash_profile 経由/サブシェル共用設定
alias ls='ls -aF --color=auto --show-control-chars'
alias tree='tree -N'
alias python2='py -2'
alias python3='py -3'
alias python='python3'
alias pip2='python2 -m pip'
alias pip3='python3 -m pip'
alias pip='pip3'


# ■ 非対話ログインで不要かつ対話ログインで使いたい設定(環境変数定義)
export EDITOR=vim

その他の覚え書き等

ユーザー独自のファイル(bashスクリプト)をログインシェル/サブシェルどちらでも呼び出す(Git BASH 独自仕様?)

/etc/profile.d/git-prompt.sh
の最後の方に、以下のような記述があることに気づいた。

# Evaluate all user-specific Bash completion scripts (if any)
if test -z "$WINELOADERNOEXEC"
then
        for c in "$HOME"/bash_completion.d/*.bash
        do
                # Handle absence of any scripts (or the folder) gracefully
                test ! -f "$c" ||
                . "$c"
        done
fi
  • /etc/profile.d 下のファイルは通常はログインシェルからしか呼ばれないものだが、git-prompt.sh に限り、サブシェルからも呼び出される(/etc/bash.bashrc 経由)
  • ~/bash_completion.d/ というディレクトリを作成し、この下に拡張子 .bash の付いた任意の bash スクリプトを置いておくと、/etc/profile.d/git-prompt.sh 経由で呼び出される(結果的にはログインシェル/サブシェルの区別なく呼ばれることになる)

参考

winpty・mintty 関連

mseeeen.msen.jp

bash 関連ファイル(~/.bash_profile・~/.bashrc 等)の動作仕様について

blog.sgry.jp
なんとなくで設定しがちだった bash の ~/.bash_profile や ~/.bashrc といったファイルの動作仕様が分かりやすくまとまっていて非常に参考になった。

Google ドライブの共用 PDF を画像データとしてダウンロードするユーザースクリプトを試作

Google ドライブで共用されている PDF ファイルを、画像データにして ZIP 化し、ダウンロードできるユーザースクリプトを作ってみました。
通常は PDF をそのままダウンロードすればよいのですが、まれにダウンロード権限が「閲覧者はダウンロードできません」となっている場合があるため、主にその対策用です。
画像として取得しても、PDF 化したり OCR にかけたりと結局は別途手間はかかってしまいますが……まぁ、手動で1ページずつ落としたりするよりは幾分マシかなと。

インストール・使い方など

github.com
をご参照下さい。

ユーザースクリプトのソースコード


はてなブログでは Gist 貼り付けしかできないみたいなので、gist-it.appspot.com - Embed files from a github repository like a gist を使って GitHub 上のソースコードを貼り付けてみました

chrome-extension-kickstart-typescript が Node.js v12 だとうまく動かない件とその対策

■ 追記
2020年02月11日にid:SWIMATH2さんが対応して下さりgenerator-chrome-extension-kickstart-typescript v4.4.1 以降では、Node.js 12 でも元の手順のままで正常動作するようになった模様です。
以下は古い情報となります。


勉強を兼ねてブラウザ拡張機能をTypeScriptで書いてみようと、swimath2.hatenablog.comgenerator-chrome-extension-kickstart-typescript を試してみたところ、Node.js v12 ではそのままでは動作しませんでした。
試行錯誤の末にとりあえず動くようになったので、覚え書きとして手順等を書いておきます。




対策(お急ぎの方はこちらだけお読みください)

試行環境
# Node.js v12.14.1 LTS および Yarn 1.21.1 は、それぞれインストーラをダウンロードしてインストール済
$ node -v && npm -v
v12.14.1
6.13.4

$ yarn -v
1.21.1

# yo および generator-chrome-extension-kickstart-typescript を npm もしくは yarn にて global インストール
#$ npm install -g yo generator-chrome-extension-kickstart-typescript
$ yarn global add yo generator-chrome-extension-kickstart-typescript

$ yo --version
3.1.1
手順

1. 拡張機能用のプロジェクト作成
拡張機能用のフォルダを作り(例では sample)chrome-extension-kickstart-typescript を --skip-install 付きで実行

$ mkdir -p sample
$ cd sample
# --skip-install を付けて、npm による自動インストールを抑制
$ yo chrome-extension-kickstart-typescript --skip-install

2. package.json 編集

$ vi ./package.json

※差分例

--- ./package.json.orig 2020-01-11 14:33:14.473509100 +0900
+++ ./package.json      2020-01-11 14:44:36.316563000 +0900
@@ -32,7 +32,7 @@
     "chromereload": "0.x.x",
     "debounce": "1.x.x",
     "del": "3.x.x",
-    "gulp": "3.x.x",
+    "gulp": "3.9.0",
     "gulp-bump": "2.x.x",
     "gulp-cache": "0.x.x",
     "gulp-clean-css": "^3.x.x",
@@ -57,6 +57,10 @@
     "vinyl-named": "1.x.x",
     "webpack": "3.x.x",
     "webpack-stream": "3.x.x",
-    "yargs": "^8.x.x"
+    "yargs": "^8.x.x",
+    "typescript": "^3.x.x"
+  },
+  "resolutions": {
+    "gulp/**/graceful-fs": "^4.x.x"
   }
 }

3. パッケージのインストール
yarn install で必要な全パッケージをインストール

$ yarn install

4. 動作確認
動作するかどうかを yarn run で確認

$ yarn run dev:chrome

※ 正常動作したときの例

yarn run v1.21.1
$ gulp --watch --vendor=chrome
[14:56:00] Requiring external module babel-core/register
[14:56:07] Using gulpfile D:\webext\sample\gulpfile.babel.js
[14:56:07] Starting 'build'...
[14:56:07] Starting 'clean'...
[14:56:07] Finished 'clean' after 3.37 ms
[14:56:07] Starting 'manifest'...
[14:56:07] Starting 'scripts'...
[14:56:07] Starting 'styles:css'...
[14:56:07] Starting 'styles:less'...
[14:56:07] Starting 'styles:sass'...
[14:56:07] Starting 'pages'...
[14:56:07] Starting 'locales'...
[14:56:07] Starting 'images'...
[14:56:07] Starting 'fonts'...
[14:56:07] Starting 'chromereload'...
[14:56:07] Starting 'livereload-server'
[14:56:07] Finished 'styles:css' after 32 ms
[14:56:07] Finished 'styles:less' after 26 ms
[14:56:07] Finished 'styles:sass' after 26 ms
[14:56:07] Starting 'styles'...
[14:56:07] Finished 'styles' after 20 μs
[14:56:07] Finished 'pages' after 27 ms
[14:56:07] Finished 'fonts' after 26 ms
[14:56:07] Finished 'manifest' after 264 ms
[14:56:07] Finished 'locales' after 237 ms
[14:56:07] Finished 'images' after 237 ms
ts-loader: Using typescript@3.7.4 and D:\webext\sample\tsconfig.json
[14:56:10] Finished 'scripts' Hash: 941f7e8c10f53a4b8956
Version: webpack 3.12.0
Time: 2076ms
        Asset     Size  Chunks             Chunk Names
background.js  6.83 kB       0  [emitted]  background
   [0] multi ./app/scripts/background.ts 28 bytes {0} [built]
   [1] ./app/scripts/background.ts 254 bytes {0} [built]
[14:56:10] webpack is watching for changes

経緯

発生した不具合

最初に、qiita.com を参考にして、

$ mkdir -p sample
$ cd sample
$ yo chrome-extension-kickstart-typescript
# 試行のためとりあえず問にはすべて[Enter]
$ npm install --save-dev typescript
$ npm install --save-dev gulp@3.9.0
$ npm run dev:chrome

のようにしたところ、

$ npm run dev:chrome

> sample@0.0.0 dev:chrome D:\webext\sample
> gulp --watch --vendor=chrome

[08:33:12] Requiring external module babel-core/register
fs.js:27
const { Math, Object } = primordials;
                         ^

ReferenceError: primordials is not defined
    at fs.js:27:26
    at req_ (D:\webext\sample\node_modules\natives\index.js:143:24)
    at Object.req [as require] (D:\webext\sample\node_modules\natives\index.js:55:10)
    at Object.<anonymous> (D:\webext\sample\node_modules\vinyl-fs\node_modules\graceful-fs\fs.js:1:37)
    at Module._compile (internal/modules/cjs/loader.js:955:30)
    at Module._extensions..js (internal/modules/cjs/loader.js:991:10)
    at Object.require.extensions.<computed> [as .js] (D:\webext\sample\node_modules\babel-register\lib\node.js:152:7)
    at Module.load (internal/modules/cjs/loader.js:811:32)
    at Function.Module._load (internal/modules/cjs/loader.js:723:14)
    at Module.require (internal/modules/cjs/loader.js:848:19)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! sample@0.0.0 dev:chrome: `gulp --watch --vendor=chrome`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the sample@0.0.0 dev:chrome script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\testuser\AppData\Roaming\npm-cache\_logs\2020-01-11T06_33_12_337Z-debug.log
調査

Node.js v12 と gulp.js 3 は相性が悪いらしい?!
とりあえず「ReferenceError: primordials is not defined」で検索してみると
stackoverflow.com
に行き当たる。
こちらの回答によると、

  1. gulp.js を version 4 にする
  2. Node.js のバージョンを v12 未満へ下げる

のいずれかで対応できるらしい。

1. の gulp.js のバージョンを変える方は、3→4 の変更に対応してソースコードも変更が必要になると思われるので手間がかかりそうだったため、2. の方法を試してみる。
nvm-windows で Node.js のバージョンを 10.18.1 LTS にしてみると、確かに動作するようになった。

Node.js v12 & gulp.js 3 のまま使いたいな……
できれば Node.js や gulp.js のバージョンを変えずに使う方法はないか、と調べていると、
https://timonweb.com/posts/how-to-fix-referenceerror-primordials-is-not-defined-error/timonweb.com
に行き当たる。

要は、gulp.js が利用している graceful-fs のバージョンが古いのが悪いらしい。

$ npm list graceful-fs

で調べてみると、他はほとんどが "graceful-fs@4.2.3" を使っているのに対し、gulp(及び
gulp が依存しているパッケージ)については

+-- gulp@3.9.0
| `-- vinyl-fs@0.3.14
|   +-- glob-watcher@0.0.6
|   | `-- gaze@0.5.2
|   |   `-- globule@0.1.0
|   |     `-- glob@3.1.21
|   |       `-- graceful-fs@1.2.3
|   `-- graceful-fs@3.0.12

のように、確かに古いバージョン("graceful-fs@1.2.3"、"graceful-fs@3.0.12")を使っている。

そういえば、yo chrome-extension-kickstart-typescript 実行時にも

npm WARN deprecated graceful-fs@1.2.3: please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js

のような警告が出ていた。これによれば、graceful-fs 4 以降を使うようにすれば良さげ。

上記の記事を参考に、npm-shrinkwrap.json を

{
  "dependencies": {
    "graceful-fs": {
        "version": "^4.x.x"
     }
  }
}

の内容で作成した後、改めて npm install 後に npm run dev:chrome をすると、

# package-lock.json は npm-shrinkwrap.json と排他なため、消しておく
$ rm package-lock.json
# パッケージのインストール
$ npm install
# ※このとき、npm-shrinkwrap.json も更新されることに注意

# 開発環境を起動
$ npm run dev:chrome

すると、今度はエラーになると起動することができた。

ただし、この方法だと、

  • npm install --save-dev でパッケージを入れたりすると、最初に指定した "dependencies" が維持されないため、再度 npm-shrinkwrap.json を上記内容に書き換えた上で npm install を実行しなおす必要がある

ということで、やや保守性に欠ける。

特定のパッケージが依存関係にあるパッケージだけバージョンを指定したい
要望としては

  • gulp が依存している graceful-fs のみ、バージョンを指定したい
  • メンテナンスは最小限(意識するのは初回のみ)としたい(パッケージの追加時等に影響無いようにしたい)

となる。

調べてみると npm の代わりに Yarn を使用し、『選択的な依存関係の解決(Selective dependency resolutions)』機能を使えばできそう(package.json に "resolutions" フィールドを追加)。

  "resolutions": {
    "gulp/**/graceful-fs": "^4.x.x"
  }

この方針で調整したのが、こちらの手順になる

参考:npm で Yarn の "resolutions" っぽいことはできないか?
一応、npm 用にそういうパッケージも存在する模様。
github.com

ただ、試してみた限りでは

  • 階層指定("gulp/**/graceful-fs" 等といった書き方)はできない
  • "scripts"セクションに"preinstall"を追加するのは、一度 npm install を実行後にする必要あり
    いったん npm install してから(package-lock.json が作成されてから)でないと、npm-force-resolutions がエラーになる
  • パッケージの追加時等でpackage-lock.jsonが更新された際には、npm install をやり直す必要あり

のような感じで、今ひとつ使い勝手が良くないように感じた。
ざっくりとか見ていないため、誤解しているかもしれない

その他

generator-chrome-extension-kickstart 及び主な fork の状況