LT:UserScriptを支える技術
LT枠はとらなかったが、飛び入りLTがあるので、発表するチャンスに備えて作っておく アドバイスがほしいので井戸端に置きましたtakker.icon
まだ体裁を整えられていない
重複もあるし日本語がおかしい部分もある
書き込んではいけない場所も書き換えてほしくない場所もないので、自由にコメントしていただけたらと思います
takker.iconのUserScript歴を書いていこうと思ったが、一つ一つの分量がおおくなってしまった
説明へたくそで伝わりにくそうなのもある
今まで作ってきたUserScriptや、UserScriptを作る上での技術を淡々と挙げていくほうがいいかな?
takker.iconからどんな話を一番聞きたいか教えてほしいですtakker.icon
自分が話したいことにすると、話題が広がりすぎて収集がつかない
今までに作ったUserScript
UserScriptの作り方
UserScript以外の話題
やりたいこと
画像を載せる
画像がないとわかりにくい
各UserScriptのページから引っ張ってくるつもり
日本語として読みやすい文章にする
分量を減らす
5分に収まらない部分や枝葉の部分は別ページに切り出す
文脈が繋がってるなら、無理に切り出す必要も無さそう?blu3mo.icon
+1nishio.icon
「分量を減らす」というより「5分でどの程度話せるのか把握して時間配分を考える」のが重要だと思った
現状全然考えてなさそうに見えるので。
なにも考えていない()takker.icon
感想
UserScriptで色々な事を実現しようとしている執念(?)と、それを可能にしている技術力/ハック技がとても面白いblu3mo.icon 他のツールを使わずに、わざわざScrapboxで実現することにこだわっているのは執念かもtakker.icon
単純に他のツールを使うハードルが高いということでもある
はるひ.iconさんのように気軽にいろんなツールに触ると楽になる?(何が)
執念でワロタMijinko_SD.icon
UserScriptの紹介だけでも新鮮かも?takker.icon
知らない人が自分の作ったものをみてどういう感想を抱くのか想像できない
初手にScrapBubbleなどのGIFを載せるだけでも面白そうblu3mo.icon
「普段こんなの作っています」でGIF載せるのはいいですねtakker.icon
下に入れておこう
いっそ発表動画を作ってしまえば時系列に依存しないLTになるinajob.icon
まぁ資料公開だけでも十分説もある
すでに参加しない人がLT資料書いてたりしますしtakker.icon
動画作るのはハードルが高く感じますtakker.icon
Aviutlのセットアップ
ゆっくり音声の作成
レイアウトの設定
...動画=ゆっくり解説動画という変換がかかってしまったtakker.icon
動画を公開するかどうかはさておき実際に発表してみて録画して見返してみてはどう?nishio.icon
これを何分で話すつもりなのか謎だなと思った
発表時間は5分なのか…20分くらいかかるのではと思ったw
5分で話せる範囲ってどれくらいだろ……谷川岳から帰ってきたら発表練習してみるか……
5分はマジで短いです。1トピックかな…基素.icon
マジで短い+1nishio.icon
確かに1トピックではなくてもいいか。研究100連発みたいな感じのスタイルもあり基素.icon 自分の視点では作ったもの紹介が一番気を引けるのではないかなと思った
めもinajob.icon
web socket → WebSocket
指摘サンクスですtakker.icon
/icons/hr.icon
自己紹介
takker.icontakker
2020-07くらいからscrapboxを使い始めた
「時々井戸端にいる」時々とは!?はるひ.iconblu3mo.icon
UserScriptをたくさん作っているらしい
普段はこういうのを作っています
https://gyazo.com/327de8a97249bf078873ccedfda9b96b
/motoso/基素.iconさんが撮影してたGIFのほうがインパクトあるかも?
どれか覚えてないですがこれでもScrapboxユーザーには十分伝わるような気がします基素.icon
一瞬何が起きているのかわからないのでリンクを表示しているよと口頭補足があると良さそう
(ページ本体も含んでいるGIFを撮影したい)
https://gyazo.com/47fb719c83929fdf20e917c9e0b2505a
LT枠はもう埋まってしまいましたが、飛び入りLT枠があるとのことなので、あわよくば発表してみたいという思いから資料を作ってみました
最近作ったもの
scrapboxのUserScriptについて
よく使う方法
開発環境
今まで作ってきたもの
など
原点
/yutaro/yutaro.iconさんが作成した、絵文字の入力補完script
自分で読んで理解したい!
Firefoxでは動かなかったので、Firefoxでも動くように改造する必要があったという事情もある
UserScriptで使う技術
基本的に、JavaScriptで実装できるものならなんでもできる
Reactを読み込んで、scrapbox上で自前のエディタを動かすことも技術的には可能
ここでは、身近な手法から紹介していく
PageMenuとPopupMenu
PageMenu
動的にtitleを変える機能がなくなってしまった
復活してほしい
PopupMenu
動的にボタンを切り替える
最近、mobile版でもPopupMenuが出るようになった
便利takker.icon*2
意外と知らない関数が生えていたりする
PageMenuのaddItemのonClickでMouseEventを取得できるのが好きtakker.icon
まあバグだと思うけど……
dom操作
このあたりから、複雑な機能も作れるようになってくる
よく使うDOMへのショートカット
文字の位置検知
.c-から取得できる
リンクや数式の取得
.cursor-lineの状態でDOM構造が変わるため、すべてのケースに対応できるよう組むさいは工夫が必要
文字入力
rest api
wrapperを作った
wrapperを作った理由
URLの組立やレスポンスの処理が特殊なAPIがあるため
そのまま使うのは面倒
TypeScriptで型付けしたかった
もちろん、あくまで内部APIなので、いつ仕様が変わってもおかしくない
preact
複雑なDOM操作が増えてきたら、これを使う
reactはファイルサイズが無駄に大きいので、preactを使っている
TODO:ここ要確認
scrapbox本体もReactではなくPreactにすればいいのになーと日頃から思っているtakker.icon
まあpackageの依存関係上無理なんだろうけど
CSSをカプセル化するのとidのダブりを防ぐのが一応目的
意味のあることかは不明
逆にUserCSSでスタイルを変えられないなどのデメリットがある
まあただの好みである
websocket
ここから上級者向け
任意のprojectの任意のページのCRUDが可能になる
scrapbox.ioのwebsocketの通信内容を調べて、模倣した
途中でsocket.ioを使っていることに気づいてからは、CDNで導入したsocket.ioを使うようにした
黒魔術
Reactで管理しているDOMには、__ReactFiberなどReactが生やした内部データがある
とれるもの
カーソル操作
これを自前で取得するのは地獄
カーソル位置や選択範囲の変更時に発火するlistenerを登録できる
これが一番便利
選択範囲内の文字列は、PCからなら#text-inputから取得できるが、mobileだと取得できない
自分で実装しようとすると非常に大変
当たり判定の計算
太字記法などで文字の大きさが変わると、位置計算が
カーソル移動の検知方法
カーソルにfocusがあるかどうかでDOMの状態が変わるので、一筋縄では行かない
かなり不安定なハック
いつscrapbox側で仕様が変わるかわからない
おそらくReact Hooksで書き換えられたら死ぬ
いつ消えるかわからないhackに依存するのはよくないのだが……メインのUserScriptで深く依存してしまっている
仕様変わって使えなくなったら発狂する自信がある
以上の手法を一つのrepoにしてgit管理している
Denoから使える
node向けpackageは作っていない。
作る予定も特にない
外部ライブラリを使う
CSPで使えるものが限られている
script-src
classic scriptで読み込めるもの
cdnjsやlocation記法に使うgoogleのコードなども読める ESModuleで読み込めるもの
scrapbox.ioのみ
ここでcdnjsも使えるようになれば、globalに変数を露出させずに済むのだが……
worker-src
scrapbox.ioのみ
connect-src
scrapbox.io, storage.google.com, cdnjs, upload.gyazo.comなど
使う方法
CSPで許可されているものを<script>から読み込む
コードブロック記法に全部張り付ける
Preactなど小さめのライブラリは直接張り付けられる
katexやsocket.ioなど数百KBあるライブラリは、CDN経由で読み込むのが無難
bundleする
esbuildはnode.js型のmodule解決しかできないので、そのままでは使えない
$ deno bundle <URL> | esbuild --minify
その後、いろいろ設定してbundleしたくなったので、esbuildにpluginを入れたDeno scriptを作った
いろいろ設定
一部のURL(画像URLやprivate project内のソースコード)をbundleからはずす
sourcemapをつける
どんなに長いコードでもscrapboxに一発で取り込めて便利
web browser上で動くbundler
リンクを踏むだけで実行できるのが最大の特徴
スマホでも動く!
Deno scriptはスマホだと動かせない
これが不満だったtakker.icon
スマホからUserScriptを更新できるようになった
UIが雑だったりバグが残っていたりするが、普段使っている範囲で問題は起きていないので、放置している
これも不便に慣れてしまうということなのだろうなあ
コードブロックへの張り付け
小さいコードはそのまま張り付ければいい
大規模なUserScriptを作っていると、minifyしても一発で張り付けられないようになる
回避策
分割して張り付ける
より巨大になると張り付けが大変
何回も張り付けなければならない
scrapboxが重くなる
最悪途中でクラッシュする
ブラウザでのrenderingを介さず、直接scrapbox.ioのDBに格納する
構文解析やrenderのコストを省けるので、1MBのコードでもいけるはず
うっかりコードを張り付けたページを開いてしまうと(お察し下さい)
閲覧者のブラウザを壊さないよう、使う際はprivate projectやbundle専用projectを作ってそちらに置くのがおすすめ
Usercssで存在を隠すという選択肢もある
コードの張り付けテクニック
何度も張り直す場合は、undoして前回のコードを消すと楽
うっかりページ遷移してundoできなくなってしまったら、がんばって手作業で消すしかない
外部APIを使う
上述したようにCSPが厳しい
何の方法もなく使えるのはGyazoのupload APIしかない
初出はしーなるすさん
これを知ったことで、UserScriptでできることがかなり広がった
作ったもの
これら2つは、後に公式で同様のものが実装された
ただし、外部リンク記法のほうは公式実装にバグがあるので、tampermonkey実装を使った方がいい scrapboxに埋め込む
iframe-srcが厳しいため、埋め込めるものはほとんどない
そもそもscriptで埋め込んでも、UserScriptを入れている人にしか効果がない
回避策:画像で埋め込む
アスキーアートを画像にするserverless function
画像にすればだいたいなんでもできる
出来ないこと
SVG内で外部リソースを読み込む
CSSやfontファイル、画像ファイルなどは読み込めない
たとえ同ドメインであっても不可
あらかじめdata URLなどで埋め込むしかない
スクロールなどの動的操作
リアルタイム更新
最速でもタブの再読込のとき
実装
vercelとdenoで作っている
deno deployも使ってみる?
突然サービスを終了しないかが心配
それなりに長く使えるところでdeployしたい
まあそんなこといったらvercelだっていつまで無料で使えるかわからないが……
不可能なこと
だとtakker.iconが考えていること
UserScriptの開発方法
最初期
直接コードブロックに書き込んでいた
自分のページのscript.jsからimportする
書き込みとリロードをひたすら繰り返して試す
Hot reload?そんなものはない
開発しているUserScript以外も毎回script.jsで読み込んでいた
最初の頃はこれでもよかったが、次第にUserScriptが肥大化し、読み込みに時間がかかるようになった
開発しているUserScriptを試したいだけなのに、毎回他のUserScriptの読み込みに数十秒とられることになった
不便に慣れてしまうタイプなのか、この状態で1年以上UserScriptを作り続けていた
さすがに我慢できなくなって、開発モードを導入した
bundle
ESModuleで大量のUserScriptを読み込んでいた
結果、UserScriptを全部読み込み終わるまでに、毎回30秒以上かかるようになってしまった
ページの切り出し等で新しいタブが開かれる度に、UserScriptの読み込みが走る
大量のリクエストが一気に飛び、ブラウザが重くなる
bundleして高速化を試みた
数秒で読み込み終わるようになった。快適
文法チェック、型チェック
Scrapboxのコードブロックは文法チェックも型チェックもしてくれない
最初の頃は大変だった
単純なスペルミスも括弧抜けも検知できない
importして初めてエラーがでる
エラーの原因を探すことからはじまる
スペルミスを直すためだけに何度もreloadする羽目になる
文法エラーを全部直して、ようやく実行時エラーの修正に移る
ここでも何度も再読込してバグを特定する
怪しい場所にconsole.logを挿入して見つける
開発コンソールのbreak pointで値を見たり、処理の流れを確認したりもする
この辺りは便利
型チェックがあれば、実行せずともつぶせたバグにも遭遇する
typescriptに移行した
当然そのままでは読み込めないので、使用前にbundleしなくてはならない
bundleしたUserScriptを使っていたので、あまり問題にはならなかった
ツール
文法チェック:deno
esbuildでもできる
型チェック:deno
なぜDeno
URLでコードを検査・実行できる
web browserと同じmodule解決方法を用いているので、Scrapboxと親和性が高い
ScrapboxはコードブロックごとにURLが発行される
bundle
読み込みに30秒かかるようになった
早く読み込みたかった
deno
単体テスト
domテストできない
書く場所
git管理してlocalで書く
つくったもの
よく使うものをまとめた
紹介するのが面倒?
UserScriptを作っている人・ヒントにした人とか紹介
(TODO:アイコンにする)
shokai.icon
開発コンソールを開かずにUserScriptの状態を知らせられる点で便利
特にスマホなどで
/yutaro/yutaro.icon
/progfay-pub/progfay.icon
いつもお世話になっていて頭が上がらないtakker.icon*3
改良したいところだが放置中
増井俊之.icon
放置中だけど……takker.icon
nishio.icon
最近ぜんぜん作ってないけど……
/foldrr/foldrr.icon
最近メンテしてない……
/scrasobox/madobe.icon
scrapboxで遊ぼうの作者
主にUserCSSを使わせていただいている
UserScript面では、bookmarkletの作成方法とweb pageのscraping方法を参考にした
yuta0801.icon
マウスクリックのjackで助言を受けた
daiiz.icon
すごすぎるtakker.icon*3
最初はこれをTypeScriptで書き換えようとしたが断念
文字入力の実装はここからとってきた
後に少し簡略化した
widthとheightをつけるvercelのserverless functionのコードをまねした
nodeで書かれた部分をDenoで書き直すのに苦労した気がする
ここで紹介したコードを使っていただいている人がいて嬉しい
そのような場を作ってくれたことに感謝takker.icon*2
ci7lus
TamperMonkeyを使う方法があることをここから知った
mizdra
学んだ点がたくさんある
これを知ってから、大規模なUserScriptはpreactで書いている
UserScriptをgit管理する
TypeScriptで書く
単体テストを書く
当時はDenoでまともにDOMテストできなかったので、役立てなかった
最近のDenoなら、npm対応したのでいけるかもしれない
そのうち試そうと思う
自分のUserScript開発歴のターニングポイントだったかも
popup menuのJSXはいろんなUserScriptで使い回させていただいている
pretterをScrapboxで動かすUserScriptも参考にした
pokutuna
同じくpreactを使ったUserScriptの実装例として参考にした htmを使うとtranspileなしでpreactを実行できることを知った typescriptに移行する前までは、htmでpreactを使ったUserScriptを書いていた
kuuote.icon
黒魔術探索で助力していただいた
yosider
一時期ここでUserScriptを書いていた
villagepumpのusers
「これができたらいい」という願望を勝手に拾って実装していった
その他、様々な人たちの発想や実装のおかげで、UserScirptを開発できています
まとめ
UserScriptは(ほぼ)なんでもできる
不満点があったらUserScriptで解決できる
(やろうと思えば)scrapbox上でwebアプリを作成できる
欠点もあるので注意
不具合が増える
scrapboxの更新に対応しつづけなければならない
仕様変更で突然動かなくなることもある
UserScriptを増やしまくると大変な目にあう
scrapboxのバグをバグだと気づかずにUserCSS/UserScriptで直してしまう
これは実害ない
UserScriptを書く人がもっと増えてくれたら嬉しいです
基本自分は他人のUserScriptのアイデアをパクって改造したものしか作ってない……takker.icon
アイデア面で貧弱なので、もっと書く人が増えていろんな発想でUserScriptを作ってくれる人が増えてくれると嬉しい