User:半导体果冻/common.js

来自Noita Wiki
跳到导航 跳到搜索

注意:在发布之后,您可能需要清除浏览器缓存才能看到所作出的变更的影响。

  • Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5Ctrl-R(Mac为⌘-R
  • Google Chrome:Ctrl-Shift-R(Mac为⌘-Shift-R
  • Internet Explorer或Edge:按住Ctrl的同时单击刷新,或按Ctrl-F5
  • Opera:Ctrl-F5
(function () {
    var parser = new DOMParser();
    var codeElements = document.querySelectorAll("code[data-inject-js]");
    /** @type {typeof Function} Function构造器 防止编辑器警告 */
    var _ = Function.prototype.constructor;
    Function.prototype.constructor = null; // 防止通过原型链获取Function构造能力
    var i;
    var codeElement;
    // 需要被消毒的html 标签
    var sterilize_elementTags = ["SCRIPT", "IMG", "AUDIO", "VIDEO", "EMBED", "OBJECT", "LINK", "INFRME"];
    /** @param {String} htmlStr 待消毒的html字符串 */
    function sterilize(htmlStr) {
        try {
            var fragment = new DocumentFragment();
            var doc = parser.parseFromString(htmlStr, "text/html");
            var allNodes = doc.querySelectorAll("*");
            for (var i = 0; i < allNodes.length; i++) {
                if (sterilize_elementTags.includes(allNodes[i].tagName)) allNodes[i].remove();
            }

            var childNodes = doc.body.cloneNode(true).childNodes;
            for (i = 0; i < childNodes.length; i++) fragment.append(childNodes[i]);
            return fragment;
        } catch (error) {
            console.error(error);
            var codeElement_error = document.createElement("code");
            codeElement_error.innerText = String(error);
            return codeElement_error;
        }
    }
    var $window = new Proxy(
        {},
        {
            set: function (target, p, newValue, receiver) {
                target[p] = newValue;
                window[p] = newValue;
            },
            get: function (target, p, receiver) {
                return target[p];
            }
        }
    );

    // DOM对象代理createElement
    var document_ = new Proxy(
        {
            // 这里的所有属性会代理 document中的属性
            //
            // 防止从iframe 中获取window对象
            createElement: function (tag, opt) {
                return tag === "iframe" ? null : document.createElement(tag, opt);
            },
            defaultView: null
        },
        {
            get: function (target, p, receiver) {
                if (p in target) return target[p];
                else {
                    var r = document[p];
                    if (typeof r === "function") r = r.bind(document);
                    return r;
                }
            }
        }
    );

    for (i = 0; i < codeElements.length; i++)
        (function (element) {
            element.style.display = "none";
            function $return(htmlStr) {
                if (element.isConnected) element.replaceWith(sterilize(htmlStr));
                else console.error(new Error("仅能使用一次 $return"));
            }
            // 屏蔽危险的api
            new _("$return", "window", "document", "fetch", "XMLHttpRequest", "eval", "Function", "$", element.innerText).bind(null)($return, $window, document_, null, null, null, null, null);
        })(codeElements[i]);

    codeElements = document.querySelectorAll("code[data-inject-html]");

    for (i = 0; i < codeElements.length; i++) {
        codeElement = codeElements[i];
        codeElement.replaceWith(sterilize(codeElement.innerText));
    }
})();