您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Preserve indent on alt+enter
// ==UserScript== // @name Google Docs Preserve Indent // @namespace http://tampermonkey.net/ // @version 1.0 // @description Preserve indent on alt+enter // @match https://docs.google.com/* // @license MIT // @grant none // ==/UserScript== (function() { 'use strict'; // --- utility to simulate mouse events --- function simulateMouseEvent(type, x, y) { const evt = new MouseEvent(type, { bubbles: true, cancelable: true, view: window, clientX: x, clientY: y, button: 0 }); document.elementFromPoint(x, y)?.dispatchEvent(evt); } // --- find the indent-end handle --- function getIndentHandle() { return document.querySelector( '#kix-horizontal-ruler .docs-ruler-inner > div:nth-child(6) .docs-ruler-indent-end' ); } // --- send a plain Enter keypress into the editor iframe --- function sendPlainEnter() { const iframe = document.querySelector('iframe.docs-texteventtarget-iframe'); const win = iframe?.contentWindow || window; const target = iframe?.contentDocument?.body || document.body; const down = new KeyboardEvent('keydown', { key: 'Enter', code: 'Enter', keyCode: 13, which: 13, bubbles: true }); const up = new KeyboardEvent('keyup', { key: 'Enter', code: 'Enter', keyCode: 13, which: 13, bubbles: true }); target.dispatchEvent(down); target.dispatchEvent(up); } // --- main preserve-indent routine --- function preserveIndent() { const handle = getIndentHandle(); if (!handle) return; // capture the old "left" in px const initialLeft = parseFloat(getComputedStyle(handle).left); // insert new line sendPlainEnter(); // after the new line is created, the indent handle moves; // wait a moment then drag it back setTimeout(() => { const h2 = getIndentHandle(); if (!h2) return; // compute how much the handle has shifted const newLeft = parseFloat(getComputedStyle(h2).left); const delta = initialLeft - newLeft; // center of the little handle glyph const rect2 = h2.getBoundingClientRect(); const originX = rect2.left + rect2.width / 2; const originY = rect2.top + rect2.height / 2; const targetX = originX + delta; simulateMouseEvent('mousedown', originX, originY); simulateMouseEvent('mousemove', targetX, originY); simulateMouseEvent('mouseup', targetX, originY); }, 100); } // --- intercept Alt+Enter --- function handleKeydown(e) { if (e.altKey && !e.ctrlKey && !e.shiftKey && e.key === 'Enter') { e.preventDefault(); e.stopImmediatePropagation(); preserveIndent(); } } // --- attach to both top window and the editor iframe --- function attachListeners() { // top‐level (for menus, etc.) window.addEventListener('keydown', handleKeydown, true); // inside the document editing iframe const iframe = document.querySelector('iframe.docs-texteventtarget-iframe'); if (iframe) { const doc = iframe.contentDocument || iframe.contentWindow.document; doc.addEventListener('keydown', handleKeydown, true); } else { // retry if iframe not yet present setTimeout(attachListeners, 500); } } // wait for overall load window.addEventListener('load', attachListeners); })();