yangyangyixia 发表于 2025-10-31 09:32:28

明经复制/下载代码篡改猴扩展

本帖最后由 yangyangyixia 于 2025-11-3 10:28 编辑

原贴:http://bbs.mjtd.com/thread-193463-1-1.html

增加了一个下载按钮,直接下载为:代码.lsp


有缺陷,部分代码复制错误,我再研究研究……
修改了一下,不会漏掉代码了。
还是不太完美:下载下来的lsp文件,如果代码中有中文,格式会自动保存为utf8编码,需要手动改为ansi编码,这个我不会优化了

// ==UserScript==
// @name         明经复制/下载代码扩展
// @namespace    http://tampermonkey.net/
// @version      2025.10.31.1
// @description复制明经论坛代码区的代码并支持下载为.lsp文件
// @author       edata yangyangyixia
// @match      *://*.mjtd.com/*
// @icon         http://bbs.mjtd.com/favicon.ico
// @grant      none
// ==/UserScript==

(function() {
    'use strict';

    // 复制到剪贴板函数
    function copyToClipboard(text) {
      return new Promise((resolve, reject) => {
            if (navigator.clipboard) {
                navigator.clipboard.writeText(text).then(resolve).catch(reject);
            } else {
                // 兼容旧版浏览器的备用方法
                const textarea = document.createElement('textarea');
                textarea.value = text;
                textarea.style.position = 'fixed';
                textarea.style.opacity = '0';
                document.body.appendChild(textarea);
                textarea.select();

                try {
                  const successful = document.execCommand('copy');
                  document.body.removeChild(textarea);
                  successful ? resolve() : reject(new Error('复制失败'));
                } catch (err) {
                  document.body.removeChild(textarea);
                  reject(err);
                }
            }
      });
    }

    // 下载文件函数
    function downloadFile(filename, content) {
      const blob = new Blob(, { type: 'text/plain;charset=utf-8' });
      const url = URL.createObjectURL(blob);
      const link = document.createElement('a');

      link.href = url;
      link.download = filename;
      link.style.display = 'none';

      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);

      // 清理URL对象
      setTimeout(() => URL.revokeObjectURL(url), 100);
    }

    // 转换html转义字符为正常字符
    function unescapeHTML(str) {
      if (!str) return '';
      const entities = {
            'nbsp': ' ',
            'lt': '<',
            'gt': '>',
            'amp': '&',
            'quot': '"',
            '#39': "'",
            '#60': '<',
            '#62': '>',
            '#32': ' ',
            '#160': ' '
      };
      return str.replace(/&([^;]+);/g, function(match, entity) {
            if (entity in entities) {
                return entities;
            }
            // 处理数字实体如 < >   等
            if (entity.startsWith('#')) {
                const code = entity.substring(1);
                return String.fromCharCode(parseInt(code));
            }
            return match;
      });
    }

    // 安全地移除HTML标签(保留代码中的 < > 符号)
    function removeTags(str) {
      if (!str) return '';

      // 先解码所有HTML实体
      let decoded = unescapeHTML(str);

      // 只移除真正的HTML标签,保留代码中的 < 和 > 符号
      // 匹配以 < 开头,后跟字母或/,然后以 > 结尾的标签
      return decoded.replace(/<\/?[\s\S]*?>/gi, "");
    }

    // 移除换行<br />标记
    function removeBrTags(str) {
      if (!str) return '';
      return str.toString().replace(/<br\s*\/?>/gi, "\n");
    }

    // 清理和格式化代码文本(复制和下载使用相同的格式化函数)
    function formatCodeText(text) {
      if (!text) return '';

      // 先解码HTML实体(包括 < > & nbsp 等)
      let formatted = text;

      // 多次解码,确保所有HTML实体都被处理
      let previous = '';
      while (formatted !== previous) {
            previous = formatted;
            formatted = unescapeHTML(formatted);
      }

      // 将<br>标签转换为换行符
      formatted = removeBrTags(formatted);

      // 移除其他HTML标签(但保留代码中的 < > 符号)
      formatted = removeTags(formatted);

      // 彻底处理所有nbsp和不间断空格,但保留原始空格结构
      // 只替换nbsp相关实体,不修改普通空格
      formatted = formatted.replace(/ /g, ' ');
      formatted = formatted.replace(/\u00A0/g, ' ');
      formatted = formatted.replace(/ /g, ' ');
      formatted = formatted.replace(/ /g, ' ');

      // 清理多余的空行(但保留代码缩进)
      formatted = formatted.replace(/\n\s*\n/g, '\n').trim();

      return formatted;
    }

    // 添加样式
    function addStyles() {
      const style = document.createElement('style');
      style.textContent = `
            .copy-btn, .download-btn {
                display: inline-block;
                margin-left: 10px;
                padding: 2px 8px;
                border-radius: 3px;
                font-size: 12px;
                cursor: pointer;
                transition: background 0.3s;
                border: none;
                font-family: inherit;
            }
            .copy-btn {
                background: #4CAF50;
                color: white;
            }
            .copy-btn:hover {
                background: #45a049;
            }
            .copy-btn:active {
                background: #3d8b40;
            }
            .copy-btn.copied {
                background: #2196F3;
            }
            .download-btn {
                background: #ff9800;
                color: white;
            }
            .download-btn:hover {
                background: #f57c00;
            }
            .download-btn:active {
                background: #ef6c00;
            }
            .download-btn.downloaded {
                background: #9c27b0;
            }
            .code-buttons {
                display: inline-block;
                margin-left: 10px;
            }
      `;
      document.head.appendChild(style);
    }

    // 获取代码内容
    function getCodeContent(element) {
      const textarea = element.querySelector('textarea');
      if (textarea) {
            // 对于textarea,优先使用value,如果没有则用innerHTML
            return textarea.value || textarea.innerHTML;
      }

      const codeContent = element.querySelector('.jssccodecontent');
      if (codeContent) {
            return codeContent.innerHTML || codeContent.textContent || codeContent.innerText;
      }

      return '';
    }

    // 处理复制操作
    async function handleCopy(element, copyBtn) {
      const rawText = getCodeContent(element);
      const formattedText = formatCodeText(rawText);

      try {
            if (typeof setCopy === 'function') {
                setCopy(formattedText, "代码已复制到剪贴板");
            } else {
                await copyToClipboard(formattedText);
                setCopy(formattedText, "代码已复制到剪贴板");
            }

            copyBtn.textContent = '复制成功!';
            copyBtn.classList.add('copied');
            setTimeout(() => {
                copyBtn.textContent = '格式复制';
                copyBtn.classList.remove('copied');
            }, 2000);

      } catch (err) {
            console.error('复制失败:', err);
            copyBtn.textContent = '复制失败';
            setTimeout(() => {
                copyBtn.textContent = '格式复制';
            }, 2000);
      }
    }

    // 处理下载操作
    function handleDownload(element, downloadBtn) {
      const rawText = getCodeContent(element);
      // 使用与复制相同的格式化函数,确保格式一致
      const formattedText = formatCodeText(rawText);

      if (!formattedText.trim()) {
            setCopy(formattedText, "没有可下载的代码内容");
            return;
      }

      const filename = `代码.lsp`;
      downloadFile(filename, formattedText);

      downloadBtn.textContent = '下载成功!';
      downloadBtn.classList.add('downloaded');
      setCopy(formattedText, "已下载为代码.lsp");
      setTimeout(() => {
            downloadBtn.textContent = '下载lsp';
            downloadBtn.classList.remove('downloaded');
      }, 2000);
    }

    // 主处理函数 - 添加复制和下载按钮
    function addCodeButtons() {
      // 获取所有以"mc_code"开头的元素
      const elements = [];
      let index = 0;

      while (true) {
            const element = document.getElementById(`mc_code${index}`);
            if (!element) break;
            elements.push(element);
            index++;
      }

      // 处理每个找到的元素
      elements.forEach(element => {
            const titleElement = element.querySelector('.jssccodetitle');
            if (!titleElement) return;

            // 检查是否已添加按钮容器
            let buttonsContainer = titleElement.querySelector('.code-buttons');
            if (buttonsContainer) return;

            // 创建按钮容器
            buttonsContainer = document.createElement('span');
            buttonsContainer.className = 'code-buttons';

            // 创建复制按钮
            const copyBtn = document.createElement('button');
            copyBtn.className = 'copy-btn';
            copyBtn.textContent = '格式复制';
            copyBtn.title = '点击复制格式化后的代码';

            // 创建下载按钮
            const downloadBtn = document.createElement('button');
            downloadBtn.className = 'download-btn';
            downloadBtn.textContent = '下载.lsp';
            downloadBtn.title = '点击下载为.lsp文件';

            // 添加点击事件
            copyBtn.addEventListener('click', () => handleCopy(element, copyBtn));
            downloadBtn.addEventListener('click', () => handleDownload(element, downloadBtn));

            // 插入按钮
            buttonsContainer.appendChild(copyBtn);
            buttonsContainer.appendChild(downloadBtn);
            titleElement.appendChild(buttonsContainer);
      });
    }

    // 初始化函数
    function init() {
      addStyles();
      addCodeButtons();

      // 监听DOM变化,动态添加按钮
      const observer = new MutationObserver(() => {
            addCodeButtons();
      });

      observer.observe(document.body, {
            childList: true,
            subtree: true
      });

      // 页面加载完成后再次检查
      window.addEventListener('load', addCodeButtons);
    }

    // 延迟初始化,确保页面加载完成
    if (document.readyState === 'loading') {
      document.addEventListener('DOMContentLoaded', init);
    } else {
      init();
    }
})();





maiko 发表于 2025-10-31 12:29:58

这个更加高级了

429014673 发表于 2025-10-31 10:58:25

这个更好                                 

magicheno 发表于 2025-10-31 12:56:36

点击格式复制,直接复制到篡改猴里面会有一处格式有问题的地方,不知道什么原因,如果直接从下到上手选复制就没有这个问题了


http://www.mjtd.com/static/image/common/emp.gif

zsw23 发表于 2025-10-31 10:00:35


感谢,好用

qifeifei 发表于 2025-10-31 11:05:27

更高级了 可以下载为lsp了

nzl1116 发表于 2025-10-31 11:34:46

这个更加高级了

sowin 发表于 2025-10-31 12:14:37

这个可以,很实用

szhorse 发表于 2025-10-31 12:29:25

本帖最后由 szhorse 于 2025-12-11 11:32 编辑

这个太给力了
感谢大佬脚本,确实方便了不少,部分代码【下载.lsp】后,运行时提示缺括号,跑不起来

429014673 发表于 2025-10-31 13:42:26

测试了这个http://bbs.mjtd.com/thread-193886-1-1.html,会缺括号
页: [1] 2
查看完整版本: 明经复制/下载代码篡改猴扩展