ES6でクラス名を動的に変更する方法

ES7のdecoratorsでクラスを生成するとクラス名がそのデコレータのものになってしまいます。
例えば:

import React from 'react'

function addAwesomeProperty (Spec, Component = Spec) {
  class AwesomeClass extends React.Component {
    render () {
      return React.createElement(
        Component,
        Object.assign({ awesome: 'yes!' }, this.props)
      )
    }
  }
  return AwesomeClass
}

@addAwesomeProperty
class OriginalClass extends React.Component {
  ...
}

こうすると生成後のクラスの名前は AwesomeClass になってしまいます。これは不便。
だからといってクラス名を以下のように変えようとしても出来ません:

AwesomeClass.name = 'OriginalClass'

なぜなら name プロパティは writable ではないからです:

Object.getOwnPropertyDescriptor(AwesomeClass, 'name')
    { value: 'func',
      writable: false,
      enumerable: false,
      configurable: true }

しかしES6の仕様によると以下の方法で変更できるとの記述を見つけました:

> Object.defineProperty(func, 'name', {value: 'foo', configurable: true});
> func.name
  'foo'

という事は、前述の例を以下のように修正すればクラス名に影響を与えずに済みます:

import React from 'react'

function addAwesomeProperty (Spec, Component = Spec) {
  class AwesomeClass extends React.Component {
    render () {
      return React.createElement(
        Component,
        Object.assign({ awesome: 'yes!' }, this.props)
      )
    }
  }
  // 追加
  Object.defineProperty(AwesomeClass, 'name', { value: Component.name, configurable: true })

  return AwesomeClass
}

まぁ、これが設計として正しいのかは謎です。

蛇足

動的なクラス名を定義する方法として、

const classes = { [ dynamicClassName ]: class { ... } }
classes[dynamicClassName].name  // => dynamicClassName

みたいな方法もあるみたいだけど、自分の環境では常に _class となって上手く行かなかった。
自分のbabelの設定が悪いのかもしれないけど。

Dockerで子プロセスからのstdoutをsupervisordにリダイレクトする方法

Dockerではsupervisordを使ってプロセス管理をする事が多いですね。
そのようなコンテナでは、以下のコマンドでsupervisordが吐いたログを確認できます:

docker logs -f <container_id>

さらに、子プロセスが吐いたstdout/stderrを同様に確認したくなることがあります。
例えばmysqlapache2のログなどです。
いちいちコンテナにログインしてtail -fなんてやってられませんよね。
supervisord.confを以下のように設定すれば、これら子プロセスのログをsupervisordに転送できます:

続きを読む Dockerで子プロセスからのstdoutをsupervisordにリダイレクトする方法

neovimインストール時にluaパッケージが無いと言われた時の対処

neovimをHomebrewでインストールした時、以下のようなエラーを得た:

$ brew install neovim/neovim/neovim
==> Installing neovim from neovim/neovim
==> Downloading https://github.com/neovim/neovim/archive/v0.1.7.tar.gz
Already downloaded: /Users/***/Library/Caches/Homebrew/neovim-0.1.7.tar.gz
==> Downloading https://github.com/luvit/luv/archive/146f1ce4c08c3b67f604c9ee1e124b1cf5c15cf3.tar.gz
Already downloaded: /Users/***/Library/Caches/Homebrew/neovim--luv-3.tar.gz
==> Downloading https://raw.githubusercontent.com/neovim/deps/master/opt/LuaJIT-2.0.4.tar.gz
Already downloaded: /Users/***/Library/Caches/Homebrew/neovim--luajit-2.0.4.tar.gz
==> Downloading https://github.com/keplerproject/luarocks/archive/5d8a16526573b36d5b22aa74866120c998466697.tar.gz
Already downloaded: /Users/***/Library/Caches/Homebrew/neovim--luarocks-998466697.tar.gz
==> Building third-party dependencies.
==> cmake ../third-party -DUSE_BUNDLED_BUSTED=OFF -DUSE_BUNDLED_GPERF=OFF -DUSE_BUNDLED_LIBUV=OFF -DUSE_BUNDLED_MSGPACK=OFF -DUSE_BUNDLED_UNIBILIUM=OFF -DUSE_BUNDLED_LIBTERMKEY=OFF -DUSE_BUNDLED_LIBVTERM=OFF -DUSE_BUNDLED_JEMALLOC=OFF -DUSE_EXISTING_SRC_DIR=ON -DCMAKE_C_FLAGS_RELEASE=-DNDEBUG -DCMAKE_CXX_FLAGS_RELEASE=-DNDEBUG -DCMAKE_INSTALL_PREFIX=/
==> make VERBOSE=1
==> Building Neovim.
==> cmake .. -DCMAKE_C_FLAGS_RELEASE=-DNDEBUG -DCMAKE_CXX_FLAGS_RELEASE=-DNDEBUG -DCMAKE_INSTALL_PREFIX=/usr/local/Cellar/neovim/0.1.7 -DCMAKE_BUILD_TYPE=Release -DCMAKE_FIND_FRAMEWORK=LAST -DCMAKE_VERBOSE_MAKEFILE=ON -Wno-dev -DDEPS_PREFIX=../deps-build/usr -DCMAKE_BUILD_TYPE=RelWithDebInfo -DJEMALLOC_LIBRARY=/usr/local/opt/jemalloc/lib/libjemalloc.a
Last 15 lines from /Users/***/Library/Logs/Homebrew/neovim/03.cmake:
-- Found Iconv
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - found
-- Found Threads: TRUE
-- Checking Lua interpreter /tmp/neovim-20170125-64421-1l8rrfq/neovim-0.1.7/deps-build/usr/bin/luajit
-- [/tmp/neovim-20170125-64421-1l8rrfq/neovim-0.1.7/deps-build/usr/bin/luajit] The 'lpeg' lua package is required for building Neovim
CMake Error at CMakeLists.txt:409 (message):
  A suitable Lua interpreter was not found.


