您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
shows user statistics as total installs, total scripts etc.
当前为
// ==UserScript== // @name Greasy Fork User Statistics+ // @namespace - // @version 1.3.0 // @description shows user statistics as total installs, total scripts etc. // @author NotYou // @include *greasyfork.org/*/users/* // @include *sleazyfork.org/*/users/* // @license GPL-3.0-or-later // @run-at document-end // @grant none // ==/UserScript== (function() { let translations = { 'ar': { stats: 'إحصائيات المستخدم', works: 'يعمل المستخدم', }, 'bg': { stats: 'Потребителска статистика', works: 'Потребителят работи', }, 'cs': { stats: 'Statistiky uživatelů', works: 'Uživatel pracuje', }, 'da': { stats: 'Brugerstatistik', works: 'Brugeren fungerer', }, 'de': { stats: 'Benutzerstatistiken', works: 'Benutzer funktioniert', }, 'el': { stats: 'Στατιστικά στοιχεία χρηστών', works: 'Ο χρήστης λειτουργεί', }, 'en': { stats: 'User statistics', works: 'User works', }, 'eo': { stats: 'Statistiko de uzantoj', works: 'Uzanto funkcias', }, 'es': { stats: 'Estadísticas de usuario', works: 'El usuario trabaja', }, 'fi': { stats: 'Käyttäjätilastot', works: 'Käyttäjä toimii', }, 'fr': { stats: 'Statistiques d\'utilisateurs', works: 'L\'utilisateur travaille', }, 'he': { stats: 'סטטיסטיקות משתמשים', works: 'משתמש עובד', }, 'hu': { stats: 'Felhasználói statisztikák', works: 'Felhasználó működik', }, 'id': { stats: 'Statistik pengguna', works: 'Pengguna bekerja', }, 'it': { stats: 'Statistiche utente', works: 'L\'utente lavora', }, 'ja': { stats: 'ユーザー統計', works: 'ユーザーは動作します', }, 'ko': { stats: '사용자 통계', works: '사용자 작품', }, 'ne': { stats: 'Gebruikersstatistieken', works: 'Gebruiker werkt', }, 'pl': { stats: 'Statystyki użytkowników', works: 'Użytkownik pracuje', }, 'ro': { stats: 'Statistici utilizatori', works: 'Utilizatorul lucrează', }, 'ru': { stats: 'Статистика пользователей', works: 'Пользовательские работы', }, 'tr': { stats: 'Kullanıcı istatistikleri', works: 'Kullanıcı işleri', }, 'uk': { stats: 'Статистика користувачів', works: 'Користувач працює', }, 'vi': { stats: 'Thống kê người dùng', works: 'Người dùng hoạt động', }, 'zh-CN': { stats: '用户统计', works: '用户作品', }, 'zh-TW': { stats: '用戶統計', works: '用戶作品', }, } let currentTranslation = translations[document.querySelector('#language-selector-locale').value] || translations.en let data = new Proxy({ total: 0, daily: 0, scripts: 0, styles: 0, libraries: 0, stats: 0, works: 0, }, { set(target, prop, value) { let t = target t[prop] = value t.stats = t.total + t.daily t.works = t.scripts + t.styles + t.libraries } }) let stats = document.createElement('div') let isCitrusGF = Boolean(document.querySelector('#script-table')) stats.id = 'user-statistics' addStyle({ '#user-statistics': { position: 'relative', }, '.statistics-bar': { width: 'calc(100% - 2.4vw)', margin: '1em', marginBottom: '1.5em', }, '.statistics-bar div': { height: '3px', borderRadius: '20px', padding: '3px', position: 'relative', }, '.statistics-bar div[style*=" 0%"]': { padding: '0', }, '.statistics-bar div[style*=" 0%"] + span': { color: 'unset !important', }, '#user-statistics-pin-btn': { width: '25px', height: '25px', backgroundColor: 'rgb(191, 191, 191)', display: 'block', position: 'absolute', right: '10px', top: '10px', borderRadius: '50%', cursor: 'pointer', backgroundImage: 'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAACDElEQVR42mNkoDFgJFejk6igUIWGfKrb4QudNLGgWE3Ou0RNbvPlj1+qgZa0U92C+SaaBe7iQn0g9pVPX3FaQpYFDVqKNmmKUtsYGRl5Qfz/QHDp45cajyMX2yi2AGR4upL0NqCZPEALGGEWvPn2g+HE2/fVaZfutZNtAczlQCYPsjjI8Lffv4PZt7/9QLGEaAvQXQ5yNUg/1PD/yL5BtoQoC4CGWwMN3w5k8oIMgFkANJzx3Y8fDDAxmAUg5q2v38uAlvRgtaBdR9nVSpg/XICVRQLozO9i7Kzu+IIFCbzf++Zj5d1vP+9c//Lt1IVP375gtcBBVEB0vonWXg5mJl1k1yFFKCN6sIAMn/f4tevip6/PERXJMEvYmRh1iHH5vMevgIa/OYcugTcO0HzCgByhSHHxDpfhREVynreHXqEo9/nPDx8wIUcovmAh2gI7ByfJ6vrGfc/v3VYTWTX3H8+nDyzEupygBTDDHz17qnb/0YOLV1cujcpi/7OKjRESJy9+/l4Wef52DKEQYCTG8JXz57vcvXXznSk/t2iLhhww4pl0X/z8tTbi3O0Qki3AZThMHmbJw28/D6ZdvpdLkgWEDEe2xFiAR3PGw5eHSLJg3ZbtG99+/OiDz3BSAdwCY1Mz/oyCorvXblzbtWnlyhxqGI5igZyCAg8w/f17fP/+N2oYjDWIaAFobgEA6ol7KD65m7AAAAAASUVORK5CYII=)', backgroundSize: '80% 80%', backgroundRepeat: 'no-repeat', backgroundPosition: '40% 40%', filter: 'grayscale(1)', }, '#user-statistics.stats-pinned': { position: 'fixed', zIndex: '100', right: '10px', top: 'calc(50vh - 175px)', borderRadius: '4px', width: '400px', height: '350px', padding: '4px', border: '1px solid rgb(0, 0 ,0)', }, '#user-statistics.stats-pinned #user-statistics-pin-btn': { /* GPL-3.0 @Saki */ backgroundImage: 'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAABqUlEQVR42u2USUvDUBSF8zIYEzqXlnbR/gYHdCe4VRyg0ILiwuF3OSxEsYWCInUruFMcfkO7KZ2blrRmIJ4XWsnCgVREhDwINDd957vvnJsQ5pcX8QAegIlEIpymaTP9fv/RWff5fAuiKD43m01jYkA8Hud1XT8MhUJZRVFyELseQddQy7fb7SIge9VqVXcNCAaDPMuyR6lUaofneQLAoNPpZC3LYsLhcCEQCEimaVrlcvmMELLbarUMVwBJkuYSicQdOpUgQCBs9Xo9DT+pPVP2ZixAB7VabRkW3ru2CJ2uRqNR2q1MAWPQ+DlEh7BtC91f/iTkFVxFv98vOgEQ15BBrtFoXE0cMl04wQYAeQpw1pHJEPZkALiZGADhTQDOIS59ZBEyGcCeLK6SawBCXkwmk7c0ZIfgK9VHJu+ngU1qvV5fgmVPrgAQ5tHwSTqd3uY4zh5T2i3dM7JsGmPKVCqVU/xv3/WY0hWLxQTDMI4xTRn4nYOI/aLhfh0NXKBWEAThAGP66dv8bcj0JPhUzKqq+uCsy7I8D/GXbrdrfrX/7z92HuD/A94AoxXXGeB8ZfgAAAAASUVORK5CYII=)', }, '#user-statistics.stats-pinned .statistics-bar': { margin: '.5em', }, '.statistics-bar div::before': { content: '""', position: 'absolute', width: 'calc(100% - 2px)', height: '7px', margin: '-5px -5px', borderRadius: '20px', boxShadow: '0 0 4px 0 rgba(0, 0, 0, 0.3), 0 0 4px 0 rgba(0, 0, 0, 0.3) inset', border: '1px solid rgb(34, 34, 34)', padding: '2px', }, }) let pinBtn = document.createElement('div') pinBtn.id = 'user-statistics-pin-btn' pinBtn.addEventListener('click', () => { let styles = window.getComputedStyle(document.body) if(stats.classList.contains('stats-pinned')) { stats.style.cssText = '' } else { stats.style.backgroundColor = styles.backgroundColor stats.style.color = styles.color } stats.classList.toggle('stats-pinned') }) stats.appendChild(pinBtn) document.querySelectorAll('.script-list > li, #script-table tbody tr').forEach(e => { let dataset = e.dataset if(isCitrusGF && Object.keys(dataset).length === 0) { data.daily += +e.querySelector(':nth-child(4)').textContent data.total += +e.querySelector(':nth-child(5)').textContent data.scripts++ } else { data.total += +dataset.scriptTotalInstalls data.daily += +dataset.scriptDailyInstalls if(dataset.scriptType === 'library') { data.libraries++ } else { data[dataset.scriptLanguage === 'js' ? 'scripts' : 'styles']++ } } }) createStat({ title: 'stats', values: [ 'total', 'daily', ] }) createStat({ title: 'works', values: [ 'scripts', 'styles', 'libraries', ] }) function createStat(input) { let { values, title } = input let titleEl = document.createElement('h3') if(data[title] > 0) { titleEl.textContent = currentTranslation[title] stats.appendChild(titleEl) values.forEach(e => { let value = data[e] let total = data[title] let width = value / total * 100 if(width > 0) { createBar(width, e, value) } }) } } function createBar(width, name, value) { let bar = document.createElement('div') let barActual = document.createElement('div') let text = document.createElement('span') let bg = '128, 128, 128' bar.className = 'statistics-bar' switch (name) { case 'total': bg = '255, 28, 28' break case 'daily': bg = '255, 58, 58' break case 'styles': bg = '50, 149, 208' break case 'scripts': bg = '236, 203, 27' break case 'libraries': bg = '221, 102, 15' break } barActual.style.width = width + '%' barActual.style.backgroundColor = 'rgba(' + bg + ', .7)' text.textContent = capitalize(name) + ` (${value.toLocaleString()})` bar.appendChild(text) bar.appendChild(barActual) stats.appendChild(bar) } function addStyle(css) { let keys = Object.keys(css) let cssActual = '' let style = document.createElement('style') keys.forEach(e => { let _keys = Object.keys(css[e]) cssActual += e + '{' _keys.forEach(r => { cssActual += r.replace(/[A-Z]/, m => `-${m.toLowerCase()}`) + ':' + css[e][r] + ';' }) cssActual += '}' }) style.textContent = cssActual document.querySelector('head').appendChild(style) } function capitalize(str) { return str[0].toUpperCase() + str.slice(1) } document.querySelector('#about-user').appendChild(stats) })()