MediaWiki:Gadget-NoteTA.js
注意:在发布之后,您可能需要清除浏览器缓存才能看到所作出的变更的影响。
- Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5或Ctrl-R(Mac为⌘-R)
- Google Chrome:按Ctrl-Shift-R(Mac为⌘-Shift-R)
- Internet Explorer或Edge:按住Ctrl的同时单击刷新,或按Ctrl-F5
- Opera:按 Ctrl-F5。
/**
* SPDX-License-Identifier: CC-BY-SA-4.0
* _addText: '{{Gadget Header|license=CC-BY-SA-4.0}}'
*
* @base {@link https://zh.wikipedia.org/wiki/MediaWiki:Gadget-noteTA.js}
* @source {@link https://git.qiuwen.net.cn/InterfaceAdmin/QiuwenGadgets/src/branch/master/src/NoteTA}
* @license CC-BY-SA-4.0 {@link https://www.qiuwenbaike.cn/wiki/H:CC-BY-SA-4.0}
*/
/**
* +------------------------------------------------------------+
* | === WARNING: GLOBAL GADGET FILE === |
* +------------------------------------------------------------+
* | All changes should be made in the repository, |
* | otherwise they will be lost. |
* +------------------------------------------------------------+
* | Changes to this page may affect many users. |
* | Please discuss changes by opening an issue before editing. |
* +------------------------------------------------------------+
*/
/* <nowiki> */
(() => {
"use strict";
// dist/NoteTA/NoteTA.js
function _createForOfIteratorHelper(r, e) {
var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
if (!t) {
if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) {
t && (r = t);
var n = 0, F = function() {
};
return { s: F, n: function() {
return n >= r.length ? { done: true } : { done: false, value: r[n++] };
}, e: function(r2) {
throw r2;
}, f: F };
}
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
var o, a = true, u = false;
return { s: function() {
t = t.call(r);
}, n: function() {
var r2 = t.next();
return a = r2.done, r2;
}, e: function(r2) {
u = true, o = r2;
}, f: function() {
try {
a || null == t.return || t.return();
} finally {
if (u) throw o;
}
} };
}
function _unsupportedIterableToArray(r, a) {
if (r) {
if ("string" == typeof r) return _arrayLikeToArray(r, a);
var t = {}.toString.call(r).slice(8, -1);
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
}
}
function _arrayLikeToArray(r, a) {
(null == a || a > r.length) && (a = r.length);
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
return n;
}
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
var _iterator = _createForOfIteratorHelper(__getOwnPropNames(from)), _step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done; ) {
let key = _step.value;
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: () => from[key],
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target,
mod
));
//! src/NoteTA/options.json
var version = "1.0";
var portletClass = "x-noteTA-viewer";
//! src/NoteTA/modules/util/ApiRetryFailError.tsx
var import_ext_gadget2 = __toESM(require("ext.gadget.React"), 1);
//! src/NoteTA/modules/i18n.ts
var import_ext_gadget = require("ext.gadget.i18n");
var getI18nMessages = () => {
return {
ApiRetryFailError: (0, import_ext_gadget.localize)({
en: "Api calls failed $1 time(s) in a row. Errors: ",
"zh-hans": "Api 调用连续失败 $1 次,$1 次调用的错误分别为:",
"zh-hant": "Api 調用連續失敗 $1 次,$1 次調用的錯誤分別為:"
}),
Loading: (0, import_ext_gadget.localize)({
en: "Loading...",
"zh-hans": "正在加载……",
"zh-hant": "正在載入……"
}),
Title: (0, import_ext_gadget.localize)({
en: "NoteTA",
"zh-hans": "字词转换",
"zh-hant": "字詞轉換"
})
};
};
var i18nMessages = getI18nMessages();
var getMessage = (key) => {
return i18nMessages[key] || key;
};
//! src/NoteTA/modules/util/ApiRetryFailError.tsx
var ApiRetryFailError = class extends Error {
errors;
constructor(errors) {
super("Api calls failed ".concat(errors.length, " time(s) in a row."));
this.name = "ApiRetryFailError";
this.errors = errors;
}
toJQuery() {
const errorCount = this.errors.length;
const element = /* @__PURE__ */ import_ext_gadget2.default.createElement("div", {
className: "error"
}, /* @__PURE__ */ import_ext_gadget2.default.createElement("p", null, getMessage("ApiRetryFailError").replace(/\$1/g, errorCount.toString())), /* @__PURE__ */ import_ext_gadget2.default.createElement("ol", null, this.errors.map((error, index) => /* @__PURE__ */ import_ext_gadget2.default.createElement("li", {
key: index
}, error.split("\n").map((line, number) => /* @__PURE__ */ import_ext_gadget2.default.createElement("p", {
key: number
}, line))))));
const $element = $(element);
return $element;
}
};
//! src/NoteTA/modules/api.ts
var import_ext_gadget3 = require("ext.gadget.Util");
var api = (0, import_ext_gadget3.initMwApi)("NoteTA/".concat(version));
//! src/NoteTA/modules/parseWikitext.ts
var parseWithRetry = (args, count = 3, previousErrors = []) => {
if (!count) {
return $.Deferred().reject(new ApiRetryFailError(previousErrors));
}
const deferred = $.Deferred();
void api.parse(...args).then((response) => {
void deferred.resolve(response);
}).catch((error) => {
console.error(error);
if (error && typeof error === "object" && "stack" in error) {
previousErrors[previousErrors.length] = error.stack;
} else {
previousErrors[previousErrors.length] = String(error);
}
parseWithRetry(args, --count, previousErrors).then((newResponse) => {
void deferred.resolve(newResponse);
}).catch((newError) => {
void deferred.reject(newError);
});
});
return deferred;
};
var parseWikitext = (...args) => {
return parseWithRetry(args);
};
//! src/NoteTA/modules/viewer.tsx
var import_ext_gadget4 = __toESM(require("ext.gadget.React"), 1);
//! src/NoteTA/modules/util/assert.ts
function assert(value, valueName) {
if (!value) {
throw new Error("Assert Fail, ".concat(valueName, " == false."));
}
}
//! src/NoteTA/modules/initViewMap.ts
var viewerMap = /* @__PURE__ */ new Map();
//! src/NoteTA/modules/initWindowManager.ts
var initWindowManager = () => {
return new OO.ui.WindowManager();
};
var windowManager = initWindowManager();
//! src/NoteTA/modules/viewer.tsx
var getViewer = ($body, hash) => {
if (viewerMap.has(hash)) {
const storedViewer = viewerMap.get(hash);
assert(storedViewer, "viewer");
return storedViewer;
}
const $targetElement = $body.find("#noteTA-".concat(hash));
if (!$targetElement.length) {
throw new Error(`Can't get Element "#noteTA-`.concat(hash, '".'));
}
const {
wgPageName,
wgUserVariant
} = mw.config.get();
class NoteTAViewer extends OO.ui.ProcessDialog {
dataIsLoaded;
executePromise;
mutationObserver;
$realContent;
$body;
static lastError;
static noteTAParseText;
constructor() {
super({
size: "larger"
});
this.dataIsLoaded = false;
this.$realContent = $(/* @__PURE__ */ import_ext_gadget4.default.createElement("div", null));
this.mutationObserver = new MutationObserver(this.updateSize.bind(this));
this.mutationObserver.observe(this.$realContent.get(0), {
childList: true,
subtree: true
});
}
initialize() {
super.initialize();
const panelLayout = new OO.ui.PanelLayout({
expanded: false,
padded: true
});
this.$realContent.appendTo(panelLayout.$element);
panelLayout.$element.appendTo(this.$body);
return this;
}
getSetupProcess(data) {
return super.getSetupProcess(data).next(() => {
void this.doExecuteWrap();
void this.executeAction("main");
});
}
getActionProcess(action) {
const isMainAction = action === "main";
return super.getActionProcess(action).next(() => {
if (isMainAction) {
return this.doExecuteWrap();
}
}).next(() => {
if (isMainAction && NoteTAViewer.lastError) {
return NoteTAViewer.lastError;
}
return super.getActionProcess(action).execute();
});
}
destroy() {
this.mutationObserver.disconnect();
}
static getNoteTAParseText() {
if (NoteTAViewer.noteTAParseText) {
return $.Deferred().resolve(NoteTAViewer.noteTAParseText);
}
const $noteTAtitle = $targetElement.find(".noteTA-title");
const actualTitle = wgPageName.replace(/_/g, " ");
let wikitext = "";
const titleDeferred = $.Deferred();
if ($noteTAtitle.length) {
const titleConv = $noteTAtitle.attr("data-noteta-code");
assert(titleConv, "titleConv");
let titleDesc = $noteTAtitle.attr("data-noteta-desc");
if (titleDesc) {
titleDesc = "(".concat(titleDesc, ")");
} else {
titleDesc = "";
}
wikitext += '<span style="float:right">{{edit|'.concat(actualTitle, "|section=0}}</span>\n");
wikitext += "; 本文使用[[Help:字词转换处理|标题手工转换]]\n";
wikitext += "* 转换标题为:-{D|".concat(titleConv, "}-").concat(titleDesc, "\n");
wikitext += "* 实际标题为:-{R|".concat(actualTitle, "}-;当前显示为:-{|").concat(titleConv, "}-\n");
void titleDeferred.resolve();
} else {
parseWikitext("{{noteTA/multititle|".concat(actualTitle, "}}"), {
title: actualTitle,
variant: "zh"
}).then((resultHtml) => {
const $multiTitle = $($.parseHTML(resultHtml)).find(".noteTA-multititle");
if ($multiTitle.length) {
wikitext += "; 本文[[Help:字词转换处理|标题可能经过转换]]\n* 转换标题为:";
const textVariant = {};
const variantText = {};
var _iterator2 = _createForOfIteratorHelper($multiTitle.children()), _step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done; ) {
const element = _step2.value;
const $element = $(element);
const variant = $element.attr("data-noteta-multititle-variant");
assert(variant, "variant");
const text = $element.text().trim();
variantText[variant] = text;
const textVariantArray = textVariant[text];
if (textVariantArray) {
textVariantArray[textVariantArray.length] = variant;
} else {
textVariant[text] = [variant];
}
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
const titleConverted = variantText[wgUserVariant];
const multiTitle = [];
for (const key in variantText) {
if (!Object.hasOwn(variantText, key)) {
continue;
}
const text = variantText[key];
if (text === null || text === void 0) {
continue;
}
const variants = textVariant[text];
if (!variants) {
continue;
}
var _iterator3 = _createForOfIteratorHelper(variants), _step3;
try {
for (_iterator3.s(); !(_step3 = _iterator3.n()).done; ) {
const variant = _step3.value;
variantText[variant] = null;
}
} catch (err) {
_iterator3.e(err);
} finally {
_iterator3.f();
}
const variantsName = variants.map((variant) => "-{R|{{MediaWiki:Variantname-".concat(variant, "}}}-")).join("、");
multiTitle[multiTitle.length] = "".concat(variantsName, ":-{R|").concat(text, "}-");
}
const subItemSeparator = "\n** ";
wikitext += "".concat(subItemSeparator).concat(multiTitle.join(subItemSeparator));
wikitext += "\n* 实际标题为:-{R|".concat(actualTitle, "}-;当前显示为:-{R|").concat(titleConverted, "}-\n");
}
void titleDeferred.resolve();
}).catch((error) => {
void titleDeferred.reject(error);
});
}
const deferred = $.Deferred();
titleDeferred.then(() => {
const $noteTAgroups = $targetElement.find(".noteTA-group > *[data-noteta-group]");
var _iterator4 = _createForOfIteratorHelper($noteTAgroups), _step4;
try {
for (_iterator4.s(); !(_step4 = _iterator4.n()).done; ) {
const element = _step4.value;
const $element = $(element);
switch ($element.attr("data-noteta-group-source")) {
case "template":
wikitext += "{{CGroup/".concat($element.attr("data-noteta-group"), "}}\n");
break;
case "module":
wikitext += "{{#invoke:CGroupViewer|dialog|".concat($element.attr("data-noteta-group"), "}}\n");
break;
case "none":
wikitext += "; 本文使用的公共转换组“".concat($element.attr("data-noteta-group"), "”尚未创建\n");
wikitext += "* {{edit|Module:CGroup/".concat($element.attr("data-noteta-group"), "|创建公共转换组“").concat($element.attr("data-noteta-group"), "”}}\n");
break;
default:
wikitext += "; 未知公共转换组“".concat($element.attr("data-noteta-group"), "”来源“").concat($element.attr("data-noteta-group-source"), "”\n");
}
}
} catch (err) {
_iterator4.e(err);
} finally {
_iterator4.f();
}
const $noteTAlocal = $targetElement.find(".noteTA-local");
if ($noteTAlocal.length) {
wikitext += '<span style="float:right">{{edit|'.concat(actualTitle, "|section=0}}</span>\n");
wikitext += "; 本文使用[[Help:字词转换处理|全文手工转换]]\n";
const $noteTAlocals = $noteTAlocal.children("*[data-noteta-code]");
var _iterator5 = _createForOfIteratorHelper($noteTAlocals), _step5;
try {
for (_iterator5.s(); !(_step5 = _iterator5.n()).done; ) {
const element = _step5.value;
const $element = $(element);
let localDesc = $element.attr("data-noteta-desc");
if (localDesc) {
localDesc = "(".concat(localDesc, ")");
} else {
localDesc = "";
}
const localConv = $element.attr("data-noteta-code");
wikitext += "* -{D|".concat(localConv, "}-").concat(localDesc, "当前显示为:-{").concat(localConv, "}-\n");
}
} catch (err) {
_iterator5.e(err);
} finally {
_iterator5.f();
}
}
wikitext += "{{noteTA/footer}}\n";
NoteTAViewer.noteTAParseText = wikitext;
void deferred.resolve(wikitext);
}).catch((error) => {
void deferred.reject(error);
});
return deferred;
}
doExecute() {
if (this.dataIsLoaded) {
return $.Deferred().resolve();
}
this.$realContent.empty().append(/* @__PURE__ */ import_ext_gadget4.default.createElement("p", null, getMessage("Loading")));
return NoteTAViewer.getNoteTAParseText().then((wikitext) => parseWikitext(wikitext, {
title: "Template:CGroup/-",
variant: wgUserVariant
})).then((parsedHtml) => {
this.$realContent.empty().html(parsedHtml).addClass("".concat(portletClass, "-output"));
this.$realContent.find(".mw-collapsible").makeCollapsible();
this.updateSize();
this.dataIsLoaded = true;
}).catch((error) => {
if (error instanceof ApiRetryFailError) {
throw new OO.ui.Error(error.toJQuery(), {
recoverable: true
});
} else {
throw new OO.ui.Error(String(error), {
recoverable: false
});
}
});
}
doExecuteWrap() {
if (this.executePromise === void 0) {
this.executePromise = this.doExecute();
delete NoteTAViewer.lastError;
const executeDeferred = $.Deferred();
void this.executePromise.then((response) => {
void executeDeferred.resolve(response);
}).catch((error) => {
if (error instanceof OO.ui.Error) {
NoteTAViewer.lastError = error;
} else {
void executeDeferred.reject(error);
}
}).always(() => {
delete this.executePromise;
});
return executeDeferred;
}
const deferred = $.Deferred();
void this.executePromise.then((response) => {
void deferred.resolve(response);
}).catch((error) => {
if (error instanceof OO.ui.Error) {
NoteTAViewer.lastError = error;
} else {
void deferred.reject(error);
}
}).always(() => {
delete this.executePromise;
});
return deferred;
}
}
NoteTAViewer.static = {
...OO.ui.ProcessDialog.static
};
NoteTAViewer.static.name = "NoteTAViewer-".concat(hash);
NoteTAViewer.static.title = getMessage("Title");
NoteTAViewer.static.actions = [{
label: mw.msg("ooui-dialog-process-dismiss"),
flags: "safe"
}];
const viewer = new NoteTAViewer();
windowManager.addWindows([viewer]);
viewerMap.set(hash, viewer);
return viewer;
};
var resetAllViewer = () => {
var _iterator6 = _createForOfIteratorHelper(viewerMap.values()), _step6;
try {
for (_iterator6.s(); !(_step6 = _iterator6.n()).done; ) {
const viewer = _step6.value;
viewer.destroy();
}
} catch (err) {
_iterator6.e(err);
} finally {
_iterator6.f();
}
viewerMap.clear();
void windowManager.clearWindows();
};
//! src/NoteTA/modules/initGlobalMethods.ts
var portletId;
var initGlobalMethods = ($body) => {
const globalMethods = {
init() {
},
deInit() {
}
};
const {
skin
} = mw.config.get();
if (skin === "vector") {
portletId = "p-noteTA";
let $noteTATab;
globalMethods.init = () => {
if ($noteTATab || !portletId) {
return;
}
const noteTATab = mw.util.addPortlet(portletId);
if (!noteTATab) {
return;
}
$noteTATab = $(noteTATab);
$noteTATab.removeClass("mw-portlet-".concat(portletId)).addClass(["mw-portlet-".concat(portletId.replace("p-", "")), "vector-menu-tabs", "vector-menu-tabs-legacy"]);
$body.find("#p-variants").after($noteTATab);
};
globalMethods.deInit = () => {
if (!$noteTATab) {
return;
}
$noteTATab.find("ul").empty();
if (portletId) {
mw.util.hidePortlet(portletId);
}
};
} else if (skin === "vector-2022") {
portletId = "p-associated-pages";
globalMethods.deInit = () => {
$body.find(".".concat(portletClass)).remove();
};
}
return globalMethods;
};
//! src/NoteTA/NoteTA.ts
var import_ext_gadget6 = require("ext.gadget.Util");
//! src/NoteTA/modules/util/generatePortletLink.tsx
var import_ext_gadget5 = __toESM(require("ext.gadget.React"), 1);
var generatePortletLink = (hash) => {
if (!portletId) {
return;
}
const portletLink = mw.util.addPortletLink(portletId, "#", "汉/漢", "ca-noteTA-".concat(hash));
if (!portletLink) {
return;
}
portletLink.classList.add("ca-noteTA");
const $portletLink = $(portletLink).addClass(portletClass);
$portletLink.find("a").empty().append(/* @__PURE__ */ import_ext_gadget5.default.createElement("div", null, /* @__PURE__ */ import_ext_gadget5.default.createElement("span", {
className: ["".concat(portletClass, "__label"), "".concat(portletClass, "__label-hans")]
}, "汉"), /* @__PURE__ */ import_ext_gadget5.default.createElement("span", {
className: ["".concat(portletClass, "__label"), "".concat(portletClass, "__label-hant")]
}, "漢")));
return $portletLink;
};
//! src/NoteTA/NoteTA.ts
var isInit = false;
mw.hook("wikipage.content").add(function noteTA($content) {
const $body = $content.parents("body");
if (!isInit) {
isInit = true;
windowManager.$element.appendTo($body);
}
resetAllViewer();
const globalMethods = initGlobalMethods($body);
globalMethods.deInit();
globalMethods.init();
var _iterator7 = _createForOfIteratorHelper($body.find(".mw-indicator[id^=mw-indicator-noteTA-]")), _step7;
try {
for (_iterator7.s(); !(_step7 = _iterator7.n()).done; ) {
const element = _step7.value;
const hash = element.id.replace(/^mw-indicator-noteTA-/, "");
let $element = $(element);
if (portletId) {
$element.hide();
const $portletLink = generatePortletLink(hash);
if (!$portletLink) {
continue;
}
$element = $portletLink;
}
const openerListener = (event) => {
if (!(0, import_ext_gadget6.checkA11yConfirmKey)(event)) {
return;
}
event.preventDefault();
getViewer($body, hash).open();
};
$element.on("click", openerListener);
$element.on("keydown", openerListener);
}
} catch (err) {
_iterator7.e(err);
} finally {
_iterator7.f();
}
});
})();