您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Convert single column layout to multi-column layout only when printing. Press Ctrl+S to open settings.
// ==UserScript== // @name Multi-Column Layout for printing (Print Only) // @namespace http://tampermonkey.net/ // @license MIT // @version 2.5 // @description Convert single column layout to multi-column layout only when printing. Press Ctrl+S to open settings. // @author KQ yang // @match *://*/* // @match file:///* // @match http://127.0.0.1:*/* // @match http://localhost:*/* // @grant GM_addStyle // @run-at document-start // @noframes // ==/UserScript== (function() { 'use strict'; // Add colorful title and usage instructions right after initialization console.log('%c Multi-Column Layout for Printing v2.3 ', 'background: #4A90E2; color: white; font-size: 14px; font-weight: bold; padding: 8px; border-radius: 4px; text-shadow: 1px 1px 1px rgba(0,0,0,0.2);'); console.log('%c 📖 Usage: Press Ctrl+S to open settings, customize your layout, then Ctrl+P to print! ', 'background: #2ECC71; color: white; font-size: 12px; padding: 6px; border-radius: 4px;'); // Default configuration const DEFAULT_CONFIG = { columns: 1, columnGap: '30px', fontSize: '16px', paragraphSpacing: '1em', enablePageBreak: true, lineHeight: '1.5', }; // Load config from localStorage or use defaults let CONFIG = loadConfig(); function loadConfig() { const savedConfig = localStorage.getItem('printLayoutConfig'); return savedConfig ? {...DEFAULT_CONFIG, ...JSON.parse(savedConfig)} : DEFAULT_CONFIG; } function saveConfig(config) { localStorage.setItem('printLayoutConfig', JSON.stringify(config)); CONFIG = config; updateStyles(); } let configModal = null; // 将configModal提升为全局变量 // Create and inject the configuration UI function createConfigUI() { // 如果已经存在modal,先移除 if (configModal) { configModal.remove(); } configModal = document.createElement('div'); configModal.id = 'print-layout-config-modal'; configModal.setAttribute('style', ` all: initial; position: fixed !important; top: 50% !important; left: 50% !important; transform: translate(-50%, -50%) !important; background: white !important; padding: 30px !important; border-radius: 12px !important; box-shadow: 0 8px 24px rgba(0,0,0,0.15) !important; z-index: 2147483647 !important; display: none !important; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif !important; min-width: 320px !important; max-width: 90vw !important; animation: modalFadeIn 0.3s ease-out !important; color: black !important; `); const styleElement = document.createElement('style'); styleElement.textContent = ` @keyframes modalFadeIn { from { opacity: 0; transform: translate(-50%, -48%); } to { opacity: 1; transform: translate(-50%, -50%); } } .settings-row { margin-bottom: 20px; display: flex; align-items: center; justify-content: space-between; } .settings-row label { color: #333; font-size: 14px; margin-right: 15px; } .settings-row input[type="number"], .settings-row input[type="text"] { width: 100px; padding: 8px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px; transition: border-color 0.2s; } .settings-row input:focus { outline: none; border-color: #4A90E2; box-shadow: 0 0 0 2px rgba(74,144,226,0.2); } .settings-row input[type="checkbox"] { width: 18px; height: 18px; cursor: pointer; } .modal-title { color: #333; margin: 0 0 25px 0; font-size: 18px; font-weight: 600; border-bottom: 2px solid #eee; padding-bottom: 15px; } .modal-footer { margin-top: 25px; padding-top: 20px; border-top: 2px solid #eee; text-align: right; } .save-button { background: #4A90E2; color: white; border: none; padding: 10px 20px; border-radius: 6px; font-size: 14px; cursor: pointer; transition: background-color 0.2s; } .save-button:hover { background: #357ABD; } .close-button { position: absolute; top: 15px; right: 15px; background: none; border: none; font-size: 20px; cursor: pointer; color: #666; padding: 5px; line-height: 1; } .close-button:hover { color: #333; } #print-layout-config-modal { visibility: visible !important; display: block !important; } `; document.head.appendChild(styleElement); configModal.innerHTML = ''; // 清空现有内容 const modalContent = document.createElement('div'); modalContent.style.cssText = ` all: initial; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important; color: black !important; `; modalContent.innerHTML = ` <h3 class="modal-title">Print Layout Settings</h3> <button class="close-button" title="Close">×</button> <div class="settings-row"> <label>Columns (1-4):</label> <input type="number" id="columns" min="1" max="4" value="${CONFIG.columns}"> </div> <div class="settings-row"> <label>Column Gap:</label> <input type="text" id="columnGap" value="${CONFIG.columnGap}"> </div> <div class="settings-row"> <label>Font Size:</label> <input type="text" id="fontSize" value="${CONFIG.fontSize}"> </div> <div class="settings-row"> <label>Paragraph Spacing:</label> <input type="text" id="paragraphSpacing" value="${CONFIG.paragraphSpacing}"> </div> <div class="settings-row"> <label>Line Height:</label> <input type="text" id="lineHeight" value="${CONFIG.lineHeight}"> </div> <div class="settings-row"> <label>Enable Page Break:</label> <input type="checkbox" id="enablePageBreak" ${CONFIG.enablePageBreak ? 'checked' : ''}> </div> <div class="modal-footer"> <button class="save-button">Save Changes</button> </div> `; configModal.appendChild(modalContent); document.documentElement.appendChild(configModal); // Save button handler const saveButton = configModal.querySelector('.save-button'); if (saveButton) { saveButton.addEventListener('click', () => { const newConfig = { columns: parseInt(configModal.querySelector('#columns').value, 10), columnGap: configModal.querySelector('#columnGap').value, fontSize: configModal.querySelector('#fontSize').value, paragraphSpacing: configModal.querySelector('#paragraphSpacing').value, lineHeight: configModal.querySelector('#lineHeight').value, enablePageBreak: configModal.querySelector('#enablePageBreak').checked }; saveConfig(newConfig); configModal.style.setProperty('display', 'none', 'important'); }); } // Close button handler const closeButton = configModal.querySelector('.close-button'); if (closeButton) { closeButton.addEventListener('click', () => { configModal.style.setProperty('display', 'none', 'important'); }); } // Click outside to close configModal.addEventListener('click', (e) => { if (e.target === configModal) { configModal.style.setProperty('display', 'none', 'important'); } }); return configModal; } function showConfigModal() { console.log('Showing config modal'); // 调试日志 if (!configModal) { configModal = createConfigUI(); } configModal.style.setProperty('display', 'block', 'important'); configModal.style.setProperty('visibility', 'visible', 'important'); } function hideConfigModal() { if (configModal) { configModal.style.setProperty('display', 'none', 'important'); } } function toggleConfigModal() { if (!configModal || configModal.style.display === 'none') { showConfigModal(); } else { hideConfigModal(); } } // Create and update styles based on current config function updateStyles() { const styleSheet = ` @media print { html, body { margin: 0 !important; padding: 0 !important; min-height: 0 !important; height: auto !important; } .print-column-container { column-count: ${CONFIG.columns} !important; column-gap: ${CONFIG.columnGap} !important; column-rule: 1px solid #ddd !important; width: 100% !important; margin: 0 !important; padding: 0 !important; min-height: 0 !important; height: auto !important; overflow: visible !important; box-sizing: border-box !important; font-size: ${CONFIG.fontSize} !important; line-height: ${CONFIG.lineHeight} !important; ${CONFIG.enablePageBreak ? '' : 'page-break-inside: avoid !important;'} } .print-column-container > * { break-inside: avoid !important; margin-bottom: ${CONFIG.paragraphSpacing} !important; max-width: 100% !important; box-sizing: border-box !important; page-break-inside: avoid !important; } .print-column-container img { max-width: 100% !important; height: auto !important; page-break-inside: avoid !important; } } `; const existingStyle = document.getElementById('print-layout-style'); if (existingStyle) { existingStyle.remove(); } const style = document.createElement('style'); style.id = 'print-layout-style'; style.textContent = styleSheet; document.head.appendChild(style); } // Apply columns to main content function applyPrintColumns() { const mainContent = document.querySelector('.target-content') || document.body; mainContent.classList.add('print-column-container'); const printStyle = document.createElement('style'); printStyle.media = 'print'; printStyle.textContent = ` @page { margin: 1cm !important; padding: 0 !important; size: auto !important; } `; document.head.appendChild(printStyle); } // Initialize modal globally configModal = createConfigUI(); // Handle Ctrl+S shortcut with improved event handling document.addEventListener('keydown', function(e) { if (e.ctrlKey && (e.key === 's' || e.key === 'S' || e.keyCode === 83)) { console.log('Ctrl+S detected'); // 调试日志 e.stopPropagation(); e.preventDefault(); toggleConfigModal(); return false; } }, true); // Initial style application updateStyles(); // Handle DOMContentLoaded function onDOMContentLoaded() { applyPrintColumns(); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', onDOMContentLoaded); } else { onDOMContentLoaded(); } // Add a global function for testing window.togglePrintLayoutConfig = toggleConfigModal; })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址