floating-memo.app

名前の通り最前面に表示されてる事を前提にした簡易なメモアプリです。

node-webkitで最前面なアプリが書けることに気づいたので簡単に作りました。

img

今のところMacのみのサポートとしています(DayOneに依存してるので)、別の所に保存する実装等があれば他のプラットフォームでも動かせるようになると思います。

以下から、ダウンロードすることが出来ます。

仕組み

node-webkit

floating-memo.appはnode-webkitで書かれています。

node-webkitはnode-webkitとは何かでも書いていましたが、ブラウザのcontextとnode.jsのcontextの2つを持っています。

このアプリでは、表示やエディタ部分はブラウザのcontextで、DayOneに保存するところだけnode.jsのcontextで動いています。(ブラウザじゃできないところをnode.jsで処理するという形ですね)

このcontextの違いはごちゃ混ぜに出来てしまうのも特徴ですが、今回は明確にentry pointで切り分けました。

詳しくはManifest format · rogerwang/node-webkit Wikiに書いてありますが、node-webkitアプリのpackage.jsonではmainの他にnode-mainというプロパティを指定することが出来ます。

  • main はブラウザでcontextで動くHTMLを指定します
    • mainから node.js contextで実行するのも可能です(これがややこしい原因ですが)
  • node-main は node.jsのcontextで動くjsを指定します

普通の考えなら、main <-> node-mainのやり取りは通信やメッセージングを使いますが(むしろそうした方がいい気がする)、node-webkitの場合はこのcontextの境界が薄いので、普通にglobal.windowに関数を貼ったりすれば相互に呼び出し出来てしまいます!

今回は面倒だった小さいアプリなので、node-mainからglobal.window.dayoneという関数を生やして、それをブラウザcontextから呼び出す事でDayOneに保存できるようにしました。

node-webkitはホビー用途だとかなり気軽で楽しいのでオススメです。

Chrome stableに近いバージョンで動いて遊べるので、最近はMV*ライブラリなどを試したりする遊び場になってます。(Browserifyなくてもnpmが使えて楽というのもあります)

最前面表示

node-webkitでアプリを最前面にするのは簡単でWindow.setAlwaysOnTop(Boolean top)を使うだけです。

また、クリップボード, フルスクリーンやWebNotification、style="-webkit-app-region: drag"というスタイルを使ってアプリのドラッグ移動の対応など、簡単なビューアアプリを作る場合に適した機能が既に入っています。 (コマンドライン関係ならnode.jsから直接プロセスを読んだりすれば大体できます)

ウィンドウの透過はまだないようです。

Macのネイティブメニュー

node-webkit 0.10からMacのネイティブメニューは自動では作られなくなりました。 menu

これで何が困るかというと、MacだとCmd+QやCmd+a等のショートカットはメニューに定義されているため、どのアプリも共通にあるショートカットが効かなくなってしまう点です。

そのため、以下のようにMenu.createMacBuiltin(appname)を使って明示的にデフォルトのメニューを追加する必要があります。

var gui = require('nw.gui');
var win = gui.Window.get();
if (process.platform == 'darwin') {
    var mb = new gui.Menu({type: "menubar"});
    mb.createMacBuiltin(require("../package.json").name);
    win.menu = mb;
}

CodeMirror

メインのエディタとなる部分にはCodeMirrorを使っています。 CodeMirrorはIMEとの相性も悪くなく(より良くする場合はCodeMirror Composition Modを当てる)、豊富なAPIやプラグイン(Addon)が用意されているので、結構手軽に使えます。

特にMarkdownエディタとしてはそこらのネイティブアプリより素で出来がいいと思います。

  • CodeMirror: GFM mode のサポート
  • シンタックスハイライト
    • コードブロックで別言語の部分のシンタックスハイライトも可能
  • CSSでの制御(シンタックスハイライト、文字サイズやレイアウトとかも)
  • Addonでの拡張(GFMモードとかも拡張ベースです)

以下のようにベースと必要なAddonを読み込んでやるだけでGitHub flavored markdown対応のエディタが用意出来ます。(npmにも対応してるので、requireする方法でも使えます)

<script src="node_modules/codemirror/lib/codemirror.js"></script>
<script src="node_modules/codemirror/addon/mode/overlay.js"></script>
<script src="node_modules/codemirror/mode/javascript/javascript.js"></script>
<script src="node_modules/codemirror/mode/markdown/markdown.js"></script>
<script src="node_modules/codemirror/mode/gfm/gfm.js"></script>
var editor = CodeMirror.fromTextArea(document.getElementById("floating-memo"), {
    mode: "gfm"
});

注意点としては以下のような感じでした。

  • それぞれシンタックスハイライトした言語のmodeも読み込む
  • gfm.jsはmarkdown.jsとoverlay.jsに依存する

他にはCodeMirrorでカーソル位置が常に中央になるアドオンを書いた | Web Scratchでも書いてますが、幾つかAddonを使っています。

普通に必要になるレベルのAPIは大体揃ってるので、いじるのもそこまで難しい(選択範囲とか考えると面倒ですが)という感じじゃないので触ってみると面白いと思います。

自分的にはFoldingTextがCodeMirrorを使ったアプリとしてよくできてると思います。 Mac用のMarkdownアプリなのですが、内部でCodeMirrorを使っていて、CodeMirrorと同じ手法で拡張を書けるようになっていて面白いと思います。

Mercury

最近node-webkitアプリを書く時、何かしらのMV*やデータバインディングライブラリと言われるものを試しているのですが、floating-memo.appではRaynos/mercuryを使いました。

mercury は以下のような特徴を持ってます。

  • 完全にモジューラーな実装
  • Virtual DOM
  • FRP
  • 軽量

mercuryについては長くなったので別記事にしました

まとめ

node-webkitアプリは最前面表示や枠なしのウィンドウ表示もできるので、 プレビューツールみたいな小物アプリを書くのに便利です。