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.3
// @match https://forum.questionablequesting.com/threads/*
// @match https://forums.spacebattles.com/threads/*
// @match https://forums.sufficientvelocity.com/threads/*
// @namespace https://greasyfork.org/users/1376767
// ==/UserScript==
'use strict';
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);
}
}
}