2023年政策修订增补工作正在进行中,欢迎参与!
  • Moegirl.ICU:萌娘百科流亡社群 581077156(QQ),欢迎对萌娘百科运营感到失望的编辑者加入
  • Moegirl.ICU:账号认领正在试运行,有意者请参照账号认领流程

User:AnnAngela/js/wikiplus-highlight.js

萌娘百科,万物皆可萌的百科全书!转载请标注来源页面的网页链接,并声明引自萌娘百科。内容不可商用。
跳转到导航 跳转到搜索

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

  • Firefox/Safari:按住“Shift”的同时单击“刷新”,或按“Ctrl-F5”或“Ctrl-R”(Mac为“⌘-R”)
  • Google Chrome:按“Ctrl-Shift-R”(Mac为“⌘-Shift-R”)
  • Internet Explorer:按住“Ctrl”的同时单击“刷新”,或按“Ctrl-F5”
  • Opera:在“工具→首选项”中清除缓存
如果您已登录但该页面出现未登录状态,请尝试在地址栏的地址最后添加代码?_=1来访问最新页面。
添加代码后的本页地址如下:-{R|https://moegirl.icu/User:AnnAngela/js/wikiplus-highlight.js?_=1}-
// From [[Special:固定链接/5281362]]
/* jshint bitwise: true, curly: true, nonew: true, singleGroups: true, unused: true, varstmt: true */
/* global CodeMirror, Wikiplus */
"use strict";
$(() => (async () => {
    await mw.loader.using(["oojs-ui-windows", "mediawiki.util"]);
    mw.util.escapeRegExp = mw.util.escapeRegExp || mw.RegExp.escape;
    const contentModel = mw.config.get("wgPageContentModel");
    const modes = {
        css: ["css", "//cdn.jsdelivr.net/npm/[email protected]/mode/css/css.min.js"],
        "sanitized-css": ["css", "//cdn.jsdelivr.net/npm/[email protected]/mode/css/css.min.js"],
        javascript: ["javascript", "//cdn.jsdelivr.net/npm/[email protected]/mode/javascript/javascript.min.js"],
        json: ["javascript", "//cdn.jsdelivr.net/npm/[email protected]/mode/javascript/javascript.min.js"],
        Scribunto: ["lua", "//cdn.jsdelivr.net/npm/[email protected]/mode/lua/lua.min.js"],
        wikitext: ["mediawiki", "//cdn.jsdelivr.net/gh/bhsd-harry/[email protected]/otherwiki/mediawiki.min.js"],
    };
    const existing = mw.config.get("wgArticleId");
    const revid = mw.config.get("wgRevisionId");
    if (!mw.config.get("wgIsArticle") || !(window.Wikiplus ||
        ["ready", "loaded", "loading", "executing"].includes(mw.loader.getState("ext.gadget.Wikiplus")))) {
        return;
    }
    let inited, cm, mode, lastPtn = "";
    const $search = $("<input>", {
        id: "Wikiplus-Quickedit-Search", placeholder: "查找",
    });
    const $searchClose = $("<span>", {
        text: "×", id: "Wikiplus-Quickedit-Search-Close",
    });
    const overlay = {
        token: () => {
        },
    };
    const onInput = () => {
        $search.css("background-color", "").off("input", onInput);
    };
    const token = (str) => {
        const ini = new RegExp(`[^${mw.util.escapeRegExp(str[0])}]`, "i");
        return (stream) => {
            if (stream.match(str, true, true)) {
                return "search";
            }
            stream.next();
            stream.eatWhile(ini);
        };
    };
    const findNext = () => {
        const ptn = $search.val();
        if (!ptn) {
            return;
        }
        if (ptn !== lastPtn) {
            cm.removeOverlay(overlay);
            overlay.token = token(ptn);
            cm.addOverlay(overlay);
            lastPtn = ptn;
        }
        const regexp = new RegExp(mw.util.escapeRegExp(ptn), "i");
        const { line, ch } = cm.getCursor();
        let anchor, head, search = cm.getLine(line).slice(ch).search(regexp);
        if (search >= 0) {
            anchor = {
                line, ch: ch + search,
            };
            head = {
                line, ch: ch + search + ptn.length,
            };
        } else {
            const count = cm.lineCount();
            let i;
            for (i = line + 1; i <= line + count; i++) {
                search = cm.getLine(i % count).search(regexp);
                if (search >= 0) {
                    break;
                }
            }
            if (i <= line + count) {
                anchor = {
                    line: i % count, ch: search,
                };
                head = {
                    line: i % count, ch: search + ptn.length,
                };
            } else {
                $search.css("background-color", "pink").on("input", onInput);
                return;
            }
        }
        cm.setSelection(anchor, head);
        cm.scrollIntoView({
            from: anchor, to: head,
        });
    };
    const highlight = ($textarea) => {
        const height = $textarea.height();
        const update = () => {
            cm.save();
        };
        const $summary = $textarea.nextAll("#Wikiplus-Quickedit-Summary-Input");
        const $submit = $textarea.nextAll("button").mousedown(update).first();
        const $minor = $submit.prev().children("#Wikiplus-Quickedit-MinorEdit");
        const $searchContainer = $("<div>", {
            id: "Wikiplus-Quickedit-Search-Div", html: [$search, $searchClose],
        }).hide().insertBefore($textarea);
        const findNew = () => {
            $searchContainer.show();
            $search.select().focus()[0].scrollIntoView({
                behavior: "smooth",
            });
        };
        $searchClose.click(() => {
            cm.removeOverlay(overlay);
            $searchContainer.hide();
            lastPtn = "";
        });
        if (cm) {
            cm.toTextArea();
        }
        cm = CodeMirror.fromTextArea($textarea[0], $.extend({
            mode: mode[0], mwConfig: window.mwConfig, lineWrapping: true, lineNumbers: true,
        }, contentModel === "wikitext" ? {} : {
            indentUnit: 4, indentWithTabs: true,
        }, contentModel === "json" ? {
            json: true,
        } : {}));
        mw.hook("wiki-codemirror").fire(cm);
        cm.setSize(null, height);
        cm.addKeyMap({
            "Ctrl-S": () => {
                update();
                $submit.triggerHandler("click");
            }, "Shift-Ctrl-S": () => {
                update();
                $minor.click();
                $submit.triggerHandler("click");
            },
        });
        $textarea.closest(".Wikiplus-InterBox").keydown(e => {
            if (!e.metaKey && !e.ctrlKey || !["f", "g"].includes(e.key)) {
                return;
            }
            e.preventDefault();
            if (e.key === "f") {
                findNew();
            } else {
                findNext();
            }
        });
        $summary.add([$minor[0], $search[0]]).off("keydown").keydown(e => {
            if (!e.metaKey && !e.ctrlKey || e.keyCode !== 83) {
                return;
            }
            e.stopImmediatePropagation();
            update();
            if (e.shiftKey) {
                $minor.click();
            }
            $submit.triggerHandler("click");
        });
        if (Wikiplus.getSetting("esc_to_exit_quickedit")) {
            cm.addKeyMap({
                Esc: () => {
                    $("#Wikiplus-Quickedit-Back").click();
                },
            });
        }
    };
    const init = async ($node) => {
        const $textarea = $node.find("#Wikiplus-Quickedit");
        const text = $textarea[0].value;
        $search.keyup(e => {
            if (e.key === "Enter") {
                findNext();
            }
        });
        if (!inited) {
            inited = true;
            mw.loader.load("//cdn.jsdelivr.net/npm/[email protected]/lib/codemirror.min.css", "text/css");
            mw.loader.addStyleTag(`.Wikiplus-InterBox {
z-index: 100 !important; }
			#Wikiplus-Quickedit + .CodeMirror {
border: 1px solid #c8ccd1; line-height: 1.3; clear: both; }
			#Wikiplus-Quickedit-Search-Div {
margin: 7px 0 5px; }
			#Wikiplus-Quickedit-Search-Close {
font-size: 20px; margin: 7px; vertical-align: middle; cursor: pointer; }
			#Wikiplus-Quickedit-Search {
width: 50%; }
			.cm-search {
background-color: rgba(255, 255, 0, .4); }` );
            if (["wikitext", "Scribunto"].includes(contentModel)) {
                mw.loader.load("//cdn.jsdelivr.net/gh/bhsd-harry/[email protected]/otherwiki/mediawiki.min.css", "text/css");
            }
        }
        let model;
        if (contentModel !== "Scribunto" || !existing) {
            model = contentModel;
        } else {
            const preload = Object.entries(Wikiplus.preloadData).filter(([, str]) => str === text);
            if (preload.every(([key]) => key.startsWith(revid))) {
                model = "Scribunto";
            } else if (preload.every(([key]) => !key.startsWith(revid))) {
                model = "wikitext";
            } else if (await OO.ui.confirm("请选择内容模型:", {
                actions: [
                    {
                        label: "Lua",
                    }, {
                        label: "Wikitext", action: "accept",
                    },
                ],
            })) {
                model = "wikitext";
            } else {
                model = "Scribunto";
            }
        }
        mode = modes[model];
        if (!window.CodeMirror) {
            await $.get({
                dataType: "script",
                cache: true,
                url: "//cdn.jsdelivr.net/npm/[email protected]/lib/codemirror.min.js",
            });
        }
        if (!window.CodeMirror) {
            window.CodeMirror = {
                modes: {},
            };
        } else if (!window.CodeMirror.modes) {
            window.CodeMirror.modes = {};
        } if (!window.CodeMirror.modes[mode[0]]) {
            await $.get({
                dataType: "script",
                cache: true,
                url: mode[1],
            });
        }
        if (!window.mwConfig && model === "wikitext") {
            window.mwConfig = window.mwConfig || await $.get({
                cache: true,
                url: "//cdn.jsdelivr.net/gh/bhsd-harry/[email protected]/otherwiki/gadget-CodeMirror.json",
            });
        }
        highlight($textarea);
    };
    const callback = (records) => {
        const $node = $(records[0].addedNodes[0]);
        if (!$node.is(".Wikiplus-InterBox:has( #Wikiplus-Quickedit )")) {
            return;
        }
        init($node);
        observer2.disconnect();
        observer2.observe($node.find("#Wikiplus-Quickedit-Preview-Output")[0], {
            childList: true,
        });
    };
    const observer = new MutationObserver(callback);
    const callback2 = (records) => {
        const $node = $(records[0].addedNodes[1]);
        if ($node.hasClass("mw-body-content")) {
            mw.hook("wikipage.content").fire($node);
        }
    };
    const observer2 = new MutationObserver(callback2);
    observer.observe(document.body, {
        childList: true,
    });

    // 以下内容引自[[MW:Extension:CodeMirror]]
    $.valHooks.textarea = {
        get: (ele) => ele.id === "Wikiplus-Quickedit" && cm ? cm.getValue() : ele.value,
        set: (ele, value) => ele.id === "Wikiplus-Quickedit" && cm ? cm.setValue(value) : ele.value = value,
    };

})());