鈴木颯介のブログ

技術的なメモとかポエムとか。

また Markdown エディタつくっちゃった

これは jsys advent calendar 2019 の 12 日目の記事です。

jsys とは?

僕の記事は jsys とは全く関係ないんですが、一応概要を書いておきましょう。jsys は筑波大学の学園祭実行委員会の情報メディアシステム局の略称です。ようは筑波大学の学園祭の情報っぽいことをやる人たちです。僕もそこに所属していて、Nuxt でウェブサイト作るお手伝いしたり React でよしなにメールを送るシステムのフロントエンドを開発したりしています。

作った、Pooh

jsys 全く関係ないのですが、Pooh という Markdown 編集環境を作りました。

多分初期レンダリングが死ぬほど重いです。あと CSS を書くのが好きじゃない上に自分しか使わない予定なので、最低限しかスタイルをあてていません。ちなみに名前がPoohなのは作り始めたときにくまのプーさんのぬいぐるみが近くにあったからです。

TypeScript と React でできています。まあ無難な構成だと思います。一個面白いことがあるとすれば、IndexedDB へのアクセス・Prettier での Markdown フォーマット・Markdown => HTML の変換を Web Worker 上でやってるくらい。

僕は昔から React が好きなんですが、ここ 1 年くらいお仕事では Vue を書いてるので、久々にガッツリ React を書いてたのしいなぁと思いました。

あんまり保存することに興味がない

僕は普段メモをとったりメールの下書きをしたりタスクを整理したりするのにプレーンな Markdown テキストを使います。それっぽいリッチなソフトウェアでうまくできないかと色々試してはみたのですが、どれもしっくりこなくて結局 Markdown に色々書き連ねています。

そんな感じで色々と Markdown を使って書いているわけですが、僕はあんまり Markdown の保存に興味がありません。書いて、15 分後にはそれを破棄するような使い方をしています。書いてる途中にぱっと新しいものが書きたくなることがあるので、一応保存は必要なんですが、長期的な保存は全くもとめていません。

そういう書き捨てることのみを考えた Markdown エディタって需要がないからか、世の中にあんまりないんですよね。

なので、これまでそんな感じのツールを何度か自分で作ってきました。

これまで触った(作った) Markdown エディタ

Boostnote

これは僕が作者というわけではないですが、高校生のとき割とずっとメンテナーをしていました。

Boostnote をひたすら触っているうちに、自分が求めている Markdown 編集環境は「デスクトップで動くものじゃなくて、ぱっとひらけるやつだ」ということに気が付きました。

Rapunzel

これは高校 3 年生のいつだっけ、秋ごろ?前職をやめるちょっと前くらいに書いたやつです。

  • https://github.com/sosukesuzuki/rapunzel-editor
    • 作り始めたときに一緒にいた人に「適当な単語言って」って言ったら「ラプンツェル」って言われたのが名前の由来です。
  • これは「デスクトップで動くものじゃなくて、ぱっとひらけるやつ」をもとめて作りました。
  • ウェブブラウザ上で動作するのでぱっとひらけるし、デスクトップ PWA なので 2 回目以降は高速に表示されます。

Boostnote は多階層のフォルダが作れなくて、それに不便をかんじていたので、BrowserFSを使ってリッチなファイルシステムもどきを実現したんですが、使ってみて思ったのは、「僕はそんなリッチなものは求めていない」ということでした。

Frozen

これは高校 3 年生の終わり頃に作ったやつです。

これはそれなりにできて、結構ちゃんと使っていました。でも長い記事とかを書いたりするとレンダリングが非常に遅かったり、ちょっと凝った実装をしちゃったりしたせいでメンテが大変になってしまいました。

しばらくつかうぞ

今回のやつはクォリティひくく見えるかもしれませんが、僕の要求に最適化されるように結構考えて作っているので、個人的にはあんまり不満はありません。しばらく使ってみて、気づいた点を徐々になおしていこうと思ってます。

  • デスクトップ PWA 化
  • IndexedDB に書き込むタイミングの最適化
  • フォーマットとSideNavのボタンにショートカット割り当てる
  • とかとか

OSS が好きな大学生増えてほしい

これは、coins Adbent Calendarの 2 日目の記事です。まにあわなかったね。

ここ半年くらい OSS への熱が高まっているので、仲間を増やしたい思いでこの記事を書いています。OSS に関わることは思ったより難しいことではないですよ記事です。

間違ったことが書いてあったら Twitter(@__sosukesuzuki)まで連絡をください。

大学生と OSS

大学生で OSS で好きな人って結構すくないです、悲しいことに。僕の友達にも1人くらいしか思い当たりません。増えて。

