MediaWiki:Gadget-ilhpp.js
外观
注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google Chrome、Firefox、Microsoft Edge及Safari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
/**!
* _________________________________________________________________________________
* | |
* | === WARNING: GLOBAL GADGET FILE === |
* | Changes to this page affect many users. |
* | Please discuss changes on the talk page, [[WP:VPT]] or GitHub before editing. |
* |_________________________________________________________________________________|
*
* Built from GitHub repository (https://github.com/diskdance/ilhpp), you should not make
* changes directly here.
*
* See https://github.com/diskdance/ilhpp/blob/main/README.MD#%E9%83%A8%E7%BD%B2%E6%96%B9%E6%B3%95 for build instructions.
*/
// <nowiki>
"use strict";
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const ext_gadget_HanAssist = require("ext.gadget.HanAssist");
const messages = {
"ilhpp-from": { "hans": "来自$1$2", "hant": "來自$1$2" },
"ilhpp-wp": { "hans": "维基百科", "hant": "維基百科" },
"ilhpp-more": { "hans": "阅读更多内容", "hant": "閱讀更多內容" },
"ilhpp-cta": { "hans": '中文维基百科暂无“$1”条目,但您可以帮助我们<a href="/w/index.php?title=$2&action=edit&redlink=1">创建它</a>!', "hant": '中文維基百科暫無「$1」條目,但您可以幫助我們<a href="/w/index.php?title=$2&action=edit&redlink=1">建立它</a>!' },
"ilhpp-settings": { "hans": "设置", "hant": "設定" },
"ilhpp-settings-footer": { "hans": "跨语言链接设置", "hant": "跨語言連結設定" },
"ilhpp-disam": { "hans": "页面标题涉及多个主题。", "hant": "頁面標題涉及多個主題。" },
"ilhpp-disam-more": { "hans": "查看相似页面", "hant": "顯示類似的頁面" },
"ilhpp-no-preview": { "hans": "该页面暂无预览。", "hant": "該頁面暫無預覽。" },
"ilhpp-error-not-found": { "hans": '该页面不存在。<br>您可以<a href="/w/index.php?title=$1&action=edit">帮助我们修复该问题</a>。', "hant": '該頁面不存在。<br>您可以<a href="/w/index.php?title=$1&action=edit">幫助我們修復該問題</a>。' },
"ilhpp-error": { "hans": "显示此预览时出现问题。", "hant": "顯示此頁面預覽時出現問題。" },
"ilhpp-goto": { "hans": "前往该页面", "hant": "前往該頁面" },
"ilhpp-close": { "hans": "关闭", "hant": "關閉" }
};
const DATA_ELEM_SELECTOR = ".ilh-all:not(.ilh-blue)";
const ORIG_A_SELECTOR = ".ilh-all:not(.ilh-blue) .ilh-page > a";
const FOREIGN_A_SELECTOR = `.ilh-all:not(.ilh-blue) .ilh-link > a`;
const ILH_LANG_SELECTOR = ".ilh-lang";
const ROOT_CLASS_DESKTOP = "ilhpp-popup-desktop";
const ROOT_CLASS_MOBILE = "ilhpp-popup-mobile";
const OVERLAY_CLASS_MOBILE = "ilhpp-mobile-overlay";
const PREF_KEY_LS = "ilhpp-prefs";
const PREF_KEY_MW = "userjs-ilhpp-prefs";
const RTL_LANGS = ["ar", "he", "fa", "ur", "ps", "sd", "ug", "dv", "syr"];
const LANG_WIKI_MAP = {
gsw: "als",
bho: "bh",
rup: "roa-rup",
lzh: "zh-classical",
nan: "zh-min-nan",
yue: "zh-yue"
};
const FOOTER_ANCHOR_ID = "ilhpp-footer-places-settings";
const DT_PTR_SHORT_SIDE_LENGTH_PX = 20;
const DT_PTR_WIDTH_PX = 8;
const DT_ATTACH_DELAY_MS = 300;
const DT_DETACH_DELAY_MS = 300;
const MB_SKELETON_STRIPE_COUNT = 6;
function isMobileDevice() {
return !!mw.config.get("wgMFMode") && matchMedia("(hover: none), (pointer: coarse)").matches;
}
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
function getDirection(langCode) {
var _a;
try {
if (Intl.Locale.prototype.getTextInfo || Intl.Locale.prototype.textInfo) {
const locale = new Intl.Locale(langCode);
return ((_a = locale.getTextInfo()) != null ? _a : locale.textInfo).direction;
}
} catch (e) {
return "ltr";
}
return RTL_LANGS.includes(langCode.split("-")[0].toLowerCase()) ? "rtl" : "ltr";
}
function normalizeTitle(title) {
return title.replace(/_/g, " ");
}
function normalizeLang(lang) {
return lang === "d" ? "en" : lang;
}
function normalizeWikiId(wikiId) {
var _a;
return (_a = LANG_WIKI_MAP[wikiId]) != null ? _a : wikiId;
}
function isWikipedia(wikiId) {
return wikiId !== "d";
}
function haveConflicts() {
return false;
}
function togglePageScroll(lock) {
document.body.classList.toggle("ilhpp-scroll-locked", lock);
}
let idCounter = 1;
function getUniqueId() {
return `ilhpp-${idCounter++}`;
}
var LinkMode = /* @__PURE__ */ ((LinkMode2) => {
LinkMode2["Orig"] = "ORIG";
LinkMode2["OrigAndUnlinkedForeign"] = "ORIG_N_UNLINKED_FOREIGN";
LinkMode2["Foreign"] = "FOREIGN";
LinkMode2["ForeignAndLangCode"] = "FOREIGN_N_LANG_CODE";
return LinkMode2;
})(LinkMode || {});
var PopupMode = /* @__PURE__ */ ((PopupMode2) => {
PopupMode2["Disabled"] = "DISABLED";
PopupMode2["OnHover"] = "ON_HOVER";
PopupMode2["OnClick"] = "ON_CLICK";
return PopupMode2;
})(PopupMode || {});
var OrigLinkColor = /* @__PURE__ */ ((OrigLinkColor2) => {
OrigLinkColor2["Red"] = "RED";
OrigLinkColor2["Green"] = "GREEN";
return OrigLinkColor2;
})(OrigLinkColor || {});
const DEFAULT_PREFS = {
link: "ORIG",
popup: "ON_HOVER",
highlightExisting: false,
origLinkColor: "GREEN"
/* Green */
};
let currentPrefs = null;
function toCSSClassName(item) {
return item.toLowerCase().replace(/_/g, "-");
}
function toCSSClassNames(prefs) {
const result = [
`ilhpp-pref-link-${toCSSClassName(prefs.link)}`,
`ilhpp-pref-popup-${toCSSClassName(prefs.popup)}`,
`ilhpp-pref-orig-link-color-${toCSSClassName(prefs.origLinkColor)}`
];
if (prefs.highlightExisting) {
result.push("ilhpp-pref-hl-existing");
}
return result;
}
function reflectChanges(prefs) {
var _a, _b;
document.documentElement.className = document.documentElement.className.replace(
/\bilhpp-pref[\w-]+\b/g,
""
);
document.documentElement.classList.add(...toCSSClassNames(prefs));
document.querySelectorAll(DATA_ELEM_SELECTOR).forEach((root) => {
const origAnchor = root.querySelector(ORIG_A_SELECTOR);
const foreignAnchor = root.querySelector(FOREIGN_A_SELECTOR);
if (!origAnchor || !foreignAnchor) {
return;
}
if (origAnchor.dataset.oldHref !== void 0) {
origAnchor.href = origAnchor.dataset.oldHref;
}
delete origAnchor.dataset.oldHref;
origAnchor.className = "new";
if ([
"FOREIGN_N_LANG_CODE",
"FOREIGN"
/* Foreign */
].includes(prefs.link)) {
origAnchor.dataset.oldHref = origAnchor.href;
origAnchor.href = foreignAnchor.href;
origAnchor.className = "extiw";
}
});
(_a = document.getElementById(FOOTER_ANCHOR_ID)) == null ? void 0 : _a.remove();
if (prefs.popup === "DISABLED") {
const li = document.createElement("li");
li.id = FOOTER_ANCHOR_ID;
const settingsAnchor = document.createElement("a");
settingsAnchor.href = "#";
settingsAnchor.innerText = mw.msg("ilhpp-settings-footer");
settingsAnchor.addEventListener("click", (ev) => {
ev.preventDefault();
void (() => __async(this, null, function* () {
const { showSettingsDialog } = yield mw.loader.using("ext.gadget.ilhpp-settings").then((require2) => require2("ext.gadget.ilhpp-settings"));
showSettingsDialog();
}))();
});
li.appendChild(settingsAnchor);
(_b = document.getElementById("footer-places")) == null ? void 0 : _b.appendChild(li);
}
}
function getPreferences() {
var _a;
if (currentPrefs) {
return deepClone(currentPrefs);
}
let result = deepClone(DEFAULT_PREFS);
try {
const mwOptionSerialized = mw.user.options.get(PREF_KEY_MW);
const localStorageSerialized = localStorage.getItem(PREF_KEY_LS);
let mwOptionPrefs = null;
let localStoragePrefs = null;
if (mwOptionSerialized) {
const maybePrefs = JSON.parse(mwOptionSerialized);
if (Object.values(LinkMode).includes(maybePrefs.link) && Object.values(PopupMode).includes(maybePrefs.popup) && typeof maybePrefs.highlightExisting === "boolean" && Object.values(OrigLinkColor).includes(maybePrefs.origLinkColor)) {
mwOptionPrefs = maybePrefs;
}
}
if (localStorageSerialized) {
const maybePrefs = JSON.parse(localStorageSerialized);
if (Object.values(LinkMode).includes(maybePrefs.link) && Object.values(PopupMode).includes(maybePrefs.popup) && typeof maybePrefs.highlightExisting === "boolean" && Object.values(OrigLinkColor).includes(maybePrefs.origLinkColor)) {
localStoragePrefs = maybePrefs;
}
}
result = (_a = mwOptionPrefs != null ? mwOptionPrefs : localStoragePrefs) != null ? _a : result;
if (!mwOptionPrefs) {
if (mw.user.isNamed()) {
void new mw.Api().saveOption(
PREF_KEY_MW,
// Only set good shaped local storage prefs
JSON.stringify(localStoragePrefs != null ? localStoragePrefs : DEFAULT_PREFS)
);
}
if (!localStoragePrefs) {
localStorage.setItem(PREF_KEY_LS, JSON.stringify(DEFAULT_PREFS));
}
} else {
localStorage.setItem(PREF_KEY_LS, JSON.stringify(mwOptionPrefs));
}
} catch (e) {
}
currentPrefs = result;
reflectChanges(result);
return result;
}
function setPreferences(prefs) {
return __async(this, null, function* () {
currentPrefs = deepClone(prefs);
const serialized = JSON.stringify(prefs);
if (mw.user.isNamed()) {
const response = yield new mw.Api().saveOption(PREF_KEY_MW, serialized);
if (response.options !== "success") {
throw new Error("Failed to save options!");
}
}
localStorage.setItem(PREF_KEY_LS, serialized);
reflectChanges(prefs);
});
}
const hostRest = location.hostname.endsWith("wmflabs.org") ? ".wikipedia.beta.wmflabs.org" : ".wikipedia.org";
function getPagePreview(wikiId, title, signal) {
return __async(this, null, function* () {
var _a;
if (wikiId === "d") {
throw new DOMException("No preview for this wiki", "NotSupportedError");
}
const resp = yield fetch(
`https://${wikiId}${hostRest}/api/rest_v1/page/summary/${encodeURIComponent(title)}`,
{
signal,
// Design decision: we want to minimize loading time as much as possible as it introduces
// visual glitches, so uses cache if present regardless of its freshness
cache: "force-cache"
// FIXME: Need workaround, adding this causes CORS preflight requests
/* headers: {
'Api-User-Agent': API_USER_AGENT,
}, */
}
);
if (resp.status === 404) {
throw new DOMException("Page not found", "NotFoundError");
}
if (!resp.ok) {
throw new DOMException("Invalid response", "InvalidStateError");
}
const respJson = yield resp.json();
if (!respJson.extract_html) {
throw new DOMException("No preview for this page", "NotSupportedError");
}
const temp = document.createElement("div");
temp.innerHTML = respJson.displaytitle;
const displayTitle = (_a = temp.textContent) != null ? _a : "";
return {
isDisambiguation: respJson.type === "disambiguation",
title: displayTitle,
dir: respJson.dir,
description: respJson.description,
mainHtml: respJson.extract_html
};
});
}
function createPopupBase(anchor) {
var _a;
const dataElement = anchor.closest(DATA_ELEM_SELECTOR);
if (!dataElement) {
return null;
}
const foreignAnchor = dataElement.querySelector(FOREIGN_A_SELECTOR);
if (!foreignAnchor) {
return null;
}
const foreignHref = foreignAnchor.href;
const origTitle = dataElement.dataset.origTitle;
const wikiId = dataElement.dataset.langCode;
const langCode = wikiId;
const langName = (_a = dataElement.querySelector(ILH_LANG_SELECTOR)) == null ? void 0 : _a.innerText;
const foreignTitle = dataElement.dataset.foreignTitle;
if (!origTitle || !wikiId || !langCode || !langName || !foreignTitle) {
return null;
}
return {
origTitle,
wikiId: normalizeWikiId(wikiId),
langCode: normalizeLang(langCode),
langName,
foreignTitle: normalizeTitle(foreignTitle),
foreignHref
};
}
let overriddenPopupMode = null;
function setOverriddenPopupMode(popupMode) {
overriddenPopupMode = popupMode;
}
function getOverriddenPopupMode() {
const prefs = getPreferences();
if (prefs.popup === PopupMode.OnHover) {
return overriddenPopupMode != null ? overriddenPopupMode : prefs.popup;
}
return prefs.popup;
}
function getRealRect(elem) {
const sandbox = document.createElement("div");
sandbox.style.position = "absolute";
sandbox.style.visibility = "hidden";
sandbox.style.width = "0px";
sandbox.style.height = "0px";
sandbox.appendChild(elem);
document.body.appendChild(sandbox);
const result = elem.getBoundingClientRect();
elem.remove();
sandbox.remove();
return result;
}
function getLayout(layoutParam) {
var _a, _b;
const pageScrollOffsetX = window.scrollX;
const pageScrollOffsetY = window.scrollY;
const viewpointWidth = document.documentElement.clientWidth;
const viewpointHeight = document.documentElement.clientHeight;
const width = layoutParam.popupRect.width;
const height = layoutParam.popupRect.height;
const cursorPageX = (_b = (_a = layoutParam.cursor) == null ? void 0 : _a.pageX) != null ? _b : layoutParam.anchorBoundingRect.left + DT_PTR_SHORT_SIDE_LENGTH_PX;
const currentAnchorLineRect = layoutParam.cursor ? [...layoutParam.anchorRects].map(
(rect) => [
rect,
Math.abs(
pageScrollOffsetY + (rect.top + rect.bottom) / 2 - layoutParam.cursor.pageY
)
]
).reduce((prev, curr) => curr[1] < prev[1] ? curr : prev)[0] : layoutParam.anchorBoundingRect;
const anchorPageTop = currentAnchorLineRect.top + pageScrollOffsetY;
const anchorPageBottom = currentAnchorLineRect.bottom + pageScrollOffsetY;
const isRight = cursorPageX < pageScrollOffsetX + viewpointWidth / 2;
const pageX = isRight ? cursorPageX - DT_PTR_SHORT_SIDE_LENGTH_PX : cursorPageX - width + DT_PTR_SHORT_SIDE_LENGTH_PX;
const isBottom = anchorPageTop < pageScrollOffsetY + viewpointHeight / 2;
const pageY = isBottom ? anchorPageBottom + DT_PTR_WIDTH_PX : anchorPageTop - height - DT_PTR_WIDTH_PX;
return { pageX, pageY, isRight, isBottom };
}
function buildPopup$1(popup) {
const root = popup.elem;
root.id = getUniqueId();
root.className = `${ROOT_CLASS_DESKTOP} ${ROOT_CLASS_DESKTOP}--foreign-${getDirection(popup.langCode)} ${ROOT_CLASS_DESKTOP}--loading`;
root.setAttribute("role", "dialog");
const header = document.createElement("a");
header.id = getUniqueId();
header.href = popup.foreignHref;
header.className = `${ROOT_CLASS_DESKTOP}__header ilhpp-text-like ilhpp-auto-hyphen`;
header.lang = popup.langCode;
header.dir = "auto";
header.innerText = popup.foreignTitle;
root.setAttribute("aria-labelledby", header.id);
const subheader = document.createElement("div");
subheader.className = `${ROOT_CLASS_DESKTOP}__subheader`;
subheader.dir = "auto";
subheader.innerText = mw.msg(
"ilhpp-from",
popup.langName,
isWikipedia(popup.wikiId) ? mw.msg("ilhpp-wp") : ""
);
const main = document.createElement("div");
main.className = `${ROOT_CLASS_DESKTOP}__main ${ROOT_CLASS_DESKTOP}__main--loading`;
const extract = document.createElement("a");
extract.href = popup.foreignHref;
extract.lang = popup.langCode;
extract.className = `${ROOT_CLASS_DESKTOP}__main__extract ilhpp-text-like ilhpp-auto-hyphen ilhpp-extract`;
extract.dir = "auto";
const more = document.createElement("a");
more.href = popup.foreignHref;
more.className = `${ROOT_CLASS_DESKTOP}__main__more`;
more.innerText = mw.msg("ilhpp-more");
main.append(extract, more);
const cta = document.createElement("footer");
cta.className = `${ROOT_CLASS_DESKTOP}__cta`;
const ctaInner = document.createElement("div");
ctaInner.className = `${ROOT_CLASS_DESKTOP}__cta__inner`;
ctaInner.innerHTML = mw.msg("ilhpp-cta", popup.origTitle, encodeURIComponent(popup.origTitle));
const settingsButton = document.createElement("button");
settingsButton.className = `${cta.className}__settings`;
settingsButton.ariaLabel = settingsButton.title = mw.msg("ilhpp-settings");
settingsButton.addEventListener("click", () => {
void (() => __async(this, null, function* () {
settingsButton.disabled = true;
const { showSettingsDialog } = yield mw.loader.using("ext.gadget.ilhpp-settings").then((require2) => require2("ext.gadget.ilhpp-settings"));
yield detachPopup$1(popup);
showSettingsDialog();
}))();
});
cta.append(ctaInner, settingsButton);
root.append(header, subheader, main, cta);
const rect = getRealRect(root);
const layout = getLayout({
popupRect: rect,
anchorBoundingRect: popup.anchor.getBoundingClientRect(),
anchorRects: popup.anchor.getClientRects(),
cursor: popup.cursor
});
root.style.top = `${layout.pageY}px`;
root.style.left = `${layout.pageX}px`;
root.classList.add(`${ROOT_CLASS_DESKTOP}--${layout.isBottom ? "bottom" : "top"}`);
root.classList.add(`${ROOT_CLASS_DESKTOP}--${layout.isRight ? "right" : "left"}`);
if (!layout.isBottom) {
const observer = new MutationObserver(() => {
const newTop = layout.pageY + rect.height - root.clientHeight;
root.style.top = `${newTop}px`;
});
observer.observe(popup.elem, { subtree: true, childList: true });
}
root.addEventListener("mouseleave", popup.detachHandler);
root.addEventListener("mouseenter", popup.cancelDetachingHandler);
void getPagePreview(popup.wikiId, popup.foreignTitle, popup.abortController.signal).then(
(preview) => {
root.classList.remove(`${ROOT_CLASS_DESKTOP}--loading`);
header.innerText = preview.title;
if (preview.isDisambiguation) {
root.classList.add(`${ROOT_CLASS_DESKTOP}--disam`);
extract.removeAttribute("lang");
extract.innerText = mw.msg("ilhpp-disam");
more.innerText = mw.msg("ilhpp-disam-more");
} else {
root.classList.add(`${ROOT_CLASS_DESKTOP}--standard`);
extract.innerHTML = preview.mainHtml;
}
},
(err) => {
switch (err == null ? void 0 : err.name) {
case "AbortError":
break;
case "NotSupportedError":
root.classList.remove(`${ROOT_CLASS_DESKTOP}--loading`);
root.classList.add(`${ROOT_CLASS_DESKTOP}--no-preview`);
extract.removeAttribute("lang");
extract.innerText = mw.msg("ilhpp-no-preview");
more.innerText = mw.msg("ilhpp-goto");
break;
case "NotFoundError":
root.classList.remove(`${ROOT_CLASS_DESKTOP}--loading`);
root.classList.add(`${ROOT_CLASS_DESKTOP}--error`);
extract.removeAttribute("lang");
extract.innerHTML = mw.msg(
"ilhpp-error-not-found",
encodeURIComponent(mw.config.get("wgPageName"))
);
more.innerText = mw.msg("ilhpp-goto");
break;
default:
root.classList.remove(`${ROOT_CLASS_DESKTOP}--loading`);
root.classList.add(`${ROOT_CLASS_DESKTOP}--error`);
extract.removeAttribute("lang");
extract.innerText = mw.msg("ilhpp-error");
more.innerText = mw.msg("ilhpp-goto");
break;
}
}
);
}
function attachPopup$1(anchor, oldTooltip, cursor) {
const popupBase = createPopupBase(anchor);
if (!popupBase) {
return null;
}
let timeoutId;
const popup = __spreadProps(__spreadValues({}, popupBase), {
state: "attached",
elem: document.createElement("div"),
anchor,
oldTooltip,
cursor,
// Support Safari 11.1: Partial support is enough for our use case
// eslint-disable-next-line compat/compat
abortController: new AbortController(),
detachHandler() {
if (getOverriddenPopupMode() === PopupMode.OnHover) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
void detachPopup$1(popup);
}, DT_DETACH_DELAY_MS);
}
},
cancelDetachingHandler() {
if (getOverriddenPopupMode() === PopupMode.OnHover) {
clearTimeout(timeoutId);
}
}
});
buildPopup$1(popup);
popup.anchor.addEventListener("mouseleave", popup.detachHandler);
popup.anchor.addEventListener("mouseenter", popup.cancelDetachingHandler);
popup.anchor.setAttribute("aria-haspopup", "dialog");
popup.anchor.setAttribute("aria-controls", popup.elem.id);
document.body.appendChild(popup.elem);
return popup;
}
function detachPopup$1(popup) {
return __async(this, null, function* () {
if (popup.state === "detached") {
return;
}
popup.state = "detached";
popup.abortController.abort();
popup.elem.classList.add(`${ROOT_CLASS_DESKTOP}--out`);
if (popup.oldTooltip !== null) {
popup.anchor.title = popup.oldTooltip;
}
yield new Promise((resolve) => {
popup.elem.addEventListener("animationend", resolve, { once: true });
});
popup.anchor.removeEventListener("mouseleave", popup.detachHandler);
popup.anchor.removeEventListener("mouseenter", popup.cancelDetachingHandler);
popup.anchor.removeAttribute("aria-haspopup");
popup.anchor.removeAttribute("aria-controls");
popup.elem.remove();
});
}
let activePopup = null;
let activeAnchor = null;
let activeAnchorTooltip = null;
let mouseOverTimeoutId;
let isTabPressed = false;
function run$1() {
[
"pointercancel",
"pointerdown",
"pointermove",
"pointerout",
"pointerover",
"pointerup"
].forEach((eventName) => {
document.body.addEventListener(
eventName,
(ev) => {
if (getPreferences().popup === PopupMode.OnHover) {
setOverriddenPopupMode(ev.pointerType === "touch" ? PopupMode.OnClick : null);
}
},
{
passive: true,
capture: true
// Add at capture phase to be triggered as early as possible
}
);
});
document.body.addEventListener("mouseover", (ev) => {
if (getOverriddenPopupMode() === PopupMode.OnHover && ev.target instanceof HTMLElement) {
const targetAnchor = ev.target.closest(ORIG_A_SELECTOR);
clearTimeout(mouseOverTimeoutId);
if (activeAnchor && activeAnchorTooltip && (activePopup == null ? void 0 : activePopup.state) !== "attached") {
activeAnchor.title = activeAnchorTooltip;
activeAnchor = null;
activeAnchorTooltip = null;
}
if (targetAnchor && ((activePopup == null ? void 0 : activePopup.state) === "attached" && (activePopup == null ? void 0 : activePopup.anchor) !== targetAnchor || (activePopup == null ? void 0 : activePopup.state) !== "attached")) {
if (activePopup) {
void detachPopup$1(activePopup);
}
activeAnchorTooltip = targetAnchor.getAttribute("title");
targetAnchor.removeAttribute("title");
activeAnchor = targetAnchor;
mouseOverTimeoutId = setTimeout(() => {
activePopup = attachPopup$1(targetAnchor, activeAnchorTooltip, {
pageX: ev.pageX,
pageY: ev.pageY
});
}, DT_ATTACH_DELAY_MS);
}
}
});
document.body.addEventListener(
"click",
(ev) => {
if (getOverriddenPopupMode() === PopupMode.OnClick && ev.target instanceof HTMLElement) {
const targetAnchor = ev.target.closest(ORIG_A_SELECTOR);
if (targetAnchor && // When clicking on the same <a> with a popup, detach that popup
((activePopup == null ? void 0 : activePopup.state) === "attached" && (activePopup == null ? void 0 : activePopup.anchor) !== targetAnchor || (activePopup == null ? void 0 : activePopup.state) !== "attached")) {
ev.stopImmediatePropagation();
ev.preventDefault();
if (activePopup && activePopup.state === "attached") {
if (activePopup.anchor !== targetAnchor) {
void detachPopup$1(activePopup);
} else {
return;
}
}
const oldTooltip = targetAnchor.getAttribute("title");
targetAnchor.removeAttribute("title");
activePopup = attachPopup$1(targetAnchor, oldTooltip, {
pageX: ev.pageX,
pageY: ev.pageY
});
} else if (!(activePopup == null ? void 0 : activePopup.elem.contains(ev.target))) {
if (activePopup && activePopup.state === "attached") {
ev.stopImmediatePropagation();
ev.preventDefault();
void detachPopup$1(activePopup);
}
}
}
},
{
passive: false,
capture: true
// Add at capture phase to "mock an overlay"
}
);
document.body.addEventListener("keydown", (ev) => {
if (ev.key === "Tab") {
isTabPressed = true;
}
});
document.body.addEventListener("keyup", (ev) => {
if (ev.key === "Tab") {
isTabPressed = false;
}
});
document.body.addEventListener("focusin", (ev) => {
if (isTabPressed && getOverriddenPopupMode() !== PopupMode.Disabled && ev.target instanceof HTMLElement) {
const targetAnchor = ev.target.closest(ORIG_A_SELECTOR);
if (targetAnchor) {
if ((activePopup == null ? void 0 : activePopup.state) === "attached" && (activePopup == null ? void 0 : activePopup.anchor) !== targetAnchor || (activePopup == null ? void 0 : activePopup.state) !== "attached") {
if (activePopup && activePopup.state === "attached" && activePopup.anchor !== targetAnchor) {
void detachPopup$1(activePopup);
}
const oldTooltip = targetAnchor.getAttribute("title");
targetAnchor.removeAttribute("title");
activePopup = attachPopup$1(targetAnchor, oldTooltip);
}
} else if (!(activePopup == null ? void 0 : activePopup.elem.contains(ev.target))) {
if (activePopup && activePopup.state === "attached") {
void detachPopup$1(activePopup);
}
}
}
});
}
function buildPopup(popup) {
const dir = getDirection(popup.langCode);
const root = popup.elem;
root.id = getUniqueId();
root.setAttribute("role", "dialog");
root.setAttribute("aria-modal", "true");
root.classList.add(
ROOT_CLASS_MOBILE,
`${ROOT_CLASS_MOBILE}--foreign-${dir}`,
`${ROOT_CLASS_MOBILE}--loading`
);
let effectiveTouchInitialState = null;
let touchOffset = 0;
root.addEventListener("touchstart", (ev) => {
var _a;
if (((_a = window.getSelection()) == null ? void 0 : _a.type) === "Range") {
return;
}
popup.overlay.classList.add("ilhpp-mobile-panned");
root.classList.add("ilhpp-mobile-panned");
if (!effectiveTouchInitialState) {
effectiveTouchInitialState = ev.touches[0];
}
});
root.addEventListener("touchmove", (ev) => {
var _a;
if (((_a = window.getSelection()) == null ? void 0 : _a.type) === "Range" || // Do not respond to touch actions if something is selected
!effectiveTouchInitialState) {
return;
}
const effectiveTouch = [...ev.changedTouches].find(
(touch) => touch.identifier === effectiveTouchInitialState.identifier
);
if (!effectiveTouch) {
return;
}
touchOffset = effectiveTouch.screenY - effectiveTouchInitialState.screenY;
if (touchOffset >= 0) {
root.style.transform = `translateY(${touchOffset}px)`;
popup.overlay.style.opacity = `${1 - touchOffset / root.offsetHeight}`;
} else {
root.style.transform = `translateY(${Math.expm1(touchOffset / 100) * 20}px)`;
popup.overlay.style.removeProperty("opacity");
}
});
["touchend", "touchcancel"].forEach((eventName) => {
root.addEventListener(eventName, (ev) => {
if (ev.touches.length === 0 && effectiveTouchInitialState) {
popup.overlay.classList.remove("ilhpp-mobile-panned");
root.classList.remove("ilhpp-mobile-panned");
effectiveTouchInitialState = null;
if (touchOffset / root.offsetHeight > 0.1) {
void detachPopup(popup);
} else {
popup.overlay.style.removeProperty("opacity");
root.style.removeProperty("transform");
}
}
});
});
const header = document.createElement("a");
header.id = getUniqueId();
header.href = popup.foreignHref;
header.className = `${ROOT_CLASS_MOBILE}__header ilhpp-text-like ilhpp-auto-hyphen`;
header.lang = popup.langCode;
header.dir = "auto";
header.innerText = popup.foreignTitle;
root.setAttribute("aria-labelledby", header.id);
const subheader = document.createElement("div");
subheader.className = `${ROOT_CLASS_MOBILE}__subheader`;
subheader.dir = "auto";
subheader.innerText = mw.msg(
"ilhpp-from",
popup.langName,
isWikipedia(popup.wikiId) ? mw.msg("ilhpp-wp") : ""
);
const closeButton = document.createElement("button");
closeButton.className = `${ROOT_CLASS_MOBILE}__close ilhpp-mobile-button`;
closeButton.ariaLabel = closeButton.title = mw.msg("ilhpp-close");
closeButton.addEventListener("click", () => {
void detachPopup(popup);
});
const moreButton = document.createElement("a");
moreButton.role = "button";
moreButton.href = popup.foreignHref;
moreButton.className = `${ROOT_CLASS_MOBILE}__more ilhpp-mobile-button ilhpp-mobile-button--primary-progressive`;
moreButton.innerText = mw.msg("ilhpp-more");
const extract = document.createElement("div");
extract.lang = popup.langCode;
extract.dir = "auto";
extract.className = `${ROOT_CLASS_MOBILE}__extract ilhpp-auto-hyphen ilhpp-extract`;
const skeletonContainer = document.createElement("div");
skeletonContainer.setAttribute("aria-hidden", "true");
skeletonContainer.className = `${ROOT_CLASS_MOBILE}__extract__skeleton-container`;
Array.from({ length: MB_SKELETON_STRIPE_COUNT }).forEach(() => {
const skeletonStripe = document.createElement("div");
skeletonStripe.className = "ilhpp-mobile-skeleton";
skeletonContainer.appendChild(skeletonStripe);
});
extract.appendChild(skeletonContainer);
const cta = document.createElement("footer");
cta.className = `${ROOT_CLASS_MOBILE}__cta`;
const ctaInner = document.createElement("div");
ctaInner.className = `${ROOT_CLASS_MOBILE}__cta__inner`;
ctaInner.innerHTML = mw.msg("ilhpp-cta", popup.origTitle, encodeURIComponent(popup.origTitle));
cta.append(ctaInner);
const settingsButton = document.createElement("button");
settingsButton.className = `${ROOT_CLASS_MOBILE}__settings ilhpp-mobile-button`;
settingsButton.ariaLabel = settingsButton.title = mw.msg("ilhpp-settings");
settingsButton.addEventListener("click", () => {
void (() => __async(this, null, function* () {
settingsButton.disabled = true;
const { showSettingsDialog } = yield mw.loader.using("ext.gadget.ilhpp-settings").then((require2) => require2("ext.gadget.ilhpp-settings"));
yield detachPopup(popup);
showSettingsDialog();
}))();
});
root.append(header, subheader, closeButton, extract, moreButton, cta, settingsButton);
void getPagePreview(popup.wikiId, popup.foreignTitle, popup.abortController.signal).then(
(preview) => {
root.classList.remove(`${ROOT_CLASS_MOBILE}--loading`);
header.innerText = preview.title;
if (preview.isDisambiguation) {
root.classList.add(`${ROOT_CLASS_MOBILE}--disam`);
extract.removeAttribute("lang");
extract.insertAdjacentText("beforeend", mw.msg("ilhpp-disam"));
moreButton.innerText = mw.msg("ilhpp-disam-more");
} else {
root.classList.add(`${ROOT_CLASS_MOBILE}--standard`);
extract.insertAdjacentHTML("beforeend", preview.mainHtml);
}
},
(err) => {
switch (err == null ? void 0 : err.name) {
case "AbortError":
break;
case "NotSupportedError":
root.classList.remove(`${ROOT_CLASS_MOBILE}--loading`);
root.classList.add(`${ROOT_CLASS_MOBILE}--no-preview`);
extract.removeAttribute("lang");
extract.insertAdjacentText("beforeend", mw.msg("ilhpp-no-preview"));
moreButton.innerText = mw.msg("ilhpp-goto");
break;
case "NotFoundError":
root.classList.remove(`${ROOT_CLASS_MOBILE}--loading`);
root.classList.add(`${ROOT_CLASS_MOBILE}--error`);
extract.removeAttribute("lang");
extract.insertAdjacentHTML(
"beforeend",
mw.msg("ilhpp-error-not-found", encodeURIComponent(mw.config.get("wgPageName")))
// messages.json is trusted
);
moreButton.innerText = mw.msg("ilhpp-goto");
break;
default:
root.classList.remove(`${ROOT_CLASS_MOBILE}--loading`);
root.classList.add(`${ROOT_CLASS_MOBILE}--error`);
extract.removeAttribute("lang");
extract.insertAdjacentText("beforeend", mw.msg("ilhpp-error"));
moreButton.innerText = mw.msg("ilhpp-goto");
break;
}
}
);
}
function attachPopup(anchor) {
const popupBase = createPopupBase(anchor);
if (!popupBase) {
return null;
}
const abortController = new AbortController();
const popup = __spreadProps(__spreadValues({}, popupBase), {
overlay: document.createElement("div"),
elem: document.createElement("div"),
anchor,
abortController
});
togglePageScroll(true);
buildPopup(popup);
popup.overlay.className = OVERLAY_CLASS_MOBILE;
popup.overlay.setAttribute("aria-hidden", "true");
popup.overlay.addEventListener("click", () => {
void detachPopup(popup);
});
popup.anchor.setAttribute("aria-haspopup", "dialog");
popup.anchor.setAttribute("aria-controls", popup.elem.id);
document.body.append(popup.overlay, popup.elem);
return popup;
}
function detachPopup(popup) {
return __async(this, null, function* () {
popup.abortController.abort();
popup.overlay.classList.add(`${OVERLAY_CLASS_MOBILE}--out`);
popup.elem.classList.add(`${ROOT_CLASS_MOBILE}--out`);
yield Promise.all(
[popup.overlay, popup.elem].map(
(target) => new Promise((resolve) => {
target.addEventListener("animationend", resolve, { once: true });
}).then(() => {
target.remove();
})
)
);
popup.anchor.removeAttribute("aria-haspopup");
popup.anchor.removeAttribute("aria-controls");
togglePageScroll(false);
});
}
function run() {
mw.hook("wikipage.content").add(($content) => {
$content.each((_, root) => {
root.addEventListener(
"click",
(ev) => {
if (getPreferences().popup !== PopupMode.Disabled && ev.target instanceof HTMLElement) {
const anchor = ev.target.closest(ORIG_A_SELECTOR);
if (anchor) {
ev.preventDefault();
ev.stopImmediatePropagation();
attachPopup(anchor);
}
}
},
true
// Make it fire earlier than MF a.new handler
);
});
});
}
mw.messages.set(ext_gadget_HanAssist.batchConv(messages, mw.config.get("wgUserVariant")));
getPreferences();
if (mw.config.get("wgMFMode")) {
void mw.loader.using("mobile.startup").then((require2) => require2("mobile.startup")).then(({ getOverlayManager }) => {
getOverlayManager();
const overlayContainer = document.getElementsByClassName("mw-overlays-container")[0];
if (!overlayContainer) {
return;
}
const observer = new MutationObserver(() => {
const veOverlay = overlayContainer.querySelector(".editor-overlay.editor-overlay-ve");
document.documentElement.classList.toggle("ilhpp-inactive", !!veOverlay);
});
observer.observe(overlayContainer, {
childList: true,
attributes: true,
attributeFilter: ["style"]
});
});
}
if (isMobileDevice()) {
run();
} else {
run$1();
}
exports.LinkMode = LinkMode;
exports.OrigLinkColor = OrigLinkColor;
exports.PopupMode = PopupMode;
exports.getPreferences = getPreferences;
exports.haveConflicts = haveConflicts;
exports.setPreferences = setPreferences;
// </nowiki>