您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Automatically pastes clipboard content into specific input fields on right-click. Clipboard access requires HTTPS and user permission. Right-clicking on target fields will auto-paste clipboard content. (Note: Clipboard API support may vary by browser.)
// ==UserScript== // @name Garmin Connect - Auto-Paste on Right Click // @namespace typpi.online // @version 1.7 // @description Automatically pastes clipboard content into specific input fields on right-click. Clipboard access requires HTTPS and user permission. Right-clicking on target fields will auto-paste clipboard content. (Note: Clipboard API support may vary by browser.) // @author Nick2bad4u // @match *://connect.garmin.com/* // @license UnLicense // @tag garmin // @icon https://www.google.com/s2/favicons?sz=64&domain=connect.garmin.com // @grant none // @run-at document-end // @homepageURL https://github.com/Nick2bad4u/UserStyles // @supportURL https://github.com/Nick2bad4u/UserStyles/issues // ==/UserScript== (function () { 'use strict'; // === Configurable Section === const FIELD_CONFIG = [ { selector: 'input[name="elev-gain"]', name: 'elev-gain', sanitize: (text) => text.replace(/[^\d.-]/g, ''), }, { selector: 'input[name="elev-loss"]', name: 'elev-loss', sanitize: (text) => text.replace(/[^\d.-]/g, ''), }, { selector: 'input[name="youtubeUrl"]', name: 'youtubeUrl', // Allow more URL-safe characters sanitize: (text) => text.replace(/[^\w\-.:/?=&%#~@!$*'(),]/g, ''), }, { selector: 'textarea#activity-description', name: 'activity-description', // Allow most printable characters, but sanitize HTML special chars sanitize: (text) => text.replace(/[<>&"'`]/g, (char) => escapeMap[char] || char), }, ]; const TARGET_INPUT_SELECTOR = FIELD_CONFIG.map((f) => f.selector).join(', '); // Define escapeMap outside the event handler for efficiency const escapeMap = { '<': '<', '>': '>', '&': '&', '"': '"', "'": ''', '`': '`', }; // Add a tooltip to target fields to inform users about right-click auto-paste function addAutoPasteTooltip() { document.querySelectorAll(TARGET_INPUT_SELECTOR).forEach((input) => { if (!input.hasAttribute('data-autopaste-tooltip')) { input.setAttribute('title', 'Right-click to auto-paste clipboard content. Clipboard access required.'); input.setAttribute('aria-label', 'Right-click to auto-paste clipboard content. Clipboard access required.'); input.setAttribute('data-autopaste-tooltip', '1'); } }); } // Debounce function for performance function debounce(fn, delay) { let timer; return function (...args) { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, args), delay); }; } // Initial tooltip set and observe for dynamically added fields addAutoPasteTooltip(); const observer = new MutationObserver(debounce(addAutoPasteTooltip, 200)); observer.observe(document.body, { childList: true, subtree: true }); document.body.addEventListener('contextmenu', async function (event) { const target = event.target; // Type safety: ensure target is an input or textarea element if (!(target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement)) return; // Check if right-clicked element is one of the target input fields const field = FIELD_CONFIG.find((f) => target.matches(f.selector)); if (field) { event.preventDefault(); // Prevent default right-click menu if (navigator.clipboard && navigator.clipboard.readText) { try { // Use clipboard API to read the text and paste it const clipboardText = await navigator.clipboard.readText(); // Sanitize clipboard content to prevent injection of malicious content let sanitizedText = clipboardText.replace(/[<>&"'`]/g, (char) => escapeMap[char] || char); // Use field-specific sanitizer if available if (field.sanitize) sanitizedText = field.sanitize(sanitizedText); target.value = sanitizedText; // Paste sanitized clipboard content into the field } catch (err) { console.error( `Clipboard read error on input field "${target.name}" at URL "${window.location.href}" using browser "${navigator.userAgent}":`, err ); alert( 'Failed to access clipboard. Clipboard access may require HTTPS and browser permission. Please check your browser settings or use Ctrl+V manually.' ); } } else { alert('Clipboard API is not supported in this browser or context. Please use Ctrl+V to paste manually.'); } } }); })();