でも大学生って実は OSS と相性がいいと思うんです。長い時間働く必要がない人がほとんどで、時間に余裕がある人が多いので。しかし、そもそもそういう文化をしらなかったり、しっていても関わり方がわからなかったりする人が多いような気がしています。

OSS は誰かが作ってる

ソフトウェアが自然に発生することはなく(僕が知らないだけで本当に自然に発生したソフトウェアがあるかもしれないけど基本的には)、誰かが作っています。今あなたがこれを見るために使っているウェブブラウザも、その中のレンダリングエンジンも JavaScript エンジンも誰かが作っています。

あなたが日頃からよく使っているソフトウェアの中にも OSS があると思います。あなたは「誰か」になって、その開発に参加することができます。

OSS に貢献する

GitHub の登場で、OSS に貢献する敷居はぐっとさがったそうです(僕も 2017 年ごろから OSS と関わり始めたので GitHub 登場以前の形を見たことないのですが)。GitHub 上で公開されているような OSS に対してユーザーが貢献する方法はいくつかあります。(しかしまず色々考える前に、各 OSS に置かれているであろうコントリビューションガイドを読みましょう。例えば、Prettier ならprettier/prettier/CONTRIBUTING.mdになります。)

  • Issue を作成する
    • バグを見つけたときや、「こんな機能あったらいいなぁ」と思ったときに、Issue を作成することができます。
    • すでに同様の Issue が存在しないかを調べてから作成するといいと思います。まあ重複してしまっても、「重複してるやで」って言われるだけだと思うので悪いことは起こらないはずです。
  • Pull Request を作成する
    • タイポを見つけたらそれを修正する PR を作成すればいいし、簡単に直せそうだけど誰も手をつけてない Issue があったら直してみると良いと思います。
    • OSS によっては、「good first issue」や「help wanted」のようなラベルが Issue にはられていることもあるので、そういった Issue を解決するような PR を作成するとよいと思います。
  • 議論に参加する
    • Issue や Pull Request 上で行われている議論に参加することができます。
  • etc...

OSS をやる理由

色々ありますが、一番大きいのは

fun, cool!

先日のJSConf 2019で Babel のメンテナーであるHenry 氏が、OSS をやる理由について、「fun, cool!」と言っていましたが、僕もそうで、楽しくてかっこいいからやっています。

小学 6 年生のころにドラゴンクエスト 10 にはまっていましたが、そんなオンラインゲームのようで楽しいのです。しかも、自分の行った修正や機能追加が世界の誰かの役にたったりもするのです、かっこいいでしょう。

もちろん、全人類にとって OSS が楽しくてかっこいいことだとは思いませんが、今 OSS をやっていない人で、OSS を楽しくてかっこいいものだと思える人は存在すると思うのです。

最後に

OSS に興味を持ってくれる大学生が少しでも増えてくれたら(そして僕と友達になってくれたらいいなぁ)と思ってこの記事を書きました。

もし僕の OSS 活動を支援してくれる人がいるのなら、GitHub Sponsors をよろしくお願いしますといいたいところなのですが、国際的に通じる身分証がなく登録できていません。

なので、もしよかったらほしいものリストから水かお茶でも恵んでやってください。大喜びします。最近は JavaScript のコードフォーマッターのPrettierのメンテとかをしてます。

https://www.amazon.co.jp/hz/wishlist/ls/2VMKXAI8J8278?&sort=default

Prettier の TypeScript 3.7 で追加される新しい構文のサポートの現状と今後

TypeScript 3.7 の beta 版が公開されてから 3 週間ほど立ちました。この 3 週間、TwitterGitHub の Issue 上で、Prettier が TS 3.7 beta の新しい構文をサポートしていないことについて言及しているのを目にすることが多々あったので、状況を解説してみます。

