// ==UserScript== // @name 语雀渲染HTML附件 // @namespace http://tampermonkey.net/ // @version 1.0 // @description 拦截 /api/attachments/*/content 接口返回的 JSON 数据,解析并渲染 HTML // @author SayHeya // @match https://www.yuque.com/raw?filekey=yuque* // @grant none // @run-at document-start // @license MIT // @downloadURL none // ==/UserScript== (function () { 'use strict'; const isTargetURL = (url) => typeof url === 'string' && url.includes('/api/attachments/') && url.includes('/content'); /** 拦截 fetch */ const hookFetch = () => { const originalFetch = window.fetch; window.fetch = async function (...args) { const [url] = args; const response = await originalFetch.apply(this, args); if (isTargetURL(url)) { const cloned = response.clone(); cloned.json().then(data => { console.log('[🎯 Intercepted fetch] Data:', data); // 获取 data.content 节点中的 HTML 内容 const htmlContent = data.data.content; // 创建一个容器来插入渲染的 HTML const container = document.createElement('div'); container.style.cssText = ` padding: 20px; font-family: Arial, sans-serif; background-color: #f7f7f7; margin: 20px 0; border-radius: 8px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); `; // 将 data.content 中的 HTML 直接赋给 container 的 innerHTML container.innerHTML = htmlContent; // 将容器插入到页面中 document.body.innerHTML = ''; // 清空页面 document.body.appendChild(container); }); } return response; }; }; /** 拦截 XHR */ const hookXHR = () => { const originalOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function (method, url, ...rest) { this._intercept_url = url; return originalOpen.call(this, method, url, ...rest); }; const originalSend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.send = function (...args) { this.addEventListener('load', function () { if (isTargetURL(this._intercept_url)) { console.log('[🎯 Intercepted XHR]', this._intercept_url, this.responseText); const data = JSON.parse(this.responseText); const htmlContent = data.content; // 创建一个容器来插入渲染的 HTML const container = document.createElement('div'); container.style.cssText = ` padding: 20px; font-family: Arial, sans-serif; background-color: #f7f7f7; margin: 20px 0; border-radius: 8px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); `; // 将 data.content 中的 HTML 直接赋给 container 的 innerHTML container.innerHTML = htmlContent; // 将容器插入到页面中 document.body.innerHTML = ''; // 清空页面 document.body.appendChild(container); } }); return originalSend.apply(this, args); }; }; hookFetch(); // hookXHR(); })();