esaba(餌場)とは

https://github.com/ttskch/esaba

esa.io上の記事データをホストするためのPHP製のWebアプリケーションです。/post/{記事ID}というURLでesa.io上の任意の記事を公開できます。

社内で必要に迫られて作りましたが、割と一般的にニーズがありそうなツールなので簡単にご紹介したいと思います。

esa上のこの記事が esabaではこう表示される(デフォルトCSSでは)

esa標準の「Share Post」との違い

esaにはShare Postという機能があり、記事ごとに外部公開用のURLを発行することができます。これと比較したesabaのアドバンテージはざっと以下のとおりです。

  • 記事の表示に独自のcss/jsを使うことができる(scss/webpack対応)
  • カテゴリやタグごとに細かく公開/非公開を設定できる
  • 社内のみに公開したい場合などに便利(オンプレなのでWebサーバーレベルでアクセス制限可能)
  • 記事中に他の記事へのリンクがある場合はesabaのURLに変換して出力してくれるので、記事本体のURLと公開用のURLを別々に管理する必要がない

なぜ作ったのか

弊社では開発部という部署でのみesaを使っていて、現状は社内の全員が閲覧できるドキュメント管理ツールがありません。 全社向けのドキュメントらしいドキュメントはそんなに数がなかったこともあり、Googleドライブにpdfを置いておくぐらいの運用で騙し騙しやっていましたが、最近になっていよいよ不便さが顕在化してきたため、何とかしようと思い立ちました。

全社向けのドキュメントを書いたりメンテしたりするのはせいぜい数人なので、閲覧させるためだけに全社員にesaアカウントを発行するのはあまり経済的ではありませんでした。そこで、esaの記事データをAPIで取得してそのままホストするだけのサービスがあれば便利なのではと考えた次第です。

インストール方法

事前にesa上でPersonal access tokenを発行しておく必要があります。

esabaのインストールにはComposer(PHPのパッケージ管理ツール)とnpmが必要になります。 また、PHPのバージョンは5.6以上が必要です。

$ composer create-project ttskch/esaba   # npm installも自動で走ります
$ cd esaba
$ cp config/config.secret.php{.placeholder,}
$ vi config/config.secret.php   # esaのアクセストークンなどgitignoredな設定を書き込んでください

使い方

本番環境

/path/to/esaba/webをDocumentRootとして、PHP5.6以上が動作するWebサーバーでホストしてください。

開発環境

PHPのビルトインサーバーを使ってローカルサーバーを起動するには、以下のようにします。

$ COMPOSER_PROCESS_TIMEOUT=0 composer run

起動したら、ブラウザで http://localhost:8888/index_dev.php/post/:post_number へアクセスすれば記事が見られます。

各種設定

config/config.php で色々な設定が可能です。

カテゴリやタグによるアクセス制限

$app['config.esa.public']$app['config.esa.private'] にそれぞれカテゴリ名やタグ名をセットすることで、柔軟なアクセス制限が可能です。

例えば以下のように設定すると、

// config/config.php

$app['config.esa.public'] = [
    'categories' => [
        '公開用/公開用1',
        '公開用/公開用2',
    ],
    'tags' => [
        '公開',
    ],
];

$app['config.esa.private'] = [
    'categories' => [
        '公開用/公開用1/一旦保留中',
        '公開用/公開用2/一旦保留中',
    ],
    'tags' => [
        '非公開',
    ],
];
  • 公開用/公開用1カテゴリ配下、公開用/公開用2カテゴリ配下が公開対象となる
  • それとは別に公開タグが付いている記事も公開対象となる
  • ただし、公開用/公開用1/一旦保留中カテゴリ配下、公開用/公開用2/一旦保留中カテゴリ配下は非公開となる
  • また、非公開タグが付いている記事は他の全ての設定に優先して非公開となる

という状態になります。

HTMLの置換

記事中に他の記事へのリンクがあれば、esabaでその記事を閲覧するためのURLに自動で置き換えられます。

また、それとは別に$app['config.esa.html_replacements']にて任意の置換ルールを設定しておくこともできます。 例えば、すべてのtarget="_blank"を削除したい場合は、以下のように設定します。

// config/config.php

$app['config.esa.html_replacements'] = [
    '/target=(\'|")_blank\1/' => '',
];

置換ルールのパターン部分はPerl互換の正規表現です。詳しくはこちらをご参照いただくか、お近くのPHPerまでお尋ねください。

カテゴリ/タグに応じたcss/jsの切り替え

$app['config.esa.asset']でカテゴリやタグごとに使用したいcss/jsファイルを設定できます。

// config/config.php

$app['config.esa.asset'] = [
    '公開用/Wordっぽい文書' => [
        'css' => 'css/post/word-like.css',
        'js' => 'js/post/word-like.js',
    ],
    '#Wordっぽい文書' => [
        'css' => 'css/post/word-like.css',
        'js' => 'js/post/word-like.js',
    ],
];

上記のように設定した上で、./web/css/post/word-like.cssおよび./web/js/post/word-like.jsを設置すれば、

  • 公開用/Wordっぽい文書カテゴリ配下の記事
  • カテゴリに関わらずWordっぽい文書タグが付いている記事

にはword-like.css word-like.js が適用されます。

注:複数の条件にマッチする記事の扱い

  • ある記事が複数の条件にマッチした場合、「タグベースの条件」が「カテゴリベースの条件」よりも優先されます
  • ある記事が複数の「カテゴリベースの条件」にマッチした場合、より深いカテゴリを指定している条件が優先されます
  • ある記事が複数の「タグベースの条件」にマッチした場合、保証された優先順位はなく、いずれか1つの条件が適用されます

webpackによる独自アセットのビルド

esabaはscss/webpackに対応しています。独自アセットも、設定ファイルの変更なしでwebpackのビルド対象にすることができます。

./assets/post/*.(scss|js)が自動でビルド対象になり、以下のように./web/(css|js)/post/*.(css|js)として配置されます。

$ vi assets/scss/post/word-like.scss   # scssで書く
$ npm run build
  :
$ tree web/css/post
web/css/post
├── default.css
└── word-like.css   # cssがビルドされてる

0 directories, 2 files

Webhookを使ったキャッシュの自動更新

esabaはesaから取得した記事データをキャッシュしますが、esa Generic Webhookを使うことで、esa上で記事が作成/更新されたときに、esaba側のキャッシュを自動で更新させることができます。(ただし、WIP→WIPの更新についてはWebhookが飛ばないため自動更新されません)

// config/config.secret.php

$app['config.esa.webhook_secret'] = 'Secret here';

/webhook/へのアクセスの解放

もしWebサーバーレベルでのアクセス制限を設定している場合、/webhook/へのアクセスはesa.ioからのwebhookリクエストを受け取るために解放しておく必要があります。

例えば、Apache 2.4の場合は以下のような設定が必要になります。

<Location />
    Require ip xxx.xxx.xxx.xxx
</Location>

<LocationMatch ^/(index.php|webhook/?)$>
    Require all granted
</LocationMatch>

おわりに

弊社ではすでに社内でesabaを運用しており、散らかっていたドキュメントをesaに集約することに成功してハッピーな感じになっています :sparkles:

応用的な用途も色々と考えられそうなので、ぜひ気軽にIssueやPRをいただけると嬉しいです!

https://github.com/ttskch/esaba