您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Tema de nord dark para o kanban do incicle
// ==UserScript== // @name Incicle Dark Theme // @license MIT // @namespace Violentmonkey Scripts // @match https://projects.incicle.com/* // @grant none // @version 1.1 // @author JV // @description Tema de nord dark para o kanban do incicle // ==/UserScript== (function() { 'use strict'; // Nord Color Palette const COLORS = { // Polar Night nord0: '#2e3440', // Background nord1: '#3b4252', // Background lighter nord2: '#434c5e', // Selection background nord3: '#4c566a', // Comments, invisibles // Snow Storm nord4: '#d8dee9', // Dark text nord5: '#e5e9f0', // Text nord6: '#eceff4', // Light text // Frost nord7: '#8fbcbb', // Secondary nord8: '#88c0d0', // Light blue nord9: '#81a1c1', // Secondary blue nord10: '#5e81ac', // Primary // Aurora nord11: '#bf616a', // Red nord12: '#d08770', // Orange nord13: '#ebcb8b', // Yellow nord14: '#a3be8c' // Green }; const cssModules = { // CSS Variables variables: ` :root, html:root { --primary: ${COLORS.nord10} !important; --secondary-blue: ${COLORS.nord9} !important; --second: ${COLORS.nord7} !important; --red: ${COLORS.nord11} !important; --light-blue: ${COLORS.nord8} !important; --orange: ${COLORS.nord12} !important; --green: ${COLORS.nord14} !important; --text-color: ${COLORS.nord5} !important; --text-darker: ${COLORS.nord4} !important; --opaque-bkg: ${COLORS.nord3} !important; --light-yellow: ${COLORS.nord13} !important; --nord-bg: ${COLORS.nord0} !important; --nord-bg2: ${COLORS.nord1} !important; --nord-bg3: ${COLORS.nord2} !important; --nord-bg4: ${COLORS.nord3} !important; } `, // Base styles base: ` body, html body { background-color: var(--nord-bg) !important; color: var(--text-color) !important; } `, // Links with high specificity links: ` a, html a, body a, div a, p a, span a, li a, td a, th a, header a, nav a, main a, footer a, article a, section a, .link, [href], a.link, a[class], a[id], body div a, html body a, div.container a, .nav-link, .menu-link, .btn-link { color: var(--text-color) !important; } `, // Header styles header: ` header, body header, html body header, div header, .header, #header, [class*="header"], nav header, main header { background-color: var(--nord-bg2) !important; } .css-1vb8iuf { color: var(--text-darker) !important; } `, // Kanban specific styles kanban: ` /* Kanban Cards */ .kyhxic, [class*="card"], .kanban-card { background-color: var(--nord-bg3) !important; } /* Kanban Columns */ .hNtkvk, [class*="column"] { background-color: var(--nord-bg4) !important; } .jHmrSI { color: var(--text-darker) !important; border-color: var(--text-darker) !important; } .css-18st10o .MuiInputBase-root { background-color: transparent !important; } `, // Modal/Card styles modals: ` .css-1tx53sv { background-color: var(--nord-bg2) !important; } .css-1tx53sv h3, .css-1tx53sv button { color: var(--text-darker) !important; } .css-9aqn0s { background-color: var(--nord-bg3) !important; } .css-18z8a8c fieldset { color: var(--text-color) !important; } .css-13e5wxt { color: var(--text-darker) !important; } ` }; class IncicleThemeManager { constructor() { this.retryCount = 0; this.maxRetries = 5; this.retryDelay = 200; } // Combina todos os módulos CSS getCombinedCSS() { return Object.values(cssModules).join('\n\n'); } // Aplica estilos via Greasemonkey/Violentmonkey applyWithGM() { if (typeof GM_addStyle !== "undefined") { GM_addStyle(this.getCombinedCSS()); return true; } return false; } // Aplica estilos via DOM applyWithDOM() { const styleNode = document.createElement("style"); styleNode.appendChild(document.createTextNode(this.getCombinedCSS())); styleNode.setAttribute('data-userscript', 'incicle-dark-theme'); styleNode.setAttribute('data-version', '1.1'); const head = document.querySelector("head") || document.documentElement; head.appendChild(styleNode); } // Força estilos via JavaScript para elementos problemáticos forceStyles() { // Headers const headers = document.querySelectorAll('header, .header, #header, [class*="header"]'); headers.forEach(el => { el.style.setProperty('background-color', COLORS.nord1, 'important'); }); // Kanban cards const cards = document.querySelectorAll('.kyhxic, [class*="card"]'); cards.forEach(el => { el.style.setProperty('background-color', COLORS.nord2, 'important'); }); // Links const links = document.querySelectorAll('a, [href]'); links.forEach(el => { el.style.setProperty('color', COLORS.nord5, 'important'); }); } // Aplica estilos com retry applyStyles() { // Tenta aplicar via GM primeiro if (!this.applyWithGM()) { this.applyWithDOM(); } // Força estilos específicos após delay setTimeout(() => this.forceStyles(), 100); } // Observer para mudanças dinâmicas setupObserver() { const observer = new MutationObserver((mutations) => { let needsReapply = false; mutations.forEach((mutation) => { if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { needsReapply = true; } }); if (needsReapply) { setTimeout(() => this.forceStyles(), 50); } }); observer.observe(document.body, { childList: true, subtree: true }); } // Inicialização init() { // Aplica imediatamente this.applyStyles(); // Aplica após DOM carregar if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { this.applyStyles(); this.setupObserver(); }); } else { this.setupObserver(); } // Retry periódico para elementos que carregam dinamicamente const retryInterval = setInterval(() => { this.forceStyles(); this.retryCount++; if (this.retryCount >= this.maxRetries) { clearInterval(retryInterval); } }, this.retryDelay * this.retryCount); } } // Inicializar const themeManager = new IncicleThemeManager(); themeManager.init(); })();