Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
What We Talk About When We Talk About Editor
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Masafumi Oyamada
August 18, 2012
Programming
2.6k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
What We Talk About When We Talk About Editor
ブラウザ内のエディタ事情
Masafumi Oyamada
August 18, 2012
More Decks by Masafumi Oyamada
See All by Masafumi Oyamada
大規模言語モデルを作る、拡張する
stillpedant
46
16k
Other Decks in Programming
See All in Programming
Technical Debt: Understanding it Rightly, Engaging it Rightly #LaravelLiveJP
shogogg
0
210
IBM Bobを活用したレガシーアプリの最新化
oniak3ibm
PRO
1
180
net-httpのHTTP/2対応について
naruse
0
470
AI時代の仕事技芸論 — ソフトウェア開発で「遊ぶように働く」職人的熟達のすすめ
kuranuki
1
640
Language Server 使ってる? 〜VSCode と Zed の場合〜 / Are you using a Language Server? ~For VS Code and Zed~
handlename
0
780
スマートグラスで並列バイブコーディング
hyshu
0
110
Modding RubyKaigi for Myself
yui_knk
0
910
軽量Java基盤の設計 DIコンテナに頼らない、長期保守と1秒起動の実現 JJUG CCC 2026 Spring
macha64
0
490
Lessons from Spec-Driven Development
simas
PRO
0
150
CLIであることを活かしたGitHub Copilot CLI活用術 / GitHub Copilot CLI Pro Tips & Tricks
nao_mk2
1
1.2k
Datadog × OpenTelemetry 入門と実践のあいだ
kn_to_maxpno
1
150
正しくソフトウェアを作る、前提を疑うための認知の視点 / doubt-premise
minodriven
19
6.4k
Featured
See All Featured
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
200
Why You Should Never Use an ORM
jnunemaker
PRO
61
9.9k
Abbi's Birthday
coloredviolet
2
8k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
The untapped power of vector embeddings
frankvandijk
2
1.8k
Become a Pro
speakerdeck
PRO
31
6k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
250
Build your cross-platform service in a week with App Engine
jlugia
234
18k
The Cost Of JavaScript in 2023
addyosmani
55
10k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
55k
A Soul's Torment
seathinner
6
2.9k
SEO for Brand Visibility & Recognition
aleyda
0
4.6k
Transcript
ブラウザ内のエディタ事情 1 id: mooz / @stillpedant
id:mooz / @stillpedant ┃アドオン開発 KeySnail: Firefox を Emacs ライクに
Clipple: クリップボード拡張 gpum: Gmail 用のポップアップ・インタフェース ┃Firefox Hacks Rebooted KeySnail について ECMAScript5 について ┃See also http://mooz.github.com/index-ja.html 2
発表の内訳 エディタ 80% 拡張機能 20% 3
発表の流れ 1. <textarea> における高度な編集機能 どのように高度な編集機能が実装されるかを解説 2. 独自エディタ ブラウザ内エディタを分類しその実装を解説
3. source-editor.jsm Firefox 11 より利用可能となった source-editor.jsm に ついて概説 4
5 <textarea> における高度な編集機能
<textarea> ┃最も馴染み深いブラウザ内エディタ: <textarea> ブログの更新 Web メーラー ┃編集機能は貧弱
基本的なカーソルの移動操作 カット,ペースト,アンドゥ ┃高度な編集機能が欲しい 文字列の置換機能 スニペット機能 矩形編集機能 6 どうやって独自の編集機能を実現する?
独自の編集機能に必要なもの ┃基本的な操作 エディタ内のテキストを取得 カーソル位置の取得と設定 選択範囲の取得と設定 テキストの編集
挿入: insert(start, text) 削除: delete(start, end) ┃高度な編集機能 上記の操作を組み合わせて実装可能 7 基本的な操作はどう実現する?
テキストの取得 ┃テキストの取得 var textArea = document.querySelector(“#editor”); var wholeText
= textArea.value; ┃テキストの設定 textArea.value = “abc”; 注意点 テキストを設定するとテキストエリアのスクロール位置が先頭 へとリセットされる 設定前にスクロール位置 (scrollTop) を保存し,設定後にスク ロールし直す必要がある 8 var savedScrollTop = textArea.scrollTop; textArea.value = someText; textArea.scrollTop = savedScrollTop;
カーソル位置の操作 ┃カーソル位置 テキストの先頭からみたカーソルのオフセット 改行文字もカウントされる ┃カーソル位置の取得 ┃カーソル位置の設定 9 function
setCaret(textArea, caret) { textArea.setSelectionRange(caret, caret); } function getCaret(textArea) { return textArea.selectionStart; } abcd 3
選択範囲の取得と設定 ┃選択範囲の取得 textArea.selectionStart textArea.selectionEnd ┃選択範囲の設定 textArea.setSelectionRange(start, end)
HTML5 では setSelectionRange(start, end, “backward”) などとできる 10 forward backward
テキストの編集: 単純な方法 ┃単純な方法 編集後のテキストを文字列操作で生成 生成したテキストを textArea.value に代入 11
function insert(start, insertText) { var originalText = textArea.value; textArea.value = originalText.substring(0, start) + insertText + originalText.substring(start); } function delete(start, end) { var originalText = textArea.value; textArea.value = originalText.substring(0, start) + insertText + originalText.substring(0, end); } 手作業で 編集後の文字列を 計算してあげる 手作業で 編集後の文字列を 計算してあげる
テキストの編集: 賢い方法 ┃賢い方法 textArea の TextNode を直接操作 ┃利点
まどろっこしい文字列操作がいらない JS レベルでの操作が少ないため高速?(未検証) 12 function insert(start, text) { var textNode = textArea.firstChild; textNode.insertData(start, text); } function delete(start, end) { var textNode = textArea.firstChild; textNode.replaceData(start, end - start, „‟); } firstChild
高度な編集機能の実現 ┃基本的な操作がそろった エディタ内のテキストを取得 カーソル位置の取得と設定 選択範囲の取得と設定 テキストの編集
┃基本的な操作を組み合わせて置換機能を実現 textArea.value.indexOf() などで置換対象文字列を検索 置換対象文字を選択してハイライト delete(replacee), insert(replacer) して置換を実行 (textNode.replaceData を使えば一発) 13 基本的な操作さえあれば高度な機能が実現できる
コーヒーブレイク ┃Emacs http://www.gnu.org/software/emacs/ 14 http://cpplover.blogspot.jp/2012/08/vim-vs-emacs.html
コーヒーブレイク ┃Ymacs http://www.ymacs.org/ ブラウザ上に Emacs を再現 15
16 独自エディタ
さまざまなブラウザ内エディタ ┃Ymacs http://www.ymacs.org/ ┃CodeMirror 2 http://codemirror.net/ jsdo.it
も利用 ┃ACE Editor http://ace.ajax.org/ ┃Skywriter (Bespin) [Ace Editor へ移行] https://mozillalabs.com/en-US/skywriter/ ┃Eclipse Orion http://www.eclipse.org/orion/ Firefox の Scratch Pad も利用 17 構文の強調表示など <textarea> では実現できないことを 実現するために頑張っている
独自エディタの分類 ┃1. キーイベント全解釈タイプ Ymacs ┃2. contentEditable タイプ Eclipse
Orion CodeMirror 1 多くの WYSIWYG エディタ Evernote, Gmail, Tumblr, … ┃3. hidden textarea タイプ CodeMirror 2 ACE Editor 18 ブラウザの用意した 入力機構を使うタイプ 独自の入力機構を使うタイプ
1. キーイベント全解釈タイプ ┃方針 イベントリスナを使って全てのキーイベントを監視 イベントを順に解釈することでビューを構築 ┃例 入力イベント列:
a, b, <backspace>, c, <left>, d 生成されるビュー: a d c 19 Ymacs カーソル Ymacs ユーザ イベントリスナ キー入力 入力が不可能なビュー (<div>,<span>, …) イベントを解釈し ビューを構築
キーイベント全解釈タイプの利点・欠点 ┃利点 自由度高 ┃欠点 マルチバイト文字の入力が実現し難い IME がからむとキーイベントがまともに飛ばない
Ymacs もマルチバイト文字の入力は未サポート コンテキストメニューからの編集ができない ビューが入力可能要素ではない キーイベントが飛ばない 20 Ymacs ユーザ イベントリスナ キー入力 入力が不可能なビュー (<div>,<span>, …) イベントを解釈し ビューを構築
2. contentEditable タイプ ┃方針 ビュー要素に contentEditable 属性を設定し入力可能に ビューの構築は基本的にブラウザ任せ
一部のキー入力のみを独自に解釈 ショートカットキーの実現 21 Eclipse Orion CodeMirror 1 ユーザ キー入力 contentEditable で入力可能なビュー (<div>,<span>, …)
contentEditable タイプの利点・欠点 ┃利点 入力関係の問題が生じにくい(マルチバイト文字) コンテキストメニューからの編集も問題ない ┃欠点 ブラウザにより
contentEditable 系の挙動が異なる 差異を吸収するために多くのコードを書く必要がある CodeMirror はこれにこりて 2 で contentEditable から脱却 エディタ要素を iframe 内に仕込む必要がある 初期化が同期的ではなく,これによる問題が多々発生 22 Eclipse Orion CodeMirror 1 ユーザ キー入力 contentEditable で入力可能なビュー (<div>,<span>, …)
3. hidden textarea タイプ ┃方針 hidden な textarea を用意してユーザの入力を受け付け
textarea にフォーカスしておく textarea の内容からビューを構築 23 CodeMirror2 ACE Editor Ymacs ユーザ hidden な textarea キー入力 入力が不可能なビュー (<div>,<span>, …) textarea の中身を見て ビューを構築
hidden textarea タイプの利点・欠点 ┃利点 ブラウザ間の挙動の違いに悩まされなくて良い ┃欠点 実装が大変
http://codemirror.net/doc/internals.html コンテキストメニューからの操作がほぼ効かない 「全選択」など 24 Ymacs ユーザ hidden な textarea キー入力 入力が不可能なビュー (<div>,<span>, …) textarea の中身を見て ビューを構築 CodeMirror2 ACE Editor
さまざまなエディタ実装 ┃高度な編集機能の実現 エディタ実装毎にコードを書く必要がある 大変 きりがない ┃どうにかならないか
統一的なインタフェースがあると良い 25
26 source-editor.jsm
source-editor.jsm ┃resource:///modules/source-editor.jsm Firefox 11 より(公式に)利用可能に アドオン内でソースコードエディタを実現 ┃様々なバックエンド
SourceEditor は単なるエディタインタフェース ビューを含む実際の挙動はバックエンド次第 デフォルトのバックエンド: Eclipse Orion contentEditable タイプ 27 SourceEditor Orion アドオン YYY ZZZ
source-editor.jsm の使い方 ┃エディタの挿入場所の用意 (placeholder) ┃SourceEditor の初期化 28 <vbox id="editor" flex="1"/>
var placeholder = document.getElementById("editor"); var config = { mode: SourceEditor.MODES.JAVASCRIPT, showLineNumbers: true }; var editor = new SourceEditor(); editor.init(placeholder, config, function onInitialize() { // 初期化後の処理 });
何が嬉しいか ┃SourceEditor に対する高度な編集機能 SourceEditor の用意する基本操作を組み合わせて実現 いちど実装してしまえば様々なバックエンドで動作 エディタに対する統一的なインタフェース
┃SourceEditor の利用により もう↓のようなことにならなくて済む 29 ┃高度な編集機能の実現 エディタ実装毎にコードを書く必要がある 大変 きりがない
30 まとめ
まとめ 31 ┃<textarea> における高度な編集機能 基本的な操作さえあれば実装できる ┃ 独自エディタ 三種類の実装方式がある
高度な編集機能は実装毎に書く必要があり大変 ┃source-editor.jsm Firefox 11 より利用可能 ソースコードエディタに対する統一的なインタフェース