Gyazzみたいなエディタ作りでReact.jsを学ぶ:開発ログ
エディタとしての基本機能を実装
行の分割や結合も実装した
ここまでは問題なさそう
新たな疑問
テストを作るとしたらどうするのが良いのか・・?
抽象化層が必要かな?
reduxなら出来そうな気がするが、大がかりすぎる
あるイベントが発火したときにlines,rowが意図した変化をするかテストで保証したい気持ちがある
hookにきりだしてテストかな

これ、React以外で作る方法がイメージつかないのだが、ほかのフレームワークでも同じようなノリで作れるものなのだろうか?
マウスクリックに対応
ここも問題なし
次やること
行を分割するようなEnterが発生したときに次の行に分割後の文字列が入り、カーソルが移動するのは良いのだが、カーソルの左右位置がおかしい
今はRowはReactで制御しているがColumnはエディタコンポーネントに任せているのでそのツケが回ってきている
と思ったけどColumn制御は簡単だった
ColumnをいじったときだけuseEffectが発動するのでなんかいい感じになる
ここまででエディタコンポーネントとして割と違和感なく動くようになったような気がする
行の末尾で→、行頭で←キーを押したときにカーソルを行移動させる処理を追加
見出し書式に対応
普通のエディタっぽい見た目になった
Lineコンポーネントが見出しを判断する設計で良いかは疑問が残るな
Markdown以外に対応する必要があるか?
URLっぽい文字があるとリンクにするようにした
おーWikiっぽい
フォーカスが当たっていない行をHTMLとしてレンダリングするようにした
微妙に上下位置がずれるのが気になる
スタイルをうまいこと指定したら直った
Wikiパーサーみたいなのを書く羽目になっている
Lineコンポーネントの中に書いてしまったが、外に出した方が良い
文字列→JSXする関数を外から与える方式にすると良さそう
あとは記法をどんどん定義していけばインラインの書式は簡単に増やせる
ここは面白くないので後回し
なんとなくMarkdown風にしているが、Markdownの表とかは対応する気はない
1ペイン編集画面でMarkdownの表記法と見た目の表をうまく両立させる良い方法が思いつかない
<Enter>
で連続改行できない の解決
なんとなくフォーカスのある行を黄色くした
箇条書きのスタイル
Markdown準拠の箇条書きに対応したい
Scrapbox風でもよいのだが、ここは好み
編集行の箇条書きのバレットをどう表示するか?
a. 編集文字に含める
カーソルが当たったときに表示文字がずれるのが気になる
現行のinlineはこっち
b. 行のスタイルに含め、編集文字に含めない
箇条書きスタイルそのものを消すのがちょっと直観的でない動きになりそう
Scrapboxはこれに近そう(そもそも実装方式が違うので比較できないが)
bで実装した
リスト記法を認識して書式をつける
箇条書きのバレットを表示するのにflexを使った
改行時にリストの深さを維持する
Tab, Shift+Tabでリストのインデントを上げ下げできる
ブロック記法
今のinlineは以下のような記法
Scrapboxみたいにリスト下にブロック要素を入れられるようにしたい
markdownとの互換性は気にしない
そもそもmarkdownだとリスト下にブロック要素を入れられないからな・・
inlineのときはブロック要素を入れ子にする仕様も考えていたが、、いらないかな
ひとまず通常のブロック記法を実装してみるか
シンプルなブロック記法を実装した
ブロックのインデントを実装した
ブロック記法のバリエーション
役立つブロック記法を実装して効果を確認したい
プレビューのあるブロック
カンマ区切りテキストを表にするやつ
楽そう、これからやろう
mermaidとかが良いかな?
reactでうまくやる方法を探さないと
あった、結構新しい記事で筋が良い
inlineではプレビューは下に出るようにしたが、やはり左右2ペインにしたい
しかしスマートフォンだと下の方が良い
レスポンシブデザインにするか・・
スマートフォンは後回しにしよう
テーブル記法
ブロック記法編集を左右2ペインにした
これもflexを使ったら簡単だった
ここまででおおむね元の実装に追いついたかな
Mac/Chromeで日本語入力確定時に二重に文字が確定されてしまう
手元環境がWindowsで直すのがつらい・・(Macもあるにはある)
この問題だった
keyCode
を使うのをやめたかったのだが・・
fixed
コピーしたときにMarkdownがコピーされるようにする
list itemは簡単そう
行頭の -
は疑似要素で出しているのでコピーできない
font-size:0の要素でコピーしたいMarkdownを用意しておけばOK
できた
block要素はどうすればよいか・・
一旦似たように対応した
細かい修正
行選択
使い勝手が悪いが、切り出しなどを実装する際の布石
reactでselectionchangeイベントがサポートされていないので無理やりくっつける
折り返しがあるとレイアウトが崩れる
泥臭いtipsがたくさんある・・
display:none の要素のscrollHeightは0になってしまうので、直前でdisplay: blockにしている、最後に戻すので見た目には影響なし
文字のない行の高さが0になる問題が出ていた
1行内で選択したときも行選択が発動してうざかった
スマートフォンで行選択が動かない
Safari on iOSはselectstartをサポートしていない
操作性は悪いが修正した
グローバルにイベントハンドラを仕込みっぱなしにするのは微妙だが、仕方ない
Markdownを貼り付けたときにいい感じに整形される
メモ化
useCallbackの依存とか、「これ、人間が書くのか、、」という気持ちになるな
code actionがほしいですね

それより
var
が視界に入って発狂しそうになった

const
つかって
let
,
const
を適切に使うようにしました

フォーカスを与える処理をLineからEditorに移動させる
forwardRef
に手を出してしまった・・
なぜfunctional componentに直に
forEach
が書かれているの……?

ここですかね?

単にlinesの個数だけループさせたかっただけでlinesの中身には触っていないです
ループで作られるDOMに対してrefで参照したかったのです
例示されているコードの設計が根本的におかしいような……

refなしで設計できるのを無理やりrefで組もうとしている印象
こんな方法があったんですね

あとで(学期終了後)読んでみます
なんかやばそうな設計してそう
元の設計に戻したほうが良いかも、、

Lineでfocusの処理をするやつ
クリックした時行頭に戻る仕様をなんとかする
クリックされた場所が何文字目かを知る必要がある
これ、Scrapboxは各文字をspanで囲っていたやつでは・・
document.getSelection()
の focusNode
, focusOffset
をうまいこと見てやれば何とか文字が数えられそう
泥臭いし書式が増えたときに対応が煩雑になりそう・・
spanで囲む以外に方法なさそう……

なんとかしたが、これは・・
必須の機能ではないので、ひとまずコメントにしておこう(上のcommitに混ざってしまっている・・)
編集中の行から行選択を開始できるようにした
ポップアップメニュー
これはエディタコンポーネントに実装してよいのか?
外から別のメニューコンポーネントを重ねる方が筋が良い?
ポップアップの場所をどうやって伝えるのか?
同じスタイルのspanを作って選択範囲までの距離測定に使っている
> 同じスタイルのspanを作って選択範囲までの距離測定に使っている
これで実装してみた、ブロック構文で複数行になった時位置がおかしいけどひとまず気にしない
行選択のメニューは別の仕組みで用意した
スマートフォンでおかしな動きをするが、ひとまず気にしない