您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Displays total number of scripts, installs, and version numbers for users on Greasyfork/Sleazyfork.
当前为
- // ==UserScript==
- // @name Greasyfork/Sleazyfork Stats Display
- // @description Displays total number of scripts, installs, and version numbers for users on Greasyfork/Sleazyfork.
- // @icon https://greasyfork.org/vite/assets/blacklogo96-CxYTSM_T.png
- // @version 1.2
- // @author afkarxyz
- // @namespace https://github.com/afkarxyz/misc-scripts/
- // @supportURL https://github.com/afkarxyz/misc-scripts/issues
- // @license MIT
- // @match https://greasyfork.org/*/users/*
- // @match https://greasyfork.org/users/*
- // @match https://sleazyfork.org/*/users/*
- // @match https://sleazyfork.org/users/*
- // @match https://greasyfork.org/*/scripts*
- // @match https://greasyfork.org/scripts*
- // @match https://sleazyfork.org/*/scripts*
- // @match https://sleazyfork.org/scripts*
- // @grant none
- // ==/UserScript==
- (function() {
- 'use strict';
- const style = document.createElement('style');
- style.textContent = `
- .badge {
- border: 1px solid transparent;
- display: inline-block;
- font-size: 0.65em;
- font-weight: 600;
- line-height: 1;
- padding: 0.15em 0.3em;
- text-align: center;
- vertical-align: baseline;
- white-space: nowrap;
- margin-right: 0.5em;
- }
- .badge-js {
- background-color: #efd81d;
- color: #000;
- }
- .badge-css {
- background-color: #254bdd;
- color: #fff;
- }
- .script-version {
- color: #000;
- }
- `;
- document.head.appendChild(style);
- function hasBadge(h2Element) {
- return h2Element.querySelector('.badge') !== null;
- }
- function isCssScript(h2Element) {
- const parentLi = h2Element.closest('li[data-script-language]');
- if (parentLi && parentLi.getAttribute('data-script-language') === 'css') {
- return true;
- }
- return h2Element.querySelector('.badge-css') !== null;
- }
- function createBadge(type) {
- const badge = document.createElement('span');
- badge.className = `badge badge-${type}`;
- badge.title = type === 'js' ? 'User script' : 'CSS script';
- badge.textContent = type.toUpperCase();
- return badge;
- }
- function createVersionSpan(version) {
- const versionSpan = document.createElement('span');
- versionSpan.textContent = `v${version}`;
- versionSpan.classList.add('script-version');
- return versionSpan;
- }
- function addBadgeAndVersion(h2Element, version) {
- if (!h2Element) return;
- const scriptLink = h2Element.querySelector('.script-link');
- if (!scriptLink) return;
- const existingVersion = h2Element.querySelector('.script-version');
- const existingBadge = h2Element.querySelector('.badge');
- if (existingVersion) existingVersion.remove();
- if (existingBadge) existingBadge.remove();
- const badgeType = isCssScript(h2Element) ? 'css' : 'js';
- const badge = createBadge(badgeType);
- scriptLink.insertAdjacentElement('afterend', badge);
- if (version) {
- const versionSpan = createVersionSpan(version);
- badge.insertAdjacentElement('afterend', versionSpan);
- }
- }
- function appendVersionNumbers() {
- const listItems = document.querySelectorAll('li[data-script-id]');
- if (!listItems || listItems.length === 0) return;
- listItems.forEach(listItem => {
- const version = listItem.getAttribute('data-script-version');
- if (!version) return;
- const h2 = listItem.querySelector('h2');
- if (h2) {
- addBadgeAndVersion(h2, version);
- }
- });
- }
- function displayVersionNumbers() {
- const headings = document.querySelectorAll('h2 a.script-link');
- headings.forEach(heading => {
- const version = heading.closest('li').getAttribute('data-script-version');
- if (version) {
- addBadgeAndVersion(heading.parentElement, version);
- }
- });
- }
- function displayUserStats() {
- const parseInstallCount = text => parseInt(text.replace(/,/g, '')) || 0;
- const scripts = [...document.querySelectorAll('.script-list-total-installs span')]
- .filter(element => !element.textContent.includes('Total installs'));
- if (scripts.length === 0) return;
- const totalInstalls = scripts.reduce((sum, element) =>
- sum + parseInstallCount(element.textContent), 0);
- const statsData = {
- scriptsCount: scripts.length,
- totalInstalls: totalInstalls
- };
- if (document.getElementById('user-stats')) return;
- const statsElement = document.createElement('section');
- statsElement.id = 'user-stats';
- const userDiscussionsElement = document.getElementById('user-discussions');
- if (!userDiscussionsElement) return;
- const stylesToCopy = [
- 'padding',
- 'border',
- 'borderRadius',
- 'backgroundColor',
- 'color',
- 'fontSize',
- 'fontFamily',
- 'lineHeight'
- ];
- const computedStyle = window.getComputedStyle(userDiscussionsElement);
- stylesToCopy.forEach(property => {
- statsElement.style[property] = computedStyle.getPropertyValue(property);
- });
- const header = document.createElement('header');
- const headerStyle = window.getComputedStyle(userDiscussionsElement.querySelector('header'));
- header.style.padding = headerStyle.padding;
- header.style.borderBottom = headerStyle.borderBottom;
- const h3 = document.createElement('h3');
- h3.textContent = 'Stats';
- const originalH3Style = window.getComputedStyle(userDiscussionsElement.querySelector('h3'));
- h3.style.margin = originalH3Style.margin;
- h3.style.fontSize = originalH3Style.fontSize;
- header.appendChild(h3);
- const contentSection = document.createElement('section');
- contentSection.className = 'text-content';
- const originalContentStyle = window.getComputedStyle(userDiscussionsElement.querySelector('.text-content'));
- contentSection.style.padding = originalContentStyle.padding;
- const p = document.createElement('p');
- p.innerHTML = `This user has <strong>${statsData.scriptsCount}</strong> script${statsData.scriptsCount !== 1 ? 's' : ''} with <strong>${statsData.totalInstalls.toLocaleString()}</strong> total install${statsData.totalInstalls !== 1 ? 's' : ''}.`;
- contentSection.appendChild(p);
- statsElement.appendChild(header);
- statsElement.appendChild(contentSection);
- userDiscussionsElement.parentNode.insertBefore(statsElement, userDiscussionsElement.nextSibling);
- }
- function init() {
- const currentPath = window.location.pathname;
- if (currentPath.includes('/scripts')) {
- appendVersionNumbers();
- } else if (currentPath.includes('/users/')) {
- displayUserStats();
- displayVersionNumbers();
- }
- }
- window.addEventListener('load', init);
- let lastUrl = location.href;
- const observer = new MutationObserver((mutations) => {
- const url = location.href;
- if (url !== lastUrl) {
- lastUrl = url;
- }
- const hasRelevantChanges = mutations.some(mutation =>
- [...mutation.addedNodes].some(node =>
- node.nodeType === 1 &&
- (node.matches?.('li[data-script-id]') ||
- node.querySelector?.('li[data-script-id]') ||
- node.matches?.('h2') ||
- node.querySelector?.('h2'))
- )
- );
- if (hasRelevantChanges) {
- init();
- }
- });
- function startObserver() {
- const observeTarget = document.querySelector('#browse-script-list, .script-list');
- if (observeTarget) {
- observer.observe(observeTarget, {
- childList: true,
- subtree: true
- });
- } else {
- requestAnimationFrame(startObserver);
- }
- }
- startObserver();
- init();
- })();