+
32
-

回答

写一个油猴脚本或chrome插件

点击查看全文

// ==UserScript==
// @name         合并网页代码(HTML+CSS+JS)
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  自动合并当前页面的 HTML、CSS、JS 为带分隔的文本
// @author       You
// @match        *://*/*
// @grant        GM_setClipboard
// @grant        GM_xmlhttpRequest
// @connect      *
// @run-at       document-end
// ==/UserScript==

(function () {
    'use strict';

    // 等待所有资源加载(简单延迟,或可监听 load 事件)
    window.addEventListener('load', () => {
        setTimeout(async () => {
            let output = '';

            // 1. 原始 HTML(格式化)
            const html = document.documentElement.outerHTML;
            output += `=== HTML ===\n${html}\n\n`;

            // 2. 收集所有 CSS
            output += `=== CSS ===\n`;
            const cssPromises = [];

            // 内联样式
            document.querySelectorAll('style').forEach(style => {
                output += `\n/* Inline Style */\n${style.textContent}\n`;
            });

            // 外部样式表
            document.querySelectorAll('link[rel="stylesheet"][href]').forEach(link => {
                const href = new URL(link.href, location.href).href;
                cssPromises.push(
                    fetchResource(href).then(css => {
                        if (css) return `\n/* External CSS: ${href} */\n${css}\n`;
                        return `\n/* Failed to load: ${href} */\n`;
                    }).catch(() => `\n/* Error loading: ${href} */\n`)
                );
            });

            // 3. 收集所有 JS
            output += `\n=== JS ===\n`;
            const jsPromises = [];

            // 内联脚本
            document.querySelectorAll('script:not([src])').forEach(script => {
                if (script.textContent.trim()) {
                    output += `\n/* Inline Script */\n${script.textContent}\n`;
                }
            });

            // 外部脚本
            document.querySelectorAll('script[src]').forEach(script => {
                const src = new URL(script.src, location.href).href;
                jsPromises.push(
                    fetchResource(src).then(js => {
                        if (js) return `\n/* External JS: ${src} */\n${js}\n`;
                        return `\n/* Failed to load: ${src} */\n`;
                    }).catch(() => `\n/* Error loading: ${src} */\n`)
                );
            });

            // 等待所有外部资源加载完成
            const cssResults = await Promise.all(cssPromises);
            const jsResults = await Promise.all(jsPromises);

            output += cssResults.join('');
            output += jsResults.join('');

            // 输出结果
            console.log('合并代码完成:', output);

            // 方法1:使用 GM_setClipboard(推荐,无需权限)
            if (typeof GM_setClipboard === 'function') {
                GM_setClipboard(output, 'text');
                alert('✅ 网页代码已复制到剪贴板!\n(含 HTML + CSS + JS)');
            } else {
                // 方法2:尝试 navigator.clipboard(可能被拦截)
                try {
                    await navigator.clipboard.writeText(output);
                    alert('✅ 代码已复制到剪贴board!');
                } catch (err) {
                    // 方法3:弹出文本框让用户手动复制
                    const textarea = document.createElement('textarea');
                    textarea.value = output;
                    textarea.style.position = 'fixed';
                    textarea.style.left = '-9999px';
                    document.body.appendChild(textarea);
                    textarea.select();
                    document.execCommand('copy');
                    document.body.removeChild(textarea);
                    alert('✅ 代码已复制(备用方式)');
                }
            }

        }, 1000); // 稍等资源加载
    });

    // 安全 fetch(绕过 CORS 限制,使用 GM_xmlhttpRequest)
    function fetchResource(url) {
        return new Promise((resolve) => {
            if (typeof GM_xmlhttpRequest === 'function') {
                GM_xmlhttpRequest({
                    method: 'GET',
                    url: url,
                    onload: (res) => resolve(res.responseText || ''),
                    onerror: () => resolve(''),
                    timeout: 5000
                });
            } else {
                // 降级:普通 fetch(可能因 CORS 失败)
                fetch(url, { mode: 'no-cors' })
                    .then(res => res.text().catch(() => ''))
                    .then(resolve)
                    .catch(() => resolve(''));
            }
        });
    }
})();

网友回复

我知道答案,我要回答