跳转到内容

MediaWiki:Gadget-DotsSyntaxHighlighter.js

勤求古训,博采众方
鹿野耕云留言 | 贡献2025年11月20日 (四) 23:41的版本
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)

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

  • Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5Ctrl-R(Mac为⌘-R
  • Google Chrome:Ctrl-Shift-R(Mac为⌘-Shift-R
  • Edge:按住Ctrl的同时单击刷新,或按Ctrl-F5
mw.loader.using("jquery.client", function() {
    "use strict";
    
    // 安全的配置访问函数
    function safeConfigAccess(config, property, defaultValue) {
        if (!config || !config[property]) return defaultValue;
        return config[property];
    }
    
    // CSS颜色值验证函数
    function isValidCSSColor(colorValue) {
        if (!colorValue || typeof colorValue !== 'string') return false;
        
        // 移除前后空格
        colorValue = colorValue.trim();
        
        // 检查常见CSS颜色格式
        var colorFormats = [
            // 十六进制颜色 (#FFF, #FFFFFF)
            /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/,
            // RGB颜色 (rgb(255,255,255))
            /^rgb\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*\)$/,
            // RGBA颜色 (rgba(255,255,255,0.5))
            /^rgba\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*(0|1|0\.\d+)\s*\)$/,
            // HSL颜色 (hsl(120,100%,50%))
            /^hsl\(\s*\d{1,3}\s*,\s*\d{1,3}%\s*,\s*\d{1,3}%\s*\)$/,
            // HSLA颜色 (hsla(120,100%,50%,0.5))
            /^hsla\(\s*\d{1,3}\s*,\s*\d{1,3}%\s*,\s*\d{1,3}%\s*,\s*(0|1|0\.\d+)\s*\)$/,
            // 命名颜色 (red, blue, transparent)
            /^(transparent|inherit|initial|unset|currentColor|revert|revert-layer)$/i
        ];
        
        // 检查是否为有效的CSS命名颜色
        var namedColors = [
            'black', 'silver', 'gray', 'white', 'maroon', 'red', 'purple', 'fuchsia', 
            'green', 'lime', 'olive', 'yellow', 'navy', 'blue', 'teal', 'aqua',
            'orange', 'aliceblue', 'antiquewhite', 'aquamarine', 'azure', 'beige',
            'bisque', 'blanchedalmond', 'blueviolet', 'brown', 'burlywood', 'cadetblue',
            'chartreuse', 'chocolate', 'coral', 'cornflowerblue', 'cornsilk', 'crimson',
            'cyan', 'darkblue', 'darkcyan', 'darkgoldenrod', 'darkgray', 'darkgreen',
            'darkgrey', 'darkkhaki', 'darkmagenta', 'darkolivegreen', 'darkorange',
            'darkorchid', 'darkred', 'darksalmon', 'darkseagreen', 'darkslateblue',
            'darkslategray', 'darkslategrey', 'darkturquoise', 'darkviolet', 'deeppink',
            'deepskyblue', 'dimgray', 'dimgrey', 'dodgerblue', 'firebrick', 'floralwhite',
            'forestgreen', 'gainsboro', 'ghostwhite', 'gold', 'goldenrod', 'greenyellow',
            'grey', 'honeydew', 'hotpink', 'indianred', 'indigo', 'ivory', 'khaki',
            'lavender', 'lavenderblush', 'lawngreen', 'lemonchiffon', 'lightblue',
            'lightcoral', 'lightcyan', 'lightgoldenrodyellow', 'lightgray', 'lightgreen',
            'lightgrey', 'lightpink', 'lightsalmon', 'lightseagreen', 'lightskyblue',
            'lightslategray', 'lightslategrey', 'lightsteelblue', 'lightyellow', 'limegreen',
            'linen', 'magenta', 'mediumaquamarine', 'mediumblue', 'mediumorchid',
            'mediumpurple', 'mediumseagreen', 'mediumslateblue', 'mediumspringgreen',
            'mediumturquoise', 'mediumvioletred', 'midnightblue', 'mintcream', 'mistyrose',
            'moccasin', 'navajowhite', 'oldlace', 'olivedrab', 'orangered', 'orchid',
            'palegoldenrod', 'palegreen', 'paleturquoise', 'palevioletred', 'papayawhip',
            'peachpuff', 'peru', 'pink', 'plum', 'powderblue', 'rosybrown', 'royalblue',
            'saddlebrown', 'salmon', 'sandybrown', 'seagreen', 'seashell', 'sienna',
            'skyblue', 'slateblue', 'slategray', 'slategrey', 'snow', 'springgreen',
            'steelblue', 'tan', 'thistle', 'tomato', 'turquoise', 'violet', 'wheat',
            'whitesmoke', 'yellowgreen'
        ];
        
        // 检查格式匹配
        for (var i = 0; i < colorFormats.length; i++) {
            if (colorFormats[i].test(colorValue)) {
                return true;
            }
        }
        
        // 检查命名颜色
        if (namedColors.indexOf(colorValue.toLowerCase()) !== -1) {
            return true;
        }
        
        return false;
    }
    
    // 安全的颜色配置访问函数
    function safeColorAccess(config, property, defaultValue) {
        var colorValue = safeConfigAccess(config, property, defaultValue);
        
        // 如果颜色值为"normal",返回默认值
        if (colorValue === "normal") {
            return defaultValue;
        }
        
        // 验证颜色值有效性
        if (colorValue && !isValidCSSColor(colorValue)) {
            console.warn('Invalid CSS color value for ' + property + ': "' + colorValue + '", using default: "' + defaultValue + '"');
            return defaultValue;
        }
        
        return colorValue || defaultValue;
    }
    
    // 查找匹配的标签结束位置,处理嵌套标签
    function findMatchingTagEnd(text, startPos, tagName) {
        var openTag = "<" + tagName + ">";
        var closeTag = "</" + tagName + ">";
        var stack = 1; // 当前已经有一个开始标签
        var pos = startPos;
        
        while (pos < text.length) {
            var nextOpen = text.indexOf(openTag, pos);
            var nextClose = text.indexOf(closeTag, pos);
            
            // 如果找不到闭合标签,返回文本末尾
            if (nextClose === -1) return text.length;
            
            // 如果下一个开始标签在闭合标签之前,增加栈深度
            if (nextOpen !== -1 && nextOpen < nextClose) {
                stack++;
                pos = nextOpen + openTag.length;
            } else {
                stack--;
                pos = nextClose + closeTag.length;
                
                // 如果栈为空,返回当前闭合标签的结束位置
                if (stack === 0) return pos;
            }
        }
        
        return text.length; // 如果找不到匹配的闭合标签,返回文本末尾
    }
    
    var e = mw.config.get("wgUrlProtocols"),
        r = "&(?:(?:n(?:bsp|dash)|m(?:dash|inus)|lt|e[mn]sp|thinsp|amp|quot|gt|shy|zwnj|lrm|rlm|Alpha|Beta|Epsilon|Zeta|Eta|Iota|Kappa|[Mm]u|micro|Nu|[Oo]micron|[Rr]ho|Tau|Upsilon|Chi)|#x[0-9a-fA-F]+);\\n*",
        t = "\\[(?:\\[|(?:" + e + "))|\\{(?:\\{\\{?|\\|)|<(?:[:A-Z_a-z][-:\\w]*(?=/?>| |\\n)|!--[\\s\\S]*?-->\\n*)|(?:" + e + ")[^\\s\"<>[\\]{-}]*[^\\s\",\\.:;<>[\\]{-}]\\n*|^(?:=|[*#:;]+\\n*|-{4,}\\n*)|\\\\'\\\\'(?:\\\\')?|~{3,5}\\n*|" + r,
        l = null, g = null, d = null, c = "", y = null, p = null, f = null, b = -1,
        lastText = ""; // 记录上一次的文本内容

    var regexCache = {};
    
    function C(e) {
        var cacheKey = e;
        if (!regexCache[cacheKey]) {
            try {
                regexCache[cacheKey] = new RegExp("(" + e + ")\\n*|" + t, "gm");
            } catch (err) {
                console.error("Syntax highlighter: 正则表达式构建失败", err, "e:", e);
                regexCache[cacheKey] = new RegExp(t, "gm"); // 使用默认正则降级
            }
        }
        return regexCache[cacheKey];
    }

    var x = new RegExp(t, "gm"),
        k = C("]][a-zA-Z]*"),
        v = C("]"),
        w = C("}}}"),
        z = C("}}"),
        H = C("\\|}"),
        S = C("\\n"),
        T = {},
        L = {};

    // 增量更新状态管理
    var lastHighlightState = null,
        lastSpanCount = 0,
        spanCache = {};

    function E() {
        try {
            var currentText = g.value;
            
            // 增量更新检查:如果文本内容没有变化,直接返回
            if (currentText === lastText) {
                return;
            }
            
            // 增量更新优化:计算文本变化范围并用于局部解析
            var changeStart = 0, changeEnd = currentText.length;
            var isIncrementalUpdate = false;
            
            if (lastText && currentText !== lastText) {
                // 找到文本变化的起始位置
                for (changeStart = 0; changeStart < Math.min(currentText.length, lastText.length); changeStart++) {
                    if (currentText[changeStart] !== lastText[changeStart]) break;
                }
                
                // 找到文本变化的结束位置(从末尾开始比较)
                for (changeEnd = 0; changeEnd < Math.min(currentText.length, lastText.length); changeEnd++) {
                    if (currentText[currentText.length - 1 - changeEnd] !== lastText[lastText.length - 1 - changeEnd]) break;
                }
                changeEnd = currentText.length - changeEnd;
                
                // 判断是否适合增量更新:变化范围较小且不在语法结构边界
                isIncrementalUpdate = (changeEnd - changeStart) < Math.min(currentText.length * 0.3, 200) && 
                                     changeStart > 0 && changeEnd < currentText.length;
            }
            
            lastText = currentText;
            
            // 确保b变量有正确的初始值
            if (b === -1) {
                // 如果是第一次运行,需要初始化b为当前span数量
                var existingSpans = l.querySelectorAll('span[id^="s"]');
                b = existingSpans.length;
            }
        } catch (error) {
            // 捕获正则匹配和DOM操作中的异常
            console.error('Syntax highlighter error:', error);
            return;
        }
        
        var i, h = (c = currentText).replace(/['\\]/g, "\\$&") + "\\n",
            m = 0,
            o = "",
            r = 0;

        // 最大递归深度限制
        var MAX_RECURSION_DEPTH = 1000;

        function u(e, t) {
            t != i && (o += "'}", t && (o += "#s" + r + "{background-color:" + t + "}"), o += "#s" + r + "::after{content:'", i = t, ++r), o += e;
        }

        var e = Date.now();

        // 精确增量更新:基于changeStart和changeEnd的局部解析
        if (isIncrementalUpdate && lastHighlightState) {
            // 方法1:智能边界定位(当前实现)- 基于CSS状态复用
            var startMarker = "#s" + (Math.floor(changeStart / 50)) + "::after";
            var markerIndex = lastHighlightState.indexOf(startMarker);
            if (markerIndex !== -1) {
                var prefixCSS = lastHighlightState.substring(0, markerIndex);
                // 确保CSS语法完整
                if (prefixCSS.endsWith("'}")) {
                    o = prefixCSS;
                    r = Math.floor(changeStart / 50);
                    m = changeStart;
                }
            }
            
            // 方法2:语法边界检测(高级优化)- 需要修改递归逻辑
            // 检测变化点前后的语法结构,确保解析上下文正确
            var syntaxBoundaryStart = findSyntaxBoundary(currentText, changeStart, -1); // 向前查找语法边界
            var syntaxBoundaryEnd = findSyntaxBoundary(currentText, changeEnd, 1);      // 向后查找语法边界
            
            if (syntaxBoundaryStart >= 0 && syntaxBoundaryEnd <= currentText.length) {
                // 如果找到合适的语法边界,使用精确的局部解析
                m = Math.max(0, syntaxBoundaryStart);
                // 这里需要修改递归解析函数以支持从指定位置开始解析
                console.log("精确增量更新:从位置", m, "开始解析");
            }
        } else {
            // 如果不是增量更新或lastHighlightState为null,确保从文本开头开始解析
            m = 0;
            o = "";
            r = 0;
        }
        
        // 语法边界检测辅助函数 - 增强wikitext专属边界检测
        function findSyntaxBoundary(text, position, direction) {
            var boundary = position;
            var maxSearch = 100; // 最大搜索范围
            
            // wikitext专属语法边界列表(按优先级排序)
            var wikitextBoundaries = [
                // 多字符边界(高优先级)
                '[[', ']]', '{{', '}}', '{{{', '}}}', '{|', '|}', '<!--', '-->',
                // 单字符边界
                '\n', '>', '}', ']', '=', '<', '|', ';', '*', '#', ':', '-', '~', '\\', '&'
            ];
            
            for (var i = 0; i < maxSearch; i++) {
                var currentPos = boundary + (direction * i);
                if (currentPos < 0 || currentPos >= text.length) break;
                
                // 优先检测多字符wikitext边界
                for (var j = 0; j < wikitextBoundaries.length; j++) {
                    var boundaryStr = wikitextBoundaries[j];
                    if (boundaryStr.length > 1) {
                        // 多字符边界检测
                        if (currentPos + boundaryStr.length <= text.length && 
                            text.substring(currentPos, currentPos + boundaryStr.length) === boundaryStr) {
                            return currentPos + (direction > 0 ? boundaryStr.length : 0);
                        }
                    } else {
                        // 单字符边界检测
                        if (text.charAt(currentPos) === boundaryStr) {
                            return currentPos + (direction > 0 ? 1 : 0);
                        }
                    }
                }
            }
            
            return direction > 0 ? text.length : 0;
        }

        // 基于显式调用栈的迭代解析器
        var stack = [{
            text: h,
            pos: m,
            regex: x,
            color: "",
            boldState: false,
            italicState: false,
            context: "root"
        }];
        
        var MAX_STACK_DEPTH = 1000; // 最大栈深度限制
        
        while (stack.length > 0 && stack.length < MAX_STACK_DEPTH) {
            var currentTask = stack.pop();
            var text = currentTask.text;
            var pos = currentTask.pos;
            var regex = currentTask.regex;
            var color = currentTask.color;
            var boldState = currentTask.boldState;
            var italicState = currentTask.italicState;
            var context = currentTask.context;
            
            // 处理当前解析任务
            var match;
            regex.lastIndex = pos;
            
            while ((match = regex.exec(text)) !== null) {
                if (match[1]) {
                    // 匹配到结束标记,处理剩余文本并返回
                    u(text.substring(pos, regex.lastIndex), color);
                    m = regex.lastIndex;
                    break;
                }
                
                var matchStart = regex.lastIndex - match[0].length;
                
                // 处理匹配前的文本
                if (pos < matchStart) {
                    u(text.substring(pos, matchStart), color);
                }
                
                pos = regex.lastIndex;
                
                // 根据匹配内容处理不同的语法元素
                switch (match[0].charAt(0)) {
                    case "[":
                        if (match[0].charAt(1) === "[") {
                            // 内部链接 [[...]]
                            u("[[", safeColorAccess(syntaxHighlighterConfig, 'wikilinkColor', color) || color);
                            stack.push({
                                text: text,
                                pos: pos,
                                regex: k,
                                color: safeColorAccess(syntaxHighlighterConfig, 'wikilinkColor', color) || color,
                                boldState: boldState,
                                italicState: italicState,
                                context: "wikilink"
                            });
                        } else {
                            // 外部链接 [...]
                            u(match[0], safeColorAccess(syntaxHighlighterConfig, 'externalLinkColor', color) || color);
                            stack.push({
                                text: text,
                                pos: pos,
                                regex: v,
                                color: safeColorAccess(syntaxHighlighterConfig, 'externalLinkColor', color) || color,
                                boldState: boldState,
                                italicState: italicState,
                                context: "externalLink"
                            });
                        }
                        break;
                    
                    case "{":
                        if (match[0].charAt(1) === "{") {
                            if (match[0].length === 3) {
                                // 参数 {{{...}}}
                                u("{{{", safeColorAccess(syntaxHighlighterConfig, 'parameterColor', color) || color);
                                stack.push({
                                    text: text,
                                    pos: pos,
                                    regex: w,
                                    color: safeColorAccess(syntaxHighlighterConfig, 'parameterColor', color) || color,
                                    boldState: boldState,
                                    italicState: italicState,
                                    context: "parameter"
                                });
                            } else {
                                // 模板 {{...}}
                                u("{{", safeColorAccess(syntaxHighlighterConfig, 'templateColor', color) || color);
                                stack.push({
                                    text: text,
                                    pos: pos,
                                    regex: z,
                                    color: safeColorAccess(syntaxHighlighterConfig, 'templateColor', color) || color,
                                    boldState: boldState,
                                    italicState: italicState,
                                    context: "template"
                                });
                            }
                        } else {
                            // 表格 {|...|}
                            u("{|", safeColorAccess(syntaxHighlighterConfig, 'tableColor', color) || color);
                            stack.push({
                                text: text,
                                pos: pos,
                                regex: H,
                                color: safeColorAccess(syntaxHighlighterConfig, 'tableColor', color) || color,
                                boldState: boldState,
                                italicState: italicState,
                                context: "table"
                            });
                        }
                        break;
                    
                    case "<":
                        if (match[0].charAt(1) === "!") {
                            // 注释 <!-- ... -->
                            u(match[0], safeColorAccess(syntaxHighlighterConfig, 'commentColor', color) || color);
                        } else {
                            // HTML标签
                            var tagEnd = text.indexOf(">", pos) + 1;
                            if (tagEnd === 0) {
                                u("<", color);
                                pos = pos - match[0].length + 1;
                            } else {
                                var tagName = match[0].substring(1);
                                
                                if (text.charAt(tagEnd - 2) !== "/") {
                                    if (safeConfigAccess(syntaxHighlighterConfig, 'voidTags', []).indexOf(tagName) === -1) {
                                        if (safeConfigAccess(syntaxHighlighterConfig, 'sourceTags', []).indexOf(tagName) !== -1) {
                                            // 源代码标签
                                            var closeTag = "</" + tagName + ">";
                                            var tagEndPos = findMatchingTagEnd(text, pos, tagName);
                                            u(text.substring(pos - match[0].length, tagEndPos), safeColorAccess(syntaxHighlighterConfig, 'tagColor', color) || color);
                                            pos = tagEndPos;
                                        } else if (safeConfigAccess(syntaxHighlighterConfig, 'nowikiTags', []).indexOf(tagName) !== -1) {
                                            // nowiki标签
                                            u(text.substring(pos - match[0].length, tagEnd), safeColorAccess(syntaxHighlighterConfig, 'tagColor', color) || color);
                                            pos = tagEnd;
                                            stack.push({
                                                text: text,
                                                pos: pos,
                                                regex: L[tagName] || (L[tagName] = C("</" + tagName + ">")),
                                                color: safeColorAccess(syntaxHighlighterConfig, 'tagColor', color) || color,
                                                boldState: boldState,
                                                italicState: italicState,
                                                context: "tag"
                                            });
                                        } else {
                                            // 普通标签
                                            u(text.substring(pos - match[0].length, tagEnd), safeColorAccess(syntaxHighlighterConfig, 'tagColor', color) || color);
                                            pos = tagEnd;
                                            T[tagName] = T[tagName] || C("</" + tagName + ">");
                                            stack.push({
                                                text: text,
                                                pos: pos,
                                                regex: T[tagName],
                                                color: safeColorAccess(syntaxHighlighterConfig, 'tagColor', color) || color,
                                                boldState: boldState,
                                                italicState: italicState,
                                                context: "tag"
                                            });
                                        }
                                    } else {
                                        u(text.substring(pos - match[0].length, tagEnd), safeColorAccess(syntaxHighlighterConfig, 'tagColor', color) || color);
                                        pos = tagEnd;
                                    }
                                } else {
                                    u(text.substring(pos - match[0].length, tagEnd), safeColorAccess(syntaxHighlighterConfig, 'tagColor', color) || color);
                                    pos = tagEnd;
                                }
                            }
                        }
                        break;
                    
                    case "=":
                        if (/[^=]=+$/.test(text.substring(pos, text.indexOf("\\n", pos)))) {
                            // 标题
                            u("=", safeColorAccess(syntaxHighlighterConfig, 'headingColor', color) || color);
                            stack.push({
                                text: text,
                                pos: pos,
                                regex: S,
                                color: safeColorAccess(syntaxHighlighterConfig, 'headingColor', color) || color,
                                boldState: boldState,
                                italicState: italicState,
                                context: "heading"
                            });
                        } else {
                            u("=", color);
                        }
                        break;
                    
                    case "*":
                    case "#":
                    case ":":
                        // 列表和缩进
                        u(match[0], safeColorAccess(syntaxHighlighterConfig, 'listOrIndentColor', color) || color);
                        break;
                    
                    case ";":
                        // 定义列表
                        u(";", safeColorAccess(syntaxHighlighterConfig, 'headingColor', color) || color);
                        stack.push({
                            text: text,
                            pos: pos,
                            regex: S,
                            color: safeColorAccess(syntaxHighlighterConfig, 'headingColor', color) || color,
                            boldState: boldState,
                            italicState: italicState,
                            context: "heading"
                        });
                        break;
                    
                    case "-":
                        // 水平线
                        u(match[0], safeColorAccess(syntaxHighlighterConfig, 'hrColor', color) || color);
                        break;
                    
                    case "\\":
                        // 粗体和斜体
                        u(match[0], safeColorAccess(syntaxHighlighterConfig, 'boldOrItalicColor', color) || color);
                        
                        if (match[0].length === 6) {
                            // 处理粗体
                            if (boldState) {
                                if (!italicState) {
                                    // 结束粗体
                                    boldState = false;
                                }
                            } else {
                                if (italicState) {
                                    // 开始粗体(已有斜体)
                                    boldState = true;
                                } else {
                                    // 开始粗体
                                    stack.push({
                                        text: text,
                                        pos: pos,
                                        regex: x,
                                        color: safeColorAccess(syntaxHighlighterConfig, 'boldOrItalicColor', color) || color,
                                        boldState: true,
                                        italicState: false,
                                        context: "bold"
                                    });
                                }
                            }
                        } else {
                            // 处理斜体
                            if (italicState) {
                                if (!boldState) {
                                    // 结束斜体
                                    italicState = false;
                                }
                            } else {
                                if (boldState) {
                                    // 开始斜体(已有粗体)
                                    italicState = true;
                                } else {
                                    // 开始斜体
                                    stack.push({
                                        text: text,
                                        pos: pos,
                                        regex: x,
                                        color: safeColorAccess(syntaxHighlighterConfig, 'boldOrItalicColor', color) || color,
                                        boldState: false,
                                        italicState: true,
                                        context: "italic"
                                    });
                                }
                            }
                        }
                        break;
                    
                    case "&":
                        // HTML实体
                        u(match[0], safeColorAccess(syntaxHighlighterConfig, 'entityColor', color) || color);
                        break;
                    
                    case "~":
                        // 签名
                        u(match[0], safeColorAccess(syntaxHighlighterConfig, 'signatureColor', color) || color);
                        break;
                    
                    default:
                        // 默认处理
                        u(match[0], safeColorAccess(syntaxHighlighterConfig, 'externalLinkColor', color) || color);
                }
                
                // 将当前任务重新推入栈中,继续处理剩余文本
                stack.push({
                    text: text,
                    pos: pos,
                    regex: regex,
                    color: color,
                    boldState: boldState,
                    italicState: italicState,
                    context: context
                });
                // 移除break语句,让循环继续处理当前任务的剩余文本
            }
            
            // 如果当前任务处理完毕,处理剩余文本
            if (match === null && pos < text.length) {
                u(text.substring(pos), color);
                m = text.length;
            }
            
        }
        
        // 检查栈深度限制:使用stack.length来反映实际栈大小
        if (stack.length >= MAX_STACK_DEPTH) {
            console.error('Stack depth exceeded maximum limit:', stack.length);
            // 退出循环,避免无限递归 - 通过设置stack为空数组来终止循环
            stack = [];
        }
        
        // 处理剩余文本
        if (m < h.length) {
            u(h.substring(m), "");
        }

        var t = Date.now();
        if (t - e > safeConfigAccess(syntaxHighlighterConfig, 'timeout', 20)) {
            clearInterval(y);
            g.removeEventListener("input", E);
            g.removeEventListener("scroll", R);
            g.removeEventListener("scroll", F);
            p.disconnect();
            f.disconnect();
            d.nodeValue = "";
            var a = {
                zh: "此页面上的语法突出显示被禁用,因为它花费的时间太长。允许的突出显示时间最长为$1毫秒,而您的计算机则为$2毫秒。请尝试关闭一些标签和程序,然后单击\"显示预览\"或\"显示更改\"。如果不起作用,请尝试使用其他网页浏览器,如果还不起作用,请尝试使用速度更快的计算机。",
                "zh-hans": "此页面上的语法突出显示被禁用,因为它花费的时间太长。允许的突出显示时间最长为$1毫秒,而您的计算机则为$2毫秒。请尝试关闭一些标签和程序,然后单击\"显示预览\"或\"显示更改\"。如果不起作用,请尝试使用其他网页浏览器,如果还不起作用,请尝试使用速度更快的计算机。",
                "zh-hant": "此頁面上的語法突出顯示被禁用,因為它花費的時間太長。允許的突出顯示時間最長為$1毫秒,而您的計算機則為$2毫秒。請嘗試關閉一些標籤和程序,然後單擊\"顯示預覽\"或\"顯示更改\"。如果不起作用,請嘗試使用其他網頁瀏覽器,如果还不起作用,請嘗試使用速度更快的計算機。"
            };
            var n = mw.config.get("wgUserLanguage");
            a = a[n] || a["zh-hant"] || a.zh;
            return g.style.backgroundColor = "", g.style.marginTop = "0", l.removeAttribute("dir"), l.removeAttribute("lang"), l.setAttribute("style", "color:red; font-size:small"), void (l.textContent = a.replace("$1", safeConfigAccess(syntaxHighlighterConfig, 'timeout', 20)).replace("$2", t - e));
        }

        // 智能增量更新:只更新变化的CSS样式部分
        var newCSS = o.substring(2).replace(/\\n/g, "\\A ") + "'}";
        newCSS += "#wpTextbox0>span::after{visibility:hidden}";
        
        // 如果CSS内容没有变化,避免不必要的DOM操作
        if (lastHighlightState !== newCSS) {
            d.nodeValue = newCSS;
            lastHighlightState = newCSS;
        }
        
        // 智能span元素管理:只创建或删除需要的元素
        if (b < r) {
            // 需要添加新的span元素
            var s = document.createDocumentFragment();
            for (; b < r; b++) {
                var span = document.createElement("span");
                span.id = "s" + b;
                s.appendChild(span);
                spanCache[b] = span; // 缓存span元素
            }
            l.appendChild(s);
        } else if (b > r) {
            // 需要删除多余的span元素
            for (var j = b - 1; j >= r; j--) {
                var spanToRemove = document.getElementById("s" + j);
                if (spanToRemove && spanToRemove.parentNode === l) {
                    l.removeChild(spanToRemove);
                    delete spanCache[j]; // 清理缓存
                }
            }
            b = r;
        }
    }

    function R() {
        l.scrollLeft = g.scrollLeft;
    }

    function F() {
        l.scrollTop = g.scrollTop;
    }

    function a() {
        l.dir = g.dir;
    }

    function n() {
        g.previousSibling != l && (g.parentNode.insertBefore(l, g), f.disconnect(), f.observe(g.parentNode, {
            childList: !0
        }));
    }

    function s() {
        g.value != c && E();
        g.scrollLeft != l.scrollLeft && R();
        g.scrollTop != l.scrollTop && F();
        var e = window.getComputedStyle(l).height,
            t = g.offsetHeight ? window.getComputedStyle(g).height : "0px";
        e != t && (l.style.height = t, g.style.marginTop = "-" + t);
    }

    function i() {
        // 浏览器兼容性检查:如果MutationObserver不被支持,自动禁用高亮功能
        if (!window.MutationObserver) {
            console.warn("Syntax highlighter disabled: MutationObserver not supported");
            return;
        }
        
        // 全局变量安全检查:确保syntaxHighlighterConfig和syntaxHighlighterSiteConfig存在
        window.syntaxHighlighterConfig = window.syntaxHighlighterConfig || {};
        window.syntaxHighlighterSiteConfig = window.syntaxHighlighterSiteConfig || {};
        
        var e, t, i;

        function o(e, t, i) {
            void 0 === syntaxHighlighterConfig[e] && (syntaxHighlighterConfig[e] = syntaxHighlighterSiteConfig[e] || t);
            "normal" == syntaxHighlighterConfig[e] ? syntaxHighlighterConfig[e] = t : void 0 !== syntaxHighlighterConfig[e] || (void 0 !== syntaxHighlighterConfig.defaultColor && i ? syntaxHighlighterConfig[e] = syntaxHighlighterConfig.defaultColor : syntaxHighlighterConfig[e] = t);
        }

        (g = document.getElementById("wpTextbox1")) && (document.getElementById("wpTextbox0") || (window.syntaxHighlighterSiteConfig = window.syntaxHighlighterSiteConfig || {}, window.syntaxHighlighterConfig = window.syntaxHighlighterConfig || {}, 
        // 补充缺失的默认数组配置
        syntaxHighlighterConfig.voidTags = syntaxHighlighterConfig.voidTags || [],
        syntaxHighlighterConfig.sourceTags = syntaxHighlighterConfig.sourceTags || [],
        syntaxHighlighterConfig.nowikiTags = syntaxHighlighterConfig.nowikiTags || [],
        
        o("backgroundColor", "#FFF", !1), o("foregroundColor", "#000", !1), o("boldOrItalicColor", "#EEE", !0), o("commentColor", "#EFE", !0), o("entityColor", "#DFD", !0), o("externalLinkColor", "#EFF", !0), o("headingColor", "#EEE", !0), o("hrColor", "#EEE", !0), o("listOrIndentColor", "#EFE", !0), o("parameterColor", "#FC6", !0), o("signatureColor", "#FC6", !0), o("tagColor", "#FEF", !0), o("tableColor", "#FFC", !0), o("templateColor", "#FFC", !0), o("wikilinkColor", "#EEF", !0), syntaxHighlighterConfig.nowikiTags = syntaxHighlighterConfig.nowikiTags || syntaxHighlighterSiteConfig.nowikiTags || ["nowiki", "pre"], syntaxHighlighterConfig.sourceTags = syntaxHighlighterConfig.sourceTags || syntaxHighlighterSiteConfig.sourceTags || ["math", "syntaxhighlight", "source", "timeline", "hiero"], syntaxHighlighterConfig.voidTags = syntaxHighlighterConfig.voidTags || syntaxHighlighterSiteConfig.voidTags || [], syntaxHighlighterConfig.timeout = syntaxHighlighterConfig.timeout || syntaxHighlighterSiteConfig.timeout || 20, syntaxHighlighterConfig.nowikiTags.forEach(function(e) {
            var cacheKey = "nowiki_" + e;
            if (!regexCache[cacheKey]) {
                regexCache[cacheKey] = new RegExp("(</" + e + ">)\\n*|" + r, "gm");
            }
            L[e] = regexCache[cacheKey];
        }), l = document.createElement("div"), e = document.createElement("style"), 
        // 添加样式冲突防护
        e.setAttribute("scoped", "scoped"), // 限制样式仅作用于当前组件
        e.setAttribute("data-syntax-highlighter", "true"), // 便于识别和调试
        d = e.appendChild(document.createTextNode("")), i = "vertical" == (t = window.getComputedStyle(g)).resize || "both" == t.resize ? "vertical" : "none", l.dir = g.dir, l.id = "wpTextbox0", l.lang = g.lang, l.style.backgroundColor = syntaxHighlighterConfig.backgroundColor, l.style.borderBottomLeftRadius = t.borderBottomLeftRadius, l.style.borderBottomRightRadius = t.borderBottomRightRadius, l.style.borderBottomStyle = t.borderBottomStyle, l.style.borderBottomWidth = t.borderBottomWidth, l.style.borderColor = "transparent", l.style.borderLeftStyle = t.borderLeftStyle, l.style.borderLeftWidth = t.borderLeftWidth, l.style.borderRightStyle = t.borderRightStyle, l.style.borderRightWidth = t.borderRightWidth, l.style.borderTopLeftRadius = t.borderTopLeftRadius, l.style.borderTopRightRadius = t.borderTopRightRadius, l.style.borderTopStyle = t.borderTopStyle, l.style.borderTopWidth = t.borderTopWidth, l.style.boxSizing = "border-box", l.style.clear = t.clear, l.style.fontFamily = t.fontFamily, l.style.fontSize = t.fontSize, l.style.lineHeight = "normal", l.style.marginBottom = "0", l.style.marginLeft = "0", l.style.marginRight = "0", l.style.marginTop = "0", l.style.overflowX = "auto", l.style.overflowY = "scroll", l.style.resize = i, l.style.tabSize = t.tabSize, l.style.whiteSpace = "pre-wrap", l.style.width = "100%", l.style.wordWrap = "normal", g.style.backgroundColor = "transparent", g.style.borderBottomLeftRadius = t.borderBottomLeftRadius, g.style.borderBottomRightRadius = t.borderBottomRightRadius, g.style.borderBottomStyle = t.borderBottomStyle, g.style.borderBottomWidth = t.borderBottomWidth, g.style.borderLeftStyle = t.borderLeftStyle, g.style.borderLeftWidth = t.borderLeftWidth, g.style.borderRightStyle = t.borderRightStyle, g.style.borderRightWidth = t.borderRightWidth, g.style.borderTopLeftRadius = t.borderTopLeftRadius, g.style.borderTopRightRadius = t.borderTopRightRadius, g.style.borderTopStyle = t.borderTopStyle, g.style.borderTopWidth = t.borderTopWidth, g.style.boxSizing = "border-box", g.style.clear = t.clear, g.style.color = syntaxHighlighterConfig.foregroundColor, g.style.fontFamily = t.fontFamily, g.style.fontSize = t.fontSize, g.style.lineHeight = "normal", g.style.marginLeft = "0", g.style.marginRight = "0", g.style.marginTop = "-" + t.height, g.style.overflowX = "auto", g.style.overflowY = "scroll", g.style.padding = "0", g.style.resize = i, g.style.tabSize = t.tabSize, g.style.whiteSpace = "pre-wrap", g.style.width = "100%", g.style.wordWrap = "normal", g.parentNode.insertBefore(l, g), document.head.appendChild(e), g.addEventListener("input", E), g.addEventListener("scroll", R), g.addEventListener("scroll", F), (p = new MutationObserver(a)).observe(g, {
            attributes: !0
        }), (f = new MutationObserver(n)).observe(g.parentNode, {
            childList: !0
        }), y = setInterval(s, 500), E()));
    }

    var o = mw.config.get("wgAction"),
        e = $.client.profile().layout;
    "edit" != o && "submit" != o || "wikitext" != mw.config.get("wgPageContentModel") || "trident" == e || ("complete" == document.readyState ? i() : window.addEventListener("load", i));
    
    // 添加页面卸载时的资源清理逻辑
    function cleanup() {
        // 清理定时器
        if (y) {
            clearInterval(y);
            y = null;
        }
        // 清理观察者
        [p, f].forEach(observer => observer?.disconnect());
        // 清理事件监听
        if (g) {
            g.removeEventListener("input", E);
            g.removeEventListener("scroll", R);
            g.removeEventListener("scroll", F);
        }
        // 清理DOM元素
        l?.parentNode?.removeChild(l);
        d?.parentNode?.parentNode?.removeChild(d.parentNode); // 移除style元素
        // 重置变量
        l = g = d = c = y = p = f = b = null;
    }
    // 双重事件监听确保清理
    window.addEventListener('beforeunload', cleanup);
    window.addEventListener('unload', cleanup);
});