Greasy Fork is available in English.
粘贴或拖放时自动为代码文件添加.txt后缀并修正MIME类型,使其可正常上传。可能仍会提示不支持,但看到上传成功即可。目前选择上传方式尚未修改。
当前为
// ==UserScript==
// @name TX元宝/扣子文件盒子上传增强
// @namespace https://gist.github.com/youzhiran/4fc8fa8a34c35c34ab455cd3f76d8236
// @version 1.2
// @description 粘贴或拖放时自动为代码文件添加.txt后缀并修正MIME类型,使其可正常上传。可能仍会提示不支持,但看到上传成功即可。目前选择上传方式尚未修改。
// @author yooyi
// @match *://yuanbao.tencent.com/*
// @match *://www.coze.cn/space/*
// @grant none
// @license MIT
// ==/UserScript==
(function () {
'use strict';
const UNSUPPORTED_EXT = ['.dart', '.py', '.java', '.js', '.cpp', '.kt', '.swift', '.html', '.css', '.scss',
'.php', '.c', '.vbs', '.xml', '.ini', '.md', '.yml', '.yaml', '.cmd', '.bat', '.rs', '.go', '.ts', '.json',
'.sql', '.rb', '.cs', '.pl', '.lua', '.toml'];
// 添加域名和元素检测
function checkCozeCondition() {
if (window.location.hostname.includes('www.coze.cn')) {
const targetElement = document.querySelector('#semi-modal-body > div > div');
if (targetElement) {
dropEvent();
return true;
}
}
if (window.location.hostname.includes('yuanbao.tencent.com')) {
// 处理粘贴事件
pasteEvent();
dropEvent();
}
return false;
}
// 初始化检测
checkCozeCondition();
// 动态监听 DOM 变化
const observer = new MutationObserver(() => {
if (checkCozeCondition()) {
observer.disconnect();
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: false,
characterData: false
});
// 公共文件处理函数
function processFile(file) {
const originalName = file.name;
if (UNSUPPORTED_EXT.some(ext => originalName.toLowerCase().endsWith(ext))) {
return new File([file], `${originalName}.txt`, {type: 'text/plain'});
}
return file;
}
function pasteEvent() {
document.addEventListener('paste', function (e) {
const items = e.clipboardData.items;
const files = [];
let shouldModify = false;
for (let i = 0; i < items.length; i++) {
const item = items[i];
if (item.kind === 'file') {
const file = item.getAsFile();
const processedFile = processFile(file);
files.push(processedFile);
if (processedFile !== file) shouldModify = true;
}
}
if (shouldModify) {
e.preventDefault();
const newData = new DataTransfer();
files.forEach(f => newData.items.add(f));
const target = document.activeElement.closest('input, [contenteditable]') || document.activeElement;
if (target instanceof HTMLInputElement) {
target.files = newData.files;
} else {
const pasteEvent = new ClipboardEvent('paste', {
clipboardData: newData,
bubbles: true,
cancelable: true
});
target.dispatchEvent(pasteEvent);
}
}
}, true);
}
function dropEvent() {
document.addEventListener('drop', function (e) {
const items = e.dataTransfer.items;
if (!items.length) return;
const files = [];
let shouldModify = false;
for (let i = 0; i < items.length; i++) {
const item = items[i];
if (item.kind === 'file') {
const file = item.getAsFile();
const processedFile = processFile(file);
files.push(processedFile);
if (processedFile !== file) shouldModify = true;
}
}
if (shouldModify) {
e.preventDefault();
e.stopPropagation();
const newData = new DataTransfer();
files.forEach(f => newData.items.add(f));
// // 通过粘贴事件传递文件
// const target = document.activeElement;
// if (target instanceof HTMLInputElement) {
// target.files = newData.files;
// } else {
// const pasteEvent = new ClipboardEvent('paste', {
// clipboardData: newData,
// bubbles: true,
// cancelable: true
// });
// target.dispatchEvent(pasteEvent);
// }
// 创建完整的拖放事件序列
['dragenter', 'dragover', 'drop'].forEach(eventName => {
const event = new DragEvent(eventName, {
bubbles: true,
cancelable: true,
dataTransfer: newData
});
Object.defineProperty(event, 'dataTransfer', {
value: newData,
enumerable: true
});
e.target.dispatchEvent(event);
});
// 触发 change 事件更新文件输入
if (e.target.tagName === 'INPUT' && e.target.type === 'file') {
e.target.files = newData.files;
const changeEvent = new Event('change', {bubbles: true});
e.target.dispatchEvent(changeEvent);
}
}
}, true);
}
})();