禁止 content-wrapper 被 innerHTML 改写,禁止 script 标签后插入 div 遮罩!
// ==UserScript==
// @license MIT
// @name Yudao Doc VIP Patch (精准拦截版)
// @namespace none
// @version 5.0
// @description 禁止 content-wrapper 被 innerHTML 改写,禁止 script 标签后插入 div 遮罩!
// @author AI助手
// @match https://doc.iocoder.cn/*
// @grant none
// @run-at document-start
// ==/UserScript==
(function() {
'use strict';
// 1. 禁止 content-wrapper 的 innerHTML 被直接改写
let firstContent = null;
const realSet = Object.getOwnPropertyDescriptor(Element.prototype, 'innerHTML').set;
const realGet = Object.getOwnPropertyDescriptor(Element.prototype, 'innerHTML').get;
Object.defineProperty(Element.prototype, 'innerHTML', {
set: function(val) {
if (
this.classList &&
this.classList.contains('content-wrapper')
) {
// 只允许首次赋值(页面初始渲染),后续不允许再改写
if (firstContent === null && typeof val === 'string' && val.trim().length > 0 && !val.includes('仅 VIP 可见')) {
firstContent = val;
return realSet.call(this, val);
}
// 拦截后续所有赋值
return;
}
// 其他节点正常赋值
return realSet.call(this, val);
},
get: function() {
return realGet.call(this);
},
configurable: true
});
// 2. 禁止在最后一个 <script> 后插入 div
function blockDivAfterScript() {
const scripts = document.querySelectorAll('body > script');
if (!scripts.length) return;
const lastScript = scripts[scripts.length - 1];
let node = lastScript.nextSibling;
while (node) {
const next = node.nextSibling;
if (node.nodeType === 1 && node.tagName === 'DIV') {
node.remove();
}
node = next;
}
}
// 3. 监听 body 直系子节点变化
const bodyObserver = new MutationObserver(blockDivAfterScript);
window.addEventListener('DOMContentLoaded', blockDivAfterScript);
bodyObserver.observe(document.body, { childList: true, subtree: false });
// 4. 兜底定时清理
setInterval(blockDivAfterScript, 1000);
})();