您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Sorts Google Lens "Exact matches" results with a dropdown.
// ==UserScript== // @name Google Lens Exact Match Sorter // @namespace https://minoa.cat // @version 3.0 // @description Sorts Google Lens "Exact matches" results with a dropdown. // @author minoa.cat // @match https://www.google.com/search*udm=48* // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; // --- CORE SORTING LOGIC (Unchanged) --- function parseRelativeDate(dateString) { if (!dateString) return Infinity; const now = new Date(); const parts = dateString.toLowerCase().split(' '); const value = parseInt(parts[0]); if (isNaN(value)) return Infinity; if (parts.some(p => p.startsWith('day'))) return value; if (parts.some(p => p.startsWith('week'))) return value * 7; if (parts.some(p => p.startsWith('month'))) return value * 30.44; if (parts.some(p => p.startsWith('year'))) return value * 365.25; return Infinity; } function parseSize(sizeString) { if (!sizeString) return -1; const parts = sizeString.toLowerCase().split('x'); if (parts.length !== 2) return -1; const width = parseInt(parts[0]); const height = parseInt(parts[1]); if (isNaN(width) || isNaN(height)) return -1; return width * height; } function getResultData(resultElement) { let dateText = null; let sizeText = null; const infoContainer = resultElement.querySelector('.oYQBg.Zn52Me'); if (infoContainer) { const infoSpans = infoContainer.querySelectorAll(':scope > span'); infoSpans.forEach(span => { const text = span.innerText; if (text.includes('x') && !text.includes('ago')) { sizeText = text; } else if (text.match(/ago|year|month|week|day/i)) { dateText = text; } }); } return { date: dateText, size: sizeText }; } function sortResults(sortBy) { const resultsContainer = document.querySelector('#rso'); if (!resultsContainer) return; const results = Array.from(resultsContainer.querySelectorAll('.ULSxyf')); if (!results[0].hasAttribute('data-original-order')) { results.forEach((result, index) => { result.setAttribute('data-original-order', index); }); } results.sort((a, b) => { const dataA = getResultData(a); const dataB = getResultData(b); const dateA = parseRelativeDate(dataA.date); const dateB = parseRelativeDate(dataB.date); const sizeA = parseSize(dataA.size); const sizeB = parseSize(dataB.size); switch (sortBy) { case 'normal': return parseInt(a.getAttribute('data-original-order')) - parseInt(b.getAttribute('data-original-order')); case 'date-newest': return dateA - dateB; case 'date-oldest': return dateB - dateA; case 'size-largest': return sizeB - sizeA; case 'size-smallest': return sizeA - sizeB; case 'newest-largest': return (dateA - dateB) || (sizeB - sizeA); case 'newest-smallest': return (dateA - dateB) || (sizeA - sizeB); case 'oldest-largest': return (dateB - dateA) || (sizeB - sizeA); case 'oldest-smallest': return (dateB - dateA) || (sizeA - sizeB); default: return 0; } }); results.forEach(result => resultsContainer.appendChild(result)); } // --- UI CREATION & STYLING (Completely Revamped) --- function createStyledDropdown() { if (document.getElementById('lensSorterContainer')) return; // Prevents creating duplicates const mainHeader = document.querySelector('[data-st-tgt="fb"]'); if (!mainHeader) return; // Create a container bar for our dropdown const sortBarContainer = document.createElement('div'); sortBarContainer.id = 'lensSorterContainer'; Object.assign(sortBarContainer.style, { padding: '8px 16px', // Standard Google padding borderTop: '1px solid #3c4043', // Separator line borderBottom: '1px solid #3c4043' }); const select = document.createElement('select'); Object.assign(select.style, { backgroundColor: '#303134', // Dark theme background color: '#e8eaed', // Light theme text border: '1px solid #5f6368', // Subtle border borderRadius: '4px', padding: '6px 10px', fontFamily: 'inherit', fontSize: '14px', cursor: 'pointer' }); const options = { 'normal': 'Sort by: Default', 'date-newest': 'Date (Newest First)', 'date-oldest': 'Date (Oldest First)', 'size-largest': 'Size (Largest First)', 'size-smallest': 'Size (Smallest First)', 'newest-largest': 'Newest & Largest', 'newest-smallest': 'Newest & Smallest', 'oldest-largest': 'Oldest & Largest', 'oldest-smallest': 'Oldest & Smallest' }; for (const [value, text] of Object.entries(options)) { const option = document.createElement('option'); option.value = value; option.textContent = text; select.appendChild(option); } select.addEventListener('change', (event) => { sortResults(event.target.value); }); sortBarContainer.appendChild(select); // Inject the entire bar after the main header mainHeader.appendChild(sortBarContainer); } // --- SCRIPT INITIALIZATION --- const observer = new MutationObserver((mutationsList, observer) => { if (document.querySelector('#rso') && document.querySelector('[data-st-tgt="fb"]')) { createStyledDropdown(); // We keep observing in case of page navigation that redraws the DOM } }); observer.observe(document.body, { childList: true, subtree: true }); })();