您需要先安装一个扩展,例如 篡改猴、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.3
- // @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';
- console.log('Script initialized'); // 调试日志
- // Default configuration
- const DEFAULT_CONFIG = {
- columns: 2,
- 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');
- console.log('Loaded config:', savedConfig); // 调试日志
- return savedConfig ? {...DEFAULT_CONFIG, ...JSON.parse(savedConfig)} : DEFAULT_CONFIG;
- }
- function saveConfig(config) {
- localStorage.setItem('printLayoutConfig', JSON.stringify(config));
- CONFIG = config;
- console.log('Saved config:', config); // 调试日志
- updateStyles();
- }
- let configModal = null; // 将configModal提升为全局变量
- // Create and inject the configuration UI
- function createConfigUI() {
- console.log('Creating config UI'); // 调试日志
- // 如果已经存在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);
- console.log('Config UI created and appended to body'); // 调试日志
- // Save button handler
- const saveButton = configModal.querySelector('.save-button');
- if (saveButton) {
- saveButton.addEventListener('click', () => {
- console.log('Save button clicked'); // 调试日志
- 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', () => {
- console.log('Close button clicked'); // 调试日志
- 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() {
- console.log('Hiding config modal'); // 调试日志
- if (configModal) {
- configModal.style.setProperty('display', 'none', 'important');
- }
- }
- function toggleConfigModal() {
- console.log('Toggling config modal'); // 调试日志
- if (!configModal || configModal.style.display === 'none') {
- showConfigModal();
- } else {
- hideConfigModal();
- }
- }
- // Create and update styles based on current config
- function updateStyles() {
- console.log('Updating styles'); // 调试日志
- 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() {
- console.log('Applying print columns'); // 调试日志
- 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() {
- console.log('DOM Content Loaded'); // 调试日志
- applyPrintColumns();
- }
- if (document.readyState === 'loading') {
- document.addEventListener('DOMContentLoaded', onDOMContentLoaded);
- } else {
- onDOMContentLoaded();
- }
- // Add a global function for testing
- window.togglePrintLayoutConfig = toggleConfigModal;
- // Log usage instructions to console
- console.log(`
- Multi-Column Layout Userscript Usage:
- -----------------------------------
- 1. Press Ctrl+S (or Cmd+S on Mac) to open settings
- 2. Adjust your preferences:
- - Columns: Number of columns (1-4)
- - Column Gap: Space between columns
- - Font Size: Text size in print
- - Paragraph Spacing: Space between paragraphs
- - Line Height: Text line height
- - Enable Page Break: Allow/prevent content breaks across pages
- 3. Click Save Changes to apply settings
- 4. Settings are automatically saved between sessions
- 5. Press Ctrl+P to see the print preview with your settings
- For testing, you can also use: window.togglePrintLayoutConfig()
- Current configuration:`, CONFIG);
- })();