YAPC2016Gyazzスライド
ページ右側の Start presentation
でスライドになる
ReactでGyazzというWikiを自作して運用している話
@shokai
Nota, Inc.
スクリーンショット共有サービス
アニメGIFでも撮影できる
プルリクにも便利
私に質問や感想を言うとあげます
トーク後でも可
15枚ぐらいある
Gyazzという名のWiKi
2人で作っている
トーク概要より
WYSIWYGで画像やリンクも貼れるけど、編集ツールバーやボタンが無いエディタ
markdownより簡単なシンタックスで編集できる
Gitを参考にsubversionみたいなものを実装した
社内で運用してて、3ヶ月で900ページくらい作られている
このスライドもGyazzから生成している
「五行の送り火」を「大文字焼き」って書いたら勝手に修正されてた
ワイキキ空港のターミナル連絡バスのこと
みんなで書けるwebサイト
WiKiのつらみ
メジャーなWikiの方式
独特のシンタックスを手で書く方式
覚えるのつらい
さっき見ていた場所をちょっと直したいだけなのに、編集モードに入ると全体が生テキストになってる・・
WYSIWYGエディタ方式
見たまま編集できる
ツールバー、メニューがたくさん
一度作った綺麗な見た目の段落と、同じスタイルの段落をもう一個作るのが難しい
文章書いてる時間より装飾整えてる時間の方が長い・・ (
個人の見解です)
Gyazzとは?
が10年ぐらい前に作った
ここ数年、いろんな人がGyazzクローンを作っている
編集・閲覧のモード切り替えが無い
カーソルのある行だけがWiKi Syntaxむき出しになる
かんたんなSyntax
がんばって書いたり覚えたりしなくても、適当に見やすく表示する
ページ間リンクを貼っておけば関連検索で発見できる
階層は無い、Web的
アイディアを書いておくと、忘れた頃に関連リンクに現れてピンときたりする
複数人で同時編集できる
ほぼ 角カッコで囲うだけ
外部リンク
[URL]
内部リンク
[ページタイトル]
#ページタイトル
ハッシュタグ風
タイトル付き外部リンク
[URL タイトル]
[タイトル URL]
逆順でもいい
画像埋め込み
[画像のURL]
リンク付き画像
[画像のURL リンク先URL]
[リンク先URL 画像のURL]
逆順でもいい
アイコン記法
[ページタイトル.icon]
アイコンタワー記法
[ページタイトル.icon*数字]
太字
[[あいうえお]]
角カッコ2つ
あいうえお
インラインコード
console.log("hello")
バッククオートで囲う
コードブロック記法
test.jsfunction () {
alert('hello')
}
code:言語名
もしくは code:ファイル名
の下のブロックに色がつく
CLI記法
$ npm install jquery -save
% git init
行頭がコマンドっぽい行に色がつく
(デモ)
(デモ:ページを作ってみる)
hashタグ
関連ページ
外部リンク
画像うめこみ、リンクつける
CLI記法
codeblock記法
アイコン記法
asadf
アイコン記法で投票
カーソル行がsyntaxむき出しになるの重要
「これどう書いてるのかな?」がすぐ見れる
HTMLのソース見て勉強したのを思い出す
実装の話
実装環境
エディタの実装
カーソルの縦棒はdiv
緑の範囲選択もdiv3つ
隠し <textarea />
IMEウィンドウを見せるためだけに存在する
カーソルの右側に浮いていて、ついてくる
が参考になった
y行目のx文字目の画面上の座標はどこか?
生テキスト こんにちは
を
1文字ずつ分割して
editor.html<div class='lines'>
<div class='line' id='L1'>
<span class='c-1'>こ</span>
<span class='c-2'>ん</span>
<span class='c-3'>に</span>
<span class='c-4'>ち</span>
<span class='c-5'>は</span>
</div>
</div>
jQueryで位置を取得する
let {left, top} = $('.lines #L1 .c-4').position()
クリックした位置から何行目の何文字目なのか?を求める
逆をやればいい
あとはカーソル移動やemacsキーバインド等を自前で実装すればok
ReactとjQueryは相性悪い?
よくインターネットに書いてある
jQueryでDOM書き換えしなければok
jQuery クロスブラウザで座標の扱いが完璧っぽい
ReactとjQueryでflux
viewはstore (stateとprops)からのみ作られる
viewが他のviewを書き換えない
他のviewの位置を使って描画するviewはどうするの?
他のview componentの位置で位置補正するcomponent
storeが変更される
render()
componentDidUpdate
が発火
ここでjQueryでDOMを見て座標取得
storeを更新、もしくは自分のstateを更新する
this.setState({x: 36, y: 250}) // 座標をセット
再renderされる
Fluxの円環の理を2回回すイメージ
複数人で同時編集
同時編集
こういう「コミット」をやりとりすればなんとかなるのでは!?
commit.json{
"id": hash,
"parent_id": parent_hash, // 1つ前への参照
"changes": [ 変更内容, 変更内容, 変更内容 ]
}
編集の命令は3つだけ
insert
隣の行のidを指定して新しい行を追加
js{
_insert: positionId, // 文字を挿入する一つ下の位置にある行のId
lines: {
text: text,
id: lineId // 新しく生成された行のid
}
}
新規に行を挿入する
最後に挿入するときは、特殊IDの _end
を指定する。
複数行を挿入するときは、insertを複数個作る
update
idを指定して更新
js{
_update: lineId, // 変更する行のId
lines: { text: text }
}
行を変更する
delete
idを指定して削除
js{
_delete: lineId, // 削除する行のId
lines: -1
}
行を削除する
コンフリクトしたら?
ユーザー側でmerge画面にするわけにはいかない
コンフリクト判定はサーバー側
clientはとりあえずpushする
pushがrejectされたらpull
git rebase
のような操作をする
気合マージ
mergeしよう→コンフリクト→pullしてみる
→insertが参照していた行が削除されてる、どこにinsertしていいのかわからない!
→commitをさかのぼって、「削除された行を参照したinsertをした行」を参照してinsertする
commitの中のinsert/update系をmergeして並べ替える
自分がやった操作のみをundoしたい
同時編集中の他人の操作はundoしたくない
revertコミットを作って貯めておく
pushしてコンフリクトしなかったcommit
insert
同じ行idをdelete
update
元のテキストにupdate
delete
元の位置にinsert
ctrl-Z
で逆順に適用する
おわり・まとめ
WYSIWYGで画像やリンクも貼れるけど、編集ツールバーやボタンが無いエディタ
Socket.IOと自作の同期システムでうまいこと同時編集できる
We are hiring
五山の送り火で有名な大文字山が見える
フルリモート可
YAPC2016Gyazzスライド