Trim automatiquement les espaces au début et à la fin d'une sélection lors d'un double-clic.
// ==UserScript==
// @name MDK Trim
// @namespace MDK Scripts
// @version 2026.05.27
// @description Trim automatiquement les espaces au début et à la fin d'une sélection lors d'un double-clic.
// @author MDK
// @license MIT
// @match *://*/*
// @exclude *://docs.google.com/*
// @exclude *://*.notion.so/*
// @exclude *://*.figma.com/*
// @exclude *://*.canva.com/*
// @exclude *://*.miro.com/*
// @exclude *://*.vscode.dev/*
// @exclude *://github.dev/*
// @exclude *://*.codepen.io/*
// @exclude *://*.stackblitz.com/*
// @exclude *://*.teams.microsoft.com/*
// @exclude *://*.office.com/*
// @icon data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='48' height='48' viewBox='0 0 24 24' fill='none' stroke='%23007bff' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><circle cx='6' cy='6' r='3'/><circle cx='6' cy='18' r='3'/><line x1='8.12' y1='8.12' x2='20' y2='20'/><line x1='20' y1='4' x2='8.12' y2='15.88'/></svg>
// @grant none
// ==/UserScript==
(function() {
'use strict';
const TEXT_INPUT_TYPES = ['text', 'search', 'url', 'tel', 'email', 'password'];
let lastDblClick = 0;
function getTrimOffsets(text) {
const start = text.match(/^\s+/u)?.[0].length || 0;
const end = text.match(/\s+$/u)?.[0].length || 0;
return { start, end };
}
function isTextInput(el) {
return el &&
!el.disabled &&
(el.tagName === 'TEXTAREA' || (el.tagName === 'INPUT' && TEXT_INPUT_TYPES.includes(el.type)));
}
function getDeepActiveElement() {
let el = document.activeElement;
while (el && el.shadowRoot && el.shadowRoot.activeElement) {
el = el.shadowRoot.activeElement;
}
return el;
}
document.addEventListener('dblclick', (event) => {
const now = performance.now();
// Ignore le script si la touche Alt (ou Option sur Mac) est enfoncée
if (now - lastDblClick < 50 || event.altKey) return;
lastDblClick = now;
setTimeout(() => {
const activeEl = getDeepActiveElement();
// 1. INPUT / TEXTAREA
if (isTextInput(activeEl)) {
const start = activeEl.selectionStart;
const end = activeEl.selectionEnd;
if (start === end) return;
const text = activeEl.value.substring(start, end);
if (!text) return;
if (text.trim() === '') {
activeEl.setSelectionRange(start, start);
return;
}
const { start: s, end: e } = getTrimOffsets(text);
if (!s && !e) return;
activeEl.setSelectionRange(start + s, end - e);
return;
}
// 2. TEXTE HTML & CONTENTEDITABLE
const selection = window.getSelection();
if (!selection || selection.rangeCount === 0 || selection.type === 'Caret') return;
const text = selection.toString();
if (!text) return;
const range = selection.getRangeAt(0);
if (text.trim() === '') {
range.collapse(true);
return;
}
const { start: s, end: e } = getTrimOffsets(text);
if (!s && !e) return;
try {
if (range.startContainer.nodeType === Node.TEXT_NODE && (range.startOffset + s) <= range.startContainer.length) {
range.setStart(range.startContainer, range.startOffset + s);
}
if (range.endContainer.nodeType === Node.TEXT_NODE && (range.endOffset - e) >= 0) {
range.setEnd(range.endContainer, range.endOffset - e);
}
selection.removeAllRanges();
selection.addRange(range);
} catch (err) {
// Échec silencieux
}
}, 0);
});
})();