Standardize font size to 15px and revert justified text; avoid text that is too small or too big. Replace fonts with sans-serif/serif/monospace at calibrated sizes (avoid unsupported/mismatched desktop fonts). Dodge colored text from the background and lightly pastelize to improve contrast.
当前为
// ==UserScript==
// @name QQ/SB/SV Mobile readability
// @description Standardize font size to 15px and revert justified text; avoid text that is too small or too big. Replace fonts with sans-serif/serif/monospace at calibrated sizes (avoid unsupported/mismatched desktop fonts). Dodge colored text from the background and lightly pastelize to improve contrast.
// @author C89sd
// @version 1.7
// @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;
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.querySelectorAll('div.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: 13px;
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/')) {
// Make tables with 2/3 cols fixed 50% 33.33%
[...document.querySelectorAll('.bbTable table')]
.filter(t=>[2,3].includes(t.rows[0]?.cells.length))
.forEach(t=>{
t.style.cssText += 'table-layout:fixed;width:100%';
let w = (100/t.rows[0].cells.length).toFixed(2) + '%';
for(let c of t.rows[0].cells) c.width = w;
});
// Standardize padding around the "New Top 10" bubble
GM_addStyle(`
.bbTable td b:has( code.bbCodeInline) {
display: inline-block !important;
padding: 2px 0 !important;
}
`);
}