Mastodon 連合 or ローカルタイムライン用正規表現フィルタ Fork

    @@ -44,7 +44,7 @@ -名前も検索される文字列に含まれます。 */ - ((d = document, l = { childList: 1 }, p = $('.columns-area'), t, r, o, c, b, m, a) => { + ((d = document, l = { childList: 1 }, p = $('.columns-area'), r, x, a, f, o, c, b, t, m) => { r = new RegExp( decodeURIComponent((d.cookie.split('let_filter_regexp=')[1] || '').split(';')[0])
    @@ -52,7 +52,7 @@ ); // この辺なるたけ速い方がいいかなって思って jQuery 使ってない - o = new MutationObserver(s => s.forEach(e => { + x = e => { [...e.target.querySelectorAll('.status:not(.viewed)')].forEach(n => {
    @@ -83,13 +83,14 @@ }); - })); + }; a = s => { if (s == '🔈') { b.text('🔇'); + x({ target: t[0] }); o.observe(t[0], l); } else {
    @@ -102,6 +103,22 @@ }; + f = n => { + + n = $('.column:last>.scrollable>div:last'); + + if (!t || t[0] != n[0]) { + + t = n; + a('🔇'); + a('🔈'); + + } + + }; + + o = new MutationObserver(s => s.forEach(x)); + c = $('#mute-buttons'); if (!c[0]) c = $('<div />') .css({ position: 'fixed', height: '1em', bottom: '2em', right: 0, zIndex: 99 })
    @@ -135,32 +152,16 @@ }) .focus(function() { - this.style.paddingLeft = '0'; - this.style.width = '12em'; + $(this).css({ paddingLeft: 0, width: '12em' }); }).blur(function() { - this.style.paddingLeft = '2em'; - this.style.width = '0'; + $(this).css({ paddingLeft: '2em', width: 0 }); }) ); - f = n => { - - n = $('.column:last>.scrollable>div:last'); - - if (!t || t[0] != n[0]) { - - t = n; - a('🔇'); - a('🔈'); - - } - - }; - - new MutationObserver(s => f).observe(p[0], l); f(); + new MutationObserver(s => s.forEach(f)).observe(p[0], l); })();
  • /*
     * @title Mastodon 連合 or ローカルタイムライン用正規表現フィルタ
     * @description 名前にも適用されます。画像とか動画とか不適切系も判別できます。
     * @include *
     * @license MIT License
     * @javascript_url
     */
    
    /*
    ブックマークレットを実行すると入力欄とボタンが出ます。
    入力欄に正規表現を入れてエンターを押してください。ボタンはフィルタのオンオフです。
    諸事情あって、ブックマークレットは自動更新されません。
    新しいバージョンに変更したい場合は、一旦古いブックマークレットを削除して、新しく追加し直してください。
    
    入力例:
    
    たけのこに関するトゥートを NG
    たけのこ|タケノコ|竹の子|筍
    たけのこに関するトゥートのみ表示
    ^(?![\s\S]*(たけのこ|タケノコ|竹の子|筍))
    不適切なコンテンツを NG
    sensitive
    不適切なコンテンツのみ表示
    ^(?![\s\S]*sensitive)
    画像、動画のみ表示
    ^(?![\s\S]*media)
    画像、動画のみ表示 (誤爆なし)
    ^(?![\s\S]*	media)
    PNG のみ表示 (イラスト多めになる)
    ^(?![\s\S]*media\.png)
    動画 (GIFアニメ含む) のみ表示
    ^(?![\s\S]*media\.mp4)
    
    更新履歴:
    
    4/24
    -正規表現入力欄が入力後に隠れるようになりました。クリックするとまた出てきます。
    -フィルタが効かなくなる現象の出現頻度が低くなりました。
    -画像や動画がある場合、検索される文字列に「\tmedia」という文字列が追加されます。拡張子が判別できたら「\tmedia.png」のような文字列になります。
    -不適切なコンテンツがある場合、検索される文字列に「\tsensitive」という文字列が追加されます。「\t」はタブ文字です。
    
    4/22
    -https://mstdn.jp/users/soraki_yoshiko2/updates/1277707 こういう経緯で作りました。
    -名前も検索される文字列に含まれます。
    */
    
    ((d = document, l = { childList: 1 }, p = $('.columns-area'), r, x, a, f, o, c, b, t, m) => {
    
    	r = new RegExp(
    	 decodeURIComponent((d.cookie.split('let_filter_regexp=')[1] || '').split(';')[0])
    	 || 'きのこ|たけのこ|すぎのこ', 'i'
    	);
    
    	// この辺なるたけ速い方がいいかなって思って jQuery 使ってない
    	x = e => {
    
    		[...e.target.querySelectorAll('.status:not(.viewed)')].forEach(n => {
    
    			[...n.querySelectorAll('img[alt]')].forEach(i => {
    				
    				i.parentNode.insertBefore(Object.assign(
    				 d.createElement('span'), {
    				  style: 'display: none;',
    				  textContent: i.alt
    				 }
    				), i);
    				
    			});
    
    			m = n.querySelector('.media-spoiler') ? '\tsensitive\tmedia' : '';
    			[...n.querySelectorAll('a[href*=media_attachments], video')].forEach(a => {
    				
    				m += '\tmedia' + ((a.href || a.src).match(/(\.\w+)(?:\?|$)/) || [''])[0];
    				
    			});
    
    			if (r.test(
    			 n.querySelector('.display-name').textContent
    			 + '\t' + n.querySelector('.status__content').textContent + m
    			)) n.style.display = 'none';
    			
    			n.className += ' viewed';
    
    		});
    
    	};
    
    	a = s => {
    
    		if (s == '🔈') {
    
    			b.text('🔇');
    			x({ target: t[0] });
    			o.observe(t[0], l);
    
    		} else {
    
    			b.text('🔈');
    			o.disconnect();
    			$('.status').removeClass('viewed').filter(':hidden').show();
    
    		}
    
    	};
    
    	f = n => {
    
    		n = $('.column:last>.scrollable>div:last');
    
    		if (!t || t[0] != n[0]) {
    
    			t = n;
    			a('🔇');
    			a('🔈');
    
    		}
    
    	};
    
    	o = new MutationObserver(s => s.forEach(x));
    
    	c = $('#mute-buttons');
    	if (!c[0]) c = $('<div />')
    	 .css({ position: 'fixed', height: '1em', bottom: '2em', right: 0, zIndex: 99 })
    	 .attr('id', 'mute-buttons').appendTo(p);
    
    	b = $('<button />').text('🔈')
    	 .click(function() { a(b.text()); });
    
    	c.append(b).append(
    	 $('<input />').val(r.source).css('width', '12em')
    	 .change(function(s) {
    
    		s = this.value;
    
    		if (s.length) {
    
    			try { s = new RegExp(s); } catch(e) {}
    
    			if (typeof s == 'object') {
    
    				o.disconnect();
    				r = s;
    				d.cookie = `let_filter_regexp=${encodeURIComponent(r.source)}; path=\x2F; expires=Tue, 19 Jan 2038 03:14:07 GMT`;
    				a('🔇');
    				a('🔈');
    
    			} else a('🔇');
    
    		} else a('🔇');
    
    	 })
    	 .focus(function() {
    
    		$(this).css({ paddingLeft: 0, width: '12em' });
    
    	 }).blur(function() {
    
    		$(this).css({ paddingLeft: '2em', width: 0 });
    
    	 })
    	);
    
    	f();
    	new MutationObserver(s => s.forEach(f)).observe(p[0], l);
    
    })();
    
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。