Multi-Column Layout for printing (Print Only)

Convert single column layout to multi-column layout only when printing. Double-press Ctrl key to open settings.

目前為 2024-11-05 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Multi-Column Layout for printing (Print Only)
// @namespace    http://tampermonkey.net/
// @license MIT
// @version      2.1
// @description  Convert single column layout to multi-column layout only when printing. Double-press Ctrl key to open settings.
// @author       KQ yang
// @match        *://*
// @match        file:///*
// @match        http://127.0.0.1:*/*
// @match        http://localhost:*/*
// @grant        GM_addStyle
// @run-at       document-end
// ==/UserScript==

(function() {
    'use strict';

    // 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');
        return savedConfig ? {...DEFAULT_CONFIG, ...JSON.parse(savedConfig)} : DEFAULT_CONFIG;
    }

    function saveConfig(config) {
        localStorage.setItem('printLayoutConfig', JSON.stringify(config));
        CONFIG = config;
        updateStyles();
    }

    // Create and inject the configuration UI
    function createConfigUI() {
        const modal = document.createElement('div');
        modal.style.cssText = `
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0,0,0,0.3);
            z-index: 9999;
            display: none;
        `;

        modal.innerHTML = `
            <h3 style="margin-top: 0;">Print Layout Settings</h3>
            <div style="margin-bottom: 10px;">
                <label>Columns (1-4): </label>
                <input type="number" id="columns" min="1" max="4" value="${CONFIG.columns}">
            </div>
            <div style="margin-bottom: 10px;">
                <label>Column Gap: </label>
                <input type="text" id="columnGap" value="${CONFIG.columnGap}">
            </div>
            <div style="margin-bottom: 10px;">
                <label>Font Size: </label>
                <input type="text" id="fontSize" value="${CONFIG.fontSize}">
            </div>
            <div style="margin-bottom: 10px;">
                <label>Paragraph Spacing: </label>
                <input type="text" id="paragraphSpacing" value="${CONFIG.paragraphSpacing}">
            </div>
            <div style="margin-bottom: 10px;">
                <label>Line Height: </label>
                <input type="text" id="lineHeight" value="${CONFIG.lineHeight}">
            </div>
            <div style="margin-bottom: 10px;">
                <label>Enable Page Break: </label>
                <input type="checkbox" id="enablePageBreak" ${CONFIG.enablePageBreak ? 'checked' : ''}>
            </div>
            <div style="text-align: right; margin-top: 20px;">
                <button id="saveConfig" style="padding: 5px 10px;">Save</button>
            </div>
        `;

        document.body.appendChild(modal);

        // Save button handler
        document.getElementById('saveConfig').addEventListener('click', () => {
            const newConfig = {
                columns: parseInt(document.getElementById('columns').value, 10),
                columnGap: document.getElementById('columnGap').value,
                fontSize: document.getElementById('fontSize').value,
                paragraphSpacing: document.getElementById('paragraphSpacing').value,
                lineHeight: document.getElementById('lineHeight').value,
                enablePageBreak: document.getElementById('enablePageBreak').checked
            };
            saveConfig(newConfig);
            modal.style.display = 'none';
        });

        return modal;
    }

    // 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;
                }
            }
        `;

        // Remove existing style if any
        const existingStyle = document.getElementById('print-layout-style');
        if (existingStyle) {
            existingStyle.remove();
        }

        // Add new style
        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
    let lastCtrlPress = 0;
    const configModal = createConfigUI();

    // Handle double Ctrl press
    document.addEventListener('keydown', (e) => {
        if (e.key === 'Control') {
            const now = Date.now();
            if (now - lastCtrlPress < 300) {  // 300ms threshold for double press
                configModal.style.display = configModal.style.display === 'none' ? 'block' : 'none';
            }
            lastCtrlPress = now;
        }
    });

    // Initial style application
    updateStyles();

    // Apply columns when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', applyPrintColumns);
    } else {
        applyPrintColumns();
    }

    // Log usage instructions to console
    console.log(`
    Multi-Column Layout Userscript Usage:
    -----------------------------------
    1. Double-press Ctrl key 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 to apply changes
    4. Settings are automatically saved between sessions
    5. Press Ctrl+P to see the print preview with your settings

    Current configuration:`, CONFIG);

})();