iOSのブラウザでは外部キーボードのカーソルのキー入力イベントが出ない

菅さんがiOSデバイスでscrapboxがうまく使えないというツイートをしていて、自分はそんなに困ってないけどなとやりとりしていたら、菅さんはiPadに外部キーボードをつなげてscrapboxを使おうとしていて、カーソルキーを使った編集作業ができないので実質使えないのだそう。手元でiPhoneにbluetoothキーボードをつないで試してみたらたしかにそうだった。

ネイティブアプリではカーソルキーが使えるのでどういうことなのかなと調べてみたら、どうやらiOSのブラウザでは(JavaScriptCoreでは?)外部キーボードのカーソルキー操作時のキーイベントが出ず、カーソルキーを使った操作の実装が不可能みたい。

Official answer from Apple:

Thank you for contacting Apple Developer Technical Support (DTS). Our engineers have reviewed your request and have concluded that there is no supported way to achieve the desired functionality given the currently shipping system configurations.

ぜんぜん知らなかった。カーソルキーはページスクロールにも関わるからタッチとの齟齬を考慮して殺してあるのかな。ちなみにAndroidは問題ないようだった。


Almin on Next.js

いまつくってる新しいアプリで、せっかくなので新しいフレームワーク使おうとAlminNext.jsを使っている。

最初のころNext.jsのクライアントレンダリングとサーバサイドレンダリングの違いの意味がよくわかってなくて、Alminとどう連携させればいいのか試行錯誤が続いたんだけど、ようやくこうすればいいというのがわかった。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
const dispatcher = new Dispatcher()
const storeGroup = new StoreGroup({
DataState: new DataStore(dataRepository)
})
const appContext = new Context({
dispatcher,
store: storeGroup,
options: {
strict: true
}
})
async function loadData(req) {
return new Promise(resolve => {
if(req) {
// サーバサイドだったらdbから読む
const data = db.data.find().toArray()
resolve(data)
} else {
// クライアントサイドだったらapiから取得
axios('/api/data.json')
.then((response) => {
resolve(response)
})
});
}
}
export default class extends React.Component {
static async getInitialProps ({req}) {
const data = await loadData(req)
return { data }
}
componentWillMount () {
// Alminにデータを渡すのはgetInitialPropsではなくここで
if (this.props.data) {
appContext.useCase(LoadDataUseCase.create()).execute(this.props.data)
}
}
}

AVAをWallaby.jsで使う

ひさしぶりに完全な新規プロジェクトでプロトを作ることになったので、「Modern JavaScript概観、そしてElectronへ」を参考に、JavaScriptの最新環境を入れて使ってみている。このエントリ、「ここまで長い解説を読み通しても終わっているのは開発の事前準備だけなんだよね…」というつぶやきも読んだけど、モダンJSの環境(トランスパイラと型システム拡張、静的解析環境、テスト、UIフレームワーク、ビルドなど)について選択肢とシンプルさを重視するようなご本人の選択と、なぜそのツールが必要なのかの解説が明快でとてもうれしい。フレームワークはまだ検討段階だけど開発環境については基本的にこの解説の通りにしてる(ボイラープレートは使ってない)。

使ってみていまのところいちばんこれいいなと思っているのはAVA。先エントリに書いてあるとおりシンプルで高速でPowerAssert、That’s itというテスティングフレームワークで、しかもこれはすでにWallaby.jsに対応している。Wallaby.jsごしでもPowerAssertのアサート情報はとてもわかりやすく表示されるので、こけたテストを直すときの手数が明らかに減ってとても快適。

ava on wallaby.js

http://dm.gl/2016/04/26/wallaby-sublime-electron-ava/ より

現状バグがあるのかAVAのコールバックモード(test.cb)だと挙動が怪しいけど、これはPromiseを使えば解決するのでPromiseを使うための強制ギブスになるのも結果オーライだった。


Webpackモジュールのプライベート関数をユニットテストしたい

レガシーなJavaScriptソースをWebpackでビルドできるようにモジュールに切り分けてテストを書くことをしている(わりとヒマなので)。

jsモジュール内の機能をプライベート関数に分割して書く場合に、そのプライベート関数部分の単体テストを書きたい場合があると思うんだけど、それをどうやればいいのかわからなくていろいろ調べた。

unit testing - How to access and test an internal (non-exports) function in a node.js module? - Stack Overflow

