X(Twitter) のタイムラインで長文ツイートだけを隠す Chrome 拡張の作り方。下のファイルをコピペすれば同じように動く。
できること
- 140文字超 or「もっと見る」が付くツイートを非表示にする
- ポップアップで ON/OFF を切り替え(設定は保存される)
- スクロールで流れてくる新規ツイートにも自動で効く
用意するファイル
拡張用フォルダに次の4ファイル(と任意で icon.png)を置く。
manifest.json… 拡張の設定content.js… タイムラインに注入するスクリプト(長文判定・非表示)popup.html… ポップアップのHTMLpopup.js… ポップアップのON/OFF処理icon.png… アイコン(256×256推奨。任意)
manifest.json(全文)
{
"name": "X長文フィルタ",
"manifest_version": 3,
"version": "1.0",
"permissions": ["activeTab", "storage"],
"content_scripts": [
{
"matches": ["https://twitter.com/*", "https://x.com/*"],
"js": ["content.js"]
}
],
"action": {
"default_popup": "popup.html"
},
"icons": {
"256": "icon.png"
}
} ※ icon.png を使わないなら "icons" ブロックごと消してよい。
content.js(全文)
(function() {
'use strict';
const MAX_LENGTH = 140;
const SHOW_MORE_SELECTOR = '[data-testid="tweet-text-show-more-link"]';
let isFilterEnabled = true;
chrome.storage.local.get(['filterEnabled'], (result) => {
isFilterEnabled = result.filterEnabled !== false;
applyVisibilityAll();
});
chrome.storage.onChanged.addListener((changes) => {
if (changes.filterEnabled) {
isFilterEnabled = changes.filterEnabled.newValue;
applyVisibilityAll();
}
});
function processTweets() {
const articles = document.querySelectorAll('article[data-testid="tweet"]');
articles.forEach(article => {
if (article.dataset.isLongChecked) {
updateArticleVisibility(article);
return;
}
const textNode = article.querySelector('div[data-testid="tweetText"]');
const showMoreBtn = article.querySelector(SHOW_MORE_SELECTOR);
let isLong = false;
if (textNode) {
const textContent = textNode.textContent || "";
if (textContent.length > MAX_LENGTH || showMoreBtn !== null) isLong = true;
}
article.dataset.isLongTweet = isLong;
article.dataset.isLongChecked = "true";
updateArticleVisibility(article);
});
}
function updateArticleVisibility(article) {
const isLong = article.dataset.isLongTweet === "true";
if (isFilterEnabled && isLong) {
if (article.style.display !== 'none') article.style.display = 'none';
} else {
if (article.style.display === 'none') article.style.display = '';
}
}
function applyVisibilityAll() {
const articles = document.querySelectorAll('article[data-testid="tweet"]');
articles.forEach(article => updateArticleVisibility(article));
}
const observer = new MutationObserver(() => processTweets());
observer.observe(document.body, { childList: true, subtree: true });
})(); popup.html(全文)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
body { width: 200px; padding: 10px; font-family: sans-serif; }
.container { display: flex; align-items: center; justify-content: space-between; }
.label { font-size: 14px; font-weight: bold; }
.switch { position: relative; display: inline-block; width: 40px; height: 24px; }
.switch input { opacity: 0; width: 0; height: 0; }
.slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; transition: .4s; border-radius: 24px; }
.slider:before { position: absolute; content: ""; height: 16px; width: 16px; left: 4px; bottom: 4px; background-color: white; transition: .4s; border-radius: 50%; }
input:checked + .slider { background-color: #1DA1F2; }
input:checked + .slider:before { transform: translateX(16px); }
</style>
</head>
<body>
<div class="container">
<span class="label">長文非表示</span>
<label class="switch">
<input type="checkbox" id="toggleFilter">
<span class="slider"></span>
</label>
</div>
<script src="popup.js"></script>
</body>
</html> popup.js(全文)
document.addEventListener('DOMContentLoaded', () => {
const toggle = document.getElementById('toggleFilter');
chrome.storage.local.get(['filterEnabled'], (result) => {
toggle.checked = result.filterEnabled !== false;
});
toggle.addEventListener('change', () => {
chrome.storage.local.set({ filterEnabled: toggle.checked });
});
}); 入れ方
- 4ファイル(と必要なら icon.png)を同じフォルダに保存する
- Chrome で
chrome://extensions/を開く - 「デベロッパーモード」を ON にする
- 「パッケージ化されていない拡張機能を読み込む」でそのフォルダを指定する
X のタブで長文が非表示になり、拡張アイコンから ON/OFF を切り替えられる。
補足
- 長文の基準(140文字)は
content.jsのMAX_LENGTHを変えればよい。 - X の DOM(
data-testidなど)が変わると動かなくなることがある。そのときはセレクタを直す。