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 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==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);

})();