こういう話で、ここではrewireを使えという事になってるんだけど、これはうまくいかなかった。rewire-webpackというのもあるんだけど、これもだめだった。

でうまくいったのは、exports-loaderでプライベート関数を指定してエクスポートする方法で、

1
2
3
4
5
6
7
8
9
10
11
function privateFunc() {
return "private";
}
function exportFunc() {
return "export";
}
module.exports = exportFunc;

こういうモジュールのテストを

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
describe('test', function() {
it('モジュールのテスト', function() {
var exportFunc = require('export-module.js');
expects(exportFunc()).toBe('export');
});
it('プライベート関数のテスト', function() {
var privateFunc = require("exports?privateFunc!./export-module.js");
expects(privateFunc).toBe('private');
});
});

こんな感じにしたらうまくいった。


ChromeのDeveloper Toolで実行中のJavascriptオブジェクトをJSONで取得する

Chrome開発者ツールのコンソールに表示したObjectをクリップボードにコピーする - dackdive’s blog

というわけで既存Javascriptコードのテストをいまさら書いてるわけだけど、ユニットテストの入力を動いてるコードの変数から取れないかと思って調べたらChromeの開発者ツールのコンソールでcopy(変数)とするとjsonで取れるのがわかった。これは便利。


IDEプラグイン型の自動テストツール「Wallaby.js」を導入してみた

Wallaby - intelligent test runner for JavaScript, TypeScript, and CoffeeScript

BCCKSの組版エンジンに安定性と大規模な拡張が同時に求められる局面が生じてきたのでちゃんとテストを書いてからいじるようにしようとjsのテストフレームワークやら自動テスト環境やらを調べていたら、Intellij系のIDE(やVisual StudioとAtom)向けのプラグインとして提供され、テストのパス状態や結果がエディタのコード上に完全なかたちで統合されるというツール「Wallaby.js」を見つけたので導入してみた。1ライセンス$100でまあちょっと高いなと思うけど、1日使ってみてこれはテストうんぬんより開発ツールとして非常に便利なので確実に定着するしすでに誰かにオススメしたい感じがしている。

僕が使っているのはIntellij IDE(PhpStorm / Intellij IDEA)なのでIntellij プラグイン版のみの評価になる(Atomプラグイン版もどんな感じなのか気になるけど)。もともとIntellijのIDEには標準でもテストランナープラグインが提供されていて、それを使ってみるつもりでいろいろ調べていたんだけど、ブラウザjsのテストはjsTestDriverを起動してからブラウザを起動しないといけなかったり、いまいち乗りきれない感じがあった。Wallabyはプラグインにヘッドレスブラウザ(PhantomJS)が完全に隠蔽された形で統合されていて、テストフレームワークのインストールと設定(テスト対象のソースとテストソースの定義)をすれば実行過程のことはなにも気にしなくてもテストが実行されるようになる。導入が楽。

テスト結果のエディタ統合も想像した以上の完成度で、テスト側のソースの各行にカラーチップでテストのパス状態が信号のように表示されるのはもちろん、テストするソース側も現在のテストスイートでの各行のカバレッジ状態がやはりカラーチップで表示されるので、テストがぜんぜんないコードにテストを足していく今回のような場合でもモチベーションを上がりやすいし、キーになるロジックのテストを先に書こうといった判断もしやすい。コード修正後の反映パフォーマンスもまったく問題ない(これはまだテストが少ないせいかもしれないけど)。

Wallaby.jsのサイトからアニメgifを引用

さらに体験してみて眼からうろこが落ちたのは、Wallabyの環境だとほんとうに「テスト駆動開発」ができるということ。Wallabyプラグインはテストの状態だけでなく、テスト実行時の各行での出力やエラー内容もインラインで表示される(Chromeのjsデバッガのステップ実行状態とおなじ感じ)。コードにconsole.logを追記すれば即座にそのブロックに関するテストが実行され、出力された変数の値がインラインに表示される。Wallabyの環境でテストが書かれた環境でコードを書くと、まさにテストというエンジンに接続された動いているプログラムを動いたまま触っているような感覚で開発ができる。あまりテストツールをさわったことがないので他のツールでもできることなのかもしれないけど、これは新鮮だった。

なにしろきのう導入したばかりなのでもうちょっと使ってみないとわからない部分もあるけど(テストが増えるとどうなるかとか)、現時点ではWallabyによってコーディングの進めかた自体が変わりそうな気がしている。