まず、TypeScript 3.7 で追加される新しい構文は(おそらく)、Optional Chaining、Nullish Coalescing、Assertion Functions、あと class の declare field の 4 種類があります。(それぞれの詳細は https://devblogs.microsoft.com/typescript/announcing-typescript-3-7-beta/https://github.com/microsoft/TypeScript/pull/33509 を読んでください。)

現状

Prettier は 受け取ったソースを外部のパーサーでパースした結果の AST を見てフォーマットをしますが、Prettier の現在の最新バージョンである 1.18.2 の依存している TypeScript パーサー(の Prettier が依存しているバージョン)はこれら 4 つの構文をサポートしていないので、Prettier はこれらに対応できていません。

今後

大きく分けて 2 つの対応がされると思います。

babel-ts パーサーによる対応

Prettier は 1.19 から(おそらく) babel-ts というパーサーオプションを追加します。( https://github.com/prettier/prettier/pull/6400 ) これによって babel/parser を使って TypeScript をパースできるようになります。babel/parser は、いまのところ Optional Chaining、Nullish Coalescing をサポートしていて、Assertion Functions も対応中 ( https://github.com/babel/babel/pull/10543 )なので、 TS 3.7 で追加される構文についてもほとんどサポートできるでしょう。(デフォルトではないので、 parser オプションに babel-ts を指定する必要はあります)

実際、現在 Prettier は JavaScript のパースには babel/parser を使っているので、JavaScript のフォーマットでは Optional Chaining と Nullish Coalescing を使うことができます。( https://prettier.io/playground/#N4Igxg9gdgLgprEAuEAzVACA-FjAjPAbgB0p0sA6AwkAGhAgAcYBLaAZ2VAEMAnXiAHcACnwScU3AG4QWAEzog8vbmADWcGAGVGqllADmyGLwCucegAsYAWwA2AdUst47XWDhbxLllJcBPZHB2Tnp9djheGGEVAxtuZFRuOwj6ACt2AA8AIRV1TS1uGzgAGX04ROTUkAzMrX0DOzgARVMIeEqUixBdXgjeILxuPDg7RUZefRgHeRhLZAAOAAZ6CYgIhxVGIIm4fqkK+gBHNvgYpgkQbnYAWig4ODlHxV44E5ZXmO44hKQkrvoERsLGMZm67AaTVa7Qqfyq3RgwxmcjmyAATPQTNwWHYGgBhCA2eJBKDQQ4gUwRAAqwwk-wiAF8GUA )

余談ですが、もしかしたら今後 Prettier が使うデフォルトの TypeScript パーサーがbabel-tsに置き換わるかもしれません( https://github.com/prettier/prettier/issues/4103 )

typescript-estree のアップグレードによる対応

Prettier 1.18.2 では、TypeScript フォーマットのためのパーサーに、typescript-eslint の typescript-estree を使っています。そして typescript-estree の最新版は Optional Chaining、Nullish Coalescing、Assertion Functions に対応しています。( https://github.com/typescript-eslint/typescript-eslint/pull/1045 )

なので、Prettier が依存している typescript-estree のバージョンを最新まであげれば対応できるんですが、もうひとつ問題がでてきます。

Prettier は Node@6 をサポートしているのですが、 typescript-estree の最新版は Node@6 のサポートをしていません。なので、Prettier は typescript-estree の最新版を使うために Node@6 をドロップする必要があり、そのためにメジャーバージョンアップをする必要があります。しかし、そのためには他の色々なタスクをやらないといけなくて時間がかかってしまいます。

なので、現在主に2つのアプローチが検討されています。

がんばります

自分以外のメンテナーも色々考えていて、状況もすぐ変わっていくと思うんですが、2019/10/22 現在ではこんな雰囲気ですというくらいで捉えておいてもらえるといいかなと思います。

Prettier が Markdown のフォーマットで日本語とラテン文字の間に半角スペースを挿入してしまう理由

自分は文字コード自然言語には全然詳しくないので、変な表現をしてるかもしれません。変だと思った方はお手数ですが、コメントかツイッター(https://twitter.com/__sosukesuzuki)で教えてくれるとうれしいです..。


よくツイッターでこれについての言及をみかけるのでまとめてみます。

まず、Prettier は Markdown のフォーマットが可能なのですが、日本語ユーザーにとっては少し奇妙なフォーマットをします。

私はJavaScriptを書きます。

この Markdown を、

私は JavaScript を書きます。

という風に、日本語とラテン文字(今回の場合JavaScript)の間に半角スペースを挿入します。

これについて不満を感じているユーザーが多いようです。自分もその一人です。

もともと Prettier の Markdown フォーマット周りを管理していたメンテナーが台湾の方で、おそらく中国語基準で実装したようです。中国語では、漢字とラテン文字の間にスペースを挿入するのが一般的なようで、それに合わせたのでしょう。(https://github.com/ruanyf/document-style-guide/blob/master/docs/text.md)

その後、 https://github.com/prettier/prettier/issues/5028 という Issue がユーザーによって作成されました。簡単に言えば、「ハングル文字を含む Markdown のフォーマットで余計なスペースが挿入される」といった内容です。

そしてこれは対策がされました。(PR: https://github.com/prettier/prettier/pull/5040)

同様に日本語も対策すればいいじゃんと思われるかもしれません。実際、ハングル文字対応の PR の実装はそんなにむずかしくはないのですが、ハングル文字は識別できるのに対して、漢字があったときに、それが日本語として使われているのか、中国語として使われているのかは識別できません。

なので、 https://github.com/prettier/prettier/issues/6385 にて、「空白挿入するかどうか決めるオプション作りたい」みたいな Issue を作成しました。そしたら、「そもそも空白の挿入を機械的に決定するのって困難だから一律で自動スペース挿入を禁止すべきだよね」みたいな話になりました。My favorite hiragana is ぬ には入ってほしいけど、Reactユーザーとかには入ってほしくないよね、みたいな。(個人的には、Prettier は AST を破壊すべきではないにも関わらずこれは AST を破壊するフォーマットなのでよくないよねとも思っています。)

が、「少なくとも中国語では漢字とラテン文字の間にスペースを挿入するのは推奨形式だし、ユーザー体験のためにも、Prettier からその機能を剥がすにしてもプラグインや他のツールで対応はしないといけない。」といわれていて、「それはそう、、、」と思っています。

ので、なにかしら作ったほうがいいんですが、もう半角スペース挿入されるのに慣れてしまって、なんとも思わなくなっている自分がいる。

夏休みの目標はあまり達成できなかった

tako-programing.hatenablog.com

という記事で、夏休みの目標を立てました。夏休みが終わったので振り返ってみたらあんまり達成できてなかったという話です。

目標 1: Prettier へのコントリビューション数合計 20

これはできた。なんなら今24とかだし、コミッターになった。よかった。進捗率100%。

目標 2: 「達人プログラマー」を読む

だめだった。半分くらい読んで、飽きてしまって他の本を読んだりしていた。進捗率50%。

目標 3: Rust をちょこっと書けるようになる

これは圧倒的にだめだった。なんか続かなかった。今度は人を巻き込むとかモチベ維持のためになにかしてみようと思う。進捗率2%。

Prettier のコミット権限をもらった

Prettier のコミット権限をもらった。嬉しい。メンバーではなく、 https://github.com/prettier/prettierリポジトリのコラボレータです。

f:id:tako_programing:20190928230611p:plain

経緯

ブログでも何度か言っていたけど、5月ごろから Prettier によく貢献していました。主にバグ修正やリファクタなんかをやっていました。このPRのコメントで、

I think we can invite @sosukesuzuki as member

と。「オッ」と思っていたらコラボレータに招待されました。

これまでやったこと

https://github.com/prettier/prettier/commits?author=sosukesuzuki

いまのところ、小さな lint 修正とかも含めて 22 コントリビューション。Prettier のコラボレータはだいたい 20 コントリビューション前後から招待されるっぽい。(内容も関係あると思いますが)

これから

いままでやっていた貢献に加えて、 Issue の管理なんかも積極的にやっていけたら良いですね。

AST エクスプローラを作った

Prettier へ貢献する中で使いやすい AST エクスプローラがあったら便利だと思ったので、自分で作ってみました。

https://github.com/sosukesuzuki/AST-Explorer

ほしいもの

  • 左にテキストエディタがあって右にその内容をパースしたASTがある
  • テキストエディタにはコードを書くのでそれなりにリッチ
  • JSON のツリービュー もそれなりにリッチなのがあると嬉しい
  • ブラウザのみで動きサーバー等との通信はしない
  • 複数のパーサーの切り替えができる

できたもの

初期ローディングがすごく遅い上にデスクトップPWAとしての挙動がとても不安定なのでそこは直さないといけませんね、、、

使った技術

  • 特に強い理由はありませんが、使い慣れているため React と TypeScript を使いました。
    • このくらいの規模のものなら、Redux や MobXを導入せずにContextとuseStateだけで状態を管理した方が楽かもなぁと最近は思います。
  • @primer/components に型定義ができたのを最近知ったのでテンションあがって導入しましたが、よく考えたら UI らしい UI もないのではがすかもしれません。
  • エディタ部分はAce Editorを使っていますが、もしかしたら変えるかもしれません。
  • JSON のツリービューにはreact-json-treeというReduxの開発者ツールで使われているビューワーコンポーネントを使っていますが、こちらももしかしたら変えるかもしれません。
  • 当初 webpack の設定を書くのが面倒だったので Parcel を使っていましたが、パーサーごとバンドルするとバンドルサイズがかなりとんでもないことになるのでチャンクするために Webpack でバンドルするように変えました。(あと理由はわからないけど prettier/parser-typescript が Parcel だと動かなかった、なんでだろう)
  • パーサーは @babel/parser@typescript-eslint/typescript-estree ですがそれぞれ Prettier を経由しています。
    • あまり知られていない気がしますが、(よくない方法ですが)prettier.__debug.parse からパーサーをそのまま使うことができます。今回の場合は Prettier への貢献のためなのでこれで良いでしょう。
  • パースは重いので Web Worker 内で行います。初めて Web Worker を本格的に使ってみましたが、 Comlink や Worker Plugin 、worker-loader などのおかげで Worker を意識せずにできるので良かったです。
  • デスクトップ PWA のために WorkBox Plugin を使っていますが、インストールがなぜか激重なので直します。

今後

  • ローディングにかかる時間をなんとかしたい
  • シンタックスエラーをもっとよしなに表示したい