読者です 読者をやめる 読者になる 読者になる

CafePitchの区切り文字にheader要素を指定できるようにした

Electron JavaScript

CafePitchはElectron製のMarkdownで書けるプレゼンテーションツールです。久々のアップデートです。

github.com

久々ということでAngularをrc versionから脱却してみたりとか、TypeScriptのバージョンを上げたりとか色々した。 Angularはbootstrap周りをごっそりと書き換えたけど、それ以外はあんまり変えなくても動いた

しかしテスト周りは変わりすぎていて厳しかったので、ユニットテストは全部捨てた。もともとあまり書いていなかったし、僕の不勉強からかなりギリギリで動いている感じだったので、まぁいい機会だったかもしれない。

Spectronで書いているE2Eテストは無傷なので、そこで最低限は担保している。(はず)

今回のアップデートでは、以下のように設定用の吹き出しを出せるようにしていて、そこから区切り文字を設定できるようにした。

f:id:joe-re:20170320205829p:plain

id:catatsuy さんが以下のつぶやきをしていて、お話を聞いてみると、見出し要素を区切り文字にしたいということだった。

理由を聞いてみると、自然な文章を書いて勝手にスライドができて欲しい(水平線は普通に文章を書く時にはあまり使わない)というのが理由で、なるほどーという感じだったのでやってみた。

区切り文字を増やすにあたっては、markdownのparse結果に行番号が付いていると理想的だったんだけど、cafepitchの中で使っているmarkedでは位置情報までは取れなかったので、必要最小限の構文のみを、行単位でlexingする処理を実装した。

一応markedの実装を見て齟齬がないようにはしたつもりだけど、markdownのparseと違うロジックを使うのはバグりそうであんまり良くないよなー、という感じはあるので、本当は一緒にしたい。どなかたいい感じの実装があれば教えてください。

実際に試してみると、区切り文字を意識しなくて書けるのは結構いい感じ。 もし興味があれば是非お試しください。

FlowtypeでFluxアーキテクチャに型付けをするという発表をした

もう2週間ぐらい前になってしまいますが、ランサーズさん主催の勉強会で、Type-Safe Flux Using Flowtypeというタイトルで発表させてもらいました。

eventdots.jp

発表資料

speakerdeck.com

ここ半年ぐらいReact + Flux + Flowtypeを使った環境で開発しているのですが、Fluxにおける型付けのパターンは自分の中では大分固まってきた感覚があります。

今年の弊社AdventCalendarでも、Qiitaの記事として書きました。

qiita.com

自分の中で固まってきたとはいえ、FlowtypeもTypeScriptもどんどん進化しているし、もっと良いパターンもありそうだなー、という感覚もあります。

ぜひ知見をお持ちの方はお話ししましょう。

主催のランサーズさん、登壇者の皆様、ご参加いただいた皆様、ありがとうございました。

YAML/JSONでコマンド定義が書けるテンプレートジェネレータを作っている

JavaScript

この記事はNodeJS Adventcalendar 2016 の19日目の記事です。 もうクリスマスということで、大幅に遅れてしまって申し訳ございません。

色々とnodejsのCLIや、electronやwebなどを作っていく中で、僕の利用するスタックはだいたい同じなので、毎回package.jsonから書いていくのだるいなーというところから、YAML/JSONで定義ができる(Yet Another Yeoman的な)ツール作ろう、と思って書いて、それからずっと放置してました。 良い機会 & やる気を取り戻すためにもちょっと紹介します。

hiaというテンプレートジェネレータです。

github.com

Getting Started

github.com

hiaを利用して、簡単なジェネレータを作ってみました。 これはreact + flux-util + flowtypeのテンプレートを作ってくれます。

npm install -g @joe-re/hia-react-fluxutil

でinstallできます。 あとは以下のように適当なディレクトリを作り、hia-flux init コマンドを叩いてみてください。

$ mkdir hia-flux-sample
$ cd hia-flux-sample
$ hia-flux init
created src/components/Counter.jsx
created src/actions/CounterAction.js
created src/stores/CounterStore.js
created src/containers/CounterContainer.jsx
created src/routers/AppRouter.jsx
created src/AppDispatcher.js
created src/index.html
created src/index.jsx
created .flowconfig
created .babelrc
created webpack.config.js
created package.json

