0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ブックマークレットの document.​write が効かない事例と回避策

0
Posted at

ブックマークレット

私は、以下のブックマークレットを使用している。
これは、開いているページのタイトルとURLをコピーする用に入れたテキストボックスを新しいタブで表示し、コピーしてSNSなどで共有しやすくするためのものである。

ブックマークレット (見やすくするため改行とインデントを追加した)
javascript:window.open().document.write(
  '<input%20type=\x22text\x22%20onclick=\x22select();\x22%20value=\x22'+
  document.title.replace(/\x26/g,'\x26amp;').replace(/\x22/g,'\x26#34;')+'%20'+
  location.href.replace(/\x26/g,'\x26amp;').replace(/\x22/g,'\x26#34;')+'\x22>'
)

いつから使っているかはわからないが、だいぶ前な気がする。

効かない事例

さて、ある日、このブックマークレットをYouTubeで用いたところ、新しいタブは開いたが、テキストボックスが表示されなかった。
開発者ツールのコンソールを見ると、以下のエラーが出ていた。

Uncaught TypeError: Document.write: Sink type mismatch violation blocked by CSP

AIで殴る

よくわからないので、とりあえず Perplexity にエラーメッセージをコピペして、直し方を聞いてみた。

Perplexity に入力した質問文
> Uncaught TypeError: Document.write: Sink type mismatch violation blocked by CSP

直し方おしえろください

> Uncaught TypeError: Document.write: Sink type mismatch violation blocked by...

その結果、document.write のかわりにDOM操作を用いることで、回避できる可能性が示された。

DOM操作に置き換える

冒頭のブックマークレットをいつ作ったかは定かではないが、おそらく古い技術で作られたものだろう。
今の知識に基づいて書き直してみた。

新ブックマークレット (インデント・改行あり版)
javascript:window.open().document.body.appendChild(
  (() => {
    const i = document.createElement('input');
    i.type = 'text';
    i.value = document.title + ' ' + location.href;
    i.addEventListener('click',(e) => e.target.select());
    return i;
  })()
)
新ブックマークレット (不要な空白・改行を除去した版)
javascript:window.open().document.body.appendChild((()=>{const i=document.createElement('input');i.type='text';i.value=document.title+' '+location.href;i.addEventListener('click',(e)=>e.target.select());return i;})())

結果は成功。
以前のブックマークレットでテキストボックスが出なかったYouTubeでも、テキストボックスを出すことができた。
さらに、以前のブックマークレットではテキストボックスは出せてもフォーカス時に自動で中身を選択する機能が動かないサイトもあったが、そのようなサイトでも新しいブックマークレットで出したテキストボックスでは自動選択が動作するようだった。

さらに、以前のブックマークレットでは &" を手動でエスケープしていたが、新ブックマークレットではエスケープせずにそのまま属性に代入するだけになり、コードがスッキリした。

おわりに

ブックマークレットで用いている document.write が動かないサイトがあることを発見し、AI に対処方法を聞いたところ「かわりに通常のDOM操作を用いるとよい」という回答を得たので、その通りにすることで動作が改善した事例を紹介した。

今回の記事はあくまで「今回のケースにおいては、こうすると問題が解決した」という事例の紹介であり、常にこれが良い対処法であることは保証しない。
また、将来のWebブラウザなどの仕様変更により、今回の対策が使えなくなってしまう可能性もないとはいえない。
今回の情報を利用するかどうかの判断、および利用は自己責任で行うこと。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?