- // ==UserScript==
- // @name GitHub Utils
- // @name:vi Tiện ích GitHub
- // @name:zh-cn GitHub 实用工具
- // @name:zh-tw GitHub 實用工具
- // @name:ru Утилиты GitHub
- // @namespace http://tampermonkey.net/
- // @version 2024.12.30.1
- // @description GitHub utilities including file icons replacement and auto-fill repo name
- // @description:vi Tiện ích GitHub bao gồm thay thế biểu tượng tệp và tự động điền tên repo
- // @description:zh-cn GitHub 实用工具,包括文件图标替换和自动填充仓库名
- // @description:zh-tw GitHub 實用工具,包括文件圖標替換和自動填充倉庫名
- // @description:ru Утилиты GitHub, включая замену иконок файлов и автозаполнение имени репозитория
- // @author Yuusei
- // @match https://github.com/*
- // @icon https://github.githubassets.com/favicon.ico
- // @grant GM_addStyle
- // @require https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js
- // @run-at document-start
- // @license GPL-3.0-only
- // @compatible chrome
- // @compatible firefox
- // @compatible edge
- // @compatible safari
- // ==/UserScript==
- (function ($) {
- 'use strict';
- // Add custom styles
- GM_addStyle(`
- .material-icon {
- width: 20px;
- height: 20px;
- vertical-align: text-bottom;
- margin-right: 4px;
- transition: transform 0.2s ease;
- }
- .material-icon:hover {
- transform: scale(1.2);
- }
- @media (max-width: 768px) {
- .material-icon {
- width: 16px;
- height: 16px;
- margin-right: 2px;
- }
- }
- `);
- const iconMap = {
- // Development
- '.ts': 'typescript',
- '.tsx': 'react_ts',
- '.js': 'javascript',
- '.jsx': 'react',
- '.py': 'python',
- '.java': 'java',
- '.cpp': 'cpp',
- '.c': 'c',
- '.cs': 'csharp',
- '.go': 'go',
- '.rb': 'ruby',
- '.php': 'php',
- '.rs': 'rust',
- '.swift': 'swift',
- '.kt': 'kotlin',
- '.scala': 'scala',
- '.dart': 'dart',
- '.lua': 'lua',
- '.r': 'r',
- '.sh': 'console',
- '.ps1': 'powershell',
- '.bat': 'console',
- '.cmd': 'console',
- '.wasm': 'assembly',
- '.code-workspace': 'vscode',
- '.sln': 'visualstudio',
- // Web
- '.html': 'html',
- '.htm': 'html',
- '.css': 'css',
- '.scss': 'sass',
- '.sass': 'sass',
- '.less': 'less',
- '.styl': 'stylus',
- '.vue': 'vue',
- '.svelte': 'svelte',
- '.angular': 'angular',
- // Data & Config
- '.json': 'json',
- '.yml': 'yaml',
- '.yaml': 'yaml',
- '.xml': 'xml',
- '.toml': 'settings',
- '.ini': 'settings',
- '.env': 'tune',
- '.conf': 'settings',
- '.sql': 'database',
- '.db': 'database',
- '.sqlite': 'database',
- '.graphql': 'graphql',
- '.proto': 'protobuf',
- // Documentation
- '.md': 'markdown',
- '.mdx': 'markdown',
- '.txt': 'document',
- '.pdf': 'pdf',
- '.doc': 'word',
- '.docx': 'word',
- '.odt': 'document',
- '.rtf': 'document',
- // Images
- '.svg': 'svg',
- '.png': 'image',
- '.jpg': 'image',
- '.jpeg': 'image',
- '.gif': 'image',
- '.ico': 'image',
- '.webp': 'image',
- '.bmp': 'image',
- // Media
- '.mp3': 'audio',
- '.wav': 'audio',
- '.ogg': 'audio',
- '.mp4': 'video',
- '.webm': 'video',
- '.avi': 'video',
- '.mov': 'video',
- // Archives
- '.zip': 'zip',
- '.rar': 'zip',
- '.7z': 'zip',
- '.tar': 'zip',
- '.gz': 'zip',
- '.bz2': 'zip',
- // System
- '.exe': 'exe',
- '.dll': 'dll',
- '.so': 'lib',
- '.dylib': 'lib',
- '.sys': 'windows',
- '.reg': 'windows',
- // Design
- '.fig': 'figma',
- '.sketch': 'sketch',
- '.ai': 'illustrator',
- '.psd': 'photoshop',
- '.xd': 'xd',
- // 3D & Game
- '.unity': 'unity',
- '.blend': 'blender',
- '.fbx': '3d',
- '.obj': '3d',
- '.gltf': '3d',
- '.uasset': 'unreal',
- '.upk': 'unreal',
- // Mobile
- '.apk': 'android',
- '.ipa': 'apple',
- '.xcodeproj': 'xcode',
- '.pbxproj': 'xcode',
- // Container & Cloud
- Dockerfile: 'docker',
- '.dockerignore': 'docker',
- '.tf': 'terraform',
- '.tfvars': 'terraform',
- '.vagrant': 'vagrant',
- '.helm': 'kubernetes',
- };
- const specialFiles = {
- // Package managers
- 'package.json': 'nodejs',
- 'package-lock.json': 'nodejs',
- 'yarn.lock': 'yarn',
- 'pnpm-lock.yaml': 'pnpm',
- 'bun.lockb': 'bun',
- 'composer.json': 'composer',
- 'composer.lock': 'composer',
- Gemfile: 'ruby',
- 'Gemfile.lock': 'ruby',
- 'requirements.txt': 'python',
- 'poetry.lock': 'python',
- 'Cargo.toml': 'rust',
- 'Cargo.lock': 'rust',
- // Config files
- 'tsconfig.json': 'typescript',
- '.eslintrc': 'eslint',
- '.prettierrc': 'prettier',
- '.editorconfig': 'editorconfig',
- 'webpack.config.js': 'webpack',
- 'vite.config.js': 'vite',
- 'rollup.config.js': 'rollup',
- 'babel.config.js': 'babel',
- 'jest.config.js': 'jest',
- 'karma.conf.js': 'karma',
- 'cypress.config.js': 'cypress',
- 'playwright.config.js': 'playwright',
- // Documentation
- 'README.md': 'markdown',
- LICENSE: 'certificate',
- 'CHANGELOG.md': 'markdown',
- 'CONTRIBUTING.md': 'markdown',
- // Git
- '.gitignore': 'git',
- '.gitattributes': 'git',
- '.gitmodules': 'git',
- '.gitmessage': 'git',
- '.gitkeep': 'git',
- // CI/CD
- '.travis.yml': 'travis',
- '.gitlab-ci.yml': 'gitlab',
- Jenkinsfile: 'jenkins',
- 'azure-pipelines.yml': 'azure',
- 'bitbucket-pipelines.yml': 'bitbucket',
- // Docker
- Dockerfile: 'docker',
- 'docker-compose.yml': 'docker',
- 'docker-compose.yaml': 'docker',
- 'docker-compose.override.yml': 'docker',
- // Framework configs
- 'angular.json': 'angular',
- 'next.config.js': 'next',
- 'nuxt.config.js': 'nuxt',
- 'svelte.config.js': 'svelte',
- 'capacitor.config.json': 'capacitor',
- 'ionic.config.json': 'ionic',
- // Build tools
- Makefile: 'makefile',
- 'CMakeLists.txt': 'cmake',
- 'build.gradle': 'gradle',
- 'pom.xml': 'maven',
- 'build.sbt': 'sbt',
- // Environment
- '.env': 'tune',
- '.env.local': 'tune',
- '.env.development': 'tune',
- '.env.production': 'tune',
- '.env.test': 'tune',
- // Version managers
- '.nvmrc': 'nodejs',
- '.node-version': 'nodejs',
- '.ruby-version': 'ruby',
- '.python-version': 'python',
- '.java-version': 'java',
- };
- function replaceIcons() {
- $('.react-directory-row-name-cell-large-screen, .react-directory-row-name-cell-small-screen').each(function () {
- const $filenameElement = $(this).find('.react-directory-filename-cell');
- if ($filenameElement.length) {
- const filename = $filenameElement.text();
- let iconName = specialFiles[filename];
- if (!iconName) {
- const extension = Object.keys(iconMap).find(ext => filename.toLowerCase().endsWith(ext));
- iconName = extension ? iconMap[extension] : null;
- }
- if (iconName) {
- const $oldSvg = $(this).find('svg');
- if ($oldSvg.length) {
- const $newIcon = $('<img>', {
- src: `https://raw.githubusercontent.com/material-extensions/vscode-material-icon-theme/refs/heads/main/icons/${iconName}.svg`,
- class: 'material-icon',
- alt: iconName,
- });
- $oldSvg.replaceWith($newIcon);
- }
- }
- }
- });
- }
- // Auto fill repo name functionality
- function setupAutoFill() {
- const observer = new MutationObserver(mutations => {
- mutations.forEach(mutation => {
- if (mutation.addedNodes.length) {
- const dialog = document.querySelector('#repo-delete-menu-dialog');
- if (dialog) {
- const repoName = document.querySelector('.text-bold.f3.mt-2')?.textContent.trim();
- if (repoName) {
- const input = document.querySelector('#verification_field');
- if (input) {
- input.value = repoName;
- input.dispatchEvent(
- new Event('input', {
- bubbles: true,
- cancelable: true,
- })
- );
- }
-
- const deleteBtn = document.querySelector('#repo-delete-proceed-button');
- if (deleteBtn) {
- deleteBtn.disabled = false;
- }
- }
- }
- }
- });
- });
-
- observer.observe(document.body, {
- childList: true,
- subtree: true,
- });
- }
- // Initial setup
- $(document).ready(() => {
- replaceIcons();
- setupAutoFill();
- });
- // Watch for DOM changes for icon replacement
- const iconObserver = new MutationObserver(replaceIcons);
- iconObserver.observe(document.body, {
- childList: true,
- subtree: true,
- });
- })(jQuery);