您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在Twitter信息流中显示图片的ALT信息
当前为
- // ==UserScript==
- // @name Twitter ALT info
- // @namespace https://twitter.com/shangrenxi
- // @version 1.0.1
- // @description 在Twitter信息流中显示图片的ALT信息
- // @icon http://www.google.com/s2/favicons?domain=twitter.com
- // @author Alban
- // @match https://twitter.com/*
- // @grant GM_addStyle
- // @license MIT Alban
- // ==/UserScript==
- const tweetSelector = 'article[data-testid="tweet"]';
- const tweetTextSelector = 'div[data-testid="tweetText"]';
- const tweetPhotoSelector = 'div[data-testid^="tweetPhoto"]';
- const appendAltText = (tweet, altText) => {
- const tweetTextElement = tweet.querySelector(tweetTextSelector);
- const existingList =
- tweetTextElement?.querySelector(".alt-list") ??
- (() => {
- const newList = document.createElement("ol");
- newList.className = "alt-list";
- const altPromptText = document.createTextNode("ALTs: ");
- const altPrompt = document.createElement("span");
- altPrompt.className = "alt-prompt";
- altPrompt.appendChild(altPromptText);
- const container = document.createElement("div");
- container.className = "alt-container";
- container.appendChild(altPrompt);
- container.appendChild(newList);
- tweetTextElement.appendChild(container);
- return newList;
- })();
- const listItem = document.createElement("li");
- const altTextNode = document.createTextNode(altText);
- const altTextContainer = document.createElement("div");
- altTextContainer.className = "alt-text"
- altTextContainer.appendChild(altTextNode);
- listItem.appendChild(altTextContainer);
- existingList.appendChild(listItem);
- };
- const processedTweets = new Map();
- const processTweet = (tweet) => {
- if (processedTweets.get(tweet)) {
- return;
- }
- processedTweets.set(tweet, true);
- tweet.querySelectorAll(tweetPhotoSelector).forEach((photo) => {
- const altText = photo.getAttribute("aria-label");
- if (altText && altText.length >= 10) {
- appendAltText(tweet, altText);
- }
- });
- };
- const intersectionObserver = new IntersectionObserver(
- (entries) => {
- entries.forEach((entry) => {
- if (
- entry.isIntersecting &&
- !processedTweets.get(entry.target) &&
- entry.target.matches(tweetSelector) &&
- entry.target.querySelector(tweetPhotoSelector)
- ) {
- processTweet(entry.target);
- }
- });
- },
- { threshold: 0.5 }
- );
- const observerConfig = { childList: true, subtree: true };
- const mutationObserver = new MutationObserver((mutationsList) =>
- mutationsList.forEach(({ addedNodes }) =>
- addedNodes.forEach((node) => {
- if (node.nodeType === Node.ELEMENT_NODE) {
- node.querySelectorAll(tweetSelector).forEach((tweet) => {
- intersectionObserver.observe(tweet);
- });
- }
- })
- )
- );
- document.querySelectorAll(tweetSelector).forEach((tweet) => {
- intersectionObserver.observe(tweet);
- });
- mutationObserver.observe(document.body, observerConfig);
- GM_addStyle(`
- .alt-container {
- display: block;
- margin-top: 10px;
- background-color: #cce6ff5e;
- padding: 8px;
- border-radius: 8px;
- border-style: solid;
- border-color: #cce6ff;
- }
- .alt-prompt {
- font-weight: bold;
- color: #1d9bf0;
- font-size: 15px;
- }
- .alt-list {
- padding-left: 20px;
- margin-block-start: 0.2em;
- margin-block-end: 0.2em;
- }
- .alt-text {
- padding: .2em;
- font-size: 15px;
- }
- `);