您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Apply custom userscripts, CSS, and JS globally across Blacket; manage via /settings page UI panel styled like General box with buttons and icon styling matching Blacket UI.
// ==UserScript== // @name Blacket Global Scripts Manager // @namespace http://tampermonkey.net/ // @version 2.5 // @description Apply custom userscripts, CSS, and JS globally across Blacket; manage via /settings page UI panel styled like General box with buttons and icon styling matching Blacket UI. // @author You // @match https://*.blacket.org/* // @grant none // ==/UserScript== (function () { 'use strict'; const applyAll = () => { const css = localStorage.getItem('bb_saved_css'); if (css) { let el = document.getElementById('bb_injectedCSS'); if (!el) { el = document.createElement('style'); el.id = 'bb_injectedCSS'; document.head.appendChild(el); } el.textContent = css; } const js = localStorage.getItem('bb_saved_js'); if (js) { const script = document.createElement('script'); script.textContent = js; document.body.appendChild(script); script.remove(); } const userscript = localStorage.getItem('bb_saved_userscript'); if (userscript) { const script = document.createElement('script'); script.textContent = userscript; document.body.appendChild(script); script.remove(); } }; applyAll(); if (!location.pathname.startsWith('/settings')) return; // ---------- UI PANEL BELOW ONLY RENDERS ON /settings ---------- function createStyledButton(text, onClick) { const btnWrapper = document.createElement('div'); btnWrapper.className = 'styles__button___1_E-G-camelCase styles__upgradeButton___3UQMv-camelCase'; btnWrapper.setAttribute('role', 'button'); btnWrapper.setAttribute('tabindex', '0'); const anchor = document.createElement('a'); anchor.href = '#'; anchor.style.textDecoration = 'none'; anchor.addEventListener('click', e => { e.preventDefault(); onClick(); }); const shadowDiv = document.createElement('div'); shadowDiv.className = 'styles__shadow___3GMdH-camelCase'; const edgeDiv = document.createElement('div'); edgeDiv.className = 'styles__edge___3eWfq-camelCase'; edgeDiv.style.backgroundColor = 'var(--secondary)'; const frontDiv = document.createElement('div'); frontDiv.className = 'styles__front___vcvuy-camelCase styles__upgradeButtonInside___396BT-camelCase'; frontDiv.style.backgroundColor = 'var(--secondary)'; frontDiv.style.display = 'flex'; frontDiv.style.justifyContent = 'center'; frontDiv.style.alignItems = 'center'; frontDiv.textContent = text; anchor.appendChild(shadowDiv); anchor.appendChild(edgeDiv); anchor.appendChild(frontDiv); btnWrapper.appendChild(anchor); return btnWrapper; } function tryCloneGeneralBox() { const boxes = document.querySelectorAll('.styles__infoContainer___2uI-S-camelCase'); for (const box of boxes) { const header = box.querySelector('.styles__infoHeader___1lsZY-camelCase'); if (header?.textContent?.trim() === 'General') { const clone = box.cloneNode(true); clone.querySelector('.styles__infoHeader___1lsZY-camelCase').textContent = 'Scripts Manager'; const oldIcon = clone.querySelector('i.fas.fa-cog.styles__headerIcon___1ykdN-camelCase'); if (oldIcon) { const icon = document.createElement('i'); icon.className = 'fas fa-plus styles__headerIcon___1ykdN-camelCase'; icon.setAttribute('aria-hidden', 'true'); oldIcon.replaceWith(icon); } clone.querySelectorAll('a.styles__link___5UR6_-camelCase').forEach(link => link.remove()); const btn = createStyledButton('Manage Scripts', () => { const modal = document.getElementById('bb_scriptsManagerModal'); if (modal) modal.style.visibility = 'visible'; }); clone.appendChild(btn); box.parentNode.insertBefore(clone, box.nextSibling); break; } } } function addModal() { if (document.getElementById('bb_scriptsManagerModal')) return; const overlay = document.createElement('div'); overlay.id = 'bb_scriptsManagerModal'; Object.assign(overlay.style, { position: 'fixed', top: 0, left: 0, width: '100vw', height: '100vh', backgroundColor: 'rgba(0,0,0,0.7)', display: 'flex', justifyContent: 'center', alignItems: 'center', zIndex: 9999, visibility: 'hidden', }); const modal = document.createElement('div'); modal.style.background = '#1e1e1e'; modal.style.borderRadius = '8px'; modal.style.padding = '20px'; modal.style.maxWidth = '600px'; modal.style.width = '100%'; modal.style.color = '#fff'; const header = document.createElement('div'); header.style.display = 'flex'; header.style.alignItems = 'center'; header.style.marginBottom = '10px'; const icon = document.createElement('i'); icon.className = 'fas fa-plus styles__headerIcon___1ykdN-camelCase'; icon.setAttribute('aria-hidden', 'true'); icon.style.marginRight = '10px'; const title = document.createElement('div'); title.className = 'styles__infoHeader___1lsZY-camelCase'; title.textContent = 'Manage Scripts'; const close = document.createElement('div'); close.textContent = '×'; close.style.marginLeft = 'auto'; close.style.cursor = 'pointer'; close.onclick = () => overlay.style.visibility = 'hidden'; header.appendChild(icon); header.appendChild(title); header.appendChild(close); modal.appendChild(header); const editors = [ { id: 'userscript', label: 'Userscript JS', placeholder: '// Paste userscript here' }, { id: 'css', label: 'CSS', placeholder: '/* Paste CSS here */' }, { id: 'js', label: 'JavaScript', placeholder: '// Paste JavaScript here' } ]; editors.forEach(({ id, label, placeholder }) => { const wrap = document.createElement('div'); wrap.style.marginBottom = '16px'; const l = document.createElement('label'); l.textContent = label; const ta = document.createElement('textarea'); ta.placeholder = placeholder; ta.id = 'bb_' + id + '_textarea'; ta.value = localStorage.getItem('bb_saved_' + id) || ''; Object.assign(ta.style, { width: '100%', height: '100px', background: '#111', color: '#fff', border: '1px solid #444', borderRadius: '4px', padding: '6px', marginTop: '6px', fontFamily: 'monospace' }); const btnWrap = document.createElement('div'); btnWrap.style.marginTop = '6px'; btnWrap.style.display = 'flex'; btnWrap.style.gap = '10px'; const apply = createStyledButton('Apply', () => { const val = ta.value; localStorage.setItem('bb_saved_' + id, val); applyAll(); }); const remove = createStyledButton('Remove', () => { ta.value = ''; localStorage.removeItem('bb_saved_' + id); if (id === 'css') { const el = document.getElementById('bb_injectedCSS'); if (el) el.remove(); } }); btnWrap.appendChild(apply); btnWrap.appendChild(remove); wrap.appendChild(l); wrap.appendChild(ta); wrap.appendChild(btnWrap); modal.appendChild(wrap); }); overlay.appendChild(modal); document.body.appendChild(overlay); } // Run UI creation on settings page only tryCloneGeneralBox(); addModal(); })();