Last active
May 12, 2026 10:48
-
-
Save shuantsu/d550c00b228271c9bdd7195c4244276c to your computer and use it in GitHub Desktop.
make tabnews better
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name TABNEWS BETTER DESIGN | |
| // @namespace http://tampermonkey.net/ | |
| // @version 2026-05-12 | |
| // @description try to take over the world! | |
| // @author You | |
| // @match https://www.tabnews.com.br/ | |
| // @icon https://www.google.com/s2/favicons?sz=64&domain=github.com | |
| // @grant none | |
| // ==/UserScript== | |
| (function() { | |
| 'use strict'; | |
| // 1. Configurações de Identidade Visual (Avatares e Cores) | |
| const AVATAR_COLORS = ['#6f42c1', '#0969da', '#1a7f37', '#d73a49', '#6e40c9', '#b45309', '#0f6e56', '#c11574']; | |
| function avatarColor(n) { | |
| let h = 0; | |
| for (let i = 0; i < n.length; i++) h = (h * 31 + n.charCodeAt(i)) & 0xffffff; | |
| return AVATAR_COLORS[Math.abs(h) % AVATAR_COLORS.length]; | |
| } | |
| function initials(n) { | |
| return n.replace(/[^a-zA-Z]/g, '').slice(0, 2).toUpperCase() || '??'; | |
| } | |
| // 2. CSS Moderno: Masonry Real + Full Width + Estilo de Cards | |
| const style = document.createElement('style'); | |
| style.innerHTML = ` | |
| main.gVvXqe { max-width: 100% !important; width: 100% !important; padding: 20px !important; background: #f6f8fa !important; } | |
| ol.bKvFHa { display: none !important; } | |
| #tn-masonry-grid { | |
| display: grid !important; | |
| grid-template-columns: repeat(auto-fill, minmax(380px, 1fr)) !important; | |
| grid-auto-rows: 1px !important; | |
| gap: 0 24px !important; | |
| width: 100% !important; | |
| align-items: start !important; | |
| } | |
| .tn-creator-card { | |
| background: #ffffff !important; | |
| border: 1px solid #d0d7de !important; | |
| border-radius: 12px !important; | |
| margin-bottom: 24px !important; | |
| box-shadow: 0 4px 12px rgba(0,0,0,0.05) !important; | |
| overflow: hidden !important; | |
| padding: 0 !important; | |
| } | |
| .card-inner { padding: 24px !important; display: flex !important; flex-direction: column !important; } | |
| /* Cabeçalho do Card com Avatar */ | |
| .tn-card-header { | |
| display: flex !important; | |
| align-items: center !important; | |
| gap: 12px !important; | |
| margin-bottom: 15px !important; | |
| } | |
| .tn-avatar { | |
| width: 38px; height: 38px; border-radius: 50%; | |
| color: #fff; display: flex; align-items: center; justify-content: center; | |
| font-size: 14px; font-weight: 800; flex-shrink: 0; | |
| box-shadow: inset 0 0 0 1px rgba(0,0,0,0.1); | |
| } | |
| .tn-creator-name { | |
| background: #6f42c1; color: #fff; padding: 4px 12px; | |
| border-radius: 6px; font-weight: 800; font-size: 1.1rem; | |
| text-decoration: none !important; | |
| } | |
| /* Divisão de Posts */ | |
| .tn-post-item { | |
| padding: 16px 0 !important; | |
| border-bottom: 2px solid #444 !important; | |
| } | |
| .tn-post-item:last-child { border-bottom: none !important; } | |
| .tn-post-title { | |
| font-weight: 700; color: #0969da; text-decoration: none; | |
| font-size: 1.1rem; display: block; margin-bottom: 5px; | |
| } | |
| .tn-post-title:hover { text-decoration: underline; } | |
| .tn-post-meta { font-size: 0.85rem; color: #57606a; line-height: 1.4; } | |
| .tn-post-meta b { color: #0969da; } | |
| `; | |
| document.head.appendChild(style); | |
| const list = document.querySelector('ol.bKvFHa'); | |
| if (!list) return; | |
| // Função de ajuste de altura (Masonry) | |
| function resizeGridItem(item) { | |
| const inner = item.querySelector('.card-inner'); | |
| if (!inner) return; | |
| const contentHeight = inner.getBoundingClientRect().height; | |
| const rowSpan = Math.ceil(contentHeight + 24); | |
| item.style.gridRowEnd = "span " + rowSpan; | |
| } | |
| function renderEnhancer() { | |
| const posts = []; | |
| list.querySelectorAll('li').forEach(li => { | |
| const titleEl = li.querySelector('a.hnyTjC') || li.querySelector('a.kMiBSO') || li.querySelector('a'); | |
| const authorEl = li.querySelector('address a') || li.querySelector('a.hQluGh') || li.querySelector('a[href^="/"]'); | |
| const coinsEl = li.querySelector('span[role="tooltip"]'); | |
| const timeEl = li.querySelector('time'); | |
| if (!titleEl || !authorEl) return; | |
| const authorName = authorEl.textContent.trim().replace('@', ''); | |
| posts.push({ | |
| title: titleEl.textContent.trim(), | |
| href: titleEl.getAttribute('href'), | |
| author: authorName, | |
| authorHref: authorEl.getAttribute('href'), | |
| coins: coinsEl ? coinsEl.textContent.trim() : '0 tabcoins', | |
| time: timeEl ? timeEl.textContent.trim() : '', | |
| }); | |
| }); | |
| const groups = {}; | |
| posts.forEach(p => { | |
| if (!groups[p.author]) groups[p.author] = { name: p.author, href: p.authorHref, posts: [] }; | |
| groups[p.author].posts.push(p); | |
| }); | |
| const sortedAuthors = Object.values(groups).sort((a, b) => b.posts.length - a.posts.length); | |
| let grid = document.getElementById('tn-masonry-grid'); | |
| if (!grid) { | |
| grid = document.createElement('div'); | |
| grid.id = 'tn-masonry-grid'; | |
| list.parentNode.insertBefore(grid, list); | |
| } | |
| grid.innerHTML = ''; | |
| sortedAuthors.forEach(g => { | |
| const color = avatarColor(g.name); | |
| const card = document.createElement('div'); | |
| card.className = 'tn-creator-card'; | |
| const postsHtml = g.posts.map(p => ` | |
| <div class="tn-post-item"> | |
| <a class="tn-post-title" href="${p.href}">${p.title}</a> | |
| <div class="tn-post-meta"><b>${p.coins}</b> · ${p.time}</div> | |
| </div> | |
| `).join(''); | |
| card.innerHTML = ` | |
| <div class="card-inner"> | |
| <div class="tn-card-header"> | |
| <div class="tn-avatar" style="background:${color}">${initials(g.name)}</div> | |
| <a href="${g.href}" class="tn-creator-name">${g.name}</a> | |
| <span style="margin-left:auto; font-size:0.8rem; color:#888;">${g.posts.length} posts</span> | |
| </div> | |
| <div>${postsHtml}</div> | |
| </div> | |
| `; | |
| grid.appendChild(card); | |
| }); | |
| requestAnimationFrame(() => { | |
| document.querySelectorAll('.tn-creator-card').forEach(resizeGridItem); | |
| }); | |
| } | |
| // Execução única | |
| renderEnhancer(); | |
| // Re-calcula Masonry se a janela mudar de tamanho | |
| window.addEventListener('resize', () => { | |
| document.querySelectorAll('.tn-creator-card').forEach(resizeGridItem); | |
| }); | |
| console.log('%c TabNews Masonry Enhancer Ativado ', 'background:#6f42c1;color:#fff;font-weight:bold;padding:4px;'); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment