- 积分
- 11979
- 明经币
- 个
- 注册时间
- 2024-4-9
- 在线时间
- 小时
- 威望
-
- 金钱
- 个
- 贡献
-
- 激情
-
|
本帖最后由 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([content], { 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[entity];
- }
- // 处理数字实体如 < > 等
- 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(/<\/?[a-z][\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();
- }
- })();
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?注册
x
评分
-
查看全部评分
|