2023年政策修订增补工作正在进行中,欢迎参与!
User:AnnAngela/js/wikiplus-highlight.js
< User:AnnAngela | 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,
};
})());