ファイルが作成されたら、npm installの後にnpm startを叩くことで、アプリケーションが動きます。

f:id:joe-re:20161225011134p:plain

YAML定義の例

実際にどんな感じのyamlを定義するのか、というとこんな感じです。

---
basedir: ./test
command: hia
subcommands:
  test:view:
    description: generate view template.
    input: true
    templates:
      src: fixtures/component.ejs
    script:
      fixtures/scripts/test.js
    output:
      dir: test/dist
      filename: '[name].jsx'
    args:
      feature_name:
        aliase: f
        description: Feature name. It is used as second directory name.(If you specify calendar, create 'test/dist/calendar/[name].jsx')
      require_args:
        aliase: r
        description: require args.
        required: true
      question_args:
        aliase: q
        description: This is Question Section.
        before: fixtures/scripts/before.js
        question: true
      default_args:
        aliase: d
        description: set default value.
        default: 'default value'

コマンド定義の説明

command: hiaでcommand名を定義しています。

  subcommands:
    test:view:

みたいな感じでsubcommandを定義しています。つまりこれでhia test:viewコマンドが定義されました。 このコマンドはinput:trueを設定しているので、inputを受け付けます。 つまりhia test:view <INPUT>という形式のコマンドとなります。

最後にargsセクションで以下のような定義をしています。

    args:
      feature_name:
        aliase: f
        description: Feature name. It is used as second directory name.(If you specify calendar, create 'test/dist/calendar/[name].jsx')
      require_args:
        aliase: r
        description: require args.
        required: true
      question_args:
        aliase: q
        description: This is Question Section.
        before: fixtures/scripts/before.js
        question: true
      default_args:
        aliase: d
        description: set default value.
        default: 'default value'

これらはそれぞれ、CLIのオプションとして渡せます。 --feature_name hoge ならfeature_nameというオプションでhogeとして受け取れます。ここで必須にしたいパラメータは required: true で表現します。default valueの設定もできます。

ちなみにこれらの定義をしただけで、なんとなく良い感じのhelpが表示されるようにしています。

$ hia -h
  Easy and customizable generator system for creating template.

  Usage:
    hia <SUBCOMMAND> <INPUT>
      -h, --help             Show list available subcommands and some concept guides.
      -c, --config           specify config file path.

  Subcommands:
    hia component <INPUT>    generate view template.
      -t, --text             text on your component.

テンプレートのrenderの定義の説明

テンプレートはejsを解釈してrenderします。inputやargsセクションの定義で受け取った値は、そのままinputならinput、argsならそれぞれのオプション名が変数名になります。

templatesセクションには、{ src: 'ファイルパス', name: 'ファイル名の文字列' } というオブジェクトの配列を設定できます。このsrcにejsのファイルパスを設定します。ここで設定したnameは、outputセクションで{ filename: '[name].js' }と設定することで出力時の名前として使うことができます。

scriptセクションを設定することで、render直前にスクリプトを挟むこともできます。scriptは以下のように記述します。

module.exports = function script(params) {
  params.subcommand.output.dir += '/exchanged';
  params.cliParams.input += 'Exchanged';
  return params;
};

paramsはsubcommandとcliParamsの2つのオブジェクトを持っています。 引数で受け取ったオブジェクトを、変更してreturnで返すことでrenderされる直前にパラメータを変更することが可能です。

subcommandはhia.yaml(json)で定義したコマンドの設定を含みます。上の例では出力先ディレクトリを変更しています。 cliParamsはinputやargsで受け取ったparameterを持っています。

所感

1人でやっている分には、初回設定が楽になるわー、ぐらいの感覚で使えているのだけど、大勢の人に使ってもらおうと思うと完全に雑な作りなので、もっと改良していきたい。具体的にはwiredep的な機能付けて、templateに追加でコードが書けるような仕組み欲しいなー、とか思っている。 やっていきを継続して行きたい。