您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Standardize font size to 15px, revert justified text, replace fonts with sans-serif/serif/monospace at calibrated sizes (avoid unsupported/mismatched desktop fonts), dodge colored text from the background and lightly pastelize them to improve contrast, detect centered text and add Uncenter toggle.
- // ==UserScript==
- // @name AH/QQ/SB/SV Mobile readability
- // @description Standardize font size to 15px, revert justified text, replace fonts with sans-serif/serif/monospace at calibrated sizes (avoid unsupported/mismatched desktop fonts), dodge colored text from the background and lightly pastelize them to improve contrast, detect centered text and add Uncenter toggle.
- // @author C89sd
- // @version 1.10
- // @match https://www.alternatehistory.com/*
- // @match https://questionablequesting.com/*
- // @match https://forum.questionablequesting.com/*
- // @match https://forums.spacebattles.com/*
- // @match https://forums.sufficientvelocity.com/*
- // @grant GM_addStyle
- // @namespace https://greasyfork.org/users/1376767
- // @noframes
- // ==/UserScript==
- 'use strict';
- const IS_THREAD = document.URL.includes('/threads/');
- if (!IS_THREAD) return;
- // Centered text toggle
- const OP = document.querySelector('.username.u-concealed')?.textContent || '!';
- const messages = document.getElementsByClassName('message');
- let foundCentered = false;
- for (let message of messages) {
- if (message.getAttribute('data-author') === OP || message.classList.contains('hasThreadmark')) {
- const centeredDiv = message.querySelector('.bbWrapper:first-of-type > div[style*="text-align: center"], .bbWrapper > div.uncentered');
- if (centeredDiv) {
- foundCentered = true;
- break;
- }
- }
- }
- if (foundCentered) {
- let buttonGrp = document.querySelector('.block-outer-threadmarks .buttonGroup');
- let centered = true;
- if (buttonGrp) {
- buttonGrp.insertAdjacentHTML('afterbegin', '<div class="buttonGroup buttonGroup-buttonWrapper"><span class="button--link button" style="cursor:pointer" title="Toggle center text">Uncenter</span></div>');
- buttonGrp.firstElementChild.firstElementChild.addEventListener('click', function() {
- document.querySelectorAll(centered ? '.bbWrapper > div[style*="text-align: center"]' : '.bbWrapper > div.uncentered').forEach(el => {
- if (centered) {
- el.classList.add('uncentered');
- el.style.textAlign = '';
- } else {
- el.style.textAlign = 'center';
- }
- });
- centered = !centered;
- });
- }
- }
- const colorCache = new Map();
- const adjustTextColor = (textRGBStr) => {
- if (colorCache.has(textRGBStr)) {
- return colorCache.get(textRGBStr);
- }
- function toRGB(str) { // can return up to 3 values [] to [r,g,b]
- const nums = str.match(/\d+/g);
- return nums ? nums.map(Number).slice(0, 3) : [];
- }
- let fg = toRGB(textRGBStr);
- const bg = toRGB("rgb(39, 39, 39)");
- if (fg.length !== 3) { return textRGBStr }
- const clamp = v => Math.max(0, Math.min(255, v));
- const pastelize = ([r, g, b]) => {
- const neutral = 128;
- const whiteBoost = Math.pow((r + g + b) / (3 * 255), 10);
- const factor = 0.8 + 0.1*whiteBoost;
- return [
- neutral + factor * (r - neutral),
- neutral + factor * (g - neutral),
- neutral + factor * (b - neutral)
- ].map(clamp);
- };
- fg = pastelize(fg);
- let positiveDiff = 0;
- positiveDiff += Math.max(0, fg[0] - 39);
- positiveDiff += Math.max(0, fg[1] - 39);
- positiveDiff += Math.max(0, fg[2] - 39);
- const threshold = 180;
- if (positiveDiff < threshold) {
- fg[0] = Math.max(fg[0], 39);
- fg[1] = Math.max(fg[1], 39);
- fg[2] = Math.max(fg[2], 39);
- const avg = (fg[0]+fg[1]+fg[2])/3;
- const boost = Math.min(1.0, (Math.abs(fg[0]-avg)+Math.abs(fg[1]-avg)+Math.abs(fg[2]-avg))/255/0.2); // grays = 0, colors >= 1
- let correction = Math.round((threshold - positiveDiff) / 3 + boost*40);
- fg = fg.map(c => Math.min(c + correction, 255));
- }
- const result = `rgb(${fg[0]}, ${fg[1]}, ${fg[2]})`;
- colorCache.set(textRGBStr, result);
- return result;
- };
- const SANS_SERIF = /arial|tahoma|trebuchet ms|verdana/;
- const MONOSPACE = /courier new/;
- const SERIF = /times new roman|georgia|book antiqua/;
- const wrappers = document.getElementsByClassName('bbWrapper');
- for (let wrapper of wrappers) {
- wrapper.style.fontSize = '15px';
- const children = wrapper.querySelectorAll('*');
- for (let child of children) {
- const style = child.style;
- if (style.fontSize) {
- style.fontSize = '';
- }
- if (style.fontFamily) {
- const font = style.fontFamily;
- if (SANS_SERIF.test(font)) {
- style.fontFamily = 'sans-serif';
- } else if (MONOSPACE.test(font)) {
- style.fontFamily = 'monospace';
- style.fontSize = '13.5px';
- } else if (SERIF.test(font)) {
- style.fontFamily = 'serif';
- }
- }
- if (style.textAlign) {
- if (style.textAlign !== 'center' && style.textAlign !== 'right') {
- style.textAlign = '';
- }
- }
- if (style.color && style.color.startsWith('rgb')) {
- style.color = adjustTextColor(style.color);
- }
- }
- }
- // Smaller tables
- GM_addStyle(`
- .bbTable {
- font-size: 13.5px;
- overflow: visible;
- table-layout: auto;
- }
- .bbTable td {
- vertical-align: top;
- white-space: normal;
- word-wrap: normal;
- word-break: break-word;
- }
- `);
- // SB Weekly stats thread
- if (document.URL.includes('.1140820/')) {
- // Fixed 2/3 columns
- const w = {2: '50%', 3: '33.33%'};
- for (const t of document.querySelectorAll('.bbTable table')) {
- const c = t.rows[0]?.cells, n = c?.length;
- if (w[n]) {
- t.style.cssText = 'table-layout:fixed;width:100%';
- for (const cell of c) cell.style.width = w[n];
- }
- }
- GM_addStyle(`
- /* Indicator */
- .bbTable td > b:first-of-type:has(code.bbCodeInline) { display: inline-block; padding: 2px 0; }
- .bbTable td > b:first-of-type code.bbCodeInline { font-size: 11px; }
- .bbTable span:has(.username) { font-size: 11.5px; } /* Name */
- .bbTable span:has(.bbc-abbr) { font-size: 12.5px; } /* Metric */
- /* Bottom Tags */
- .bbTable td > span:last-child:has(>code.bbCodeInline) { display: inline-flex; flex-wrap: wrap; gap: 1px; padding-top: 6px; }
- .bbTable td > span:last-child > code.bbCodeInline { font-size: 9px; padding: 1px 3px; }
- /* Inline break with sliced decorations
- .bbTable td > span:last-child:has(>code.bbCodeInline) { display: inline-block; padding-top: 2px; }
- .bbTable td > span:last-child > code.bbCodeInline { margin: 1px 1px; box-decoration-break: slice; }
- */
- `);
- }