fix(ui): 批量替换所有组件中残留的硬编码深色值以彻底支持浅色主题
This commit is contained in:
+128
@@ -0,0 +1,128 @@
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
async function walk(dir) {
|
||||
const files = await fs.readdir(dir, { withFileTypes: true });
|
||||
let results = [];
|
||||
for (const file of files) {
|
||||
const res = path.resolve(dir, file.name);
|
||||
if (file.isDirectory()) {
|
||||
results = results.concat(await walk(res));
|
||||
} else if (file.name.endsWith('.vue')) {
|
||||
results.push(res);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
async function fixColors() {
|
||||
const dirs = [path.resolve('app', 'components'), path.resolve('app', 'pages'), path.resolve('app', 'layouts')];
|
||||
let files = [];
|
||||
for (const dir of dirs) {
|
||||
try {
|
||||
files = files.concat(await walk(dir));
|
||||
} catch (e) {
|
||||
// Ignore if dir doesn't exist
|
||||
}
|
||||
}
|
||||
|
||||
for (const file of files) {
|
||||
let content = await fs.readFile(file, 'utf-8');
|
||||
let original = content;
|
||||
|
||||
// Generic regex for hardcoded grayscales in styles
|
||||
const grayscales = {
|
||||
'#000000': 'var(--bg-primary, #111111)',
|
||||
'#000': 'var(--bg-primary, #111111)',
|
||||
'#111111': 'var(--bg-primary, #111111)',
|
||||
'#111': 'var(--bg-primary, #111111)',
|
||||
'#1a1a1a': 'var(--bg-secondary, #1a1a1a)',
|
||||
'#222222': 'var(--bg-tertiary, #222222)',
|
||||
'#222': 'var(--bg-tertiary, #222222)',
|
||||
'#2a2a2a': 'var(--bg-tertiary, #2a2a2a)',
|
||||
'#333333': 'var(--bg-quaternary, #333333)',
|
||||
'#333': 'var(--bg-quaternary, #333333)',
|
||||
'#3a3a3a': 'var(--bg-quaternary, #3a3a3a)',
|
||||
'#444444': 'var(--text-disabled, #444444)',
|
||||
'#444': 'var(--text-disabled, #444444)',
|
||||
'#666666': 'var(--text-quaternary, #666666)',
|
||||
'#666': 'var(--text-quaternary, #666666)',
|
||||
'#888888': 'var(--text-tertiary, #888888)',
|
||||
'#888': 'var(--text-tertiary, #888888)',
|
||||
'#999999': 'var(--text-tertiary, #999999)',
|
||||
'#999': 'var(--text-tertiary, #999999)',
|
||||
'#aaaaaa': 'var(--text-secondary, #aaaaaa)',
|
||||
'#aaa': 'var(--text-secondary, #aaaaaa)',
|
||||
'#cccccc': 'var(--text-secondary, #cccccc)',
|
||||
'#ccc': 'var(--text-secondary, #cccccc)',
|
||||
'#dddddd': 'var(--border-secondary, #dddddd)',
|
||||
'#ddd': 'var(--border-secondary, #dddddd)',
|
||||
'#eeeeee': 'var(--border-primary, #eeeeee)',
|
||||
'#eee': 'var(--border-primary, #eeeeee)',
|
||||
'#ffffff': 'var(--text-primary, #ffffff)',
|
||||
'#fff': 'var(--text-primary, #ffffff)'
|
||||
};
|
||||
|
||||
// We only want to replace inside <style> blocks.
|
||||
const styleBlocks = content.match(/<style[^>]*>[\s\S]*?<\/style>/gi);
|
||||
if (styleBlocks) {
|
||||
for (const block of styleBlocks) {
|
||||
let newBlock = block;
|
||||
|
||||
// Match CSS properties like background: #1a1a1a;
|
||||
newBlock = newBlock.replace(/(background(-color)?|color|border(-color)?|border-(top|right|bottom|left)(-color)?|fill|stroke):\s*([^;}]*?)(#[0-9a-fA-F]{3,6})/gi, (match, p1, p2, p3, p4, p5, p6, hex) => {
|
||||
const hexLower = hex.toLowerCase();
|
||||
|
||||
// Don't replace if it's already inside a var()
|
||||
if (p6.includes('var(')) return match;
|
||||
|
||||
let replacement = hex;
|
||||
|
||||
if (grayscales[hexLower]) {
|
||||
// Determine if it's a background, border, or text color
|
||||
if (p1.startsWith('border')) {
|
||||
replacement = `var(--border-secondary, ${hexLower})`;
|
||||
} else if (p1.startsWith('background')) {
|
||||
if (hexLower === '#ffffff' || hexLower === '#fff') {
|
||||
replacement = `var(--card-bg, ${hexLower})`; // White background is usually a card
|
||||
} else {
|
||||
replacement = grayscales[hexLower].replace('text', 'bg'); // Force bg variables for background
|
||||
}
|
||||
} else if (p1 === 'color') {
|
||||
if (['#000000', '#000', '#111111', '#111', '#1a1a1a', '#222222', '#222', '#2a2a2a'].includes(hexLower)) {
|
||||
replacement = `var(--text-primary, ${hexLower})`;
|
||||
} else {
|
||||
replacement = grayscales[hexLower].replace('bg', 'text'); // Force text variables for color
|
||||
}
|
||||
} else {
|
||||
replacement = grayscales[hexLower];
|
||||
}
|
||||
} else {
|
||||
// Heuristic for unknown grayscales or dark colors
|
||||
// Check if it's a dark shade (e.g. #040e15, #242f38)
|
||||
if (p1.startsWith('background') && match.match(/#0[0-9a-f]{5}/i)) {
|
||||
replacement = `var(--bg-secondary, ${hexLower})`;
|
||||
} else if (p1.startsWith('background') && match.match(/#1[0-9a-f]{5}/i)) {
|
||||
replacement = `var(--bg-secondary, ${hexLower})`;
|
||||
} else if (p1.startsWith('background') && match.match(/#2[0-9a-f]{5}/i)) {
|
||||
replacement = `var(--bg-tertiary, ${hexLower})`;
|
||||
} else if (p1.startsWith('border') && match.match(/#[1-4][0-9a-f]{5}/i)) {
|
||||
replacement = `var(--border-secondary, ${hexLower})`;
|
||||
}
|
||||
}
|
||||
|
||||
return `${p1}: ${p6}${replacement}`;
|
||||
});
|
||||
|
||||
content = content.replace(block, newBlock);
|
||||
}
|
||||
}
|
||||
|
||||
if (content !== original) {
|
||||
await fs.writeFile(file, content, 'utf-8');
|
||||
console.log('Fixed', file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fixColors().catch(console.error);
|
||||
Reference in New Issue
Block a user