// ==UserScript==
// @name Wenku8 字型+大小調整
// @namespace http://tampermonkey.net/
// @version 1.3
// @description 即時調整 Wenku8 內容區字型與大小
// @author shanlan(ChatGPT o3-mini)
// @match http*://www.wenku8.net/modules/article/reader.php*cid=*
// @match http*://www.wenku8.cc/modules/article/reader.php*cid=*
// @grant none
// @run-at document-end
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// 為了避免外部 CSS 干擾,本腳本建立一個獨立的 style 區塊,套用在我們的介面上
const uiStyle = document.createElement('style');
uiStyle.textContent = `
/* 強制介面(按鈕與面板)的樣式採用深色模式 */
.tm-ui-btn, .tm-ui-panel {
all: unset;
box-sizing: border-box;
font-family: sans-serif;
}
.tm-ui-btn {
position: fixed;
right: 12px;
top: 12px;
width: 32px;
height: 32px;
background: #333 !important;
color: #f1f1f1 !important;
border: 1px solid #555 !important;
border-radius: 50% !important;
box-shadow: 0 2px 8px rgba(0,0,0,0.5) !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
font-weight: bold !important;
font-size: 18px !important;
cursor: pointer !important;
z-index: 9999 !important;
user-select: none !important;
}
.tm-ui-panel {
position: fixed;
right: 12px;
top: 56px;
background: #222 !important;
color: #f1f1f1 !important;
border: 1px solid #555 !important;
border-radius: 8px !important;
box-shadow: 0 2px 8px rgba(0,0,0,0.5) !important;
padding: 12px !important;
font-size: 14px !important;
display: none;
z-index: 9999 !important;
}
.tm-ui-panel select,
.tm-ui-panel input,
.tm-ui-panel button {
background: #333 !important;
color: #f1f1f1 !important;
border: 1px solid #555 !important;
border-radius: 4px !important;
padding: 2px 4px !important;
}
.tm-ui-panel button {
cursor: pointer !important;
}
.tm-ui-panel label,
.tm-ui-panel span {
color: #f1f1f1 !important;
}
`;
document.head.appendChild(uiStyle);
// 以下代碼參考自原 Wenku8 字型+大小調整介面,做部份修改以符合深色主題
const fonts = [
['', '預設'],
['"Noto Sans TC", "思源黑體", "Microsoft JhengHei", "微軟正黑體", sans-serif', '思源黑體'],
['"Noto Serif TC", "思源宋體", "PMingLiU", "新細明體", serif', '思源宋體'],
['"Microsoft JhengHei", "微軟正黑體", sans-serif', '微軟正黑體'],
['"PMingLiU", "新細明體", serif', '新細明體'],
['Arial, Helvetica, sans-serif', 'Arial'],
['serif', 'Serif']
];
let font = localStorage.getItem('wenku8_font') || '';
let size = parseInt(localStorage.getItem('wenku8_fontsize')) || 18;
function updateStyle() {
let s = document.getElementById('wenku8-style');
if (!s) {
s = document.createElement('style');
s.id = 'wenku8-style';
document.head.appendChild(s);
}
s.textContent = `#content, #content * { font-family: ${font || 'inherit'} !important; font-size: ${size}px !important; }`;
}
updateStyle();
// 主按鈕,加入 tm-ui-btn class 以套用深色設定
const mainBtn = document.createElement('div');
mainBtn.textContent = '字';
mainBtn.classList.add('tm-ui-btn');
// 面板,下拉選單容器,同樣加入 tm-ui-panel class
const panel = document.createElement('div');
panel.classList.add('tm-ui-panel');
// 字型選擇下拉選單
const fontLabel = document.createElement('label');
fontLabel.textContent = '字型:';
fontLabel.style.marginRight = '4px';
const fontSel = document.createElement('select');
fonts.forEach(([v, n]) => {
const opt = new Option(n, v);
if (v === font) opt.selected = true;
fontSel.add(opt);
});
fontSel.style.marginRight = '12px';
// 字體大小容器
const sizeContainer = document.createElement('span');
sizeContainer.style.display = 'inline-flex';
sizeContainer.style.alignItems = 'center';
const sizeLabel = document.createElement('span');
sizeLabel.textContent = '大小:';
sizeLabel.style.marginRight = '4px';
const btnMinus = document.createElement('button');
btnMinus.textContent = '-';
Object.assign(btnMinus.style, {
width: '28px',
height: '28px',
fontSize: '16px',
marginRight: '4px'
});
const sizeInput = document.createElement('input');
Object.assign(sizeInput, { type: 'text', value: size });
sizeInput.style.width = '44px';
sizeInput.style.textAlign = 'center';
sizeInput.style.marginRight = '4px';
const btnPlus = document.createElement('button');
btnPlus.textContent = '+';
Object.assign(btnPlus.style, {
width: '28px',
height: '28px',
fontSize: '16px'
});
sizeContainer.append(sizeLabel, btnMinus, sizeInput, btnPlus);
panel.append(fontLabel, fontSel, sizeContainer);
// 更新邏輯
function updateAll() {
font = fontSel.value;
if (sizeInput.value.trim() === "") return;
let num = parseInt(sizeInput.value, 10);
if (num <= 0) num = 18;
size = num;
sizeInput.value = size;
localStorage.setItem('wenku8_font', font);
localStorage.setItem('wenku8_fontsize', size);
updateStyle();
}
fontSel.addEventListener('change', updateAll);
sizeInput.addEventListener('input', updateAll);
btnMinus.addEventListener('click', () => {
size = Math.max(1, size - 2);
sizeInput.value = size;
updateAll();
});
btnPlus.addEventListener('click', () => {
size = size + 2;
sizeInput.value = size;
updateAll();
});
mainBtn.addEventListener('click', () => {
panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
});
document.body.append(mainBtn, panel);
// 點擊介面外部時,隱藏控制面板
document.addEventListener('mousedown', (e) => {
if (!panel.contains(e.target) && e.target !== mainBtn) {
panel.style.display = 'none';
}
});
})();