Closed7

HTML 要素を非表示にするブラウザ拡張

sankantsusankantsu

筆者は Web ページ上の広告 (特に動くタイプの広告, または美容・健康系) が非常に苦手だ。
特に美容・健康系 (人体の一部の画像/描写を含む) ものが生理的に受け付けず、とにかく目に入れたくない。

いったん目に入ると、読みたいページの内容が頭に入ってこないばかりでなく、しばらく記憶に残ってしまい、思考を阻害される気がする。
できるだけ広告ブロックを使用するようにはしているが、それでも防ぎきれないもの、あるいは広告ブロックだとページの表示に支障が出る/表示できないパターンがあり、 100% 広告から身を守ることが難しい。

sankantsusankantsu

そこでその場しのぎの対策としてよくやっていたのが、要素を (できるだけ注視しないようにしながら) 右クリックし、 "Inspect" で developer tool を起動し、コンソール上から $0.remove() を実行して要素を一時的に消すというものである。
正直言って Web ページを開くたびにこんなことをやっていたら時間がかかってしょうがないし、作業が進まないのだが、それでもやらないとページの内容をまともに読めないので、やらざるを得ないのである。
とはいえこんなことをいちいちやっているのは面倒臭くてしょうがないので、ブラウザ拡張機能として実装できるんじゃないかと思った。

sankantsusankantsu

要求する機能自体は比較的単純なので、自分でも頑張ればつくれそうな気もしたのだが、ブラウザ拡張機能はつくったことがないし、基本的にフロントエンドの知識が無さすぎるので少々面倒である。
もしすでによくできたものがあれば使いたいと思った。
調べて出てきたのが、以下の 2 つ

https://chromewebstore.google.com/detail/click-to-remove-element/jcgpghgjhhahcefnfpbncdmhhddedhnk

https://chromewebstore.google.com/detail/remove-html-elements/enegojdnkeicfoiknhfjaedhlckeahmf?hl=en

おそらく同じような機能を提供しているのではないかと思うのだが、ユーザー数の多さなどから "Click to Remove Element" のほうを使ってみることにした

sankantsusankantsu

使い方は簡単

拡張機能のパネルから選択または ⌘+Shift+X でアクティベートすると、左下に拡張機能 window が出てきて、選択要素がハイライトされる。

今回は Zenn のページで記事を書いた人のアイコンを選択してみる。

この状態で左クリックすると要素が見えなくなる。

いくつかのページで試したが、広告等も $0.remove() を手でやるよりははるかに素早く隠せるのでなかなか良い。

sankantsusankantsu

自分でつくってみたい気持ちも多少あるし、何やってるかわからないとなんとなく不安なので一応ソースもちょっと見ておく。

Click to Remove Element の拡張機能のページからは blade.sk という著者の個人サイトらしきページへの link がある。
Portfolio のひとつとしてこの拡張機能が紹介されているが、ソース等は載せていない様子である。

拡張機能のソースを取得する方法を調べたところ、 CRX downloader という拡張機能を使うと拡張機能のファイル一式を zip 形式でダウンロードしてこれることがわかった。

https://chromewebstore.google.com/detail/crx-extractordownloader/ajkhmmldknmfjnmeedkbkkojgobmljda?hl=ja

拡張機能のストアのページから CRX downloader をアクティベートすると、 "Download as Zip" というボタンが出てきて、押すと拡張機能のファイル一式をまとめた zip がダウンロードできた。

sankantsusankantsu

Click to Remove Element の中身はこんな感じ

$ unzip -l Click-to-Remove-Element-Chrome-Web-Store.zip
Archive:  Click-to-Remove-Element-Chrome-Web-Store.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
     9307  11-23-2023 10:27   background.js
     6893  11-23-2023 10:28   content.css
    29904  11-23-2023 10:27   ctre_content.js
        0  03-14-2019 02:42   icons/
     1496  11-28-2018 16:26   icons/action_active.png
     1506  11-28-2018 16:26   icons/action_inactive.png
     1454  11-28-2018 16:26   icons/action_unavailable.png
     4535  10-10-2012 14:58   icons/icon_128.png
     2201  10-10-2012 14:37   icons/icon_48.png
      987  11-23-2023 10:26   manifest.json
        0  11-23-2023 10:26   _metadata/
     2082  11-23-2023 10:26   _metadata/verified_contents.json
---------                     -------
    60365                     12 files

どうやら ctre_content.js というのが実装本体らしい。
中身を見ると minify されていたりする様子はなく読めそう、良かった。

ライセンス自体は不明なため注意

sankantsusankantsu

簡単に実装を確認すると、以下のような流れで処理しているのがわかった。

  • 拡張機能のアクティベート時に各種 eventhandler を追加
		ctre.targetingMode = true
		document.addEventListener('mouseover', ctre.handleMouseover, true)
		document.addEventListener('mousedown', ctre.hideTarget, true)
		document.addEventListener('mouseup', ctre.preventEvent, true)
		document.addEventListener('click', ctre.preventEvent, true)
		document.addEventListener('scroll', ctre.updateHighlighterPos, true)
  • mouseover された要素をハイライトする
	handleMouseover: function(e) {
                ...
		
		if (ctre.hoveredElement != e.target) {
			ctre.transpose = 0;
			ctre.hoveredElement = e.target
			ctre.highlightElement()
		}
	},
  • mousedown でハイライト中の要素を hiddenElements という配列に追加, CSS を更新
	hideTarget: function(mouseEvt/* optional */) {
                ...
		let selector = ctre.getSelector(ctre.markedElement)
		if (!selector) return
                ...
		ctre.unhighlightElement()

		ctre.hiddenElements.push({
			selector,
			permanent: !!ctre.settings.remember,
		})
                ...
		ctre.updateCSS()
                ...
	},
  • updateCSS()hiddenElementsdisplay: none 属性を指定する
		for (let i in ctre.hiddenElements) {
			let selector = ctre.hiddenElements[i].selector
			if (selector == ctre.previewedHiddenSelector) {
				cssLines.push(selector + ' { outline: solid 5px rgba(0,214,255,0.5) !important; outline-offset: -5px; }')
			} else if (selector == 'body' || selector == 'html') {
				cssLines.push(selector + ' { background: transparent !important; }')
			} else {
				cssLines.push(selector + ' { display: none !important; }')
			}
		}
                ...
		styleElm.appendChild(document.createTextNode(cssLines.join('\n')))
このスクラップは2ヶ月前にクローズされました