您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a button on the Replit side bar that lets you open the Developer Frameworks page, instead of being restricted to the Agent input
// ==UserScript== // @name BBDF (Bring Back Developer Frameworks) // @namespace https://spin.rip/ // @match https://replit.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=replit.com // @grant none // @version 1.3.1 // @author Spinfal // @description Adds a button on the Replit side bar that lets you open the Developer Frameworks page, instead of being restricted to the Agent input // @license GPL-3.0-or-later // @run-at document-idle // ==/UserScript== (function () { const BTN_ID = 'bbdf-developer-frameworks-btn'; // minimal: add the button, keep it present across spa route changes function addButtonIfMissing() { const newReplBtn = document.querySelector('[data-cy="sidebar-new-repl-btn"]'); if (!newReplBtn) return; const container = newReplBtn.parentElement || newReplBtn.closest('div'); if (!container) return; if (container.querySelector('#' + BTN_ID)) return; const a = document.createElement('a'); a.id = BTN_ID; a.setAttribute('data-cy', 'bbdf-developer-frameworks-btn'); a.className = 'Button_button__oRQ_x css-7x8c3s'; a.href = '/developer-frameworks'; a.role = 'link'; a.ariaLabel = 'Developer Frameworks'; a.style.cssText = '--Button--height:32px;--Button--shrink:0;--Button--align-self:auto;--Button--alignment:center;display:flex;'; a.innerHTML = ` <div class="useView_view__C2mnv useView_isHorizontal__Q1YOp" style="--useView--gap:8px;--useView--justify:center;--useView--align:center;--useView--grow:1;--useView--shrink:1;"> <svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" focusable="false" style="width:16px;height:16px;"> <rect x="2" y="2" width="20" height="20" rx="4" ry="4" fill="currentColor" opacity="0.12"></rect> <text x="12" y="16" text-anchor="middle" font-size="11" font-family="Inter, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif" font-weight="700" fill="currentColor"><3</text> </svg> <span class="Text_singleLineWrapper__REG8N" style="--Text--font-size:var(--font-size-default);--Text--font-family:inherit;"> <span class="useView_view__C2mnv Text_text__T_hn_ Text_singleLine__lXpWA" style="--Text--font-family:inherit;--Text--font-size:var(--font-size-default);--Text--line-height:var(--line-height-default);">Developer Frameworks</span> </span> </div> `; container.appendChild(a); } function hookHistory() { const origPush = history.pushState; const origReplace = history.replaceState; if (!history._bbdfHooked) { history.pushState = function () { const ret = origPush.apply(this, arguments); window.dispatchEvent(new Event('bbdf:navigation')); return ret; }; history.replaceState = function () { const ret = origReplace.apply(this, arguments); window.dispatchEvent(new Event('bbdf:navigation')); return ret; }; history._bbdfHooked = true; } window.addEventListener('popstate', () => window.dispatchEvent(new Event('bbdf:navigation'))); } function startObserver() { const obs = new MutationObserver(addButtonIfMissing); obs.observe(document.documentElement, { childList: true, subtree: true }); window.__BBDF_OBSERVER__ = obs; } function init() { hookHistory(); startObserver(); addButtonIfMissing(); window.addEventListener('bbdf:navigation', addButtonIfMissing); let tries = 0; const iv = setInterval(() => { addButtonIfMissing(); if (++tries > 20) clearInterval(iv); }, 250); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init, { once: true }); } else { init(); } })();