-- Configuring incomplete, errors occurred!
See also "/tmp/neovim-20170125-64421-1l8rrfq/neovim-0.1.7/build/CMakeFiles/CMakeOutput.log".
See also "/tmp/neovim-20170125-64421-1l8rrfq/neovim-0.1.7/build/CMakeFiles/CMakeError.log".

If reporting this issue please do so at (not Homebrew/brew or Homebrew/core):
https://github.com/neovim/homebrew-neovim/issues

These open issues may also help:
Build a proper release version of neovim, not a release with debugging info version https://github.com/neovim/homebrew-neovim/issues/209
Can't install via homebrew-neovim if luarocks path is set explicitly https://github.com/neovim/homebrew-neovim/issues/149

これはluaのlpegというパッケージが無いという内容。
luarocksというluaのパッケージマネージャで依存パッケージをインストールする。lpegmpackの二種類が必要。

luarocks install lpeg
luarocks install mpack

これで無事インストールできた。

macOS SierraでSSH Keyを自動でKeychainに登録する方法

Yosemiteまではssh-add -K <key>でOSにキーを覚えさせておく事ができました。しかしこれは現在うまく行きません。
さらに、ssh-add -KもSierraからはkeychainに保存されなくなってしまいました。
なので、ターミナルを新しく立ち上げる度にパスワードを入力しなくてはなりません。不便すぎます。

そこで回避方法が提案されています:

簡単に言えば、OSの起動時にキーを覚えさせる対処法です。
以下の手順でできます

  1. ssh-add -K </key><key>でキーを登録。キーファイルは絶対パスで指定すること。
  2. curl -o ~/Library/LaunchAgents/ssh.add.a.plist https://raw.githubusercontent.com/jirsbek/SSH-keys-in-macOS-Sierra-keychain/master/ssh.add.a.plist を実行してplistを登録。

これだけです。
詳しくは上記GitHubを参照ください。

remark+ReactでMarkdownをレンダリングする

本記事は React Advent Calendar 2016 9日目の記事です。

本稿では、remarkというプラグインベースのMarkdownプロセッサを用いて、ReactのdangerouslySetInnerHTMLを使わずにMarkdownをレンダリングする方法をご紹介します。
InkdropというMarkdown専用ノートアプリを作っていて、その中でこのremarkを使っています。

XSSを回避してReact方式でDOM操作したい

ReactでMarkdownをレンダリングしようと思うと、markedとかmarkdown-itを使ってHTMLの文字列に変換してからdangerouslySetInnerHTMLで無理やりねじ込む実装方法が多いと思います。

続きを読む remark+ReactでMarkdownをレンダリングする

atomエディタのソースコードを再利用してアプリのカスタマイズ性を高めよう

本記事はElectron Advent Calendar 2016 5日目の記事です。

InkdropというElectron製ノートアプリを作っています。
このアプリにはプラグイン機構による拡張性を備えているのですが、これはatomからコードを拝借して実装しました。
atomはMITライセンスによるオープンソースのテキストエディタです。
その際に得た知見を共有したいと思います。
これをきっかけにあなたのElectronアプリ改善のお役に立てれば幸いです。
atomのパッケージを作ったことのある方ならすんなり理解できると思います。

続きを読む atomエディタのソースコードを再利用してアプリのカスタマイズ性を高めよう

ノートアプリ「Inkdrop」のスマホ版を考える

これは拙作のハッカー向けノートアプリ Inkdropに関する記事です。

そろそろスマホ版が欲しい。
寝る前とか出先でアイデアを思いついた時やメモを見返したい時に、やっぱりあると便利ですよね。
というわけで、どうやって作るか検討したいと思います。

ハイブリッドで作ってみる

結論から言うとハイブリッドで組んでみたいと思います。
ハイブリッドとは、Webの技術とネイティブの技術を組み合わせてアプリをつくる方法です。
デスクトップ版InkdropもElectronで作ってあるのでハイブリッドですね。

続きを読む ノートアプリ「Inkdrop」のスマホ版を考える