テーマテンプレートからシングルページを作るだけのHexoプラグイン

archivesページを整える[2015/01/28]1のときにいまいちな感じにしていたサイトの構成をちゃんとするために、Hexoのgeneratorプラグインをつくった。標準のpageと同じ感じだけど専用のレイアウトテンプレートでヘルパーを使って内容が更新されるページが作れる。

これを使ってHighlightsをまとまった読み物が並ぶページにして、Archivesはもとに戻した。

ちなみにこないだ作ったmonthly_post_listもあげてある。


Hexoプラグインを試作した

せっかく毎日blogを書いているので、月末にまとめ記事を作れるようにしたいなと思っていて、それを実現するHexoプラグインを手探りでつくった。

1
2
3
{% monthly\_post\_list 201502 book %}

とすると、2015年2月のbookタグを持ったポストの一覧が生成される。

使ったページがこれ。

とりあえずHexoのブログフォルダのscriptsに置けば動くけどあとで正式なプラグインにしよう。


Hexoを3.0.0-rc.4にアップグレードした

なぜかいつのまにかHexoが動かなくなっていたので勢いで3.0.0-rc.4にしてみたら、けっこう各部が動かなくて困った。

archive画面でget_postsで記事をリスティングしてたのが動かなくなってて(v3ではヘルパーのget_postsが廃止されたそうだ)、しかもその代替コードがいまいちよくわからなったのだが、

1
2
3
\<% site.tags.find({name: 'work'}).data[0].posts.sort('date', -1).forEach(function(item){ %\>
<li><a href="<%- config.root %><%- item.path %>"><%= item.title %></a></li>
\<% }); %\>

にしたらひとまず動いた(postsを取るもっといいインターフェイスがないとおかしい気がするのだが)。

あとhexo-generator-feedがnpmにあるのだとv3に対応してないので、

1
npm install git+https://git@github.com/hexojs/hexo-generator-feed.git --save

とgitのを入れて間に合わせた。

今日はとりあえずここまで。


「紙のBCCKS」をリリースしました

Paperbccks

■ようやく…、って書き出そうとしてエディタ公開のときもそう言ってるのに気付きましたがはやりようやく、BCCKSでつくった本が、ワンタッチでそのまま「紙の本」として印刷製本することができるサービスその名も『紙のBCCKS』が昨日未明にサービスインしました。詳細はまだあんまりどこにも書けてないです(すいません)。やや堅苦しいですがサービス概要に本の仕様とか価格とかの情報はまとまっております。単価については「買う本」の値段としてはちょっと割高に見えるかと思いますけど、「作る本」としてはかなりがんばった値段にしてあります。

紙のBCCKSのためにバージョンアップされた本のフォーマットと紙本の自慢ポイントなんかはこちらの本『書籍002参考書』にまとまっております。あと自分の紙の本をつくるためのサンプルとしてこの本を再編集した「紙の本見本」を買いやすい値段で販売する予定(もうすぐ)なので、それが出たらぜひ買って手に取ってみていただきたいです。

Jacket 160

■「紙のBCCKS」はいちおうニュースリリース的には「電子書籍を紙の本に印刷製本するサービス」という言いかたで紹介することになっているんですが、今回開発に関わってきた僕(ふくむBCCKSチーム)からすると、逆にむしろこの「紙の本」こそがアーキタイプで、このかたちの「本」をだれでも、どこでも、つくって読める環境を実現するために外堀を埋めるような開発を続けてきたというべきではないかという印象があります。先日のマガジン航『本は、ひろがる』リリース記念公開鼎談で弦人さんが言ってたこと(「ページ数が決まってると埋めたり削ったりしたくなるから内容が締まるはず」という発言がありました)になるほどと思いましたけど、ひとつの「紙の本」という形も量も固定されたアンドゥーの効かない形に書き出される、あるいはそのような可能性を持たないと、そのコンテンツらしくあるべき外形が意識されず、そのコンテンツにあるべき価値も生まれず、そのコンテンツにお金を払う気にならない、といったことは往々にしてあるわけです。そういった意味で、「紙のBCCKS」というサービスが「本」とよばれるコンテンツをつくるための「計量カップ」になったりするとおもいろいなーと思います。ぜひためしに使ってみてくださいませ。