MediaWiki:Gadget-Navigation popups.js:修订间差异
外观
删除的内容 添加的内容
小 鹿野耕云移动页面MediaWiki:Gadget-popups-core.js至MediaWiki:Gadget-Navigation popups.js,不留重定向 |
无编辑摘要 |
||
| 第1行: | 第1行: | ||
/** |
|||
// STARTFILE: main.js |
|||
* SPDX-License-Identifier: CC-BY-SA-4.0 |
|||
// ********************************************************************** |
|||
* _addText: '{{Gadget Header|license=CC-BY-SA-4.0}}' |
|||
// ** ** |
|||
* |
|||
// ** changes to this file affect many users. ** |
|||
* @base {@link https://en.wikipedia.org/wiki/MediaWiki:Gadget-popups.js} |
|||
// ** please discuss on the talk page before editing ** |
|||
* @base {@link https://zh.wikipedia.org/w/index.php?title=User:Lupin/strings-draft&oldid=579996170} |
|||
// ** ** |
|||
* @base {@link https://zh.wikipedia.org/wiki/MediaWiki:Gadget-navpop.css} |
|||
// ********************************************************************** |
|||
* @source {@link https://git.qiuwen.net.cn/InterfaceAdmin/QiuwenGadgets/src/branch/master/src/Navigation_popups} |
|||
// ** ** |
|||
* @license CC-BY-SA-4.0 {@link https://www.qiuwenbaike.cn/wiki/H:CC-BY-SA-4.0} |
|||
// ** if you do edit this file, be sure that your editor recognizes it ** |
|||
*/ |
|||
// ** as utf8, or the weird and wonderful characters in the namespaces ** |
|||
/** |
|||
// ** below will be completely broken. You can check with the show ** |
|||
* +------------------------------------------------------------+ |
|||
// ** changes button before submitting the edit. ** |
|||
* | === WARNING: GLOBAL GADGET FILE === | |
|||
* +------------------------------------------------------------+ |
|||
// ** ** |
|||
* | All changes should be made in the repository, | |
|||
// ********************************************************************** |
|||
* | otherwise they will be lost. | |
|||
/* eslint-env browser */ |
|||
* +------------------------------------------------------------+ |
|||
/* global $, jQuery, mw, window */ |
|||
* | Changes to this page may affect many users. | |
|||
* | Please discuss changes by opening an issue before editing. | |
|||
* +------------------------------------------------------------+ |
|||
*/ |
|||
/* <nowiki> */ |
|||
(() => { |
|||
// Fix later |
|||
/* global log, errlog, popupStrings, wikEdUseWikEd, WikEdUpdateFrame */ |
|||
"use strict"; |
|||
$(() => { |
|||
var __getOwnPropNames = Object.getOwnPropertyNames; |
|||
////////////////////////////////////////////////// |
|||
var __commonJS = (cb, mod) => function __require() { |
|||
// Globals |
|||
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; |
|||
// |
|||
}; |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/global-this.js |
|||
// Trying to shove as many of these as possible into the pg (popup globals) object |
|||
var require_global_this = __commonJS({ |
|||
const pg = { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/global-this.js"(exports, module2) { |
|||
api: {}, // MediaWiki API requests |
|||
"use strict"; |
|||
re: {}, // regexps |
|||
var check = function(it) { |
|||
ns: {}, // namespaces |
|||
return it && it.Math === Math && it; |
|||
string: {}, // translatable strings |
|||
}; |
|||
wiki: {}, // local site info |
|||
module2.exports = // eslint-disable-next-line es/no-global-this -- safe |
|||
user: {}, // current user info |
|||
check(typeof globalThis == "object" && globalThis) || check(typeof window == "object" && window) || // eslint-disable-next-line no-restricted-globals -- safe |
|||
misc: {}, // YUCK PHOOEY |
|||
check(typeof self == "object" && self) || check(typeof global == "object" && global) || check(typeof exports == "object" && exports) || // eslint-disable-next-line no-new-func -- fallback |
|||
option: {}, // options, see newOption etc |
|||
/* @__PURE__ */ (function() { |
|||
optionDefault: {}, // default option values |
|||
return this; |
|||
flag: {}, // misc flags |
|||
})() || Function("return this")(); |
|||
cache: {}, // page and image cache |
|||
} |
|||
structures: {}, // navlink structures |
|||
}); |
|||
timer: {}, // all sorts of timers (too damn many) |
|||
counter: {}, // .. and all sorts of counters |
|||
current: {}, // state info |
|||
fn: {}, // functions |
|||
endoflist: null, |
|||
}; |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/fails.js |
|||
/* Bail if the gadget/script is being loaded twice */ |
|||
var require_fails = __commonJS({ |
|||
/* An element with id "pg" would add a window.pg property, ignore such property */ |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/fails.js"(exports, module2) { |
|||
if (window.pg && !(window.pg instanceof HTMLElement)) { |
|||
"use strict"; |
|||
return; |
|||
module2.exports = function(exec) { |
|||
} |
|||
try { |
|||
return !!exec(); |
|||
} catch (error) { |
|||
return true; |
|||
} |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/descriptors.js |
|||
/* Export to global context */ |
|||
var require_descriptors = __commonJS({ |
|||
window.pg = pg; |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/descriptors.js"(exports, module2) { |
|||
"use strict"; |
|||
var fails = require_fails(); |
|||
module2.exports = !fails(function() { |
|||
return Object.defineProperty({}, 1, { get: function() { |
|||
return 7; |
|||
} })[1] !== 7; |
|||
}); |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/function-bind-native.js |
|||
/// Local Variables: /// |
|||
var require_function_bind_native = __commonJS({ |
|||
/// mode:c /// |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/function-bind-native.js"(exports, module2) { |
|||
/// End: /// |
|||
"use strict"; |
|||
// ENDFILE: main.js |
|||
var fails = require_fails(); |
|||
module2.exports = !fails(function() { |
|||
var test = function() { |
|||
}.bind(); |
|||
return typeof test != "function" || test.hasOwnProperty("prototype"); |
|||
}); |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/function-call.js |
|||
// STARTFILE: actions.js |
|||
var require_function_call = __commonJS({ |
|||
function setupTooltips(container, remove, force, popData) { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/function-call.js"(exports, module2) { |
|||
log('setupTooltips, container=' + container + ', remove=' + remove); |
|||
"use strict"; |
|||
if (!container) { |
|||
var NATIVE_BIND = require_function_bind_native(); |
|||
// the main initial call |
|||
var call = Function.prototype.call; |
|||
if ( |
|||
module2.exports = NATIVE_BIND ? call.bind(call) : function() { |
|||
getValueOf('popupOnEditSelection') && |
|||
return call.apply(call, arguments); |
|||
document && |
|||
}; |
|||
document.editform && |
|||
} |
|||
document.editform.wpTextbox1 |
|||
}); |
|||
) { |
|||
document.editform.wpTextbox1.onmouseup = doSelectionPopup; |
|||
} |
|||
// article/content is a structure-dependent thing |
|||
container = defaultPopupsContainer(); |
|||
} |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-property-is-enumerable.js |
|||
if (!remove && !force && container.ranSetupTooltipsAlready) { |
|||
var require_object_property_is_enumerable = __commonJS({ |
|||
return; |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-property-is-enumerable.js"(exports) { |
|||
} |
|||
"use strict"; |
|||
container.ranSetupTooltipsAlready = !remove; |
|||
var $propertyIsEnumerable = {}.propertyIsEnumerable; |
|||
var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; |
|||
var NASHORN_BUG = getOwnPropertyDescriptor && !$propertyIsEnumerable.call({ 1: 2 }, 1); |
|||
exports.f = NASHORN_BUG ? function propertyIsEnumerable(V) { |
|||
var descriptor = getOwnPropertyDescriptor(this, V); |
|||
return !!descriptor && descriptor.enumerable; |
|||
} : $propertyIsEnumerable; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/create-property-descriptor.js |
|||
let anchors; |
|||
var require_create_property_descriptor = __commonJS({ |
|||
anchors = container.getElementsByTagName('A'); |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/create-property-descriptor.js"(exports, module2) { |
|||
setupTooltipsLoop(anchors, 0, 250, 100, remove, popData); |
|||
"use strict"; |
|||
} |
|||
module2.exports = function(bitmap, value) { |
|||
return { |
|||
enumerable: !(bitmap & 1), |
|||
configurable: !(bitmap & 2), |
|||
writable: !(bitmap & 4), |
|||
value |
|||
}; |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/function-uncurry-this.js |
|||
function defaultPopupsContainer() { |
|||
var require_function_uncurry_this = __commonJS({ |
|||
if (getValueOf('popupOnlyArticleLinks')) { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/function-uncurry-this.js"(exports, module2) { |
|||
return ( |
|||
"use strict"; |
|||
document.querySelector('.skin-vector-2022 .vector-body') || |
|||
var NATIVE_BIND = require_function_bind_native(); |
|||
document.getElementById('mw_content') || |
|||
var FunctionPrototype = Function.prototype; |
|||
document.getElementById('content') || |
|||
var call = FunctionPrototype.call; |
|||
document.getElementById('article') || |
|||
var uncurryThisWithBind = NATIVE_BIND && FunctionPrototype.bind.bind(call, call); |
|||
document |
|||
module2.exports = NATIVE_BIND ? uncurryThisWithBind : function(fn) { |
|||
); |
|||
return function() { |
|||
} |
|||
return call.apply(fn, arguments); |
|||
return document; |
|||
}; |
|||
} |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/classof-raw.js |
|||
function setupTooltipsLoop(anchors, begin, howmany, sleep, remove, popData) { |
|||
var require_classof_raw = __commonJS({ |
|||
log(simplePrintf('setupTooltipsLoop(%s,%s,%s,%s,%s)', arguments)); |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/classof-raw.js"(exports, module2) { |
|||
const finish = begin + howmany; |
|||
"use strict"; |
|||
const loopend = Math.min(finish, anchors.length); |
|||
var uncurryThis = require_function_uncurry_this(); |
|||
let j = loopend - begin; |
|||
var toString = uncurryThis({}.toString); |
|||
log( |
|||
var stringSlice = uncurryThis("".slice); |
|||
'setupTooltips: anchors.length=' + |
|||
module2.exports = function(it) { |
|||
anchors.length + |
|||
return stringSlice(toString(it), 8, -1); |
|||
', begin=' + |
|||
}; |
|||
begin + |
|||
} |
|||
', howmany=' + |
|||
}); |
|||
howmany + |
|||
', loopend=' + |
|||
loopend + |
|||
', remove=' + |
|||
remove |
|||
); |
|||
const doTooltip = remove ? removeTooltip : addTooltip; |
|||
// try a faster (?) loop construct |
|||
if (j > 0) { |
|||
do { |
|||
const a = anchors[loopend - j]; |
|||
if (typeof a === 'undefined' || !a || !a.href) { |
|||
log('got null anchor at index ' + loopend - j); |
|||
continue; |
|||
} |
|||
doTooltip(a, popData); |
|||
} while (--j); |
|||
} |
|||
if (finish < anchors.length) { |
|||
setTimeout(() => { |
|||
setupTooltipsLoop(anchors, finish, howmany, sleep, remove, popData); |
|||
}, sleep); |
|||
} else { |
|||
if (!remove && !getValueOf('popupTocLinks')) { |
|||
rmTocTooltips(); |
|||
} |
|||
pg.flag.finishedLoading = true; |
|||
} |
|||
} |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/indexed-object.js |
|||
// eliminate popups from the TOC |
|||
var require_indexed_object = __commonJS({ |
|||
// This also kills any onclick stuff that used to be going on in the toc |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/indexed-object.js"(exports, module2) { |
|||
function rmTocTooltips() { |
|||
"use strict"; |
|||
const toc = document.getElementById('toc'); |
|||
var uncurryThis = require_function_uncurry_this(); |
|||
if (toc) { |
|||
var fails = require_fails(); |
|||
const tocLinks = toc.getElementsByTagName('A'); |
|||
var classof = require_classof_raw(); |
|||
const tocLen = tocLinks.length; |
|||
var $Object = Object; |
|||
for (let j = 0; j < tocLen; ++j) { |
|||
var split = uncurryThis("".split); |
|||
removeTooltip(tocLinks[j], true); |
|||
module2.exports = fails(function() { |
|||
} |
|||
return !$Object("z").propertyIsEnumerable(0); |
|||
} |
|||
}) ? function(it) { |
|||
} |
|||
return classof(it) === "String" ? split(it, "") : $Object(it); |
|||
} : $Object; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-null-or-undefined.js |
|||
function addTooltip(a, popData) { |
|||
var require_is_null_or_undefined = __commonJS({ |
|||
if (!isPopupLink(a)) { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-null-or-undefined.js"(exports, module2) { |
|||
return; |
|||
"use strict"; |
|||
} |
|||
module2.exports = function(it) { |
|||
a.onmouseover = mouseOverWikiLink; |
|||
return it === null || it === void 0; |
|||
a.onmouseout = mouseOutWikiLink; |
|||
}; |
|||
a.onmousedown = killPopup; |
|||
} |
|||
a.hasPopup = true; |
|||
}); |
|||
a.popData = popData; |
|||
} |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/require-object-coercible.js |
|||
function removeTooltip(a) { |
|||
var require_require_object_coercible = __commonJS({ |
|||
if (!a.hasPopup) { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/require-object-coercible.js"(exports, module2) { |
|||
return; |
|||
"use strict"; |
|||
} |
|||
var isNullOrUndefined = require_is_null_or_undefined(); |
|||
a.onmouseover = null; |
|||
var $TypeError = TypeError; |
|||
a.onmouseout = null; |
|||
module2.exports = function(it) { |
|||
if (a.originalTitle) { |
|||
if (isNullOrUndefined(it)) throw new $TypeError("Can't call method on " + it); |
|||
a.title = a.originalTitle; |
|||
return it; |
|||
} |
|||
}; |
|||
a.hasPopup = false; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-indexed-object.js |
|||
function removeTitle(a) { |
|||
var require_to_indexed_object = __commonJS({ |
|||
if (!a.originalTitle) { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-indexed-object.js"(exports, module2) { |
|||
a.originalTitle = a.title; |
|||
"use strict"; |
|||
} |
|||
var IndexedObject = require_indexed_object(); |
|||
a.title = ''; |
|||
var requireObjectCoercible = require_require_object_coercible(); |
|||
} |
|||
module2.exports = function(it) { |
|||
return IndexedObject(requireObjectCoercible(it)); |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-callable.js |
|||
function restoreTitle(a) { |
|||
var require_is_callable = __commonJS({ |
|||
if (a.title || !a.originalTitle) { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-callable.js"(exports, module2) { |
|||
return; |
|||
"use strict"; |
|||
} |
|||
var documentAll = typeof document == "object" && document.all; |
|||
a.title = a.originalTitle; |
|||
module2.exports = typeof documentAll == "undefined" && documentAll !== void 0 ? function(argument) { |
|||
} |
|||
return typeof argument == "function" || argument === documentAll; |
|||
} : function(argument) { |
|||
return typeof argument == "function"; |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-object.js |
|||
function registerHooks(np) { |
|||
var require_is_object = __commonJS({ |
|||
const popupMaxWidth = getValueOf('popupMaxWidth'); |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-object.js"(exports, module2) { |
|||
"use strict"; |
|||
var isCallable = require_is_callable(); |
|||
module2.exports = function(it) { |
|||
return typeof it == "object" ? it !== null : isCallable(it); |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/get-built-in.js |
|||
if (typeof popupMaxWidth === 'number') { |
|||
var require_get_built_in = __commonJS({ |
|||
const setMaxWidth = function () { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/get-built-in.js"(exports, module2) { |
|||
np.mainDiv.style.maxWidth = popupMaxWidth + 'px'; |
|||
"use strict"; |
|||
np.maxWidth = popupMaxWidth; |
|||
var globalThis2 = require_global_this(); |
|||
}; |
|||
var isCallable = require_is_callable(); |
|||
np.addHook(setMaxWidth, 'unhide', 'before'); |
|||
var aFunction = function(argument) { |
|||
} |
|||
return isCallable(argument) ? argument : void 0; |
|||
np.addHook(addPopupShortcuts, 'unhide', 'after'); |
|||
}; |
|||
np.addHook(rmPopupShortcuts, 'hide', 'before'); |
|||
module2.exports = function(namespace, method) { |
|||
} |
|||
return arguments.length < 2 ? aFunction(globalThis2[namespace]) : globalThis2[namespace] && globalThis2[namespace][method]; |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-is-prototype-of.js |
|||
function removeModifierKeyHandler(a) { |
|||
var require_object_is_prototype_of = __commonJS({ |
|||
//remove listeners for modifier key if any that were added in mouseOverWikiLink |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-is-prototype-of.js"(exports, module2) { |
|||
document.removeEventListener('keydown', a.modifierKeyHandler, false); |
|||
"use strict"; |
|||
document.removeEventListener('keyup', a.modifierKeyHandler, false); |
|||
var uncurryThis = require_function_uncurry_this(); |
|||
} |
|||
module2.exports = uncurryThis({}.isPrototypeOf); |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/environment-user-agent.js |
|||
function mouseOverWikiLink(evt) { |
|||
var require_environment_user_agent = __commonJS({ |
|||
if (!evt && window.event) { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/environment-user-agent.js"(exports, module2) { |
|||
evt = window.event; |
|||
"use strict"; |
|||
} |
|||
var globalThis2 = require_global_this(); |
|||
var navigator2 = globalThis2.navigator; |
|||
var userAgent = navigator2 && navigator2.userAgent; |
|||
module2.exports = userAgent ? String(userAgent) : ""; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/environment-v8-version.js |
|||
// if the modifier is needed, listen for it, |
|||
var require_environment_v8_version = __commonJS({ |
|||
// we will remove the listener when we mouseout of this link or kill popup. |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/environment-v8-version.js"(exports, module2) { |
|||
if (getValueOf('popupModifier')) { |
|||
"use strict"; |
|||
// if popupModifierAction = enable, we should popup when the modifier is pressed |
|||
var globalThis2 = require_global_this(); |
|||
// if popupModifierAction = disable, we should popup unless the modifier is pressed |
|||
var userAgent = require_environment_user_agent(); |
|||
const action = getValueOf('popupModifierAction'); |
|||
var process = globalThis2.process; |
|||
const key = action == 'disable' ? 'keyup' : 'keydown'; |
|||
var Deno = globalThis2.Deno; |
|||
const a = this; |
|||
var versions = process && process.versions || Deno && Deno.version; |
|||
a.modifierKeyHandler = function (evt) { |
|||
var v8 = versions && versions.v8; |
|||
mouseOverWikiLink2(a, evt); |
|||
var match; |
|||
}; |
|||
var version; |
|||
document.addEventListener(key, a.modifierKeyHandler, false); |
|||
if (v8) { |
|||
} |
|||
match = v8.split("."); |
|||
version = match[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1]); |
|||
} |
|||
if (!version && userAgent) { |
|||
match = userAgent.match(/Edge\/(\d+)/); |
|||
if (!match || match[1] >= 74) { |
|||
match = userAgent.match(/Chrome\/(\d+)/); |
|||
if (match) version = +match[1]; |
|||
} |
|||
} |
|||
module2.exports = version; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/symbol-constructor-detection.js |
|||
return mouseOverWikiLink2(this, evt); |
|||
var require_symbol_constructor_detection = __commonJS({ |
|||
} |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/symbol-constructor-detection.js"(exports, module2) { |
|||
"use strict"; |
|||
var V8_VERSION = require_environment_v8_version(); |
|||
var fails = require_fails(); |
|||
var globalThis2 = require_global_this(); |
|||
var $String = globalThis2.String; |
|||
module2.exports = !!Object.getOwnPropertySymbols && !fails(function() { |
|||
var symbol = /* @__PURE__ */ Symbol("symbol detection"); |
|||
return !$String(symbol) || !(Object(symbol) instanceof Symbol) || // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances |
|||
!Symbol.sham && V8_VERSION && V8_VERSION < 41; |
|||
}); |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/use-symbol-as-uid.js |
|||
/** |
|||
var require_use_symbol_as_uid = __commonJS({ |
|||
* Gets the references list item that the provided footnote link targets. This |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/use-symbol-as-uid.js"(exports, module2) { |
|||
* is typically a li element within the ol.references element inside the reflist. |
|||
"use strict"; |
|||
* |
|||
var NATIVE_SYMBOL = require_symbol_constructor_detection(); |
|||
* @param {Element} a - A footnote link. |
|||
module2.exports = NATIVE_SYMBOL && !Symbol.sham && typeof Symbol.iterator == "symbol"; |
|||
* @return {Element|boolean} The targeted element, or false if one can't be found. |
|||
} |
|||
}); |
|||
function footnoteTarget(a) { |
|||
const aTitle = Title.fromAnchor(a); |
|||
// We want ".3A" rather than "%3A" or "?" here, so use the anchor property directly |
|||
const anch = aTitle.anchor; |
|||
if (!/^(cite_note-|_note-|endnote)/.test(anch)) { |
|||
return false; |
|||
} |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-symbol.js |
|||
const lTitle = Title.fromURL(location.href); |
|||
var require_is_symbol = __commonJS({ |
|||
if (lTitle.toString(true) !== aTitle.toString(true)) { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-symbol.js"(exports, module2) { |
|||
return false; |
|||
"use strict"; |
|||
} |
|||
var getBuiltIn = require_get_built_in(); |
|||
var isCallable = require_is_callable(); |
|||
var isPrototypeOf = require_object_is_prototype_of(); |
|||
var USE_SYMBOL_AS_UID = require_use_symbol_as_uid(); |
|||
var $Object = Object; |
|||
module2.exports = USE_SYMBOL_AS_UID ? function(it) { |
|||
return typeof it == "symbol"; |
|||
} : function(it) { |
|||
var $Symbol = getBuiltIn("Symbol"); |
|||
return isCallable($Symbol) && isPrototypeOf($Symbol.prototype, $Object(it)); |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/try-to-string.js |
|||
let el = document.getElementById(anch); |
|||
var require_try_to_string = __commonJS({ |
|||
while (el && typeof el.nodeName === 'string') { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/try-to-string.js"(exports, module2) { |
|||
const nt = el.nodeName.toLowerCase(); |
|||
"use strict"; |
|||
if (nt === 'li') { |
|||
var $String = String; |
|||
return el; |
|||
module2.exports = function(argument) { |
|||
} else if (nt === 'body') { |
|||
try { |
|||
return false; |
|||
return $String(argument); |
|||
} else if (el.parentNode) { |
|||
} catch (error) { |
|||
el = el.parentNode; |
|||
return "Object"; |
|||
} else { |
|||
} |
|||
return false; |
|||
}; |
|||
} |
|||
} |
|||
}); |
|||
return false; |
|||
} |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/a-callable.js |
|||
function footnotePreview(x, navpop) { |
|||
var require_a_callable = __commonJS({ |
|||
setPopupHTML('<hr />' + x.innerHTML, 'popupPreview', navpop.idNumber); |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/a-callable.js"(exports, module2) { |
|||
} |
|||
"use strict"; |
|||
var isCallable = require_is_callable(); |
|||
var tryToString = require_try_to_string(); |
|||
var $TypeError = TypeError; |
|||
module2.exports = function(argument) { |
|||
if (isCallable(argument)) return argument; |
|||
throw new $TypeError(tryToString(argument) + " is not a function"); |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/get-method.js |
|||
function modifierPressed(evt) { |
|||
var require_get_method = __commonJS({ |
|||
const mod = getValueOf('popupModifier'); |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/get-method.js"(exports, module2) { |
|||
if (!mod) { |
|||
"use strict"; |
|||
return false; |
|||
var aCallable = require_a_callable(); |
|||
} |
|||
var isNullOrUndefined = require_is_null_or_undefined(); |
|||
module2.exports = function(V, P) { |
|||
var func = V[P]; |
|||
return isNullOrUndefined(func) ? void 0 : aCallable(func); |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/ordinary-to-primitive.js |
|||
if (!evt && window.event) { |
|||
var require_ordinary_to_primitive = __commonJS({ |
|||
evt = window.event; |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/ordinary-to-primitive.js"(exports, module2) { |
|||
} |
|||
"use strict"; |
|||
var call = require_function_call(); |
|||
var isCallable = require_is_callable(); |
|||
var isObject = require_is_object(); |
|||
var $TypeError = TypeError; |
|||
module2.exports = function(input, pref) { |
|||
var fn, val; |
|||
if (pref === "string" && isCallable(fn = input.toString) && !isObject(val = call(fn, input))) return val; |
|||
if (isCallable(fn = input.valueOf) && !isObject(val = call(fn, input))) return val; |
|||
if (pref !== "string" && isCallable(fn = input.toString) && !isObject(val = call(fn, input))) return val; |
|||
throw new $TypeError("Can't convert object to primitive value"); |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-pure.js |
|||
return evt && mod && evt[mod.toLowerCase() + 'Key']; |
|||
var require_is_pure = __commonJS({ |
|||
} |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-pure.js"(exports, module2) { |
|||
"use strict"; |
|||
module2.exports = false; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/define-global-property.js |
|||
// Checks if the correct modifier pressed/unpressed if needed |
|||
var require_define_global_property = __commonJS({ |
|||
function isCorrectModifier(a, evt) { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/define-global-property.js"(exports, module2) { |
|||
if (!getValueOf('popupModifier')) { |
|||
"use strict"; |
|||
return true; |
|||
var globalThis2 = require_global_this(); |
|||
} |
|||
var defineProperty = Object.defineProperty; |
|||
// if popupModifierAction = enable, we should popup when the modifier is pressed |
|||
module2.exports = function(key, value) { |
|||
// if popupModifierAction = disable, we should popup unless the modifier is pressed |
|||
try { |
|||
const action = getValueOf('popupModifierAction'); |
|||
defineProperty(globalThis2, key, { value, configurable: true, writable: true }); |
|||
return ( |
|||
} catch (error) { |
|||
(action == 'enable' && modifierPressed(evt)) || (action == 'disable' && !modifierPressed(evt)) |
|||
globalThis2[key] = value; |
|||
); |
|||
} |
|||
} |
|||
return value; |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/shared-store.js |
|||
function mouseOverWikiLink2(a, evt) { |
|||
var require_shared_store = __commonJS({ |
|||
if (!isCorrectModifier(a, evt)) { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/shared-store.js"(exports, module2) { |
|||
return; |
|||
"use strict"; |
|||
} |
|||
var IS_PURE = require_is_pure(); |
|||
if (getValueOf('removeTitles')) { |
|||
var globalThis2 = require_global_this(); |
|||
removeTitle(a); |
|||
var defineGlobalProperty = require_define_global_property(); |
|||
} |
|||
var SHARED = "__core-js_shared__"; |
|||
if (a == pg.current.link && a.navpopup && a.navpopup.isVisible()) { |
|||
var store = module2.exports = globalThis2[SHARED] || defineGlobalProperty(SHARED, {}); |
|||
return; |
|||
(store.versions || (store.versions = [])).push({ |
|||
} |
|||
version: "3.49.0", |
|||
pg.current.link = a; |
|||
mode: IS_PURE ? "pure" : "global", |
|||
copyright: "© 2013–2025 Denis Pushkarev (zloirock.ru), 2025–2026 CoreJS Company (core-js.io). All rights reserved.", |
|||
license: "https://github.com/zloirock/core-js/blob/v3.49.0/LICENSE", |
|||
source: "https://github.com/zloirock/core-js" |
|||
}); |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/shared.js |
|||
if (getValueOf('simplePopups') && !pg.option.popupStructure) { |
|||
var require_shared = __commonJS({ |
|||
// reset *default value* of popupStructure |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/shared.js"(exports, module2) { |
|||
setDefault('popupStructure', 'original'); |
|||
"use strict"; |
|||
} |
|||
var store = require_shared_store(); |
|||
module2.exports = function(key, value) { |
|||
return store[key] || (store[key] = value || {}); |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-object.js |
|||
const article = new Title().fromAnchor(a); |
|||
var require_to_object = __commonJS({ |
|||
// set global variable (ugh) to hold article (wikipage) |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-object.js"(exports, module2) { |
|||
pg.current.article = article; |
|||
"use strict"; |
|||
var requireObjectCoercible = require_require_object_coercible(); |
|||
var $Object = Object; |
|||
module2.exports = function(argument) { |
|||
return $Object(requireObjectCoercible(argument)); |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/has-own-property.js |
|||
if (!a.navpopup) { |
|||
var require_has_own_property = __commonJS({ |
|||
a.navpopup = newNavpopup(a, article); |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/has-own-property.js"(exports, module2) { |
|||
pg.current.linksHash[a.href] = a.navpopup; |
|||
"use strict"; |
|||
pg.current.links.push(a); |
|||
var uncurryThis = require_function_uncurry_this(); |
|||
} |
|||
var toObject = require_to_object(); |
|||
if (a.navpopup.pending === null || a.navpopup.pending !== 0) { |
|||
var hasOwnProperty = uncurryThis({}.hasOwnProperty); |
|||
// either fresh popups or those with unfinshed business are redone from scratch |
|||
module2.exports = Object.hasOwn || function hasOwn(it, key) { |
|||
simplePopupContent(a, article); |
|||
return hasOwnProperty(toObject(it), key); |
|||
} |
|||
}; |
|||
a.navpopup.showSoonIfStable(a.navpopup.delay); |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/uid.js |
|||
clearInterval(pg.timer.checkPopupPosition); |
|||
var require_uid = __commonJS({ |
|||
pg.timer.checkPopupPosition = setInterval(checkPopupPosition, 600); |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/uid.js"(exports, module2) { |
|||
"use strict"; |
|||
var uncurryThis = require_function_uncurry_this(); |
|||
var id = 0; |
|||
var postfix = Math.random(); |
|||
var toString = uncurryThis(1.1.toString); |
|||
module2.exports = function(key) { |
|||
return "Symbol(" + (key === void 0 ? "" : key) + ")_" + toString(++id + postfix, 36); |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/well-known-symbol.js |
|||
if (getValueOf('simplePopups')) { |
|||
var require_well_known_symbol = __commonJS({ |
|||
if (getValueOf('popupPreviewButton') && !a.simpleNoMore) { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/well-known-symbol.js"(exports, module2) { |
|||
const d = document.createElement('div'); |
|||
"use strict"; |
|||
d.className = 'popupPreviewButtonDiv'; |
|||
var globalThis2 = require_global_this(); |
|||
const s = document.createElement('span'); |
|||
var shared = require_shared(); |
|||
d.appendChild(s); |
|||
var hasOwn = require_has_own_property(); |
|||
s.className = 'popupPreviewButton'; |
|||
var uid = require_uid(); |
|||
s['on' + getValueOf('popupPreviewButtonEvent')] = function () { |
|||
var NATIVE_SYMBOL = require_symbol_constructor_detection(); |
|||
a.simpleNoMore = true; |
|||
var USE_SYMBOL_AS_UID = require_use_symbol_as_uid(); |
|||
d.style.display = 'none'; |
|||
var Symbol2 = globalThis2.Symbol; |
|||
nonsimplePopupContent(a, article); |
|||
var WellKnownSymbolsStore = shared("wks"); |
|||
}; |
|||
var createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol2["for"] || Symbol2 : Symbol2 && Symbol2.withoutSetter || uid; |
|||
s.innerHTML = popupString('show preview'); |
|||
module2.exports = function(name) { |
|||
setPopupHTML(d, 'popupPreview', a.navpopup.idNumber); |
|||
if (!hasOwn(WellKnownSymbolsStore, name)) { |
|||
} |
|||
WellKnownSymbolsStore[name] = NATIVE_SYMBOL && hasOwn(Symbol2, name) ? Symbol2[name] : createWellKnownSymbol("Symbol." + name); |
|||
} |
|||
} |
|||
return WellKnownSymbolsStore[name]; |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-primitive.js |
|||
if (a.navpopup.pending !== 0) { |
|||
var require_to_primitive = __commonJS({ |
|||
nonsimplePopupContent(a, article); |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-primitive.js"(exports, module2) { |
|||
} |
|||
"use strict"; |
|||
} |
|||
var call = require_function_call(); |
|||
var isObject = require_is_object(); |
|||
var isSymbol = require_is_symbol(); |
|||
var getMethod = require_get_method(); |
|||
var ordinaryToPrimitive = require_ordinary_to_primitive(); |
|||
var wellKnownSymbol = require_well_known_symbol(); |
|||
var $TypeError = TypeError; |
|||
var TO_PRIMITIVE = wellKnownSymbol("toPrimitive"); |
|||
module2.exports = function(input, pref) { |
|||
if (!isObject(input) || isSymbol(input)) return input; |
|||
var exoticToPrim = getMethod(input, TO_PRIMITIVE); |
|||
var result; |
|||
if (exoticToPrim) { |
|||
if (pref === void 0) pref = "default"; |
|||
result = call(exoticToPrim, input, pref); |
|||
if (!isObject(result) || isSymbol(result)) return result; |
|||
throw new $TypeError("Can't convert object to primitive value"); |
|||
} |
|||
if (pref === void 0) pref = "number"; |
|||
return ordinaryToPrimitive(input, pref); |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-property-key.js |
|||
// simplePopupContent: the content that do not require additional download |
|||
var require_to_property_key = __commonJS({ |
|||
// (it is shown even when simplePopups is true) |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-property-key.js"(exports, module2) { |
|||
function simplePopupContent(a, article) { |
|||
"use strict"; |
|||
/* FIXME hack */ a.navpopup.hasPopupMenu = false; |
|||
var toPrimitive = require_to_primitive(); |
|||
a.navpopup.setInnerHTML(popupHTML(a)); |
|||
var isSymbol = require_is_symbol(); |
|||
fillEmptySpans({ navpopup: a.navpopup }); |
|||
module2.exports = function(argument) { |
|||
var key = toPrimitive(argument, "string"); |
|||
return isSymbol(key) ? key : key + ""; |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/document-create-element.js |
|||
if (getValueOf('popupDraggable')) { |
|||
var require_document_create_element = __commonJS({ |
|||
let dragHandle = getValueOf('popupDragHandle') || null; |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/document-create-element.js"(exports, module2) { |
|||
if (dragHandle && dragHandle != 'all') { |
|||
"use strict"; |
|||
dragHandle += a.navpopup.idNumber; |
|||
var globalThis2 = require_global_this(); |
|||
} |
|||
var isObject = require_is_object(); |
|||
setTimeout(() => { |
|||
var document2 = globalThis2.document; |
|||
a.navpopup.makeDraggable(dragHandle); |
|||
var EXISTS = isObject(document2) && isObject(document2.createElement); |
|||
}, 150); |
|||
module2.exports = function(it) { |
|||
} |
|||
return EXISTS ? document2.createElement(it) : {}; |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/ie8-dom-define.js |
|||
if (getValueOf('popupRedlinkRemoval') && a.className == 'new') { |
|||
var require_ie8_dom_define = __commonJS({ |
|||
setPopupHTML('<br>' + popupRedlinkHTML(article), 'popupRedlink', a.navpopup.idNumber); |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/ie8-dom-define.js"(exports, module2) { |
|||
} |
|||
"use strict"; |
|||
} |
|||
var DESCRIPTORS = require_descriptors(); |
|||
var fails = require_fails(); |
|||
var createElement = require_document_create_element(); |
|||
module2.exports = !DESCRIPTORS && !fails(function() { |
|||
return Object.defineProperty(createElement("div"), "a", { |
|||
get: function() { |
|||
return 7; |
|||
} |
|||
}).a !== 7; |
|||
}); |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-get-own-property-descriptor.js |
|||
function debugData(navpopup) { |
|||
var require_object_get_own_property_descriptor = __commonJS({ |
|||
if (getValueOf('popupDebugging') && navpopup.idNumber) { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-get-own-property-descriptor.js"(exports) { |
|||
setPopupHTML( |
|||
"use strict"; |
|||
'idNumber=' + navpopup.idNumber + ', pending=' + navpopup.pending, |
|||
var DESCRIPTORS = require_descriptors(); |
|||
'popupError', |
|||
var call = require_function_call(); |
|||
navpopup.idNumber |
|||
var propertyIsEnumerableModule = require_object_property_is_enumerable(); |
|||
); |
|||
var createPropertyDescriptor = require_create_property_descriptor(); |
|||
} |
|||
var toIndexedObject = require_to_indexed_object(); |
|||
} |
|||
var toPropertyKey = require_to_property_key(); |
|||
var hasOwn = require_has_own_property(); |
|||
var IE8_DOM_DEFINE = require_ie8_dom_define(); |
|||
var $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; |
|||
exports.f = DESCRIPTORS ? $getOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P) { |
|||
O = toIndexedObject(O); |
|||
P = toPropertyKey(P); |
|||
if (IE8_DOM_DEFINE) try { |
|||
return $getOwnPropertyDescriptor(O, P); |
|||
} catch (error) { |
|||
} |
|||
if (hasOwn(O, P)) return createPropertyDescriptor(!call(propertyIsEnumerableModule.f, O, P), O[P]); |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/v8-prototype-define-bug.js |
|||
function newNavpopup(a, article) { |
|||
var require_v8_prototype_define_bug = __commonJS({ |
|||
const navpopup = new Navpopup(); |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/v8-prototype-define-bug.js"(exports, module2) { |
|||
navpopup.fuzz = 5; |
|||
"use strict"; |
|||
navpopup.delay = getValueOf('popupDelay') * 1000; |
|||
var DESCRIPTORS = require_descriptors(); |
|||
// increment global counter now |
|||
var fails = require_fails(); |
|||
navpopup.idNumber = ++pg.idNumber; |
|||
module2.exports = DESCRIPTORS && fails(function() { |
|||
navpopup.parentAnchor = a; |
|||
return Object.defineProperty(function() { |
|||
navpopup.parentPopup = a.popData && a.popData.owner; |
|||
}, "prototype", { |
|||
navpopup.article = article; |
|||
value: 42, |
|||
registerHooks(navpopup); |
|||
writable: false |
|||
return navpopup; |
|||
}).prototype !== 42; |
|||
} |
|||
}); |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/an-object.js |
|||
// Should we show nonsimple context? |
|||
var require_an_object = __commonJS({ |
|||
// If simplePopups is set to true, then we do not show nonsimple context, |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/an-object.js"(exports, module2) { |
|||
// but if a bottom "show preview" was clicked we do show nonsimple context |
|||
"use strict"; |
|||
function shouldShowNonSimple(a) { |
|||
var isObject = require_is_object(); |
|||
return !getValueOf('simplePopups') || a.simpleNoMore; |
|||
var $String = String; |
|||
} |
|||
var $TypeError = TypeError; |
|||
module2.exports = function(argument) { |
|||
if (isObject(argument)) return argument; |
|||
throw new $TypeError($String(argument) + " is not an object"); |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-define-property.js |
|||
// Should we show nonsimple context govern by the option (e.g. popupUserInfo)? |
|||
var require_object_define_property = __commonJS({ |
|||
// If the user explicitly asked for nonsimple context by setting the option to true, |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-define-property.js"(exports) { |
|||
// then we show it even in nonsimple mode. |
|||
"use strict"; |
|||
function shouldShow(a, option) { |
|||
var DESCRIPTORS = require_descriptors(); |
|||
if (shouldShowNonSimple(a)) { |
|||
var IE8_DOM_DEFINE = require_ie8_dom_define(); |
|||
return getValueOf(option); |
|||
var V8_PROTOTYPE_DEFINE_BUG = require_v8_prototype_define_bug(); |
|||
} else { |
|||
var anObject = require_an_object(); |
|||
return typeof window[option] != 'undefined' && window[option]; |
|||
var toPropertyKey = require_to_property_key(); |
|||
} |
|||
var $TypeError = TypeError; |
|||
} |
|||
var $defineProperty = Object.defineProperty; |
|||
var $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; |
|||
var ENUMERABLE = "enumerable"; |
|||
var CONFIGURABLE = "configurable"; |
|||
var WRITABLE = "writable"; |
|||
exports.f = DESCRIPTORS ? V8_PROTOTYPE_DEFINE_BUG ? function defineProperty(O, P, Attributes) { |
|||
anObject(O); |
|||
P = toPropertyKey(P); |
|||
anObject(Attributes); |
|||
if (typeof O === "function" && P === "prototype" && "value" in Attributes && WRITABLE in Attributes && !Attributes[WRITABLE]) { |
|||
var current = $getOwnPropertyDescriptor(O, P); |
|||
if (current && current[WRITABLE]) { |
|||
O[P] = Attributes.value; |
|||
Attributes = { |
|||
configurable: CONFIGURABLE in Attributes ? Attributes[CONFIGURABLE] : current[CONFIGURABLE], |
|||
enumerable: ENUMERABLE in Attributes ? Attributes[ENUMERABLE] : current[ENUMERABLE], |
|||
writable: false |
|||
}; |
|||
} |
|||
} |
|||
return $defineProperty(O, P, Attributes); |
|||
} : $defineProperty : function defineProperty(O, P, Attributes) { |
|||
anObject(O); |
|||
P = toPropertyKey(P); |
|||
anObject(Attributes); |
|||
if (IE8_DOM_DEFINE) try { |
|||
return $defineProperty(O, P, Attributes); |
|||
} catch (error) { |
|||
} |
|||
if ("get" in Attributes || "set" in Attributes) throw new $TypeError("Accessors not supported"); |
|||
if ("value" in Attributes) O[P] = Attributes.value; |
|||
return O; |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/create-non-enumerable-property.js |
|||
function nonsimplePopupContent(a, article) { |
|||
var require_create_non_enumerable_property = __commonJS({ |
|||
let diff = null, |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/create-non-enumerable-property.js"(exports, module2) { |
|||
history = null; |
|||
"use strict"; |
|||
const params = parseParams(a.href); |
|||
var DESCRIPTORS = require_descriptors(); |
|||
const oldid = typeof params.oldid == 'undefined' ? null : params.oldid; |
|||
var definePropertyModule = require_object_define_property(); |
|||
if (shouldShow(a, 'popupPreviewDiffs')) { |
|||
var createPropertyDescriptor = require_create_property_descriptor(); |
|||
diff = params.diff; |
|||
module2.exports = DESCRIPTORS ? function(object, key, value) { |
|||
} |
|||
return definePropertyModule.f(object, key, createPropertyDescriptor(1, value)); |
|||
if (shouldShow(a, 'popupPreviewHistory')) { |
|||
} : function(object, key, value) { |
|||
history = params.action == 'history'; |
|||
object[key] = value; |
|||
} |
|||
return object; |
|||
a.navpopup.pending = 0; |
|||
}; |
|||
const referenceElement = footnoteTarget(a); |
|||
} |
|||
if (referenceElement) { |
|||
}); |
|||
footnotePreview(referenceElement, a.navpopup); |
|||
} else if (diff || diff === 0) { |
|||
loadDiff(article, oldid, diff, a.navpopup); |
|||
} else if (history) { |
|||
loadAPIPreview('history', article, a.navpopup); |
|||
} else if (shouldShowNonSimple(a) && pg.re.contribs.test(a.href)) { |
|||
loadAPIPreview('contribs', article, a.navpopup); |
|||
} else if (shouldShowNonSimple(a) && pg.re.backlinks.test(a.href)) { |
|||
loadAPIPreview('backlinks', article, a.navpopup); |
|||
} else if ( |
|||
// FIXME should be able to get all preview combinations with options |
|||
article.namespaceId() == pg.nsImageId && |
|||
(shouldShow(a, 'imagePopupsForImages') || !anchorContainsImage(a)) |
|||
) { |
|||
loadAPIPreview('imagepagepreview', article, a.navpopup); |
|||
loadImage(article, a.navpopup); |
|||
} else { |
|||
if (article.namespaceId() == pg.nsCategoryId && shouldShow(a, 'popupCategoryMembers')) { |
|||
loadAPIPreview('category', article, a.navpopup); |
|||
} else if ( |
|||
(article.namespaceId() == pg.nsUserId || article.namespaceId() == pg.nsUsertalkId) && |
|||
shouldShow(a, 'popupUserInfo') |
|||
) { |
|||
loadAPIPreview('userinfo', article, a.navpopup); |
|||
} |
|||
if (shouldShowNonSimple(a)) { |
|||
startArticlePreview(article, oldid, a.navpopup); |
|||
} |
|||
} |
|||
} |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/function-name.js |
|||
function pendingNavpopTask(navpop) { |
|||
var require_function_name = __commonJS({ |
|||
if (navpop && navpop.pending === null) { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/function-name.js"(exports, module2) { |
|||
navpop.pending = 0; |
|||
"use strict"; |
|||
} |
|||
var DESCRIPTORS = require_descriptors(); |
|||
++navpop.pending; |
|||
var hasOwn = require_has_own_property(); |
|||
debugData(navpop); |
|||
var FunctionPrototype = Function.prototype; |
|||
} |
|||
var getDescriptor = DESCRIPTORS && Object.getOwnPropertyDescriptor; |
|||
var EXISTS = hasOwn(FunctionPrototype, "name"); |
|||
var PROPER = EXISTS && function something() { |
|||
}.name === "something"; |
|||
var CONFIGURABLE = EXISTS && (!DESCRIPTORS || DESCRIPTORS && getDescriptor(FunctionPrototype, "name").configurable); |
|||
module2.exports = { |
|||
EXISTS, |
|||
PROPER, |
|||
CONFIGURABLE |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/inspect-source.js |
|||
function completedNavpopTask(navpop) { |
|||
var require_inspect_source = __commonJS({ |
|||
if (navpop && navpop.pending) { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/inspect-source.js"(exports, module2) { |
|||
--navpop.pending; |
|||
"use strict"; |
|||
} |
|||
var uncurryThis = require_function_uncurry_this(); |
|||
debugData(navpop); |
|||
var isCallable = require_is_callable(); |
|||
} |
|||
var store = require_shared_store(); |
|||
var functionToString = uncurryThis(Function.toString); |
|||
if (!isCallable(store.inspectSource)) { |
|||
store.inspectSource = function(it) { |
|||
return functionToString(it); |
|||
}; |
|||
} |
|||
module2.exports = store.inspectSource; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/weak-map-basic-detection.js |
|||
function startArticlePreview(article, oldid, navpop) { |
|||
var require_weak_map_basic_detection = __commonJS({ |
|||
navpop.redir = 0; |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/weak-map-basic-detection.js"(exports, module2) { |
|||
loadPreview(article, oldid, navpop); |
|||
"use strict"; |
|||
} |
|||
var globalThis2 = require_global_this(); |
|||
var isCallable = require_is_callable(); |
|||
var WeakMap = globalThis2.WeakMap; |
|||
module2.exports = isCallable(WeakMap) && /native code/.test(String(WeakMap)); |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/shared-key.js |
|||
function loadPreview(article, oldid, navpop) { |
|||
var require_shared_key = __commonJS({ |
|||
if (!navpop.redir) { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/shared-key.js"(exports, module2) { |
|||
navpop.originalArticle = article; |
|||
"use strict"; |
|||
} |
|||
var shared = require_shared(); |
|||
article.oldid = oldid; |
|||
var uid = require_uid(); |
|||
loadAPIPreview('revision', article, navpop); |
|||
var keys = shared("keys"); |
|||
} |
|||
module2.exports = function(key) { |
|||
return keys[key] || (keys[key] = uid(key)); |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/hidden-keys.js |
|||
function loadPreviewFromRedir(redirMatch, navpop) { |
|||
var require_hidden_keys = __commonJS({ |
|||
// redirMatch is a regex match |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/hidden-keys.js"(exports, module2) { |
|||
const target = new Title().fromWikiText(redirMatch[2]); |
|||
"use strict"; |
|||
// overwrite (or add) anchor from original target |
|||
module2.exports = {}; |
|||
// mediawiki does overwrite; eg [[User:Lupin/foo3#Done]] |
|||
} |
|||
if (navpop.article.anchor) { |
|||
}); |
|||
target.anchor = navpop.article.anchor; |
|||
} |
|||
navpop.redir++; |
|||
navpop.redirTarget = target; |
|||
const warnRedir = redirLink(target, navpop.article); |
|||
setPopupHTML(warnRedir, 'popupWarnRedir', navpop.idNumber); |
|||
navpop.article = target; |
|||
fillEmptySpans({ redir: true, redirTarget: target, navpopup: navpop }); |
|||
return loadPreview(target, null, navpop); |
|||
} |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/internal-state.js |
|||
function insertPreview(download) { |
|||
var require_internal_state = __commonJS({ |
|||
if (!download.owner) { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/internal-state.js"(exports, module2) { |
|||
return; |
|||
"use strict"; |
|||
} |
|||
var NATIVE_WEAK_MAP = require_weak_map_basic_detection(); |
|||
var globalThis2 = require_global_this(); |
|||
var isObject = require_is_object(); |
|||
var createNonEnumerableProperty = require_create_non_enumerable_property(); |
|||
var hasOwn = require_has_own_property(); |
|||
var shared = require_shared_store(); |
|||
var sharedKey = require_shared_key(); |
|||
var hiddenKeys = require_hidden_keys(); |
|||
var OBJECT_ALREADY_INITIALIZED = "Object already initialized"; |
|||
var TypeError2 = globalThis2.TypeError; |
|||
var WeakMap = globalThis2.WeakMap; |
|||
var set; |
|||
var get; |
|||
var has; |
|||
var enforce = function(it) { |
|||
return has(it) ? get(it) : set(it, {}); |
|||
}; |
|||
var getterFor = function(TYPE) { |
|||
return function(it) { |
|||
var state; |
|||
if (!isObject(it) || (state = get(it)).type !== TYPE) { |
|||
throw new TypeError2("Incompatible receiver, " + TYPE + " required"); |
|||
} |
|||
return state; |
|||
}; |
|||
}; |
|||
if (NATIVE_WEAK_MAP || shared.state) { |
|||
store = shared.state || (shared.state = new WeakMap()); |
|||
store.get = store.get; |
|||
store.has = store.has; |
|||
store.set = store.set; |
|||
set = function(it, metadata) { |
|||
if (store.has(it)) throw new TypeError2(OBJECT_ALREADY_INITIALIZED); |
|||
metadata.facade = it; |
|||
store.set(it, metadata); |
|||
return metadata; |
|||
}; |
|||
get = function(it) { |
|||
return store.get(it) || {}; |
|||
}; |
|||
has = function(it) { |
|||
return store.has(it); |
|||
}; |
|||
} else { |
|||
STATE = sharedKey("state"); |
|||
hiddenKeys[STATE] = true; |
|||
set = function(it, metadata) { |
|||
if (hasOwn(it, STATE)) throw new TypeError2(OBJECT_ALREADY_INITIALIZED); |
|||
metadata.facade = it; |
|||
createNonEnumerableProperty(it, STATE, metadata); |
|||
return metadata; |
|||
}; |
|||
get = function(it) { |
|||
return hasOwn(it, STATE) ? it[STATE] : {}; |
|||
}; |
|||
has = function(it) { |
|||
return hasOwn(it, STATE); |
|||
}; |
|||
} |
|||
var store; |
|||
var STATE; |
|||
module2.exports = { |
|||
set, |
|||
get, |
|||
has, |
|||
enforce, |
|||
getterFor |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/make-built-in.js |
|||
const redirMatch = pg.re.redirect.exec(download.data); |
|||
var require_make_built_in = __commonJS({ |
|||
if (download.owner.redir === 0 && redirMatch) { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/make-built-in.js"(exports, module2) { |
|||
loadPreviewFromRedir(redirMatch, download.owner); |
|||
"use strict"; |
|||
return; |
|||
var uncurryThis = require_function_uncurry_this(); |
|||
} |
|||
var fails = require_fails(); |
|||
var isCallable = require_is_callable(); |
|||
var hasOwn = require_has_own_property(); |
|||
var DESCRIPTORS = require_descriptors(); |
|||
var CONFIGURABLE_FUNCTION_NAME = require_function_name().CONFIGURABLE; |
|||
var inspectSource = require_inspect_source(); |
|||
var InternalStateModule = require_internal_state(); |
|||
var enforceInternalState = InternalStateModule.enforce; |
|||
var getInternalState = InternalStateModule.get; |
|||
var $String = String; |
|||
var defineProperty = Object.defineProperty; |
|||
var stringSlice = uncurryThis("".slice); |
|||
var replace = uncurryThis("".replace); |
|||
var join = uncurryThis([].join); |
|||
var CONFIGURABLE_LENGTH = DESCRIPTORS && !fails(function() { |
|||
return defineProperty(function() { |
|||
}, "length", { value: 8 }).length !== 8; |
|||
}); |
|||
var TEMPLATE = String(String).split("String"); |
|||
var makeBuiltIn = module2.exports = function(value, name, options) { |
|||
if (stringSlice($String(name), 0, 7) === "Symbol(") { |
|||
name = "[" + replace($String(name), /^Symbol\(([^)]*)\).*$/, "$1") + "]"; |
|||
} |
|||
if (options && options.getter) name = "get " + name; |
|||
if (options && options.setter) name = "set " + name; |
|||
if (!hasOwn(value, "name") || CONFIGURABLE_FUNCTION_NAME && value.name !== name) { |
|||
if (DESCRIPTORS) defineProperty(value, "name", { value: name, configurable: true }); |
|||
else value.name = name; |
|||
} |
|||
if (CONFIGURABLE_LENGTH && options && hasOwn(options, "arity") && value.length !== options.arity) { |
|||
defineProperty(value, "length", { value: options.arity }); |
|||
} |
|||
try { |
|||
if (options && hasOwn(options, "constructor") && options.constructor) { |
|||
if (DESCRIPTORS) defineProperty(value, "prototype", { writable: false }); |
|||
} else if (value.prototype) value.prototype = void 0; |
|||
} catch (error) { |
|||
} |
|||
var state = enforceInternalState(value); |
|||
if (!hasOwn(state, "source")) { |
|||
state.source = join(TEMPLATE, typeof name == "string" ? name : ""); |
|||
} |
|||
return value; |
|||
}; |
|||
Function.prototype.toString = makeBuiltIn(function toString() { |
|||
return isCallable(this) && getInternalState(this).source || inspectSource(this); |
|||
}, "toString"); |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/define-built-in.js |
|||
if (download.owner.visible || !getValueOf('popupLazyPreviews')) { |
|||
var require_define_built_in = __commonJS({ |
|||
insertPreviewNow(download); |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/define-built-in.js"(exports, module2) { |
|||
} else { |
|||
"use strict"; |
|||
const id = download.owner.redir ? 'PREVIEW_REDIR_HOOK' : 'PREVIEW_HOOK'; |
|||
var isCallable = require_is_callable(); |
|||
download.owner.addHook( |
|||
var definePropertyModule = require_object_define_property(); |
|||
() => { |
|||
var makeBuiltIn = require_make_built_in(); |
|||
insertPreviewNow(download); |
|||
var defineGlobalProperty = require_define_global_property(); |
|||
return true; |
|||
module2.exports = function(O, key, value, options) { |
|||
}, |
|||
if (!options) options = {}; |
|||
'unhide', |
|||
var simple = options.enumerable; |
|||
'after', |
|||
var name = options.name !== void 0 ? options.name : key; |
|||
id |
|||
if (isCallable(value)) makeBuiltIn(value, name, options); |
|||
); |
|||
if (options.global) { |
|||
} |
|||
if (simple) O[key] = value; |
|||
} |
|||
else defineGlobalProperty(key, value); |
|||
} else { |
|||
try { |
|||
if (!options.unsafe) delete O[key]; |
|||
else if (O[key]) simple = true; |
|||
} catch (error) { |
|||
} |
|||
if (simple) O[key] = value; |
|||
else definePropertyModule.f(O, key, { |
|||
value, |
|||
enumerable: false, |
|||
configurable: !options.nonConfigurable, |
|||
writable: !options.nonWritable |
|||
}); |
|||
} |
|||
return O; |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/math-trunc.js |
|||
function insertPreviewNow(download) { |
|||
var require_math_trunc = __commonJS({ |
|||
if (!download.owner) { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/math-trunc.js"(exports, module2) { |
|||
return; |
|||
"use strict"; |
|||
} |
|||
var ceil = Math.ceil; |
|||
const wikiText = download.data; |
|||
var floor = Math.floor; |
|||
const navpop = download.owner; |
|||
module2.exports = Math.trunc || function trunc(x) { |
|||
const art = navpop.redirTarget || navpop.originalArticle; |
|||
var n = +x; |
|||
return (n > 0 ? floor : ceil)(n); |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-integer-or-infinity.js |
|||
makeFixDabs(wikiText, navpop); |
|||
var require_to_integer_or_infinity = __commonJS({ |
|||
if (getValueOf('popupSummaryData')) { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-integer-or-infinity.js"(exports, module2) { |
|||
getPageInfo(wikiText, download); |
|||
"use strict"; |
|||
setPopupTrailer(getPageInfo(wikiText, download), navpop.idNumber); |
|||
var trunc = require_math_trunc(); |
|||
} |
|||
module2.exports = function(argument) { |
|||
var number = +argument; |
|||
return number !== number || number === 0 ? 0 : trunc(number); |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-absolute-index.js |
|||
let imagePage = ''; |
|||
var require_to_absolute_index = __commonJS({ |
|||
if (art.namespaceId() == pg.nsImageId) { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-absolute-index.js"(exports, module2) { |
|||
imagePage = art.toString(); |
|||
"use strict"; |
|||
} else { |
|||
var toIntegerOrInfinity = require_to_integer_or_infinity(); |
|||
imagePage = getValidImageFromWikiText(wikiText); |
|||
var max = Math.max; |
|||
} |
|||
var min = Math.min; |
|||
if (imagePage) { |
|||
module2.exports = function(index, length) { |
|||
loadImage(Title.fromWikiText(imagePage), navpop); |
|||
var integer = toIntegerOrInfinity(index); |
|||
} |
|||
return integer < 0 ? max(integer + length, 0) : min(integer, length); |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-length.js |
|||
if (getValueOf('popupPreviews')) { |
|||
var require_to_length = __commonJS({ |
|||
insertArticlePreview(download, art, navpop); |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-length.js"(exports, module2) { |
|||
} |
|||
"use strict"; |
|||
} |
|||
var toIntegerOrInfinity = require_to_integer_or_infinity(); |
|||
var min = Math.min; |
|||
module2.exports = function(argument) { |
|||
var len = toIntegerOrInfinity(argument); |
|||
return len > 0 ? min(len, 9007199254740991) : 0; |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/length-of-array-like.js |
|||
function insertArticlePreview(download, art, navpop) { |
|||
var require_length_of_array_like = __commonJS({ |
|||
if (download && typeof download.data == typeof '') { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/length-of-array-like.js"(exports, module2) { |
|||
if (art.namespaceId() == pg.nsTemplateId && getValueOf('popupPreviewRawTemplates')) { |
|||
"use strict"; |
|||
// FIXME compare/consolidate with diff escaping code for wikitext |
|||
var toLength = require_to_length(); |
|||
const h = |
|||
module2.exports = function(obj) { |
|||
'<hr /><span style="font-family: monospace;">' + |
|||
return toLength(obj.length); |
|||
download.data.entify().split('\\n').join('<br />\\n') + |
|||
}; |
|||
'</span>'; |
|||
} |
|||
setPopupHTML(h, 'popupPreview', navpop.idNumber); |
|||
}); |
|||
} else { |
|||
const p = prepPreviewmaker(download.data, art, navpop); |
|||
p.showPreview(); |
|||
} |
|||
} |
|||
} |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/array-includes.js |
|||
function prepPreviewmaker(data, article, navpop) { |
|||
var require_array_includes = __commonJS({ |
|||
// deal with tricksy anchors |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/array-includes.js"(exports, module2) { |
|||
const d = anchorize(data, article.anchorString()); |
|||
"use strict"; |
|||
const urlBase = joinPath([pg.wiki.articlebase, article.urlString()]); |
|||
var toIndexedObject = require_to_indexed_object(); |
|||
const p = new Previewmaker(d, urlBase, navpop); |
|||
var toAbsoluteIndex = require_to_absolute_index(); |
|||
return p; |
|||
var lengthOfArrayLike = require_length_of_array_like(); |
|||
} |
|||
var createMethod = function(IS_INCLUDES) { |
|||
return function($this, el, fromIndex) { |
|||
var O = toIndexedObject($this); |
|||
var length = lengthOfArrayLike(O); |
|||
if (length === 0) return !IS_INCLUDES && -1; |
|||
var index = toAbsoluteIndex(fromIndex, length); |
|||
var value; |
|||
if (IS_INCLUDES && el !== el) while (length > index) { |
|||
value = O[index++]; |
|||
if (value !== value) return true; |
|||
} |
|||
else for (; length > index; index++) { |
|||
if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0; |
|||
} |
|||
return !IS_INCLUDES && -1; |
|||
}; |
|||
}; |
|||
module2.exports = { |
|||
// `Array.prototype.includes` method |
|||
// https://tc39.es/ecma262/#sec-array.prototype.includes |
|||
includes: createMethod(true), |
|||
// `Array.prototype.indexOf` method |
|||
// https://tc39.es/ecma262/#sec-array.prototype.indexof |
|||
indexOf: createMethod(false) |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-keys-internal.js |
|||
// Try to imitate the way mediawiki generates HTML anchors from section titles |
|||
var require_object_keys_internal = __commonJS({ |
|||
function anchorize(d, anch) { |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-keys-internal.js"(exports, module2) { |
|||
if (!anch) { |
|||
"use strict"; |
|||
return d; |
|||
var uncurryThis = require_function_uncurry_this(); |
|||
} |
|||
var hasOwn = require_has_own_property(); |
|||
const anchRe = RegExp( |
|||
var toIndexedObject = require_to_indexed_object(); |
|||
'(?:=+\\s*' + |
|||
var indexOf = require_array_includes().indexOf; |
|||
literalizeRegex(anch).replace(/[_ ]/g, '[_ ]') + |
|||
var hiddenKeys = require_hidden_keys(); |
|||
'\\s*=+|\\{\\{\\s*' + |
|||
var push = uncurryThis([].push); |
|||
getValueOf('popupAnchorRegexp') + |
|||
module2.exports = function(object, names) { |
|||
'\\s*(?:\\|[^|}]*)*?\\s*' + |
|||
var O = toIndexedObject(object); |
|||
literalizeRegex(anch) + |
|||
var i = 0; |
|||
'\\s*(?:\\|[^}]*)?}})' |
|||
var result = []; |
|||
); |
|||
var key; |
|||
const match = d.match(anchRe); |
|||
for (key in O) !hasOwn(hiddenKeys, key) && hasOwn(O, key) && push(result, key); |
|||
if (match && match.length > 0 && match[0]) { |
|||
while (names.length > i) if (hasOwn(O, key = names[i++])) { |
|||
return d.substring(d.indexOf(match[0])); |
|||
~indexOf(result, key) || push(result, key); |
|||
} |
|||
} |
|||
return result; |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/enum-bug-keys.js |
|||
// now try to deal with == foo [[bar|baz]] boom == -> #foo_baz_boom |
|||
var require_enum_bug_keys = __commonJS({ |
|||
const lines = d.split('\n'); |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/enum-bug-keys.js"(exports, module2) { |
|||
for (let i = 0; i < lines.length; ++i) { |
|||
"use strict"; |
|||
lines[i] = lines[i] |
|||
module2.exports = [ |
|||
.replace(/[[]{2}([^|\]]*?[|])?(.*?)[\]]{2}/g, '$2') |
|||
"constructor", |
|||
.replace(/'''([^'])/g, '$1') |
|||
"hasOwnProperty", |
|||
.replace(/''([^'])/g, '$1'); |
|||
"isPrototypeOf", |
|||
if (lines[i].match(anchRe)) { |
|||
"propertyIsEnumerable", |
|||
return d.split('\n').slice(i).join('\n').replace(/^[^=]*/, ''); |
|||
"toLocaleString", |
|||
} |
|||
"toString", |
|||
} |
|||
"valueOf" |
|||
return d; |
|||
]; |
|||
} |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-get-own-property-names.js |
|||
function killPopup() { |
|||
var require_object_get_own_property_names = __commonJS({ |
|||
removeModifierKeyHandler(this); |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-get-own-property-names.js"(exports) { |
|||
if (getValueOf('popupShortcutKeys')) { |
|||
"use strict"; |
|||
rmPopupShortcuts(); |
|||
var internalObjectKeys = require_object_keys_internal(); |
|||
} |
|||
var enumBugKeys = require_enum_bug_keys(); |
|||
if (!pg) { |
|||
var hiddenKeys = enumBugKeys.concat("length", "prototype"); |
|||
return; |
|||
exports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) { |
|||
} |
|||
return internalObjectKeys(O, hiddenKeys); |
|||
if (pg.current.link && pg.current.link.navpopup) { |
|||
}; |
|||
pg.current.link.navpopup.banish(); |
|||
} |
|||
}); |
|||
pg.current.link = null; |
|||
abortAllDownloads(); |
|||
if (pg.timer.checkPopupPosition) { |
|||
clearInterval(pg.timer.checkPopupPosition); |
|||
pg.timer.checkPopupPosition = null; |
|||
} |
|||
return true; // preserve default action |
|||
} |
|||
// ENDFILE: actions.js |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-get-own-property-symbols.js |
|||
// STARTFILE: domdrag.js |
|||
var require_object_get_own_property_symbols = __commonJS({ |
|||
/** |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-get-own-property-symbols.js"(exports) { |
|||
* @file |
|||
"use strict"; |
|||
* The {@link Drag} object, which enables objects to be dragged around. |
|||
exports.f = Object.getOwnPropertySymbols; |
|||
* |
|||
} |
|||
}); |
|||
* ************************************************* |
|||
* dom-drag.js |
|||
* 09.25.2001 |
|||
* www.youngpup.net |
|||
* ************************************************** |
|||
* 10.28.2001 - fixed minor bug where events |
|||
* sometimes fired off the handle, not the root. |
|||
* ************************************************* |
|||
* Pared down, some hooks added by [[User:Lupin]] |
|||
* |
|||
* Copyright Aaron Boodman. |
|||
* Saying stupid things daily since March 2001. |
|||
* </pre> |
|||
*/ |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/own-keys.js |
|||
/** |
|||
var require_own_keys = __commonJS({ |
|||
* Creates a new Drag object. This is used to make various DOM elements draggable. |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/own-keys.js"(exports, module2) { |
|||
* |
|||
"use strict"; |
|||
* @constructor |
|||
var getBuiltIn = require_get_built_in(); |
|||
*/ |
|||
var uncurryThis = require_function_uncurry_this(); |
|||
function Drag() { |
|||
var getOwnPropertyNamesModule = require_object_get_own_property_names(); |
|||
/** |
|||
var getOwnPropertySymbolsModule = require_object_get_own_property_symbols(); |
|||
* Condition to determine whether or not to drag. This function should take one parameter, |
|||
var anObject = require_an_object(); |
|||
* an Event. To disable this, set it to <code>null</code>. |
|||
var concat = uncurryThis([].concat); |
|||
* |
|||
module2.exports = getBuiltIn("Reflect", "ownKeys") || function ownKeys(it) { |
|||
* @type {Function} |
|||
var keys = getOwnPropertyNamesModule.f(anObject(it)); |
|||
*/ |
|||
var getOwnPropertySymbols = getOwnPropertySymbolsModule.f; |
|||
this.startCondition = null; |
|||
return getOwnPropertySymbols ? concat(keys, getOwnPropertySymbols(it)) : keys; |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/copy-constructor-properties.js |
|||
/** |
|||
var require_copy_constructor_properties = __commonJS({ |
|||
* Hook to be run when the drag finishes. This is passed the final coordinates of the |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/copy-constructor-properties.js"(exports, module2) { |
|||
* dragged object (two integers, x and y). To disables this, set it to <code>null</code>. |
|||
"use strict"; |
|||
* |
|||
var hasOwn = require_has_own_property(); |
|||
* @type {Function} |
|||
var ownKeys = require_own_keys(); |
|||
*/ |
|||
var getOwnPropertyDescriptorModule = require_object_get_own_property_descriptor(); |
|||
this.endHook = null; |
|||
var definePropertyModule = require_object_define_property(); |
|||
} |
|||
module2.exports = function(target, source, exceptions) { |
|||
var keys = ownKeys(source); |
|||
var defineProperty = definePropertyModule.f; |
|||
var getOwnPropertyDescriptor = getOwnPropertyDescriptorModule.f; |
|||
for (var i = 0; i < keys.length; i++) { |
|||
var key = keys[i]; |
|||
if (!hasOwn(target, key) && !(exceptions && hasOwn(exceptions, key))) { |
|||
defineProperty(target, key, getOwnPropertyDescriptor(source, key)); |
|||
} |
|||
} |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-forced.js |
|||
/** |
|||
var require_is_forced = __commonJS({ |
|||
* Gets an event in a cross-browser manner. |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-forced.js"(exports, module2) { |
|||
* |
|||
"use strict"; |
|||
* @param {Event} e |
|||
var fails = require_fails(); |
|||
* @private |
|||
var isCallable = require_is_callable(); |
|||
*/ |
|||
var replacement = /#|\.prototype\./; |
|||
Drag.prototype.fixE = function (e) { |
|||
var isForced = function(feature, detection) { |
|||
if (typeof e == 'undefined') { |
|||
var value = data[normalize(feature)]; |
|||
e = window.event; |
|||
return value === POLYFILL ? true : value === NATIVE ? false : isCallable(detection) ? fails(detection) : !!detection; |
|||
} |
|||
}; |
|||
if (typeof e.layerX == 'undefined') { |
|||
var normalize = isForced.normalize = function(string) { |
|||
e.layerX = e.offsetX; |
|||
return String(string).replace(replacement, ".").toLowerCase(); |
|||
} |
|||
}; |
|||
if (typeof e.layerY == 'undefined') { |
|||
var data = isForced.data = {}; |
|||
e.layerY = e.offsetY; |
|||
var NATIVE = isForced.NATIVE = "N"; |
|||
} |
|||
var POLYFILL = isForced.POLYFILL = "P"; |
|||
return e; |
|||
module2.exports = isForced; |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/export.js |
|||
/** |
|||
var require_export = __commonJS({ |
|||
* Initialises the Drag instance by telling it which object you want to be draggable, and what |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/export.js"(exports, module2) { |
|||
* you want to drag it by. |
|||
"use strict"; |
|||
* |
|||
var globalThis2 = require_global_this(); |
|||
* @param {HTMLElement} o The "handle" by which <code>oRoot</code> is dragged. |
|||
var getOwnPropertyDescriptor = require_object_get_own_property_descriptor().f; |
|||
* @param {HTMLElement} oRoot The object which moves when <code>o</code> is dragged, or <code>o</code> if omitted. |
|||
var createNonEnumerableProperty = require_create_non_enumerable_property(); |
|||
*/ |
|||
var defineBuiltIn = require_define_built_in(); |
|||
Drag.prototype.init = function (o, oRoot) { |
|||
var defineGlobalProperty = require_define_global_property(); |
|||
const dragObj = this; |
|||
var copyConstructorProperties = require_copy_constructor_properties(); |
|||
this.obj = o; |
|||
var isForced = require_is_forced(); |
|||
o.onmousedown = function (e) { |
|||
module2.exports = function(options, source) { |
|||
dragObj.start.apply(dragObj, [e]); |
|||
var TARGET = options.target; |
|||
}; |
|||
var GLOBAL = options.global; |
|||
o.dragging = false; |
|||
var STATIC = options.stat; |
|||
o.popups_draggable = true; |
|||
var FORCED, target, key, targetProperty, sourceProperty, descriptor; |
|||
o.hmode = true; |
|||
if (GLOBAL) { |
|||
o.vmode = true; |
|||
target = globalThis2; |
|||
} else if (STATIC) { |
|||
target = globalThis2[TARGET] || defineGlobalProperty(TARGET, {}); |
|||
} else { |
|||
target = globalThis2[TARGET] && globalThis2[TARGET].prototype; |
|||
} |
|||
if (target) for (key in source) { |
|||
sourceProperty = source[key]; |
|||
if (options.dontCallGetSet) { |
|||
descriptor = getOwnPropertyDescriptor(target, key); |
|||
targetProperty = descriptor && descriptor.value; |
|||
} else targetProperty = target[key]; |
|||
FORCED = isForced(GLOBAL ? key : TARGET + (STATIC ? "." : "#") + key, options.forced); |
|||
if (!FORCED && targetProperty !== void 0) { |
|||
if (typeof sourceProperty == typeof targetProperty) continue; |
|||
copyConstructorProperties(sourceProperty, targetProperty); |
|||
} |
|||
if (options.sham || targetProperty && targetProperty.sham) { |
|||
createNonEnumerableProperty(sourceProperty, "sham", true); |
|||
} |
|||
defineBuiltIn(target, key, sourceProperty, options); |
|||
} |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-array.js |
|||
o.root = oRoot || o; |
|||
var require_is_array = __commonJS({ |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-array.js"(exports, module2) { |
|||
"use strict"; |
|||
var classof = require_classof_raw(); |
|||
module2.exports = Array.isArray || function isArray(argument) { |
|||
return classof(argument) === "Array"; |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-string-tag-support.js |
|||
if (isNaN(parseInt(o.root.style.left, 10))) { |
|||
var require_to_string_tag_support = __commonJS({ |
|||
o.root.style.left = '0px'; |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-string-tag-support.js"(exports, module2) { |
|||
} |
|||
"use strict"; |
|||
if (isNaN(parseInt(o.root.style.top, 10))) { |
|||
var wellKnownSymbol = require_well_known_symbol(); |
|||
o.root.style.top = '0px'; |
|||
var TO_STRING_TAG = wellKnownSymbol("toStringTag"); |
|||
} |
|||
var test = {}; |
|||
test[TO_STRING_TAG] = "z"; |
|||
module2.exports = String(test) === "[object z]"; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/classof.js |
|||
o.root.onthisStart = function () {}; |
|||
var require_classof = __commonJS({ |
|||
o.root.onthisEnd = function () {}; |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/classof.js"(exports, module2) { |
|||
o.root.onthis = function () {}; |
|||
"use strict"; |
|||
}; |
|||
var TO_STRING_TAG_SUPPORT = require_to_string_tag_support(); |
|||
var isCallable = require_is_callable(); |
|||
var classofRaw = require_classof_raw(); |
|||
var wellKnownSymbol = require_well_known_symbol(); |
|||
var TO_STRING_TAG = wellKnownSymbol("toStringTag"); |
|||
var $Object = Object; |
|||
var CORRECT_ARGUMENTS = classofRaw(/* @__PURE__ */ (function() { |
|||
return arguments; |
|||
})()) === "Arguments"; |
|||
var tryGet = function(it, key) { |
|||
try { |
|||
return it[key]; |
|||
} catch (error) { |
|||
} |
|||
}; |
|||
module2.exports = TO_STRING_TAG_SUPPORT ? classofRaw : function(it) { |
|||
var O, tag, result; |
|||
return it === void 0 ? "Undefined" : it === null ? "Null" : typeof (tag = tryGet(O = $Object(it), TO_STRING_TAG)) == "string" ? tag : CORRECT_ARGUMENTS ? classofRaw(O) : (result = classofRaw(O)) === "Object" && isCallable(O.callee) ? "Arguments" : result; |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-string.js |
|||
/** |
|||
var require_to_string = __commonJS({ |
|||
* Starts the drag. |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-string.js"(exports, module2) { |
|||
* |
|||
"use strict"; |
|||
* @private |
|||
var classof = require_classof(); |
|||
* @param {Event} e |
|||
var $String = String; |
|||
*/ |
|||
module2.exports = function(argument) { |
|||
if (classof(argument) === "Symbol") throw new TypeError("Cannot convert a Symbol value to a string"); |
|||
const o = this.obj; // = this; |
|||
return $String(argument); |
|||
e = this.fixE(e); |
|||
}; |
|||
if (this.startCondition && !this.startCondition(e)) { |
|||
} |
|||
return; |
|||
}); |
|||
} |
|||
const y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom, 10); |
|||
const x = parseInt(o.hmode ? o.root.style.left : o.root.style.right, 10); |
|||
o.root.onthisStart(x, y); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/create-property.js |
|||
o.lastMouseX = e.clientX; |
|||
var require_create_property = __commonJS({ |
|||
o.lastMouseY = e.clientY; |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/create-property.js"(exports, module2) { |
|||
"use strict"; |
|||
var DESCRIPTORS = require_descriptors(); |
|||
var definePropertyModule = require_object_define_property(); |
|||
var createPropertyDescriptor = require_create_property_descriptor(); |
|||
module2.exports = function(object, key, value) { |
|||
if (DESCRIPTORS) definePropertyModule.f(object, key, createPropertyDescriptor(0, value)); |
|||
else object[key] = value; |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/parse-json-string.js |
|||
const dragObj = this; |
|||
var require_parse_json_string = __commonJS({ |
|||
o.onmousemoveDefault = document.onmousemove; |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/parse-json-string.js"(exports, module2) { |
|||
o.dragging = true; |
|||
"use strict"; |
|||
document.onmousemove = function (e) { |
|||
var uncurryThis = require_function_uncurry_this(); |
|||
dragObj.drag.apply(dragObj, [e]); |
|||
var hasOwn = require_has_own_property(); |
|||
}; |
|||
var $SyntaxError = SyntaxError; |
|||
document.onmouseup = function (e) { |
|||
var $parseInt = parseInt; |
|||
dragObj.end.apply(dragObj, [e]); |
|||
var fromCharCode = String.fromCharCode; |
|||
}; |
|||
var at = uncurryThis("".charAt); |
|||
return false; |
|||
var slice = uncurryThis("".slice); |
|||
}; |
|||
var exec = uncurryThis(/./.exec); |
|||
var codePoints = { |
|||
'\\"': '"', |
|||
"\\\\": "\\", |
|||
"\\/": "/", |
|||
"\\b": "\b", |
|||
"\\f": "\f", |
|||
"\\n": "\n", |
|||
"\\r": "\r", |
|||
"\\t": " " |
|||
}; |
|||
var IS_4_HEX_DIGITS = /^[\da-f]{4}$/i; |
|||
var IS_C0_CONTROL_CODE = /^[\u0000-\u001F]$/; |
|||
module2.exports = function(source, i) { |
|||
var unterminated = true; |
|||
var value = ""; |
|||
while (i < source.length) { |
|||
var chr = at(source, i); |
|||
if (chr === "\\") { |
|||
var twoChars = slice(source, i, i + 2); |
|||
if (hasOwn(codePoints, twoChars)) { |
|||
value += codePoints[twoChars]; |
|||
i += 2; |
|||
} else if (twoChars === "\\u") { |
|||
i += 2; |
|||
var fourHexDigits = slice(source, i, i + 4); |
|||
if (!exec(IS_4_HEX_DIGITS, fourHexDigits)) throw new $SyntaxError("Bad Unicode escape at: " + i); |
|||
value += fromCharCode($parseInt(fourHexDigits, 16)); |
|||
i += 4; |
|||
} else throw new $SyntaxError('Unknown escape sequence: "' + twoChars + '"'); |
|||
} else if (chr === '"') { |
|||
unterminated = false; |
|||
i++; |
|||
break; |
|||
} else { |
|||
if (exec(IS_C0_CONTROL_CODE, chr)) throw new $SyntaxError("Bad control character in string literal at: " + i); |
|||
value += chr; |
|||
i++; |
|||
} |
|||
} |
|||
if (unterminated) throw new $SyntaxError("Unterminated string at: " + i); |
|||
return { value, end: i }; |
|||
}; |
|||
} |
|||
}); |
|||
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/modules/es.json.parse.js |
|||
/** |
|||
var require_es_json_parse = __commonJS({ |
|||
* Does the drag. |
|||
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/modules/es.json.parse.js"() { |
|||
* |
|||
"use strict"; |
|||
* @param {Event} e |
|||
var $2 = require_export(); |
|||
* @private |
|||
var DESCRIPTORS = require_descriptors(); |
|||
*/ |
|||
var globalThis2 = require_global_this(); |
|||
Drag.prototype.drag = function (e) { |
|||
var getBuiltIn = require_get_built_in(); |
|||
e = this.fixE(e); |
|||
var uncurryThis = require_function_uncurry_this(); |
|||
const o = this.obj; |
|||
var call = require_function_call(); |
|||
var isCallable = require_is_callable(); |
|||
var isObject = require_is_object(); |
|||
var isArray = require_is_array(); |
|||
var hasOwn = require_has_own_property(); |
|||
var toString = require_to_string(); |
|||
var lengthOfArrayLike = require_length_of_array_like(); |
|||
var createProperty = require_create_property(); |
|||
var fails = require_fails(); |
|||
var parseJSONString = require_parse_json_string(); |
|||
var NATIVE_SYMBOL = require_symbol_constructor_detection(); |
|||
var JSON2 = globalThis2.JSON; |
|||
var Number2 = globalThis2.Number; |
|||
var SyntaxError2 = globalThis2.SyntaxError; |
|||
var nativeParse = JSON2 && JSON2.parse; |
|||
var enumerableOwnProperties = getBuiltIn("Object", "keys"); |
|||
var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; |
|||
var at = uncurryThis("".charAt); |
|||
var slice = uncurryThis("".slice); |
|||
var exec = uncurryThis(/./.exec); |
|||
var push = uncurryThis([].push); |
|||
var IS_DIGIT = /^\d$/; |
|||
var IS_NON_ZERO_DIGIT = /^[1-9]$/; |
|||
var IS_NUMBER_START = /^[\d-]$/; |
|||
var IS_WHITESPACE = /^[\t\n\r ]$/; |
|||
var PRIMITIVE = 0; |
|||
var OBJECT = 1; |
|||
var $parse = function(source, reviver) { |
|||
source = toString(source); |
|||
var context = new Context(source, 0, ""); |
|||
var root = context.parse(); |
|||
var value = root.value; |
|||
var endIndex = context.skip(IS_WHITESPACE, root.end); |
|||
if (endIndex < source.length) { |
|||
throw new SyntaxError2('Unexpected extra character: "' + at(source, endIndex) + '" after the parsed data at: ' + endIndex); |
|||
} |
|||
return isCallable(reviver) ? internalize({ "": value }, "", reviver, root) : value; |
|||
}; |
|||
var internalize = function(holder, name, reviver, node) { |
|||
var val = holder[name]; |
|||
var unmodified = node && val === node.value; |
|||
var context = unmodified && typeof node.source == "string" ? { source: node.source } : {}; |
|||
var elementRecordsLen, keys, len, i, P; |
|||
if (isObject(val)) { |
|||
var nodeIsArray = isArray(val); |
|||
var nodes = unmodified ? node.nodes : nodeIsArray ? [] : {}; |
|||
if (nodeIsArray) { |
|||
elementRecordsLen = nodes.length; |
|||
len = lengthOfArrayLike(val); |
|||
for (i = 0; i < len; i++) { |
|||
internalizeProperty(val, i, internalize(val, "" + i, reviver, i < elementRecordsLen ? nodes[i] : void 0)); |
|||
} |
|||
} else { |
|||
keys = enumerableOwnProperties(val); |
|||
len = lengthOfArrayLike(keys); |
|||
for (i = 0; i < len; i++) { |
|||
P = keys[i]; |
|||
internalizeProperty(val, P, internalize(val, P, reviver, hasOwn(nodes, P) ? nodes[P] : void 0)); |
|||
} |
|||
} |
|||
} |
|||
return call(reviver, holder, name, val, context); |
|||
}; |
|||
var internalizeProperty = function(object, key, value) { |
|||
if (DESCRIPTORS) { |
|||
var descriptor = getOwnPropertyDescriptor(object, key); |
|||
if (descriptor && !descriptor.configurable) return; |
|||
} |
|||
if (value === void 0) delete object[key]; |
|||
else createProperty(object, key, value); |
|||
}; |
|||
var Node = function(value, end, source, nodes) { |
|||
this.value = value; |
|||
this.end = end; |
|||
this.source = source; |
|||
this.nodes = nodes; |
|||
}; |
|||
var Context = function(source, index) { |
|||
this.source = source; |
|||
this.index = index; |
|||
}; |
|||
Context.prototype = { |
|||
fork: function(nextIndex) { |
|||
return new Context(this.source, nextIndex); |
|||
}, |
|||
parse: function() { |
|||
var source = this.source; |
|||
var i = this.skip(IS_WHITESPACE, this.index); |
|||
var fork = this.fork(i); |
|||
var chr = at(source, i); |
|||
if (exec(IS_NUMBER_START, chr)) return fork.number(); |
|||
switch (chr) { |
|||
case "{": |
|||
return fork.object(); |
|||
case "[": |
|||
return fork.array(); |
|||
case '"': |
|||
return fork.string(); |
|||
case "t": |
|||
return fork.keyword(true); |
|||
case "f": |
|||
return fork.keyword(false); |
|||
case "n": |
|||
return fork.keyword(null); |
|||
} |
|||
throw new SyntaxError2('Unexpected character: "' + chr + '" at: ' + i); |
|||
}, |
|||
node: function(type, value, start, end, nodes) { |
|||
return new Node(value, end, type ? null : slice(this.source, start, end), nodes); |
|||
}, |
|||
object: function() { |
|||
var source = this.source; |
|||
var i = this.index + 1; |
|||
var expectKeypair = false; |
|||
var object = {}; |
|||
var nodes = {}; |
|||
var closed = false; |
|||
while (i < source.length) { |
|||
i = this.until(['"', "}"], i); |
|||
if (at(source, i) === "}" && !expectKeypair) { |
|||
i++; |
|||
closed = true; |
|||
break; |
|||
} |
|||
var result = this.fork(i).string(); |
|||
var key = result.value; |
|||
i = result.end; |
|||
i = this.until([":"], i) + 1; |
|||
i = this.skip(IS_WHITESPACE, i); |
|||
result = this.fork(i).parse(); |
|||
createProperty(nodes, key, result); |
|||
createProperty(object, key, result.value); |
|||
i = this.until([",", "}"], result.end); |
|||
var chr = at(source, i); |
|||
if (chr === ",") { |
|||
expectKeypair = true; |
|||
i++; |
|||
} else if (chr === "}") { |
|||
i++; |
|||
closed = true; |
|||
break; |
|||
} |
|||
} |
|||
if (!closed) throw new SyntaxError2("Unterminated object at: " + i); |
|||
return this.node(OBJECT, object, this.index, i, nodes); |
|||
}, |
|||
array: function() { |
|||
var source = this.source; |
|||
var i = this.index + 1; |
|||
var expectElement = false; |
|||
var array = []; |
|||
var nodes = []; |
|||
var closed = false; |
|||
while (i < source.length) { |
|||
i = this.skip(IS_WHITESPACE, i); |
|||
if (at(source, i) === "]" && !expectElement) { |
|||
i++; |
|||
closed = true; |
|||
break; |
|||
} |
|||
var result = this.fork(i).parse(); |
|||
push(nodes, result); |
|||
push(array, result.value); |
|||
i = this.until([",", "]"], result.end); |
|||
if (at(source, i) === ",") { |
|||
expectElement = true; |
|||
i++; |
|||
} else if (at(source, i) === "]") { |
|||
i++; |
|||
closed = true; |
|||
break; |
|||
} |
|||
} |
|||
if (!closed) throw new SyntaxError2("Unterminated array at: " + i); |
|||
return this.node(OBJECT, array, this.index, i, nodes); |
|||
}, |
|||
string: function() { |
|||
var index = this.index; |
|||
var parsed = parseJSONString(this.source, this.index + 1); |
|||
return this.node(PRIMITIVE, parsed.value, index, parsed.end); |
|||
}, |
|||
number: function() { |
|||
var source = this.source; |
|||
var startIndex = this.index; |
|||
var i = startIndex; |
|||
if (at(source, i) === "-") i++; |
|||
if (at(source, i) === "0") i++; |
|||
else if (exec(IS_NON_ZERO_DIGIT, at(source, i))) i = this.skip(IS_DIGIT, i + 1); |
|||
else throw new SyntaxError2("Failed to parse number at: " + i); |
|||
if (at(source, i) === ".") { |
|||
var fractionStartIndex = i + 1; |
|||
i = this.skip(IS_DIGIT, fractionStartIndex); |
|||
if (fractionStartIndex === i) throw new SyntaxError2("Failed to parse number's fraction at: " + i); |
|||
} |
|||
if (at(source, i) === "e" || at(source, i) === "E") { |
|||
i++; |
|||
if (at(source, i) === "+" || at(source, i) === "-") i++; |
|||
var exponentStartIndex = i; |
|||
i = this.skip(IS_DIGIT, i); |
|||
if (exponentStartIndex === i) throw new SyntaxError2("Failed to parse number's exponent value at: " + i); |
|||
} |
|||
return this.node(PRIMITIVE, Number2(slice(source, startIndex, i)), startIndex, i); |
|||
}, |
|||
keyword: function(value) { |
|||
var keyword = "" + value; |
|||
var index = this.index; |
|||
var endIndex = index + keyword.length; |
|||
if (slice(this.source, index, endIndex) !== keyword) throw new SyntaxError2("Failed to parse value at: " + index); |
|||
return this.node(PRIMITIVE, value, index, endIndex); |
|||
}, |
|||
skip: function(regex, i) { |
|||
var source = this.source; |
|||
for (; i < source.length; i++) if (!exec(regex, at(source, i))) break; |
|||
return i; |
|||
}, |
|||
until: function(array, i) { |
|||
i = this.skip(IS_WHITESPACE, i); |
|||
var chr = at(this.source, i); |
|||
for (var j = 0; j < array.length; j++) if (array[j] === chr) return i; |
|||
throw new SyntaxError2('Unexpected character: "' + chr + '" at: ' + i); |
|||
} |
|||
}; |
|||
var NO_SOURCE_SUPPORT = fails(function() { |
|||
var unsafeInt = "9007199254740993"; |
|||
var source; |
|||
nativeParse(unsafeInt, function(key, value, context) { |
|||
source = context.source; |
|||
}); |
|||
return source !== unsafeInt; |
|||
}); |
|||
var PROPER_BASE_PARSE = NATIVE_SYMBOL && !fails(function() { |
|||
return 1 / nativeParse("-0 ") !== -Infinity; |
|||
}); |
|||
$2({ target: "JSON", stat: true, forced: NO_SOURCE_SUPPORT }, { |
|||
parse: function parse(text, reviver) { |
|||
return PROPER_BASE_PARSE && !isCallable(reviver) ? nativeParse(text) : $parse(text, reviver); |
|||
} |
|||
}); |
|||
} |
|||
}); |
|||
// dist/Navigation_popups/Navigation_popups.js |
|||
const ey = e.clientY; |
|||
//! src/Navigation_popups/modules/api.ts |
|||
const ex = e.clientX; |
|||
require_es_json_parse(); |
|||
const y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom, 10); |
|||
var _templateObject; |
|||
const x = parseInt(o.hmode ? o.root.style.left : o.root.style.right, 10); |
|||
var _templateObject2; |
|||
let nx, ny; |
|||
var _templateObject3; |
|||
var _templateObject4; |
|||
var _templateObject5; |
|||
var _templateObject6; |
|||
var _templateObject7; |
|||
var _templateObject8; |
|||
var _templateObject9; |
|||
var _templateObject0; |
|||
var _templateObject1; |
|||
var _templateObject10; |
|||
var _templateObject11; |
|||
function asyncGeneratorStep(n, t, e, r, o, a, c) { |
|||
try { |
|||
var i = n[a](c), u = i.value; |
|||
} catch (n2) { |
|||
return void e(n2); |
|||
} |
|||
i.done ? t(u) : Promise.resolve(u).then(r, o); |
|||
} |
|||
function _asyncToGenerator(n) { |
|||
return function() { |
|||
var t = this, e = arguments; |
|||
return new Promise(function(r, o) { |
|||
var a = n.apply(t, e); |
|||
function _next(n2) { |
|||
asyncGeneratorStep(a, r, o, _next, _throw, "next", n2); |
|||
} |
|||
function _throw(n2) { |
|||
asyncGeneratorStep(a, r, o, _next, _throw, "throw", n2); |
|||
} |
|||
_next(void 0); |
|||
}); |
|||
}; |
|||
} |
|||
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; |
|||
} |
|||
function _taggedTemplateLiteral(e, t) { |
|||
return t || (t = e.slice(0)), Object.freeze(Object.defineProperties(e, { raw: { value: Object.freeze(t) } })); |
|||
} |
|||
var import_ext_gadget = require("ext.gadget.Util"); |
|||
var api = (0, import_ext_gadget.initMwApi)("Navigation popups/1.0"); |
|||
//! src/Navigation_popups/modules/string.ts |
|||
var message = { |
|||
// summary data, searching etc. |
|||
article: window.wgULS("条目", "條目"), |
|||
category: window.wgULS("个分类", "個分類"), |
|||
categories: window.wgULS("个分类", "個分類"), |
|||
image: window.wgULS("个文件", "個檔案"), |
|||
images: window.wgULS("个文件", "個檔案"), |
|||
stub: "小作品", |
|||
"section stub": window.wgULS("小章节", "小章節"), |
|||
"Empty page": window.wgULS("空页面", "空頁面"), |
|||
kB: window.wgULS("千字节<sub>(以1000为一进)</sub>", "千位元組<sub>(以1000為一進)</sub>"), |
|||
bytes: window.wgULS("字节", "位元組"), |
|||
day: "天", |
|||
days: "天", |
|||
hour: window.wgULS("小时", "小時"), |
|||
hours: window.wgULS("小时", "小時"), |
|||
minute: "分", |
|||
minutes: "分", |
|||
second: "秒", |
|||
seconds: "秒", |
|||
week: "周", |
|||
weeks: "周", |
|||
month: "月", |
|||
months: "月", |
|||
year: "年", |
|||
years: "年", |
|||
search: window.wgULS("搜索", "搜尋"), |
|||
SearchHint: window.wgULS("搜索包含 %s 的页面", "搜尋包含 %s 的頁面"), |
|||
web: "Bing", |
|||
global: "全域", |
|||
"more...": "更多……", |
|||
// article-related actions and info |
|||
// (some actions also apply to user pages) |
|||
actions: window.wgULS("操作", "動作"), |
|||
// /// view articles and view talk |
|||
popupsMenu: "Popups", |
|||
"disable previews": window.wgULS("禁用预览", "禁用預覽"), |
|||
togglePreviewsHint: window.wgULS("切换本页 Popups 的预览开关", "切換本頁 Popups 的預覽開關"), |
|||
"toggle previews": window.wgULS("切换预览开关", "切換預覽開關"), |
|||
reset: window.wgULS("复位", "複位"), |
|||
disable: "禁用 Popups", |
|||
disablePopupsHint: window.wgULS("在本页禁用 Popups,刷新页面以重新启用。", "在本頁禁用 Popups,重新整理頁面以重新啟用。"), |
|||
purgePopupsHint: window.wgULS("复位 Popups,清除所有缓存数据。", "複位 Popups,清除所有快取資料。"), |
|||
PopupsHint: window.wgULS("复位 Popups,清除所有缓存数据。", "複位 Popups,清除所有快取資料。"), |
|||
spacebar: "空格", |
|||
view: window.wgULS("查看", "檢視"), |
|||
"view article": window.wgULS("查看条目", "檢視條目"), |
|||
viewHint: window.wgULS("前往 %s", "前往 %s"), |
|||
talk: window.wgULS("讨论", "討論"), |
|||
"talk page": window.wgULS("讨论页", "討論頁"), |
|||
"this revision": window.wgULS("此修订版本", "此修訂版本"), |
|||
"revision %s of %s": window.wgULS("页面 $2 的修订版本 $1", "頁面 $2 的修訂版本 $1"), |
|||
"Revision %s of %s": window.wgULS("页面 $2 的修订版本 $1", "頁面 $2 的修訂版本 $1"), |
|||
"the revision prior to revision %s of %s": window.wgULS("页面 $2 的修订版本 $1 之前的修订版本", "頁面 $2 的修訂版本 $1 之前的修訂版本"), |
|||
"Toggle image size": window.wgULS("点击切换图片大小", "點擊切換圖片大小"), |
|||
del: window.wgULS("删除", "删除"), |
|||
// /// delete, protect, move |
|||
delete: window.wgULS("删除", "删除"), |
|||
deleteHint: window.wgULS("删除 %s", "删除 %s"), |
|||
undeleteShort: window.wgULS("恢复", "恢復"), |
|||
UndeleteHint: window.wgULS("恢复 %s", "恢復 %s"), |
|||
protect: window.wgULS("保护", "保護"), |
|||
protectHint: window.wgULS("保护 %s", "保護 %s"), |
|||
unprotectShort: window.wgULS("解除", "解除"), |
|||
unprotectHint: window.wgULS("解除对 %s 的保护", "解除對 %s 的保護"), |
|||
move: window.wgULS("移动", "移動"), |
|||
"move page": window.wgULS("移动页面", "移動頁面"), |
|||
MovepageHint: window.wgULS("修改 %s 的标题", "修改 %s 的標題"), |
|||
edit: window.wgULS("编辑", "編輯"), |
|||
// /// edit articles and talk |
|||
"edit article": window.wgULS("编辑条目", "編輯條目"), |
|||
editHint: window.wgULS("修改 %s 的内容", "修改 %s 的內容"), |
|||
"edit talk": window.wgULS("编辑讨论页", "編輯對話頁"), |
|||
new: window.wgULS("新", "新"), |
|||
"new topic": window.wgULS("新话题", "新話題"), |
|||
newSectionHint: window.wgULS("在 %s 增加新的讨论话题", "在 %s 增加新的討論話題"), |
|||
"null edit": window.wgULS("空编辑", "空編輯"), |
|||
nullEditHint: window.wgULS("进行一次对 %s 的空编辑", "製造一次對 %s 的空編輯"), |
|||
hist: window.wgULS("历史", "歷史"), |
|||
// /// history, diffs, editors, related |
|||
history: window.wgULS("历史", "歷史"), |
|||
historyHint: window.wgULS("%s 的修订历史", "%s 的修訂歷史"), |
|||
last: window.wgULS("之前", "之前"), |
|||
// [[MediaWiki:Last]] |
|||
lastEdit: window.wgULS("最近更改", "最近更改"), |
|||
"show last edit": window.wgULS("最近一次更改", "最新一次修訂"), |
|||
"Show the last edit": window.wgULS("显示最近一次更改的差异", "顯示最新一次修訂的差異"), |
|||
lastContrib: window.wgULS("最近编辑", "最近編輯"), |
|||
"last set of edits": window.wgULS("最近编辑", "最近編輯"), |
|||
lastContribHint: window.wgULS("显示由最后一位编辑者造成的差异", "顯示由最後一位編輯者製造的差異"), |
|||
cur: window.wgULS("当前", "當前"), |
|||
diffCur: window.wgULS("与当前版本的差异", "與目前版本的差異"), |
|||
"Show changes since revision %s": window.wgULS("显示自修订版本 %s 的差异", "顯示自修訂版本 %s 的差異"), |
|||
"%s old": window.wgULS("%s 前的最后版本", "%s 前的最后版本"), |
|||
// as in 4 weeks old |
|||
oldEdit: window.wgULS("旧编辑", "舊編輯"), |
|||
purge: window.wgULS("清除缓存", "清除快取"), |
|||
purgeHint: window.wgULS("清除服务器中 %s 的缓存", "清除伺服器中 %s 的快取"), |
|||
raw: window.wgULS("源代码", "原始碼"), |
|||
rawHint: window.wgULS("查看 %s 的源代码", "檢視 %s 的原始碼"), |
|||
render: window.wgULS("仅正文", "僅正文"), |
|||
renderHint: window.wgULS("显示 %s 的纯HTML解析(仅正文内容)", "顯示 %s 的純HTML解析(僅正文內容)"), |
|||
"Show the edit made to get revision": window.wgULS("显示编辑以得到修订版本", "顯示編輯以得到修訂版本"), |
|||
sinceMe: window.wgULS("自我", "自我"), |
|||
"changes since mine": window.wgULS("自我修订的差异", "自我修訂的差異"), |
|||
sinceMeHint: window.wgULS("显示自我上次修改以来的差异", "顯示自我上次修改以來的差異"), |
|||
"Couldn't find an edit by %s\nin the last %s edits to\n%s": window.wgULS("在 $3 最近 $2 次编辑中找不到 $1 做出的修改", "在 $3 最近 $2 次編輯中找不到 $1 做出的修改"), |
|||
eds: window.wgULS("编辑", "編輯"), |
|||
editors: window.wgULS("编辑者", "編輯者"), |
|||
editorListHint: window.wgULS("列出编辑过 %s 的用户", "列出編輯過 %s 的使用者"), |
|||
related: window.wgULS("相关", "相關"), |
|||
relatedChanges: window.wgULS("相关更改", "相關更改"), |
|||
"related changes": window.wgULS("相关更改", "相關更改"), |
|||
RecentchangeslinkedHint: window.wgULS("显示相关 %s 的修改", "顯示相關 %s 的修改"), |
|||
editOld: window.wgULS("编辑旧版", "編輯舊版"), |
|||
// /// edit old version, or revert |
|||
rv: window.wgULS("回退", "恢復"), |
|||
revert: window.wgULS("回退", "恢復"), |
|||
revertHint: window.wgULS("回退到 %s", "恢復到 %s"), |
|||
undo: window.wgULS("撤销", "撤銷"), |
|||
undoHint: window.wgULS("撤销这次编辑", "撤銷這次編輯"), |
|||
defaultpopupRedlinkSummary: window.wgULS("移除到空页面[[%s]]的链接(Popups)", "移除到空頁面[[%s]]的連結(Popups)"), |
|||
defaultpopupFixDabsSummary: window.wgULS("消歧义[[%s]]到[[%s]](Popups)", "消歧義[[%s]]到[[%s]](Popups)"), |
|||
defaultpopupFixRedirsSummary: window.wgULS("忽略从[[%s]]到[[%s]]的重定向(Popups)", "忽略從[[%s]]到[[%s]]的重新導向(Popups)"), |
|||
defaultpopupExtendedRevertSummary: window.wgULS("回退到$2在$1时编辑的修订版本$3(Popups)", "還原到$2在$1時製作的修訂版本$3(Popups)"), |
|||
defaultpopupRevertToPreviousSummary: window.wgULS("回退到修订版本%s的上一个版本(Popups)", "還原到修訂版本%s的上一個版本(Popups)"), |
|||
defaultpopupRevertSummary: window.wgULS("回退到修订版本%s(Popups)", "還原到修訂版本%s(Popups)"), |
|||
defaultpopupQueriedRevertToPreviousSummary: window.wgULS("回退到修订版本$1的上一个版本,由$3在$2时编辑(Popups)", "還原到修訂版本$1的上一個版本,由$3在$2時製作(Popups)"), |
|||
defaultpopupQueriedRevertSummary: window.wgULS("回退到$3在$2时编辑的修订版本$1(Popups)", "還原到$3在$2時製作的修訂版本$1(Popups)"), |
|||
defaultpopupRmDabLinkSummary: window.wgULS("移除到消歧义页[[%s]]的链接(Popups)", "移除到消歧義頁[[%s]]的連結(Popups)"), |
|||
Redirects: window.wgULS("重定向", "重定向"), |
|||
// as in Redirects to ... |
|||
// " to ": window.wgULS( "到","到" ), |
|||
// as in Redirects to ... |
|||
"Bypass redirect": window.wgULS("忽略重定向", "忽略重新導向"), |
|||
"Fix this redirect": window.wgULS("修复重定向", "修復重新導向"), |
|||
disambig: window.wgULS("消歧义", "消歧義"), |
|||
// /// add or remove dab etc. |
|||
disambigHint: window.wgULS("消歧义这个链接到 [[%s]]", "消歧義這個連結到 [[%s]]"), |
|||
"Click to disambiguate this link to:": window.wgULS("点击以消歧义这个链接到:", "點擊以消歧義這個連結到:"), |
|||
"remove this link": window.wgULS("移除链接", "移除連結"), |
|||
"remove all links to this page from this article": window.wgULS("移除此条目到这页的所有链接", "移除此條目到這頁的所有連結"), |
|||
"remove all links to this disambig page from this article": window.wgULS("移除此条目到这消歧义的所有链接", "移除此條目到這消歧義的所有連結"), |
|||
mainlink: window.wgULS("主链接", "主連結"), |
|||
// /// links, watch, unwatch |
|||
wikiLink: window.wgULS("个内部链接", "个內部連結"), |
|||
wikiLinks: window.wgULS("个内部链接", "个內部連結"), |
|||
"links here": window.wgULS("链入", "鏈入"), |
|||
whatLinksHere: window.wgULS("链入页面", "鏈入頁面"), |
|||
"what links here": window.wgULS("链入页面", "鏈入頁面"), |
|||
WhatlinkshereHint: window.wgULS("显示链接到 %s 的页面", "顯示連結到 %s 的頁面"), |
|||
unwatchShort: window.wgULS("取消", "取消"), |
|||
watchThingy: window.wgULS("监视", "監視"), |
|||
// called watchThingy because {}.watch is a function |
|||
watchHint: window.wgULS("加入 %s 到我的监视列表", "加入 %s 到我的監視列表"), |
|||
unwatchHint: window.wgULS("从我的监视列表移除 %s", "從我的監視列表移除 %s"), |
|||
"Only found one editor: %s made %s edits": window.wgULS("仅找到一位编者:%s 制造了 %s 次编辑", "僅找到一位編者:%s 製造了 %s 次編輯"), |
|||
"%s seems to be the last editor to the page %s": window.wgULS("%s 看上去是 %s 这页的最后一位编者", "%s 看上去是 %s 這頁的最後一位編者"), |
|||
rss: window.wgULS("RSS", "RSS"), |
|||
// diff previews |
|||
"Diff truncated for performance reasons": window.wgULS("出于性能考虑,差异已被截断", "出於效能考慮,差異已被截斷"), |
|||
"Old revision": window.wgULS("旧版本", "舊版本"), |
|||
"New revision": window.wgULS("新版本", "新版本"), |
|||
"Something went wrong :-(": window.wgULS("出问题了 :-(", "出問題了 :-("), |
|||
"Empty revision, maybe non-existent": window.wgULS("空的修订,可能并不存在", "空的修訂,可能並不存在"), |
|||
"Unknown date": window.wgULS("未知日期", "未知日期"), |
|||
// other special previews |
|||
"Empty category": window.wgULS("空的分类", "空的分類"), |
|||
"Category members (%s shown)": window.wgULS("分类成员(%s 显示)", "分類成員(%s 顯示)"), |
|||
"No image links found": window.wgULS("未找到文件链接", "未找到檔案連結"), |
|||
"File links": window.wgULS("文件链接", "檔案連結"), |
|||
"not commons": window.wgULS("维基共享中无此名称的文件。", "維基共享中無此名稱的檔案。"), |
|||
"commons only": window.wgULS("此文件来自维基共享。", "此檔案來自維基共享。"), |
|||
"No image found": window.wgULS("找不到文件", "找不到檔案"), |
|||
"commons dupe": window.wgULS("维基共享中存在此文件的副本。", "維基共享中存在此檔案的副本。"), |
|||
"commons conflict": window.wgULS("维基共享中存在此文件名称不同的副本。", "維基共享中存在此檔名稱不同的副本。"), |
|||
// user-related actions and info |
|||
user: window.wgULS("用户", "使用者"), |
|||
// /// user page, talk, email, space |
|||
"user page": window.wgULS("用户页", "使用者頁"), |
|||
"user talk": window.wgULS("用户讨论", "使用者對話"), |
|||
"edit user talk": window.wgULS("编辑用户讨论", "編輯使用者對話"), |
|||
"leave comment": window.wgULS("留言", "留言"), |
|||
email: window.wgULS("电邮", "電郵"), |
|||
"email user": window.wgULS("电邮用户", "電郵使用者"), |
|||
EmailuserHint: window.wgULS("给 %s 发送电子邮件", "給 %s 發送電子郵件"), |
|||
space: window.wgULS("子页面", "子頁面"), |
|||
// short form for userSpace link |
|||
PrefixindexHint: window.wgULS("显示 %s 的用户页子页面", "顯示 %s 的使用者頁子頁面"), |
|||
count: window.wgULS("统计", "統計"), |
|||
// /// contributions, tree, log |
|||
"edit counter": window.wgULS("编辑次数", "編輯次數"), |
|||
katelinkHint: window.wgULS("%s 的编辑次数", "%s 的編輯次數"), |
|||
contribs: window.wgULS("贡献", "貢獻"), |
|||
contributions: window.wgULS("贡献", "貢獻"), |
|||
deletedContribs: window.wgULS("已删除的贡献", "已刪除的貢獻"), |
|||
ContributionsHint: window.wgULS("%s 的用户贡献", "%s 的使用者貢獻"), |
|||
tree: window.wgULS("树", "樹"), |
|||
contribsTreeHint: window.wgULS("根据名字空间查看 %s 的贡献", "根據命名空間檢視 %s 的貢獻"), |
|||
log: window.wgULS("日志", "日誌"), |
|||
"user log": window.wgULS("用户日志", "使用者日誌"), |
|||
userLogHint: window.wgULS("显示 %s 的用户日志", "顯示 %s 的使用者日誌"), |
|||
unblockShort: window.wgULS("解除", "解除"), |
|||
block: window.wgULS("封禁", "封鎖"), |
|||
"block user": window.wgULS("封禁用户", "封鎖使用者"), |
|||
IpblocklistHint: window.wgULS("解封 %s", "解封 %s"), |
|||
BlockipHint: window.wgULS("封禁 %s", "封鎖 %s"), |
|||
"block log": window.wgULS("封禁日志", "封鎖日誌"), |
|||
blockLogHint: window.wgULS("显示 %s 的封禁日志", "顯示 %s 的封鎖日誌"), |
|||
protectLogHint: window.wgULS("显示 %s 的保护日志", "顯示 %s 的保護日誌"), |
|||
pageLogHint: window.wgULS("显示 %s 的日志", "顯示 %s 的日誌"), |
|||
deleteLogHint: window.wgULS("显示 %s 的删除日志", "顯示 %s 的刪除日誌"), |
|||
"Invalid %s %s": window.wgULS("选项 %s 不可用:%s", "選項 %s 不可用:%s"), |
|||
m: "小", |
|||
// Autoediting |
|||
"Enter a non-empty edit summary or press cancel to abort": window.wgULS("输入编辑摘要,或按取消中止操作", "輸入編輯摘要,或按取消中止操作"), |
|||
"Failed to get revision information, please edit manually.\n\n": window.wgULS("获取修订版本信息失败,请手动修改。\n\n", "獲取修訂版本資訊失敗,請手動修改。\n\n"), |
|||
"The %s button has been automatically clicked. Please wait for the next page to load.": window.wgULS("按钮 %s 已被自动点击,请等待下一个页面加载。", "按鈕 %s 已被自動點擊,請等待下一個頁面載入。"), |
|||
"Could not find button %s. Please check the settings in your javascript file.": window.wgULS("找不到按钮 %s,请检查您 JavaScript 文件中的设置。", "找不到按鈕 %s,請檢查您 JavaScript 檔案中的設定。"), |
|||
// Popups setup |
|||
"Open full-size image": window.wgULS("查看全尺寸图像", "檢視全尺寸影像"), |
|||
// 以下内容由 AnnAngela 补正 |
|||
bingSearchHint: window.wgULS("在 Bing 上搜索“%s”", "在 bing 上搜尋「%s」"), |
|||
"enable previews": window.wgULS("启用预览", "啟用預覽"), |
|||
"show preview": window.wgULS("禁用预览", "禁用預覽"), |
|||
historyfeedHint: window.wgULS("该页面的近期更改 RSS feed", "該頁面的近期更改 RSS feed"), |
|||
"send thanks": window.wgULS("发送感谢", "傳送感謝"), |
|||
ThanksHint: window.wgULS("向该用户发送一封感谢消息", "向該使用者傳送一封感謝訊息"), |
|||
"mark patrolled": window.wgULS("标记为已巡查", "標記為已巡查"), |
|||
markpatrolledHint: window.wgULS("标记该编辑为已巡查", "標記該編輯為已巡查"), |
|||
"Could not marked this edit as patrolled": window.wgULS("无法标记该编辑为已巡查", "無法標記該編輯為已巡查"), |
|||
defaultpopupReviewedSummary: window.wgULS("标记从版本%s到%s间的编辑为已巡查", "標記從版本%s到%s間的編輯為已巡查"), |
|||
"Image from Commons": window.wgULS("来自维基共享的图片", "來自維基共用的圖片"), |
|||
"Description page": window.wgULS("图片描述页", "圖片描述頁"), |
|||
"Alt text:": window.wgULS("替换文本(Alt):", "替換文字(Alt):"), |
|||
revdel: window.wgULS("历史版本被隐藏", "歷史版本被隱藏"), |
|||
DeletedcontributionsHint: window.wgULS("用户%s的被删除编辑次数", "使用者%s的被刪除編輯次數"), |
|||
"No backlinks found": window.wgULS("找不到链入页面", "找不到鏈入頁面"), |
|||
" and more": window.wgULS("以及其他页面", "以及其他頁面"), |
|||
"Download preview data": window.wgULS("下载预览数据", "下載預覽資料"), |
|||
"Not a registered username": window.wgULS("非已注册的用户", "非已註冊的使用者"), |
|||
BLOCKED: window.wgULS("被封禁", "被封鎖"), |
|||
"Has blocks": window.wgULS("被部分封禁", "被部分封鎖"), |
|||
" edits since: ": window.wgULS("次编辑,注册日期为", "次編輯,註冊日期為"), |
|||
"last edit on ": window.wgULS("最后一次编辑于", "最後一次編輯於"), |
|||
EmailUserHint: window.wgULS("给 %s 发送电子邮件", "給 %s 發送電子郵件"), |
|||
RANGEBLOCKED: window.wgULS("IP段被封禁", "IP段被封鎖"), |
|||
"IP user": window.wgULS("IP用户", "IP使用者"), |
|||
"♀": "♀", |
|||
"♂": "♂", |
|||
HIDDEN: window.wgULS("全域隐藏", "全域隱藏"), |
|||
LOCKED: window.wgULS("全域锁定", "全域鎖定"), |
|||
"Invalid user": window.wgULS("非法用户名", "非法使用者名稱"), |
|||
diff: window.wgULS("差异", "差異"), |
|||
" to ": "至", |
|||
autoedit_version: "np20140416", |
|||
PrefixIndexHint: window.wgULS("显示用户%s的子页面", "顯示使用者%s的子頁面"), |
|||
nullEditSummary: window.wgULS("进行一次零编辑", "進行一次零編輯"), |
|||
// 用户组名称从系统消息获取 |
|||
"group-no-autoconfirmed": window.wgULS("非自动确认用户", "非自動確認使用者"), |
|||
separator: "、", |
|||
comma: "," |
|||
}; |
|||
//! src/Navigation_popups/modules/core.js |
|||
var popups = () => { |
|||
const pg = { |
|||
api: {}, |
|||
re: {}, |
|||
ns: {}, |
|||
string: {}, |
|||
wiki: {}, |
|||
user: {}, |
|||
misc: {}, |
|||
option: {}, |
|||
optionDefault: {}, |
|||
flag: {}, |
|||
cache: {}, |
|||
structures: {}, |
|||
timer: {}, |
|||
counter: {}, |
|||
current: {}, |
|||
fn: {}, |
|||
endoflist: null |
|||
}; |
|||
if (window.pg && !(window.pg instanceof HTMLElement)) { |
|||
return; |
|||
} |
|||
window.pg = pg; |
|||
const setupTooltips = (container, remove, force, popData) => { |
|||
log("setupTooltips, container=".concat(container, ", remove=").concat(remove)); |
|||
if (!container) { |
|||
if (getValueOf("popupOnEditSelection") && document && document.editform && document.editform.wpTextbox1) { |
|||
document.editform.wpTextbox1.onmouseup = doSelectionPopup; |
|||
} |
|||
container = defaultPopupsContainer(); |
|||
} |
|||
if (!remove && !force && container.ranSetupTooltipsAlready) { |
|||
return; |
|||
} |
|||
container.ranSetupTooltipsAlready = !remove; |
|||
const anchors = container.querySelectorAll("a"); |
|||
setupTooltipsLoop(anchors, 0, 250, 100, remove, popData); |
|||
}; |
|||
const defaultPopupsContainer = () => { |
|||
if (getValueOf("popupOnlyArticleLinks")) { |
|||
return document.querySelector(".skin-vector-2022 .vector-body") || document.querySelector("#mw_content") || document.querySelector("#content") || document.querySelector("#article") || document; |
|||
} |
|||
return document; |
|||
}; |
|||
const setupTooltipsLoop = function setupTooltipsLoop2(anchors, begin, howmany, sleep, remove, popData, ...args) { |
|||
log(simplePrintf("setupTooltipsLoop(%s,%s,%s,%s,%s)", [anchors, begin, howmany, sleep, remove, popData, ...args])); |
|||
const finish = begin + howmany; |
|||
const loopend = Math.min(finish, anchors.length); |
|||
let j = loopend - begin; |
|||
log("setupTooltips: anchors.length=".concat(anchors.length, ", begin=").concat(begin, ", howmany=").concat(howmany, ", loopend=").concat(loopend, ", remove=").concat(remove)); |
|||
const doTooltip = remove ? removeTooltip : addTooltip; |
|||
if (j > 0) { |
|||
do { |
|||
const a = anchors[loopend - j]; |
|||
if (a === void 0 || !a || !a.href) { |
|||
log("got null anchor at index ".concat(loopend) - j); |
|||
continue; |
|||
} |
|||
doTooltip(a, popData); |
|||
} while (--j); |
|||
} |
|||
if (finish < anchors.length) { |
|||
setTimeout(() => { |
|||
setupTooltipsLoop2(anchors, finish, howmany, sleep, remove, popData); |
|||
}, sleep); |
|||
} else { |
|||
if (!remove && !getValueOf("popupTocLinks")) { |
|||
rmTocTooltips(); |
|||
} |
|||
pg.flag.finishedLoading = true; |
|||
} |
|||
}; |
|||
const rmTocTooltips = () => { |
|||
const toc = document.querySelector("#toc"); |
|||
if (toc) { |
|||
const tocLinks = toc.querySelectorAll("a"); |
|||
const tocLen = tocLinks.length; |
|||
for (let j = 0; j < tocLen; ++j) { |
|||
removeTooltip(tocLinks[j], true); |
|||
} |
|||
} |
|||
}; |
|||
const addTooltip = (a, popData) => { |
|||
if (!isPopupLink(a)) { |
|||
return; |
|||
} |
|||
a.onmouseover = mouseOverWikiLink; |
|||
a.onmouseout = mouseOutWikiLink; |
|||
a.onmousedown = killPopup; |
|||
a.hasPopup = true; |
|||
a.popData = popData; |
|||
}; |
|||
const removeTooltip = (a) => { |
|||
if (!a.hasPopup) { |
|||
return; |
|||
} |
|||
a.onmouseover = null; |
|||
a.onmouseout = null; |
|||
if (a.originalTitle) { |
|||
a.title = a.originalTitle; |
|||
} |
|||
a.hasPopup = false; |
|||
}; |
|||
const removeTitle = (a) => { |
|||
a.originalTitle || (a.originalTitle = a.title); |
|||
a.title = ""; |
|||
}; |
|||
const restoreTitle = (a) => { |
|||
if (a.title || !a.originalTitle) { |
|||
return; |
|||
} |
|||
a.title = a.originalTitle; |
|||
}; |
|||
const registerHooks = (np) => { |
|||
const popupMaxWidth = getValueOf("popupMaxWidth"); |
|||
if (typeof popupMaxWidth === "number") { |
|||
const setMaxWidth = () => { |
|||
np.mainDiv.style.maxWidth = "".concat(popupMaxWidth, "px"); |
|||
np.maxWidth = popupMaxWidth; |
|||
}; |
|||
np.addHook(setMaxWidth, "unhide", "before"); |
|||
} |
|||
np.addHook(addPopupShortcuts, "unhide", "after"); |
|||
np.addHook(rmPopupShortcuts, "hide", "before"); |
|||
}; |
|||
const removeModifierKeyListener = (a) => { |
|||
document.removeEventListener("keydown", a.modifierKeyListener, false); |
|||
document.removeEventListener("keyup", a.modifierKeyListener, false); |
|||
}; |
|||
const mouseOverWikiLink = function mouseOverWikiLink3(evt) { |
|||
if (!evt && window.event) { |
|||
evt = window.event; |
|||
} |
|||
if (getValueOf("popupModifier")) { |
|||
const action = getValueOf("popupModifierAction"); |
|||
const key = action === "disable" ? "keyup" : "keydown"; |
|||
const self2 = this; |
|||
self2.modifierKeyListener = (evt2) => { |
|||
mouseOverWikiLink2(self2, evt2); |
|||
}; |
|||
document.addEventListener(key, self2.modifierKeyListener, false); |
|||
} |
|||
return mouseOverWikiLink2(this, evt); |
|||
}; |
|||
const footnoteTarget = (a) => { |
|||
const aTitle = Title.fromAnchor(a); |
|||
const anch = aTitle.anchor; |
|||
if (!/^(cite_note-|_note-|endnote)/.test(anch)) { |
|||
return false; |
|||
} |
|||
const lTitle = Title.fromURL(location.href); |
|||
if (lTitle.toString(true) !== aTitle.toString(true)) { |
|||
return false; |
|||
} |
|||
let el = document.getElementById("".concat(anch)); |
|||
while (el && typeof el.nodeName === "string") { |
|||
const nt = el.nodeName.toLowerCase(); |
|||
if (nt === "li") { |
|||
return el; |
|||
} else if (nt === "body") { |
|||
return false; |
|||
} else if (el.parentNode) { |
|||
el = el.parentNode; |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
return false; |
|||
}; |
|||
const footnotePreview = (x, navpop) => { |
|||
setPopupHTML("<hr>".concat(x.innerHTML), "popupPreview", navpop.idNumber); |
|||
}; |
|||
const modifierPressed = (evt) => { |
|||
const mod = getValueOf("popupModifier"); |
|||
if (!mod) { |
|||
return false; |
|||
} |
|||
if (!evt && window.event) { |
|||
evt = window.event; |
|||
} |
|||
return evt && mod && evt["".concat(mod.toLowerCase(), "Key")]; |
|||
}; |
|||
const isCorrectModifier = (_a, evt) => { |
|||
if (!getValueOf("popupModifier")) { |
|||
return true; |
|||
} |
|||
const action = getValueOf("popupModifierAction"); |
|||
return action === "enable" && modifierPressed(evt) || action === "disable" && !modifierPressed(evt); |
|||
}; |
|||
const mouseOverWikiLink2 = (a, evt) => { |
|||
if (!isCorrectModifier(a, evt)) { |
|||
return; |
|||
} |
|||
if (getValueOf("removeTitles")) { |
|||
removeTitle(a); |
|||
} |
|||
if (a === pg.current.link && a.navpopup && a.navpopup.isVisible()) { |
|||
return; |
|||
} |
|||
pg.current.link = a; |
|||
if (getValueOf("simplePopups") && !pg.option.popupStructure) { |
|||
setDefault("popupStructure", "original"); |
|||
} |
|||
const article = new Title().fromAnchor(a); |
|||
pg.current.article = article; |
|||
if (!a.navpopup) { |
|||
a.navpopup = newNavpopup(a, article); |
|||
pg.current.linksHash[a.href] = a.navpopup; |
|||
pg.current.links.push(a); |
|||
} |
|||
if (a.navpopup.pending === null || a.navpopup.pending !== 0) { |
|||
simplePopupContent(a, article); |
|||
} |
|||
a.navpopup.showSoonIfStable(a.navpopup.delay); |
|||
clearInterval(pg.timer.checkPopupPosition); |
|||
pg.timer.checkPopupPosition = setInterval(checkPopupPosition, 600); |
|||
if (getValueOf("simplePopups") && getValueOf("popupPreviewButton") && !a.simpleNoMore) { |
|||
const d = document.createElement("div"); |
|||
d.className = "popupPreviewButtonDiv"; |
|||
const s = document.createElement("span"); |
|||
d.append(s); |
|||
s.className = "popupPreviewButton"; |
|||
s["on".concat(getValueOf("popupPreviewButtonEvent"))] = () => { |
|||
a.simpleNoMore = true; |
|||
d.style.display = "none"; |
|||
nonsimplePopupContent(a, article); |
|||
}; |
|||
s.innerHTML = popupString("show preview"); |
|||
setPopupHTML(d, "popupPreview", a.navpopup.idNumber); |
|||
} |
|||
if (a.navpopup.pending !== 0) { |
|||
nonsimplePopupContent(a, article); |
|||
} |
|||
}; |
|||
const simplePopupContent = (a, article) => { |
|||
a.navpopup.hasPopupMenu = false; |
|||
a.navpopup.setInnerHTML(popupHTML(a)); |
|||
fillEmptySpans({ |
|||
navpopup: a.navpopup |
|||
}); |
|||
if (getValueOf("popupDraggable")) { |
|||
let dragHandle = getValueOf("popupDragHandle") || null; |
|||
if (dragHandle && dragHandle !== "all") { |
|||
dragHandle += a.navpopup.idNumber; |
|||
} |
|||
setTimeout(() => { |
|||
a.navpopup.makeDraggable(dragHandle); |
|||
}, 150); |
|||
} |
|||
if (getValueOf("popupRedlinkRemoval") && a.className === "new") { |
|||
setPopupHTML("<br>".concat(popupRedlinkHTML(article)), "popupRedlink", a.navpopup.idNumber); |
|||
} |
|||
}; |
|||
const debugData = (navpopup) => { |
|||
if (getValueOf("popupDebugging") && navpopup.idNumber) { |
|||
setPopupHTML("idNumber=".concat(navpopup.idNumber, ", pending=").concat(navpopup.pending), "popupError", navpopup.idNumber); |
|||
} |
|||
}; |
|||
const newNavpopup = (a, article) => { |
|||
const navpopup = new Navpopup(); |
|||
navpopup.fuzz = 5; |
|||
navpopup.delay = getValueOf("popupDelay") * 1e3; |
|||
navpopup.idNumber = ++pg.idNumber; |
|||
navpopup.parentAnchor = a; |
|||
navpopup.parentPopup = a.popData && a.popData.owner; |
|||
navpopup.article = article; |
|||
registerHooks(navpopup); |
|||
return navpopup; |
|||
}; |
|||
const shouldShowNonSimple = (a) => { |
|||
return !getValueOf("simplePopups") || a.simpleNoMore; |
|||
}; |
|||
const shouldShow = (a, option) => { |
|||
if (shouldShowNonSimple(a)) { |
|||
return getValueOf(option); |
|||
} |
|||
return window[option] !== void 0 && window[option]; |
|||
}; |
|||
const nonsimplePopupContent = (a, article) => { |
|||
let diff2; |
|||
let history; |
|||
const params = parseParams(a.href); |
|||
const oldid = params.oldid === void 0 ? null : params.oldid; |
|||
if (shouldShow(a, "popupPreviewDiffs")) { |
|||
({ |
|||
diff: diff2 |
|||
} = params); |
|||
} |
|||
if (shouldShow(a, "popupPreviewHistory")) { |
|||
history = params.action === "history"; |
|||
} |
|||
a.navpopup.pending = 0; |
|||
const referenceElement = footnoteTarget(a); |
|||
if (referenceElement) { |
|||
footnotePreview(referenceElement, a.navpopup); |
|||
} else if (diff2 || diff2 === 0) { |
|||
loadDiff(article, oldid, diff2, a.navpopup); |
|||
} else if (history) { |
|||
loadAPIPreview("history", article, a.navpopup); |
|||
} else if (shouldShowNonSimple(a) && pg.re.contribs.test(a.href)) { |
|||
loadAPIPreview("contribs", article, a.navpopup); |
|||
} else if (shouldShowNonSimple(a) && pg.re.backlinks.test(a.href)) { |
|||
loadAPIPreview("backlinks", article, a.navpopup); |
|||
} else if ( |
|||
// FIXME should be able to get all preview combinations with options |
|||
article.namespaceId() === pg.nsImageId && (shouldShow(a, "imagePopupsForImages") || !anchorContainsImage(a)) |
|||
) { |
|||
loadAPIPreview("imagepagepreview", article, a.navpopup); |
|||
loadImage(article, a.navpopup); |
|||
} else { |
|||
if (article.namespaceId() === pg.nsCategoryId && shouldShow(a, "popupCategoryMembers")) { |
|||
loadAPIPreview("category", article, a.navpopup); |
|||
} else if ((article.namespaceId() === pg.nsUserId || article.namespaceId() === pg.nsUsertalkId) && shouldShow(a, "popupUserInfo")) { |
|||
loadAPIPreview("userinfo", article, a.navpopup); |
|||
} |
|||
if (shouldShowNonSimple(a)) { |
|||
startArticlePreview(article, oldid, a.navpopup); |
|||
} |
|||
} |
|||
}; |
|||
const pendingNavpopTask = (navpop) => { |
|||
if (navpop && navpop.pending === null) { |
|||
navpop.pending = 0; |
|||
} |
|||
++navpop.pending; |
|||
debugData(navpop); |
|||
}; |
|||
const completedNavpopTask = (navpop) => { |
|||
if (navpop && navpop.pending) { |
|||
--navpop.pending; |
|||
} |
|||
debugData(navpop); |
|||
}; |
|||
const startArticlePreview = (article, oldid, navpop) => { |
|||
navpop.redir = 0; |
|||
loadPreview(article, oldid, navpop); |
|||
}; |
|||
const loadPreview = (article, oldid, navpop) => { |
|||
if (!navpop.redir) { |
|||
navpop.originalArticle = article; |
|||
} |
|||
article.oldid = oldid; |
|||
loadAPIPreview("revision", article, navpop); |
|||
}; |
|||
const loadPreviewFromRedir = (redirMatch, navpop) => { |
|||
const target = new Title().fromWikiText(redirMatch[2]); |
|||
if (navpop.article.anchor) { |
|||
target.anchor = navpop.article.anchor; |
|||
} |
|||
navpop.redir++; |
|||
navpop.redirTarget = target; |
|||
const warnRedir = redirLink(target, navpop.article); |
|||
setPopupHTML(warnRedir, "popupWarnRedir", navpop.idNumber); |
|||
navpop.article = target; |
|||
fillEmptySpans({ |
|||
redir: true, |
|||
redirTarget: target, |
|||
navpopup: navpop |
|||
}); |
|||
return loadPreview(target, null, navpop); |
|||
}; |
|||
const insertPreview = (download) => { |
|||
if (!download.owner) { |
|||
return; |
|||
} |
|||
const redirMatch = pg.re.redirect.exec(download.data); |
|||
if (download.owner.redir === 0 && redirMatch) { |
|||
loadPreviewFromRedir(redirMatch, download.owner); |
|||
return; |
|||
} |
|||
if (download.owner.visible || !getValueOf("popupLazyPreviews")) { |
|||
insertPreviewNow(download); |
|||
} else { |
|||
const id = download.owner.redir ? "PREVIEW_REDIR_HOOK" : "PREVIEW_HOOK"; |
|||
download.owner.addHook(() => { |
|||
insertPreviewNow(download); |
|||
return true; |
|||
}, "unhide", "after", id); |
|||
} |
|||
}; |
|||
const insertPreviewNow = (download) => { |
|||
if (!download.owner) { |
|||
return; |
|||
} |
|||
const wikiText = download.data; |
|||
const navpop = download.owner; |
|||
const art = navpop.redirTarget || navpop.originalArticle; |
|||
makeFixDabs(wikiText, navpop); |
|||
if (getValueOf("popupSummaryData")) { |
|||
getPageInfo(wikiText, download); |
|||
setPopupTrailer(getPageInfo(wikiText, download), navpop.idNumber); |
|||
} |
|||
let imagePage = ""; |
|||
imagePage = art.namespaceId() === pg.nsImageId ? art.toString() : getValidImageFromWikiText(wikiText); |
|||
if (imagePage) { |
|||
loadImage(Title.fromWikiText(imagePage), navpop); |
|||
} |
|||
if (getValueOf("popupPreviews")) { |
|||
insertArticlePreview(download, art, navpop); |
|||
} |
|||
}; |
|||
const insertArticlePreview = (download, art, navpop) => { |
|||
if (download && typeof download.data === "string") { |
|||
if (art.namespaceId() === pg.nsTemplateId && getValueOf("popupPreviewRawTemplates")) { |
|||
const h = '<hr><span style="font-family: monospace;">'.concat(download.data.entify().split(String.raw(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n"], ["\\n"])))).join(String.raw(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["<br>\n"], ["<br>\\n"])))), "</span>"); |
|||
setPopupHTML(h, "popupPreview", navpop.idNumber); |
|||
} else { |
|||
const p = prepPreviewmaker(download.data, art, navpop); |
|||
p.showPreview(); |
|||
} |
|||
} |
|||
}; |
|||
const prepPreviewmaker = (data, article, navpop) => { |
|||
const d = anchorize(data, article.anchorString()); |
|||
const urlBase = joinPath([pg.wiki.articlebase, article.urlString()]); |
|||
const p = new Previewmaker(d, urlBase, navpop); |
|||
return p; |
|||
}; |
|||
const anchorize = (d, anch) => { |
|||
if (!anch) { |
|||
return d; |
|||
} |
|||
const anchRe = new RegExp("(?:=+\\s*".concat(literalizeRegex(anch).replace(/[ _]/g, "[_ ]"), "\\s*=+|\\{\\{\\s*").concat(getValueOf("popupAnchorRegexp"), "\\s*(?:\\|[^|}]*)*?\\s*").concat(literalizeRegex(anch), "\\s*(?:\\|[^}]*)?}})")); |
|||
const match = d.match(anchRe); |
|||
if (match && match.length > 0 && match[0]) { |
|||
return d.slice(Math.max(0, d.indexOf(match[0]))); |
|||
} |
|||
const lines = d.split("\n"); |
|||
for (let i = 0; i < lines.length; ++i) { |
|||
lines[i] = lines[i].replace(/\[{2}([^\]|]*?\|)?(.*?)]{2}/g, "$2").replace(/'''([^'])/g, "$1").replace(/''([^'])/g, "$1"); |
|||
if (anchRe.test(lines[i])) { |
|||
return d.split("\n").slice(i).join("\n").replace(/^[^=]*/, ""); |
|||
} |
|||
} |
|||
return d; |
|||
}; |
|||
const killPopup = function killPopup2() { |
|||
removeModifierKeyListener(this); |
|||
if (getValueOf("popupShortcutKeys")) { |
|||
rmPopupShortcuts(); |
|||
} |
|||
if (!pg) { |
|||
return; |
|||
} |
|||
if (pg.current.link && pg.current.link.navpopup) { |
|||
pg.current.link.navpopup.banish(); |
|||
} |
|||
pg.current.link = null; |
|||
abortAllDownloads(); |
|||
if (pg.timer.checkPopupPosition) { |
|||
clearInterval(pg.timer.checkPopupPosition); |
|||
pg.timer.checkPopupPosition = null; |
|||
} |
|||
return true; |
|||
}; |
|||
class Drag { |
|||
constructor() { |
|||
this.startCondition = null; |
|||
this.endHook = null; |
|||
} |
|||
/** |
|||
* Gets an event in a cross-browser manner. |
|||
* |
|||
* @param {Event} e |
|||
* @private |
|||
*/ |
|||
static fixE(e) { |
|||
if (e === void 0) { |
|||
e = window.event; |
|||
} |
|||
if (e.layerX === void 0) { |
|||
e.layerX = e.offsetX; |
|||
} |
|||
if (e.layerY === void 0) { |
|||
e.layerY = e.offsetY; |
|||
} |
|||
return e; |
|||
} |
|||
/** |
|||
* Initialises the Drag instance by telling it which object you want to be draggable, and what |
|||
* you want to drag it by. |
|||
* |
|||
* @param {DOMElement} o The "handle" by which <code>oRoot</code> is dragged. |
|||
* @param {DOMElement} oRoot The object which moves when <code>o</code> is dragged, or <code>o</code> if omitted. |
|||
*/ |
|||
init(o, oRoot) { |
|||
const self2 = this; |
|||
this.obj = o; |
|||
o.onmousedown = (e) => { |
|||
self2.start(e); |
|||
}; |
|||
o.dragging = false; |
|||
o.popups_draggable = true; |
|||
o.hmode = true; |
|||
o.vmode = true; |
|||
o.root = oRoot || o; |
|||
if (Number.isNaN(Number.parseInt(o.root.style.left, 10))) { |
|||
o.root.style.left = "0px"; |
|||
} |
|||
if (Number.isNaN(Number.parseInt(o.root.style.top, 10))) { |
|||
o.root.style.top = "0px"; |
|||
} |
|||
o.root.onthisStart = () => { |
|||
}; |
|||
o.root.onthisEnd = () => { |
|||
}; |
|||
o.root.onthis = () => { |
|||
}; |
|||
} |
|||
/** |
|||
* Starts the drag. |
|||
* |
|||
* @private |
|||
* @param {Event} e |
|||
*/ |
|||
start(e) { |
|||
const o = this.obj; |
|||
e = Drag.fixE(e); |
|||
if (this.startCondition && !this.startCondition(e)) { |
|||
return; |
|||
} |
|||
const y = Number.parseInt(o.vmode ? o.root.style.top : o.root.style.bottom, 10); |
|||
const x = Number.parseInt(o.hmode ? o.root.style.left : o.root.style.right, 10); |
|||
o.root.onthisStart(x, y); |
|||
o.lastMouseX = e.clientX; |
|||
o.lastMouseY = e.clientY; |
|||
const self2 = this; |
|||
o.onmousemoveDefault = document.onmousemove; |
|||
o.dragging = true; |
|||
document.onmousemove = (e2) => { |
|||
self2.drag(e2); |
|||
}; |
|||
document.onmouseup = (e2) => { |
|||
self2.end(e2); |
|||
}; |
|||
return false; |
|||
} |
|||
/** |
|||
* Does the drag. |
|||
* |
|||
* @param {Event} e |
|||
* @private |
|||
*/ |
|||
drag(e) { |
|||
e = Drag.fixE(e); |
|||
const o = this.obj; |
|||
const ey = e.clientY; |
|||
const ex = e.clientX; |
|||
const y = Number.parseInt(o.vmode ? o.root.style.top : o.root.style.bottom, 10); |
|||
const x = Number.parseInt(o.hmode ? o.root.style.left : o.root.style.right, 10); |
|||
const nx = x + (ex - o.lastMouseX) * (o.hmode ? 1 : -1); |
|||
const ny = y + (ey - o.lastMouseY) * (o.vmode ? 1 : -1); |
|||
this.obj.root.style[o.hmode ? "left" : "right"] = "".concat(nx, "px"); |
|||
this.obj.root.style[o.vmode ? "top" : "bottom"] = "".concat(ny, "px"); |
|||
this.obj.lastMouseX = ex; |
|||
this.obj.lastMouseY = ey; |
|||
this.obj.root.onthis(nx, ny); |
|||
return false; |
|||
} |
|||
/** |
|||
* Ends the drag. |
|||
* |
|||
* @private |
|||
*/ |
|||
end() { |
|||
document.onmousemove = this.obj.onmousemoveDefault; |
|||
document.onmouseup = null; |
|||
this.obj.dragging = false; |
|||
if (this.endHook) { |
|||
this.endHook(Number.parseInt(this.obj.root.style[this.obj.hmode ? "left" : "right"], 10), Number.parseInt(this.obj.root.style[this.obj.vmode ? "top" : "bottom"], 10)); |
|||
} |
|||
} |
|||
} |
|||
pg.structures.original = {}; |
|||
pg.structures.original.popupLayout = () => { |
|||
return ["popupError", "popupImage", "popupTopLinks", "popupTitle", "popupUserData", "popupData", "popupOtherLinks", "popupRedir", ["popupWarnRedir", "popupRedirTopLinks", "popupRedirTitle", "popupRedirData", "popupRedirOtherLinks"], "popupMiscTools", ["popupRedlink"], "popupPrePreviewSep", "popupPreview", "popupSecondPreview", "popupPreviewMore", "popupPostPreview", "popupFixDab"]; |
|||
}; |
|||
pg.structures.original.popupRedirSpans = () => { |
|||
return ["popupRedir", "popupWarnRedir", "popupRedirTopLinks", "popupRedirTitle", "popupRedirData", "popupRedirOtherLinks"]; |
|||
}; |
|||
pg.structures.original.popupTitle = (x) => { |
|||
log("defaultstructure.popupTitle"); |
|||
if (!getValueOf("popupNavLinks")) { |
|||
return navlinkStringToHTML("<b><<mainlink>></b>", x.article, x.params); |
|||
} |
|||
return ""; |
|||
}; |
|||
pg.structures.original.popupTopLinks = (x) => { |
|||
log("defaultstructure.popupTopLinks"); |
|||
if (getValueOf("popupNavLinks")) { |
|||
return navLinksHTML(x.article, x.hint, x.params); |
|||
} |
|||
return ""; |
|||
}; |
|||
pg.structures.original.popupImage = (x) => { |
|||
log("original.popupImage, x.article=".concat(x.article, ", x.navpop.idNumber=").concat(x.navpop.idNumber)); |
|||
return imageHTML(x.article, x.navpop.idNumber); |
|||
}; |
|||
pg.structures.original.popupRedirTitle = pg.structures.original.popupTitle; |
|||
pg.structures.original.popupRedirTopLinks = pg.structures.original.popupTopLinks; |
|||
const copyStructure = (oldStructure, newStructure) => { |
|||
pg.structures[newStructure] = {}; |
|||
for (const prop in pg.structures[oldStructure]) { |
|||
if (!Object.hasOwn(pg.structures[oldStructure], prop)) { |
|||
continue; |
|||
} |
|||
pg.structures[newStructure][prop] = pg.structures[oldStructure][prop]; |
|||
} |
|||
}; |
|||
copyStructure("original", "nostalgia"); |
|||
pg.structures.nostalgia.popupTopLinks = (x) => { |
|||
let str = ""; |
|||
str += "<b><<mainlink|shortcut= >></b>"; |
|||
str += "if(user){<br><<contribs|shortcut=c>>"; |
|||
str += "if(wikimedia){*<<count|shortcut=#>>}"; |
|||
str += "if(ipuser){}else{*<<email|shortcut=E>>}if(admin){*<<block|shortcut=b>>}}"; |
|||
const editstr = "<<edit|shortcut=e>>"; |
|||
const editOldidStr = "if(oldid){<<editOld|shortcut=e>>|<<revert|shortcut=v|rv>>|<<edit|cur>>}else{".concat(editstr, "}"); |
|||
const historystr = "<<history|shortcut=h>>"; |
|||
const watchstr = "<<unwatch|unwatchShort>>|<<watch|shortcut=w|watchThingy>>"; |
|||
str += "<br>if(talk){".concat(editOldidStr, "|<<new|shortcut=+>>*").concat(historystr, "*").concat(watchstr, "*<b><<article|shortcut=a>></b>|<<editArticle|edit>>}else{").concat( |
|||
// not a talk page |
|||
editOldidStr, |
|||
"*" |
|||
).concat(historystr, "*").concat(watchstr, "*<b><<talk|shortcut=t>></b>|<<editTalk|edit>>|<<newTalk|shortcut=+|new>>}"); |
|||
str += "<br><<whatLinksHere|shortcut=l>>*<<relatedChanges|shortcut=r>>"; |
|||
str += "if(admin){<br>}else{*}<<move|shortcut=m>>"; |
|||
str += "if(admin){*<<unprotect|unprotectShort>>|<<protect|shortcut=p>>*<<undelete|undeleteShort>>|<<delete|shortcut=d>>}"; |
|||
return navlinkStringToHTML(str, x.article, x.params); |
|||
}; |
|||
pg.structures.nostalgia.popupRedirTopLinks = pg.structures.nostalgia.popupTopLinks; |
|||
copyStructure("original", "fancy"); |
|||
pg.structures.fancy.popupTitle = (x) => { |
|||
return navlinkStringToHTML("<font size=+0><<mainlink>></font>", x.article, x.params); |
|||
}; |
|||
pg.structures.fancy.popupTopLinks = (x) => { |
|||
const hist = "<<history|shortcut=h|hist>>|<<lastEdit|shortcut=/|last>>|<<editors|shortcut=E|eds>>"; |
|||
const watch = "<<unwatch|unwatchShort>>|<<watch|shortcut=w|watchThingy>>"; |
|||
const move = "<<move|shortcut=m|move>>"; |
|||
return navlinkStringToHTML("if(talk){<<edit|shortcut=e>>|<<new|shortcut=+|+>>*".concat(hist, "*<<article|shortcut=a>>|<<editArticle|edit>>*").concat(watch, "*").concat(move, "}else{<<edit|shortcut=e>>*").concat(hist, "*<<talk|shortcut=t|>>|<<editTalk|edit>>|<<newTalk|shortcut=+|new>>*").concat(watch, "*").concat(move, "}<br>"), x.article, x.params); |
|||
}; |
|||
pg.structures.fancy.popupOtherLinks = (x) => { |
|||
const admin = "<<unprotect|unprotectShort>>|<<protect|shortcut=p>>*<<undelete|undeleteShort>>|<<delete|shortcut=d|del>>"; |
|||
let user = "<<contribs|shortcut=c>>if(wikimedia){|<<count|shortcut=#|#>>}"; |
|||
user += "if(ipuser){|<<arin>>}else{*<<email|shortcut=E|".concat(popupString("email"), ">>}if(admin){*<<block|shortcut=b>>}"); |
|||
const normal = "<<whatLinksHere|shortcut=l|links here>>*<<relatedChanges|shortcut=r|related>>"; |
|||
return navlinkStringToHTML("<br>if(user){".concat(user, "*}if(admin){").concat(admin, "if(user){<br>}else{*}}").concat(normal), x.article, x.params); |
|||
}; |
|||
pg.structures.fancy.popupRedirTitle = pg.structures.fancy.popupTitle; |
|||
pg.structures.fancy.popupRedirTopLinks = pg.structures.fancy.popupTopLinks; |
|||
pg.structures.fancy.popupRedirOtherLinks = pg.structures.fancy.popupOtherLinks; |
|||
copyStructure("fancy", "fancy2"); |
|||
pg.structures.fancy2.popupTopLinks = // hack out the <br> at the end and put one at the beginning |
|||
(x) => { |
|||
return "<br>".concat(pg.structures.fancy.popupTopLinks(x).replace(/<br>$/i, "")); |
|||
}; |
|||
pg.structures.fancy2.popupLayout = () => { |
|||
return ["popupError", "popupImage", "popupTitle", "popupUserData", "popupData", "popupTopLinks", "popupOtherLinks", "popupRedir", ["popupWarnRedir", "popupRedirTopLinks", "popupRedirTitle", "popupRedirData", "popupRedirOtherLinks"], "popupMiscTools", ["popupRedlink"], "popupPrePreviewSep", "popupPreview", "popupSecondPreview", "popupPreviewMore", "popupPostPreview", "popupFixDab"]; |
|||
}; |
|||
copyStructure("original", "menus"); |
|||
pg.structures.menus.popupLayout = () => { |
|||
return ["popupError", "popupImage", "popupTopLinks", "popupTitle", "popupOtherLinks", "popupRedir", ["popupWarnRedir", "popupRedirTopLinks", "popupRedirTitle", "popupRedirData", "popupRedirOtherLinks"], "popupUserData", "popupData", "popupMiscTools", ["popupRedlink"], "popupPrePreviewSep", "popupPreview", "popupSecondPreview", "popupPreviewMore", "popupPostPreview", "popupFixDab"]; |
|||
}; |
|||
pg.structures.menus.popupTopLinks = (x, shorter) => { |
|||
const s = []; |
|||
const dropdiv = '<div class="popup_drop">'; |
|||
const enddiv = "</div>"; |
|||
let hist = "<<history|shortcut=h>>"; |
|||
if (!shorter) { |
|||
hist = "<menurow>".concat(hist, "|<<historyfeed|rss>>|<<editors|shortcut=E>></menurow>"); |
|||
} |
|||
const lastedit = "<<lastEdit|shortcut=/|show last edit>>"; |
|||
const thank = "if(diff){<<thank|send thanks>>}"; |
|||
const jsHistory = "<<lastContrib|last set of edits>><<sinceMe|changes since mine>>"; |
|||
const linkshere = "<<whatLinksHere|shortcut=l|what links here>>"; |
|||
const related = "<<relatedChanges|shortcut=r|related changes>>"; |
|||
const search = "<menurow><<search|shortcut=s>></menurow>"; |
|||
const watch = "<menurow><<unwatch|unwatchShort>>|<<watch|shortcut=w|watchThingy>></menurow>"; |
|||
const protect = "<menurow><<unprotect|unprotectShort>>|<<protect|shortcut=p>>|<<protectlog|log>></menurow>"; |
|||
const del = "<menurow><<undelete|undeleteShort>>|<<delete|shortcut=d>>|<<deletelog|log>></menurow>"; |
|||
const move = "<<move|shortcut=m|move page>>"; |
|||
const nullPurge = "<menurow><<nullEdit|shortcut=n|null edit>>|<<purge|shortcut=P>></menurow>"; |
|||
const viewOptions = "<menurow><<view|shortcut=v>>|<<render|shortcut=S>>|<<raw>></menurow>"; |
|||
const editRow = "if(oldid){<menurow><<edit|shortcut=e>>|<<editOld|shortcut=e|this revision>></menurow><menurow><<revert|shortcut=v>>|<<undo>></menurow>}else{<<edit|shortcut=e>>}"; |
|||
const markPatrolled = "if(rcid){<<markpatrolled|mark patrolled>>}"; |
|||
const newTopic = "if(talk){<<new|shortcut=+|new topic>>}"; |
|||
const protectDelete = "if(admin){".concat(protect).concat(del, "}"); |
|||
if (getValueOf("popupActionsMenu")) { |
|||
s.push("<<mainlink>>*".concat(dropdiv).concat(menuTitle("actions"))); |
|||
} else { |
|||
s.push("".concat(dropdiv, "<<mainlink>>")); |
|||
} |
|||
s.push("<menu>", editRow + markPatrolled + newTopic + hist + lastedit + thank); |
|||
if (!shorter) { |
|||
s.push(jsHistory); |
|||
} |
|||
s.push(move + linkshere + related); |
|||
if (!shorter) { |
|||
s.push(nullPurge + search); |
|||
} |
|||
if (!shorter) { |
|||
s.push(viewOptions); |
|||
} |
|||
s.push("<hr>".concat(watch).concat(protectDelete), "<hr>if(talk){<<article|shortcut=a|view article>><<editArticle|edit article>>}else{<<talk|shortcut=t|talk page>><<editTalk|edit talk>><<newTalk|shortcut=+|new topic>>}</menu>".concat(enddiv)); |
|||
const email = "<<email|shortcut=E|email user>>"; |
|||
const contribs = "if(wikimedia){<menurow>}<<contribs|shortcut=c|contributions>>if(wikimedia){</menurow>}if(admin){<menurow><<deletedContribs>></menurow>}"; |
|||
s.push("if(user){*".concat(dropdiv).concat(menuTitle("user")), "<menu>", "<menurow><<userPage|shortcut=u|user page>>|<<userSpace|space>></menurow>", "<<userTalk|shortcut=t|user talk>><<editUserTalk|edit user talk>><<newUserTalk|shortcut=+|leave comment>>"); |
|||
if (shorter) { |
|||
s.push("if(ipuser){}else{".concat(email, "}")); |
|||
} else { |
|||
s.push("if(ipuser){<<arin>>}else{".concat(email, "}")); |
|||
} |
|||
s.push("<hr>".concat(contribs, "<<userlog|shortcut=L|user log>>"), "if(wikimedia){<<count|shortcut=#|edit counter>>}", "if(admin){<menurow><<unblock|unblockShort>>|<<block|shortcut=b|block user>></menurow>}", "<<blocklog|shortcut=B|block log>>", "</menu>".concat(enddiv, "}")); |
|||
if (getValueOf("popupSetupMenu") && !x.navpop.hasPopupMenu) { |
|||
x.navpop.hasPopupMenu = true; |
|||
s.push("*".concat(dropdiv).concat(menuTitle("popupsMenu"), "<menu>"), "<<togglePreviews|toggle previews>>", "<<purgePopups|reset>>", "<<disablePopups|disable>>", "</menu>".concat(enddiv)); |
|||
} |
|||
return navlinkStringToHTML(s.join(""), x.article, x.params); |
|||
}; |
|||
const menuTitle = (s) => { |
|||
return '<a href="#" noPopup=1>'.concat(popupString(s), "</a>"); |
|||
}; |
|||
pg.structures.menus.popupRedirTitle = pg.structures.menus.popupTitle; |
|||
pg.structures.menus.popupRedirTopLinks = pg.structures.menus.popupTopLinks; |
|||
copyStructure("menus", "shortmenus"); |
|||
pg.structures.shortmenus.popupTopLinks = (x) => { |
|||
return pg.structures.menus.popupTopLinks(x, true); |
|||
}; |
|||
pg.structures.shortmenus.popupRedirTopLinks = pg.structures.shortmenus.popupTopLinks; |
|||
pg.structures.lite = {}; |
|||
pg.structures.lite.popupLayout = () => { |
|||
return ["popupTitle", "popupPreview"]; |
|||
}; |
|||
pg.structures.lite.popupTitle = (x) => { |
|||
log("".concat(x.article, ": structures.lite.popupTitle")); |
|||
return '<div><span class="popup_mainlink"><b>'.concat(x.article.toString(), "</b></span></div>"); |
|||
}; |
|||
const substitute = (data, cmdBody) => { |
|||
const fromRe = new RegExp(cmdBody.from, cmdBody.flags); |
|||
return data.replace(fromRe, cmdBody.to); |
|||
}; |
|||
const execCmds = (data, cmdList) => { |
|||
var _iterator = _createForOfIteratorHelper(cmdList), _step; |
|||
try { |
|||
for (_iterator.s(); !(_step = _iterator.n()).done; ) { |
|||
const element = _step.value; |
|||
data = element.action(data, element); |
|||
} |
|||
} catch (err) { |
|||
_iterator.e(err); |
|||
} finally { |
|||
_iterator.f(); |
|||
} |
|||
return data; |
|||
}; |
|||
const parseCmd = function parseCmd2(str) { |
|||
if (str.length === 0) { |
|||
return []; |
|||
} |
|||
let p = false; |
|||
switch (str.charAt(0)) { |
|||
case "s": |
|||
p = parseSubstitute(str); |
|||
break; |
|||
default: |
|||
return false; |
|||
} |
|||
if (p) { |
|||
return [p, parseCmd2(p.remainder)]; |
|||
} |
|||
return false; |
|||
}; |
|||
const unEscape = (str, sep) => { |
|||
return str.split("\\\\").join("\\").split("\\".concat(sep)).join(sep).split(String.raw(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n"], ["\\n"])))).join("\n"); |
|||
}; |
|||
const parseSubstitute = (str) => { |
|||
let from; |
|||
let to; |
|||
let flags; |
|||
let tmp; |
|||
if (str.length < 4) { |
|||
return false; |
|||
} |
|||
const sep = str.charAt(1); |
|||
str = str.slice(2); |
|||
tmp = skipOver(str, sep); |
|||
if (tmp) { |
|||
from = tmp.segment; |
|||
str = tmp.remainder; |
|||
} else { |
|||
return false; |
|||
} |
|||
tmp = skipOver(str, sep); |
|||
if (tmp) { |
|||
to = tmp.segment; |
|||
str = tmp.remainder; |
|||
} else { |
|||
return false; |
|||
} |
|||
flags = ""; |
|||
if (str.length > 0) { |
|||
tmp = skipOver(str, ";") || skipToEnd(str, ";"); |
|||
if (tmp) { |
|||
flags = tmp.segment; |
|||
str = tmp.remainder; |
|||
} |
|||
} |
|||
return { |
|||
action: substitute, |
|||
from, |
|||
to, |
|||
flags, |
|||
remainder: str |
|||
}; |
|||
}; |
|||
const skipOver = (str, sep) => { |
|||
const endSegment = findNext(str, sep); |
|||
if (endSegment < 0) { |
|||
return false; |
|||
} |
|||
const segment = unEscape(str.slice(0, Math.max(0, endSegment)), sep); |
|||
return { |
|||
segment, |
|||
remainder: str.slice(Math.max(0, endSegment + 1)) |
|||
}; |
|||
}; |
|||
const skipToEnd = (str, _sep) => { |
|||
return { |
|||
segment: str, |
|||
remainder: "" |
|||
}; |
|||
}; |
|||
const findNext = (str, ch) => { |
|||
for (let i = 0; i < str.length; ++i) { |
|||
if (str.charAt(i) === "\\") { |
|||
i += 2; |
|||
} |
|||
if (str.charAt(i) === ch) { |
|||
return i; |
|||
} |
|||
} |
|||
return -1; |
|||
}; |
|||
const setCheckbox = (param, box) => { |
|||
const val = mw.util.getParamValue(param); |
|||
if (val) { |
|||
switch (val) { |
|||
case "1": |
|||
case "yes": |
|||
case "true": |
|||
box.checked = true; |
|||
break; |
|||
case "0": |
|||
case "no": |
|||
case "false": |
|||
box.checked = false; |
|||
} |
|||
} |
|||
}; |
|||
const autoEdit = function autoEdit4() { |
|||
setupPopups(() => { |
|||
if (mw.util.getParamValue("autoimpl") !== popupString("autoedit_version")) { |
|||
return false; |
|||
} |
|||
if (mw.util.getParamValue("autowatchlist") && mw.util.getParamValue("actoken") === autoClickToken()) { |
|||
pg.fn.modifyWatchlist(mw.util.getParamValue("title"), mw.util.getParamValue("action")); |
|||
} |
|||
if (!document.editform) { |
|||
return false; |
|||
} |
|||
if (autoEdit4.alreadyRan) { |
|||
return false; |
|||
} |
|||
autoEdit4.alreadyRan = true; |
|||
const cmdString = mw.util.getParamValue("autoedit"); |
|||
if (cmdString) { |
|||
try { |
|||
const editbox = document.editform.wpTextbox1; |
|||
const cmdList = parseCmd(cmdString); |
|||
const input = editbox.value; |
|||
const output = execCmds(input, cmdList); |
|||
editbox.value = output; |
|||
} catch { |
|||
return; |
|||
} |
|||
} |
|||
setCheckbox("autominor", document.editform.wpMinoredit); |
|||
setCheckbox("autowatch", document.editform.wpWatchthis); |
|||
const rvid = mw.util.getParamValue("autorv"); |
|||
if (rvid) { |
|||
const url = "".concat(pg.wiki.apiwikibase, "?action=query&format=json&formatversion=2&prop=revisions&revids=").concat(rvid); |
|||
startDownload(url, null, autoEdit2); |
|||
} else { |
|||
autoEdit2(); |
|||
} |
|||
}); |
|||
}; |
|||
const autoEdit2 = (d) => { |
|||
let summary = mw.util.getParamValue("autosummary"); |
|||
let summaryprompt = mw.util.getParamValue("autosummaryprompt"); |
|||
let summarynotice = ""; |
|||
if (d && d.data && mw.util.getParamValue("autorv")) { |
|||
const s = getRvSummary(summary, d.data); |
|||
if (s === false) { |
|||
summaryprompt = true; |
|||
summarynotice = popupString("Failed to get revision information, please edit manually.\n\n"); |
|||
summary = simplePrintf(summary, [mw.util.getParamValue("autorv"), "(unknown)", "(unknown)"]); |
|||
} else { |
|||
summary = s; |
|||
} |
|||
} |
|||
if (summaryprompt) { |
|||
const txt = summarynotice + popupString("Enter a non-empty edit summary or press cancel to abort"); |
|||
const response = prompt(txt, summary); |
|||
if (response) { |
|||
summary = response; |
|||
} else { |
|||
return; |
|||
} |
|||
} |
|||
if (summary) { |
|||
document.editform.wpSummary.value = summary; |
|||
} |
|||
setTimeout(autoEdit3, 100); |
|||
}; |
|||
const autoClickToken = () => { |
|||
return mw.user.sessionId(); |
|||
}; |
|||
const autoEdit3 = () => { |
|||
if (mw.util.getParamValue("actoken") !== autoClickToken()) { |
|||
return; |
|||
} |
|||
const btn = mw.util.getParamValue("autoclick"); |
|||
if (btn) { |
|||
if (document.editform && document.editform[btn]) { |
|||
const button = document.editform[btn]; |
|||
const msg = tprintf("The %s button has been automatically clicked. Please wait for the next page to load.", [button.value]); |
|||
bannerMessage(msg); |
|||
document.title = "(".concat(document.title, ")"); |
|||
button.click(); |
|||
} else { |
|||
void mw.notify(tprintf("Could not find button %s. Please check the settings in your javascript file.", [btn]), { |
|||
tag: "popups", |
|||
type: "error" |
|||
}); |
|||
} |
|||
} |
|||
}; |
|||
const bannerMessage = (s) => { |
|||
const headings = document.querySelectorAll("h1"); |
|||
if (headings) { |
|||
const div = document.createElement("div"); |
|||
div.innerHTML = "<font size=+1><b>".concat(pg.escapeQuotesHTML(s), "</b></font>"); |
|||
headings[0].parentNode.insertBefore(div, headings[0]); |
|||
} |
|||
}; |
|||
const getRvSummary = (template, json) => { |
|||
try { |
|||
const o = getJsObj(json); |
|||
const [edit] = anyChild(o.query.pages).revisions; |
|||
const timestamp = edit.timestamp.split(/[A-Z]/g).join(" ").replace(/^ *| *$/g, ""); |
|||
return simplePrintf(template, [edit.revid, timestamp, edit.userhidden ? "(hidden)" : edit.user]); |
|||
} catch { |
|||
return false; |
|||
} |
|||
}; |
|||
class Downloader { |
|||
constructor(url) { |
|||
if (typeof XMLHttpRequest !== "undefined") { |
|||
this.http = new XMLHttpRequest(); |
|||
} |
|||
this.url = url; |
|||
this.id = null; |
|||
this.lastModified = null; |
|||
this.callbackFunction = null; |
|||
this.onFailure = null; |
|||
this.aborted = false; |
|||
this.method = "GET"; |
|||
this.async = true; |
|||
} |
|||
/** |
|||
* Submits the http request. |
|||
* |
|||
* @param {*} x |
|||
*/ |
|||
send(x) { |
|||
if (!this.http) { |
|||
return null; |
|||
} |
|||
return this.http.send(x); |
|||
} |
|||
/* Aborts the download, setting the <code>aborted</code> field to true. */ |
|||
abort() { |
|||
if (!this.http) { |
|||
return null; |
|||
} |
|||
this.aborted = true; |
|||
return this.http.abort(); |
|||
} |
|||
/** Returns the downloaded data. */ |
|||
getData() { |
|||
if (!this.http) { |
|||
return null; |
|||
} |
|||
return this.http.responseText; |
|||
} |
|||
/** Prepares the download. */ |
|||
setTarget() { |
|||
if (!this.http) { |
|||
return null; |
|||
} |
|||
this.http.open(this.method, this.url, this.async); |
|||
this.http.setRequestHeader("Api-User-Agent", pg.api.userAgent); |
|||
} |
|||
/** Gets the state of the download. */ |
|||
getReadyState() { |
|||
if (!this.http) { |
|||
return null; |
|||
} |
|||
return this.http.readyState; |
|||
} |
|||
/** |
|||
* Starts the download. |
|||
* Note that setTarget {@source Downloader#setTarget} must be run first |
|||
*/ |
|||
start() { |
|||
if (!this.http) { |
|||
return; |
|||
} |
|||
const self2 = this; |
|||
pg.misc.downloadsInProgress[this.id] = self2; |
|||
this.http.send(null); |
|||
} |
|||
/** |
|||
* Gets the 'Last-Modified' date from the download headers. |
|||
* Should be run after the download completes. |
|||
* Returns <code>null</code> on failure. |
|||
* |
|||
* @return {Date} |
|||
*/ |
|||
getLastModifiedDate() { |
|||
if (!this.http) { |
|||
return null; |
|||
} |
|||
let lastmod; |
|||
try { |
|||
lastmod = this.http.getResponseHeader("Last-Modified"); |
|||
} catch { |
|||
} |
|||
if (lastmod) { |
|||
return new Date(lastmod); |
|||
} |
|||
return null; |
|||
} |
|||
/** |
|||
* Sets the callback function. |
|||
* |
|||
* @param {Function} f callback function, called as <code>f(this)</code> on success |
|||
*/ |
|||
setCallback(f) { |
|||
if (!this.http) { |
|||
return; |
|||
} |
|||
this.http.onreadystatechange = f; |
|||
} |
|||
getStatus() { |
|||
if (!this.http) { |
|||
return null; |
|||
} |
|||
return this.http.status; |
|||
} |
|||
} |
|||
new Downloader(); |
|||
pg.misc.downloadsInProgress = {}; |
|||
const newDownload = function newDownload2(url, id, callback, onfailure) { |
|||
const d = new Downloader(url); |
|||
if (!d.http) { |
|||
return "ohdear"; |
|||
} |
|||
d.id = id; |
|||
d.setTarget(); |
|||
onfailure || (onfailure = 2); |
|||
const f = function() { |
|||
if (d.getReadyState() === 4) { |
|||
delete pg.misc.downloadsInProgress[this.id]; |
|||
try { |
|||
if (d.getStatus() === 200) { |
|||
d.data = d.getData(); |
|||
d.lastModified = d.getLastModifiedDate(); |
|||
callback(d); |
|||
} else if (typeof onfailure === "number") { |
|||
if (onfailure > 0) { |
|||
newDownload2(url, id, callback, onfailure - 1); |
|||
} |
|||
} else if (typeof onfailure === "function") { |
|||
onfailure(d, url, id, callback); |
|||
} |
|||
} catch { |
|||
} |
|||
} |
|||
}; |
|||
d.setCallback(f); |
|||
return d; |
|||
}; |
|||
const fakeDownload = (url, id, callback, data, lastModified, owner) => { |
|||
const d = newDownload(url, callback); |
|||
d.owner = owner; |
|||
d.id = id; |
|||
d.data = data; |
|||
d.lastModified = lastModified; |
|||
return callback(d); |
|||
}; |
|||
const startDownload = (url, id, callback) => { |
|||
const d = newDownload(url, id, callback); |
|||
if (typeof d === "string") { |
|||
return d; |
|||
} |
|||
d.start(); |
|||
return d; |
|||
}; |
|||
const abortAllDownloads = () => { |
|||
for (const x in pg.misc.downloadsInProgress) { |
|||
if (!Object.hasOwn(pg.misc.downloadsInProgress, x)) { |
|||
continue; |
|||
} |
|||
try { |
|||
pg.misc.downloadsInProgress[x].aborted = true; |
|||
pg.misc.downloadsInProgress[x].abort(); |
|||
delete pg.misc.downloadsInProgress[x]; |
|||
} catch { |
|||
} |
|||
} |
|||
}; |
|||
const Insta = {}; |
|||
const setupLivePreview = () => { |
|||
var _Insta$conf$user; |
|||
let _b; |
|||
Insta.conf = { |
|||
baseUrl: "", |
|||
user: {}, |
|||
wiki: { |
|||
lang: pg.wiki.lang, |
|||
interwiki: pg.wiki.interwiki, |
|||
default_thumb_width: 180 |
|||
}, |
|||
paths: { |
|||
articles: "".concat(pg.wiki.articlePath, "/"), |
|||
// Only used for Insta previews with images. (not in popups) |
|||
math: "/math/", |
|||
images: "https://tu.zhongwen.wiki/images/qiuwenbaike/zh/", |
|||
images_fallback: "//wm.zhongwen.wiki/commons/" |
|||
}, |
|||
locale: { |
|||
user: mw.config.get("wgFormattedNamespaces")[pg.nsUserId], |
|||
image: mw.config.get("wgFormattedNamespaces")[pg.nsImageId], |
|||
category: mw.config.get("wgFormattedNamespaces")[pg.nsCategoryId], |
|||
// shouldn't be used in popup previews, i think |
|||
months: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] |
|||
} |
|||
}; |
|||
(_Insta$conf$user = Insta.conf.user).name || (_Insta$conf$user.name = "Qiuwen Baike contributors"); |
|||
Insta.conf.user.signature = "[[".concat(Insta.conf.locale.user, ":").concat(Insta.conf.user.name, "|").concat(Insta.conf.user.name, "]]"); |
|||
Insta.BLOCK_IMAGE = new RegExp("^\\[\\[(?:File|Image|".concat(Insta.conf.locale.image, "):.*?\\|.*?(?:frame|thumbnail|thumb|none|right|left|center)"), "i"); |
|||
}; |
|||
Insta.dump = function(from, to) { |
|||
if (typeof from === "string") { |
|||
from = document.getElementById("".concat(from)); |
|||
} |
|||
if (typeof to === "string") { |
|||
to = document.getElementById("".concat(to)); |
|||
} |
|||
to.innerHTML = this.convert(from.value); |
|||
}; |
|||
Insta.convert = (wiki) => { |
|||
const ll = typeof wiki === "string" ? wiki.replace(/\r/g, "").split(/\n/) : wiki; |
|||
let o = ""; |
|||
let p = 0; |
|||
let r; |
|||
const remain = () => { |
|||
return ll.length; |
|||
}; |
|||
const sh = () => { |
|||
return ll.shift(); |
|||
}; |
|||
const ps = (s) => { |
|||
o += s; |
|||
}; |
|||
const f = function f2(...args) { |
|||
let i = 1; |
|||
const a = args; |
|||
let [f3] = a; |
|||
let o2 = ""; |
|||
let c; |
|||
let p2; |
|||
for (; i < a.length; i++) { |
|||
if ((p2 = f3.indexOf("?")) + 1) { |
|||
c = f3.charAt(p2 + 1) === "?" ? 1 : 0; |
|||
i -= c; |
|||
o2 += f3.slice(0, Math.max(0, p2)) + (c ? "?" : a[i]); |
|||
f3 = f3.slice(p2 + 1 + c); |
|||
} else { |
|||
break; |
|||
} |
|||
} |
|||
return o2 + f3; |
|||
}; |
|||
const html_entities = (s) => { |
|||
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); |
|||
}; |
|||
const htmlescape_text = (s) => { |
|||
return s.replace(/</g, "<").replace(/>/g, ">").replace(/:/g, ":").replace(/\[/g, "[").replace(/]/g, "]"); |
|||
}; |
|||
const htmlescape_attr = (s) => { |
|||
return htmlescape_text(s).replace(/'/g, "'").replace(/"/g, """); |
|||
}; |
|||
const str_imatch = (a, b) => { |
|||
let i; |
|||
let l; |
|||
for (i = 0, l = Math.min(a.length, b.length); i < l; i++) { |
|||
if (a.charAt(i) !== b.charAt(i)) { |
|||
break; |
|||
} |
|||
} |
|||
return i; |
|||
}; |
|||
const compareLineStringOrReg = (c) => { |
|||
return typeof c === "string" ? ll[0] && ll[0].slice(0, c.length) === c : r = ll[0] && ll[0].match(c); |
|||
}; |
|||
const compareLineString = (c) => { |
|||
return ll[0] === c; |
|||
}; |
|||
const charAtPoint = (p2) => { |
|||
return ll[0].charAt(p2); |
|||
}; |
|||
const endl = (s) => { |
|||
ps(s); |
|||
sh(); |
|||
}; |
|||
const parse_list = () => { |
|||
let prev = ""; |
|||
while (remain() && compareLineStringOrReg(/^([#*:;]+)(.*)$/)) { |
|||
const l_match = r; |
|||
sh(); |
|||
const ipos = str_imatch(prev, l_match[1]); |
|||
for (let prevPos = prev.length - 1; prevPos >= ipos; prevPos--) { |
|||
const pi = prev.charAt(prevPos); |
|||
if (pi === "*") { |
|||
ps("</ul>"); |
|||
} else if (pi === "#") { |
|||
ps("</ol>"); |
|||
} else if (["", "*", "#"].indexOf(l_match[1].charAt(prevPos))) { |
|||
ps("</dl>"); |
|||
} |
|||
} |
|||
for (let matchPos = ipos; matchPos < l_match[1].length; matchPos++) { |
|||
const li = l_match[1].charAt(matchPos); |
|||
if (li === "*") { |
|||
ps("<ul>"); |
|||
} else if (li === "#") { |
|||
ps("<ol>"); |
|||
} else if (["", "*", "#"].indexOf(prev.charAt(matchPos))) { |
|||
ps("<dl>"); |
|||
} |
|||
} |
|||
switch (l_match[1].at(-1)) { |
|||
case "*": |
|||
case "#": |
|||
ps("<li>".concat(parse_inline_nowiki(l_match[2]))); |
|||
break; |
|||
case ";": { |
|||
ps("<dt>"); |
|||
const dt_match = l_match[2].match(/(.*?)(:.*?)$/); |
|||
if (dt_match) { |
|||
ps(parse_inline_nowiki(dt_match[1])); |
|||
ll.unshift(dt_match[2]); |
|||
} else { |
|||
ps(parse_inline_nowiki(l_match[2])); |
|||
} |
|||
break; |
|||
} |
|||
case ":": |
|||
ps("<dd>".concat(parse_inline_nowiki(l_match[2]))); |
|||
} |
|||
[, prev] = l_match; |
|||
} |
|||
for (let i = prev.length - 1; i >= 0; i--) { |
|||
ps(f("</?>", prev.charAt(i) === "*" ? "ul" : prev.charAt(i) === "#" ? "ol" : "dl")); |
|||
} |
|||
}; |
|||
const parse_table = () => { |
|||
endl(f("<table>", compareLineStringOrReg(/^{\|( .*)$/) ? r[1] : "")); |
|||
for (; remain(); ) { |
|||
if (compareLineStringOrReg("|")) { |
|||
switch (charAtPoint(1)) { |
|||
case "}": |
|||
endl("</table>"); |
|||
return; |
|||
case "-": |
|||
endl(f("<tr>", compareLineStringOrReg(/\|-*(.*)/)[1])); |
|||
break; |
|||
default: |
|||
parse_table_data(); |
|||
} |
|||
} else if (compareLineStringOrReg("!")) { |
|||
parse_table_data(); |
|||
} else { |
|||
sh(); |
|||
} |
|||
} |
|||
}; |
|||
const parse_table_data = () => { |
|||
let td_line; |
|||
let match_i; |
|||
const td_match = sh().match(/^(\|\+|\||!)((?:([^[|]*?)\|(?!\|))?(.*))$/); |
|||
if (td_match[1] === "|+") { |
|||
ps("<caption"); |
|||
} else { |
|||
ps("<t".concat(td_match[1] === "|" ? "d" : "h")); |
|||
} |
|||
if (td_match[3]) { |
|||
match_i = 4; |
|||
} else { |
|||
match_i = 2; |
|||
} |
|||
ps(">"); |
|||
if (td_match[1] === "|+") { |
|||
ps(parse_inline_nowiki(td_match[match_i])); |
|||
} else { |
|||
td_line = td_match[match_i].split(td_match[1] === "|" ? "||" : /\|\||!!/); |
|||
ps(parse_inline_nowiki(td_line.shift())); |
|||
while (td_line.length > 0) { |
|||
ll.unshift(td_match[1] + td_line.pop()); |
|||
} |
|||
} |
|||
let tc = 0; |
|||
const td = []; |
|||
while (remain()) { |
|||
td.push(sh()); |
|||
if (compareLineStringOrReg("|")) { |
|||
if (!tc) { |
|||
break; |
|||
} else if (charAtPoint(1) === "}") { |
|||
tc--; |
|||
} |
|||
} else if (!tc && compareLineStringOrReg("!")) { |
|||
break; |
|||
} else if (compareLineStringOrReg("{|")) { |
|||
tc++; |
|||
} |
|||
} |
|||
if (td.length > 0) { |
|||
ps(Insta.convert(td)); |
|||
} |
|||
}; |
|||
const parse_pre = () => { |
|||
ps("<pre>"); |
|||
do { |
|||
endl("".concat(parse_inline_nowiki(ll[0].slice(1)), "\n")); |
|||
} while (remain() && compareLineStringOrReg(" ")); |
|||
ps("</pre>"); |
|||
}; |
|||
const parse_block_image = () => { |
|||
ps(parse_image(sh())); |
|||
}; |
|||
const parse_image = (str) => { |
|||
let tag = str.substring(str.indexOf(":") + 1, str.length - 2); |
|||
let width; |
|||
let attr = []; |
|||
let filename; |
|||
let caption = ""; |
|||
let thumb = 0; |
|||
let frame = 0; |
|||
let center = 0; |
|||
let align = ""; |
|||
if (/\|/.test(tag)) { |
|||
let nesting = 0; |
|||
let last_attr; |
|||
for (let i = tag.length - 1; i > 0; i--) { |
|||
if (tag.charAt(i) === "|" && !nesting) { |
|||
last_attr = tag.slice(i + 1); |
|||
tag = tag.slice(0, Math.max(0, i)); |
|||
break; |
|||
} else { |
|||
switch (tag.slice(i - 1, i - 1 + 2)) { |
|||
case "]]": |
|||
nesting++; |
|||
i--; |
|||
break; |
|||
case "[[": |
|||
nesting--; |
|||
i--; |
|||
} |
|||
} |
|||
} |
|||
attr = tag.split(/\s*\|\s*/); |
|||
attr.push(last_attr); |
|||
filename = attr.shift(); |
|||
let w_match; |
|||
for (; attr.length > 0; attr.shift()) { |
|||
w_match = attr[0].match(/^(\d*)(?:[px]*\d*)?px$/); |
|||
if (w_match) { |
|||
[, width] = w_match; |
|||
} else { |
|||
switch (attr[0]) { |
|||
case "thumb": |
|||
case "thumbnail": |
|||
thumb = true; |
|||
frame = true; |
|||
break; |
|||
case "frame": |
|||
frame = true; |
|||
break; |
|||
case "none": |
|||
case "right": |
|||
case "left": |
|||
center = false; |
|||
[align] = attr; |
|||
break; |
|||
case "center": |
|||
center = true; |
|||
align = "none"; |
|||
break; |
|||
default: |
|||
if (attr.length === 1) { |
|||
[caption] = attr; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} else { |
|||
filename = tag; |
|||
} |
|||
return ""; |
|||
}; |
|||
const parse_inline_nowiki = (str) => { |
|||
let start; |
|||
let lastend = 0; |
|||
let substart = 0; |
|||
let nestlev = 0; |
|||
let open; |
|||
let close; |
|||
let subloop; |
|||
let html = ""; |
|||
while ((start = str.indexOf("<no".concat("wiki", ">"), substart)) !== -1) { |
|||
html += parse_inline_wiki(str.substring(lastend, start)); |
|||
start += 8; |
|||
substart = start; |
|||
subloop = true; |
|||
do { |
|||
open = str.indexOf("<no".concat("wiki", ">"), substart); |
|||
close = str.indexOf("</no".concat("wiki", ">"), substart); |
|||
if (close <= open || open === -1) { |
|||
if (close === -1) { |
|||
return html + html_entities(str.slice(start)); |
|||
} |
|||
substart = close + 9; |
|||
if (nestlev) { |
|||
nestlev--; |
|||
} else { |
|||
lastend = substart; |
|||
html += html_entities(str.substring(start, lastend - 9)); |
|||
subloop = false; |
|||
} |
|||
} else { |
|||
substart = open + 8; |
|||
nestlev++; |
|||
} |
|||
} while (subloop); |
|||
} |
|||
return html + parse_inline_wiki(str.slice(lastend)); |
|||
}; |
|||
const parse_inline_images = (str) => { |
|||
let start; |
|||
let substart = 0; |
|||
let nestlev = 0; |
|||
let loop; |
|||
let close; |
|||
let open; |
|||
let wiki2; |
|||
let html; |
|||
while ((start = str.indexOf("[[", substart)) !== -1) { |
|||
if (new RegExp("^(Image|File|".concat(Insta.conf.locale.image, "):"), "i").test(str.slice(start + 2))) { |
|||
loop = true; |
|||
substart = start; |
|||
do { |
|||
substart += 2; |
|||
close = str.indexOf("]]", substart); |
|||
open = str.indexOf("[[", substart); |
|||
if (close <= open || open === -1) { |
|||
if (close === -1) { |
|||
return str; |
|||
} |
|||
substart = close; |
|||
if (nestlev) { |
|||
nestlev--; |
|||
} else { |
|||
wiki2 = str.substring(start, close + 2); |
|||
html = parse_image(wiki2); |
|||
str = str.replace(wiki2, html); |
|||
substart = start + html.length; |
|||
loop = false; |
|||
} |
|||
} else { |
|||
substart = open; |
|||
nestlev++; |
|||
} |
|||
} while (loop); |
|||
} else { |
|||
break; |
|||
} |
|||
} |
|||
return str; |
|||
}; |
|||
const parse_inline_formatting = (str) => { |
|||
let em; |
|||
let st; |
|||
let i; |
|||
let li; |
|||
let o2 = ""; |
|||
while ((i = str.indexOf("''", li)) + 1) { |
|||
o2 += str.substring(li, i); |
|||
li = i + 2; |
|||
if (str.charAt(i + 2) === "'") { |
|||
li++; |
|||
st = !st; |
|||
o2 += st ? "<strong>" : "</strong>"; |
|||
} else { |
|||
em = !em; |
|||
o2 += em ? "<em>" : "</em>"; |
|||
} |
|||
} |
|||
return o2 + str.slice(li); |
|||
}; |
|||
const parse_inline_wiki = (str) => { |
|||
str = parse_inline_images(str); |
|||
str = parse_inline_formatting(str); |
|||
str = str.replace(/<math>(.*?)<\/math>/gi, ""); |
|||
let date = /* @__PURE__ */ new Date(); |
|||
let minutes = date.getUTCMinutes(); |
|||
if (minutes < 10) { |
|||
minutes = "0".concat(minutes); |
|||
} |
|||
date = f("?:?, ? ? ? (UTC)", date.getUTCHours(), minutes, date.getUTCDate(), Insta.conf.locale.months[date.getUTCMonth()], date.getUTCFullYear()); |
|||
return str.replace(/~{5}(?!~)/g, date).replace(/~{4}(?!~)/g, "".concat(Insta.conf.user.name, " ").concat(date)).replace(/~{3}(?!~)/g, Insta.conf.user.name).replace(new RegExp("\\[\\[:((?:".concat(Insta.conf.locale.category, "|Image|File|").concat(Insta.conf.locale.image, "|").concat(Insta.conf.wiki.interwiki, "):[^|]*?)\\]\\](\\w*)"), "gi"), (_$0, $1, $2) => { |
|||
return f("<a href='?'>?</a>", Insta.conf.paths.articles + htmlescape_attr($1), htmlescape_text($1) + htmlescape_text($2)); |
|||
}).replace(new RegExp("\\[\\[(?:".concat(Insta.conf.locale.category, "|").concat(Insta.conf.wiki.interwiki, "):.*?\\]\\]"), "gi"), "").replace(new RegExp("\\[\\[:((?:".concat(Insta.conf.locale.category, "|Image|File|").concat(Insta.conf.locale.image, "|").concat(Insta.conf.wiki.interwiki, "):.*?)\\|([^\\]]+?)\\]\\](\\w*)"), "gi"), (_$0, $1, $2, $3) => { |
|||
return f("<a href='?'>?</a>", Insta.conf.paths.articles + htmlescape_attr($1), htmlescape_text($2) + htmlescape_text($3)); |
|||
}).replace(/\[\[(\/[^|]*?)]]/g, (_$0, $1) => { |
|||
return f("<a href='?'>?</a>", Insta.conf.baseUrl + htmlescape_attr($1), htmlescape_text($1)); |
|||
}).replace(/\[\[(\/.*?)\|(.+?)]]/g, (_$0, $1, $2) => { |
|||
return f("<a href='?'>?</a>", Insta.conf.baseUrl + htmlescape_attr($1), htmlescape_text($2)); |
|||
}).replace(/\[\[([^[|]*?)]](\w*)/g, (_$0, $1, $2) => { |
|||
return f("<a href='?'>?</a>", Insta.conf.paths.articles + htmlescape_attr($1), htmlescape_text($1) + htmlescape_text($2)); |
|||
}).replace(/\[\[([^[]*?)\|([^\]]+?)]](\w*)/g, (_$0, $1, $2, $3) => { |
|||
return f("<a href='?'>?</a>", Insta.conf.paths.articles + htmlescape_attr($1), htmlescape_text($2) + htmlescape_text($3)); |
|||
}).replace(/\[\[([^\]]*?:)?(.*?)( *\(.*?\))?\|]]/g, (_$0, $1, $2, $3) => { |
|||
return f("<a href='?'>?</a>", Insta.conf.paths.articles + htmlescape_attr($1) + htmlescape_attr($2) + htmlescape_attr($3), htmlescape_text($2)); |
|||
}).replace(/\[(https?|news|ftp|mailto|gopher|irc):(\/*)([^\]]*?) (.*?)]/g, (_$0, $1, $2, $3, $4) => { |
|||
return f("<a class='external' href='?:?'>?</a>", htmlescape_attr($1), htmlescape_attr($2) + htmlescape_attr($3), htmlescape_text($4)); |
|||
}).replace(/\[http:\/\/(.*?)]/g, (_$0, $1) => { |
|||
return f("<a class='external' href='http://?'>[#]</a>", htmlescape_attr($1)); |
|||
}).replace(/\[(news|ftp|mailto|gopher|irc):(\/*)(.*?)]/g, (_$0, $1, $2, $3) => { |
|||
return f("<a class='external' href='?:?'>?:?</a>", htmlescape_attr($1), htmlescape_attr($2) + htmlescape_attr($3), htmlescape_text($1), htmlescape_text($2) + htmlescape_text($3)); |
|||
}).replace(/(^| )(https?|news|ftp|mailto|gopher|irc):(\/*)([^ $]*[^ !$,.:;?])/g, (_$0, $1, $2, $3, $4) => { |
|||
return f("?<a class='external' href='?:?'>?:?</a>", htmlescape_text($1), htmlescape_attr($2), htmlescape_attr($3) + htmlescape_attr($4), htmlescape_text($2), htmlescape_text($3) + htmlescape_text($4)); |
|||
}).replace("__NOTOC__", "").replace("__NOINDEX__", "").replace("__INDEX__", "").replace("__NOEDITSECTION__", ""); |
|||
}; |
|||
for (; remain(); ) { |
|||
if (compareLineStringOrReg(/^(={1,6})(.*)\1(.*)$/)) { |
|||
p = 0; |
|||
endl(f("<h?>?</h?>?", r[1].length, parse_inline_nowiki(r[2]), r[1].length, r[3])); |
|||
} else if (compareLineStringOrReg(/^[#*:;]/)) { |
|||
p = 0; |
|||
parse_list(); |
|||
} else if (compareLineStringOrReg(" ")) { |
|||
p = 0; |
|||
parse_pre(); |
|||
} else if (compareLineStringOrReg("{|")) { |
|||
p = 0; |
|||
parse_table(); |
|||
} else if (compareLineStringOrReg(/^----+$/)) { |
|||
p = 0; |
|||
endl("<hr>"); |
|||
} else if (compareLineStringOrReg(Insta.BLOCK_IMAGE)) { |
|||
p = 0; |
|||
parse_block_image(); |
|||
} else { |
|||
if (compareLineString("")) { |
|||
p = remain() > 1 && ll[1] === ""; |
|||
if (p) { |
|||
endl("<p><br>"); |
|||
} |
|||
} else { |
|||
if (!p) { |
|||
ps("<p>"); |
|||
p = 1; |
|||
} |
|||
ps("".concat(parse_inline_nowiki(ll[0]), " ")); |
|||
} |
|||
sh(); |
|||
} |
|||
} |
|||
return o; |
|||
}; |
|||
const wiki2html = (txt, baseurl) => { |
|||
Insta.conf.baseUrl = baseurl; |
|||
return Insta.convert(txt); |
|||
}; |
|||
const popupFilterPageSize = (data) => { |
|||
return formatBytes(data.length); |
|||
}; |
|||
const popupFilterCountLinks = (data) => { |
|||
const num = countLinks(data); |
|||
return "".concat(String(num), " ").concat(num === 1 ? popupString("wikiLink") : popupString("wikiLinks")); |
|||
}; |
|||
const popupFilterCountImages = (data) => { |
|||
const num = countImages(data); |
|||
return "".concat(String(num), " ").concat(num === 1 ? popupString("image") : popupString("images")); |
|||
}; |
|||
const popupFilterCountCategories = (data) => { |
|||
const num = countCategories(data); |
|||
return "".concat(String(num), " ").concat(num === 1 ? popupString("category") : popupString("categories")); |
|||
}; |
|||
const popupFilterLastModified = (_data, download) => { |
|||
const lastmod = download.lastModified; |
|||
const now = /* @__PURE__ */ new Date(); |
|||
const age = now - lastmod; |
|||
if (lastmod && getValueOf("popupLastModified")) { |
|||
return tprintf("%s old", [formatAge(age)]).replace(/ /g, " "); |
|||
} |
|||
return ""; |
|||
}; |
|||
const formatAge = (age) => { |
|||
let a = 0 + age; |
|||
const aa = a; |
|||
const seclen = 1e3; |
|||
const minlen = 60 * seclen; |
|||
const hourlen = 60 * minlen; |
|||
const daylen = 24 * hourlen; |
|||
const weeklen = 7 * daylen; |
|||
const numweeks = (a - a % weeklen) / weeklen; |
|||
a -= numweeks * weeklen; |
|||
const sweeks = addunit(numweeks, "week"); |
|||
const numdays = (a - a % daylen) / daylen; |
|||
a -= numdays * daylen; |
|||
const sdays = addunit(numdays, "day"); |
|||
const numhours = (a - a % hourlen) / hourlen; |
|||
a -= numhours * hourlen; |
|||
const shours = addunit(numhours, "hour"); |
|||
const nummins = (a - a % minlen) / minlen; |
|||
a -= nummins * minlen; |
|||
const smins = addunit(nummins, "minute"); |
|||
const numsecs = (a - a % seclen) / seclen; |
|||
a -= numsecs * seclen; |
|||
const ssecs = addunit(numsecs, "second"); |
|||
if (aa > 4 * weeklen) { |
|||
return sweeks; |
|||
} |
|||
if (aa > weeklen) { |
|||
return "".concat(sweeks, " ").concat(sdays); |
|||
} |
|||
if (aa > daylen) { |
|||
return "".concat(sdays, " ").concat(shours); |
|||
} |
|||
if (aa > 6 * hourlen) { |
|||
return shours; |
|||
} |
|||
if (aa > hourlen) { |
|||
return "".concat(shours, " ").concat(smins); |
|||
} |
|||
if (aa > 10 * minlen) { |
|||
return smins; |
|||
} |
|||
if (aa > minlen) { |
|||
return "".concat(smins, " ").concat(ssecs); |
|||
} |
|||
return ssecs; |
|||
}; |
|||
const addunit = (num, str) => { |
|||
return "".concat(num, " ").concat(num === 1 ? popupString(str) : popupString("".concat(str, "s"))); |
|||
}; |
|||
const runPopupFilters = (list, data, download) => { |
|||
const ret = []; |
|||
var _iterator2 = _createForOfIteratorHelper(list), _step2; |
|||
try { |
|||
for (_iterator2.s(); !(_step2 = _iterator2.n()).done; ) { |
|||
const element = _step2.value; |
|||
if (element && typeof element === "function") { |
|||
const s = element(data, download, download.owner.article); |
|||
if (s) { |
|||
ret.push(s); |
|||
} |
|||
} |
|||
} |
|||
} catch (err) { |
|||
_iterator2.e(err); |
|||
} finally { |
|||
_iterator2.f(); |
|||
} |
|||
return ret; |
|||
}; |
|||
const getPageInfo = (data, download) => { |
|||
if (!data || data.length === 0) { |
|||
return popupString("Empty page"); |
|||
} |
|||
const popupFilters = getValueOf("popupFilters") || []; |
|||
const extraPopupFilters = getValueOf("extraPopupFilters") || []; |
|||
const pageInfoArray = runPopupFilters([...popupFilters, ...extraPopupFilters], data, download); |
|||
let pageInfo = pageInfoArray.join(", "); |
|||
if (pageInfo !== "") { |
|||
pageInfo = upcaseFirst(pageInfo); |
|||
} |
|||
return pageInfo; |
|||
}; |
|||
const countLinks = (wikiText) => { |
|||
return wikiText.split("[[").length - 1; |
|||
}; |
|||
const countImages = (wikiText) => { |
|||
return (wikiText.split(pg.re.image).length - 1) / (pg.re.imageBracketCount + 1); |
|||
}; |
|||
const countCategories = (wikiText) => { |
|||
return (wikiText.split(pg.re.category).length - 1) / (pg.re.categoryBracketCount + 1); |
|||
}; |
|||
const popupFilterStubDetect = (data, _download, article) => { |
|||
const counts = stubCount(data, article); |
|||
if (counts.real) { |
|||
return popupString("stub"); |
|||
} |
|||
if (counts.sect) { |
|||
return popupString("section stub"); |
|||
} |
|||
return ""; |
|||
}; |
|||
const popupFilterDisambigDetect = (data, _download, article) => { |
|||
if (!getValueOf("popupAllDabsStubs") && article.namespace()) { |
|||
return ""; |
|||
} |
|||
return isDisambig(data, article) ? popupString("disambig") : ""; |
|||
}; |
|||
const formatBytes = (num) => { |
|||
return num > 949 ? Math.round(num / 100) / 10 + popupString("kB") : "".concat(num, " ").concat(popupString("bytes")); |
|||
}; |
|||
const Stringwrapper = function Stringwrapper2() { |
|||
this.indexOf = function(x) { |
|||
return this.toString().indexOf(x); |
|||
}; |
|||
this.toString = function() { |
|||
return this.value; |
|||
}; |
|||
this.split = function(x) { |
|||
return this.toString().split(x); |
|||
}; |
|||
this.substring = function(x, y) { |
|||
if (y === void 0) { |
|||
return this.toString().slice(Math.max(0, x)); |
|||
} |
|||
return this.toString().substring(x, y); |
|||
}; |
|||
this.split = function(x) { |
|||
return this.toString().split(x); |
|||
}; |
|||
this.replace = function(x, y) { |
|||
return this.toString().replace(x, y); |
|||
}; |
|||
}; |
|||
class Title extends Stringwrapper { |
|||
constructor(val) { |
|||
super(); |
|||
this.value = null; |
|||
this.anchor = ""; |
|||
this.setUtf(val); |
|||
} |
|||
/** |
|||
* Returns the canonical representation of the article title, optionally without anchor. |
|||
* |
|||
* @param {boolean} omitAnchor |
|||
* @fixme Decide specs for anchor |
|||
* @return String The article title and the anchor. |
|||
*/ |
|||
toString(omitAnchor) { |
|||
return this.value + (!omitAnchor && this.anchor ? "#".concat(this.anchorString()) : ""); |
|||
} |
|||
anchorString() { |
|||
if (!this.anchor) { |
|||
return ""; |
|||
} |
|||
const split = this.anchor.split(/((?:\.[\dA-F]{2})+)/); |
|||
const len = split.length; |
|||
let value; |
|||
for (let j = 1; j < len; j += 2) { |
|||
value = split[j].split(".").join("%"); |
|||
try { |
|||
value = decodeURIComponent(value); |
|||
} catch { |
|||
} |
|||
split[j] = value.split("_").join(" "); |
|||
} |
|||
return split.join(""); |
|||
} |
|||
urlAnchor() { |
|||
const split = this.anchor.split("/((?:[%][0-9A-F]{2})+)/"); |
|||
const len = split.length; |
|||
for (let j = 1; j < len; j += 2) { |
|||
split[j] = split[j].split("%").join("."); |
|||
} |
|||
return split.join(""); |
|||
} |
|||
anchorFromUtf(str) { |
|||
this.anchor = encodeURIComponent(str.split(" ").join("_")).split("%3A").join(":").split("'").join("%27").split("%").join("."); |
|||
} |
|||
fromURL(h) { |
|||
if (typeof h !== "string") { |
|||
this.value = null; |
|||
return this; |
|||
} |
|||
const splitted = h.split("?"); |
|||
splitted[0] = splitted[0].split("&").join("%26"); |
|||
h = splitted.join("?"); |
|||
const contribs = pg.re.contribs.exec(h); |
|||
if (contribs) { |
|||
if (contribs[1] === "title=") { |
|||
contribs[3] = contribs[3].split("+").join(" "); |
|||
} |
|||
const u = new Title(contribs[3]); |
|||
this.setUtf(Title.decodeNasties("".concat(mw.config.get("wgFormattedNamespaces")[pg.nsUserId], ":").concat(u.stripNamespace()))); |
|||
return this; |
|||
} |
|||
const email = pg.re.email.exec(h); |
|||
if (email) { |
|||
this.setUtf(Title.decodeNasties("".concat(mw.config.get("wgFormattedNamespaces")[pg.nsUserId], ":").concat(new Title(email[3]).stripNamespace()))); |
|||
return this; |
|||
} |
|||
const backlinks = pg.re.backlinks.exec(h); |
|||
if (backlinks) { |
|||
this.setUtf(Title.decodeNasties(new Title(backlinks[3]))); |
|||
return this; |
|||
} |
|||
const specialdiff = pg.re.specialdiff.exec(h); |
|||
if (specialdiff) { |
|||
this.setUtf(Title.decodeNasties(new Title("".concat(mw.config.get("wgFormattedNamespaces")[pg.nsSpecialId], ":Diff")))); |
|||
return this; |
|||
} |
|||
const m = pg.re.main.exec(h); |
|||
if (m === null) { |
|||
this.value = null; |
|||
} else { |
|||
const fromBotInterface = /\?(.+&)?title=/.test(h); |
|||
if (fromBotInterface) { |
|||
m[2] = m[2].split("+").join("_"); |
|||
} |
|||
const extracted = m[2] + (m[3] ? "#".concat(m[3]) : ""); |
|||
if (pg.flag.isSafari && /%25[\dA-Fa-f]{2}/.test(extracted)) { |
|||
this.setUtf(decodeURIComponent(unescape(extracted))); |
|||
} else { |
|||
this.setUtf(Title.decodeNasties(extracted)); |
|||
} |
|||
} |
|||
return this; |
|||
} |
|||
static decodeNasties(txt) { |
|||
try { |
|||
let ret = decodeURI(Title.decodeEscapes(txt)); |
|||
ret = ret.replace(/[ _]*$/, ""); |
|||
return ret; |
|||
} catch { |
|||
return txt; |
|||
} |
|||
} |
|||
// Decode valid %-encodings, otherwise escape them |
|||
static decodeEscapes(txt) { |
|||
const split = txt.split(/((?:%[\dA-Fa-f]{2})+)/); |
|||
const len = split.length; |
|||
if (len === 1) { |
|||
return split[0].replace(/%(?![\dA-Fa-f]{2})/g, "%25"); |
|||
} |
|||
for (let i = 1; i < len; i += 2) { |
|||
split[i] = decodeURIComponent(split[i]); |
|||
} |
|||
return split.join(""); |
|||
} |
|||
fromAnchor(a) { |
|||
if (!a) { |
|||
this.value = null; |
|||
return this; |
|||
} |
|||
return this.fromURL(a.href); |
|||
} |
|||
fromWikiText(txt) { |
|||
txt = myDecodeURI(txt); |
|||
this.setUtf(txt); |
|||
return this; |
|||
} |
|||
hintValue() { |
|||
if (!this.value) { |
|||
return ""; |
|||
} |
|||
return safeDecodeURI(this.value); |
|||
} |
|||
toUserName(withNs) { |
|||
if (this.namespaceId() !== pg.nsUserId && this.namespaceId() !== pg.nsUsertalkId) { |
|||
this.value = null; |
|||
return; |
|||
} |
|||
this.value = (withNs ? "".concat(mw.config.get("wgFormattedNamespaces")[pg.nsUserId], ":") : "") + this.stripNamespace().split("/")[0]; |
|||
} |
|||
userName(withNs) { |
|||
const t = new Title(this.value); |
|||
t.toUserName(withNs); |
|||
if (t.value) { |
|||
return t; |
|||
} |
|||
return null; |
|||
} |
|||
toTalkPage() { |
|||
if (this.value === null) { |
|||
return null; |
|||
} |
|||
const namespaceId = this.namespaceId(); |
|||
if (namespaceId >= 0 && namespaceId % 2 === 0) { |
|||
const localizedNamespace = mw.config.get("wgFormattedNamespaces")[namespaceId + 1]; |
|||
if (localizedNamespace !== void 0) { |
|||
this.value = localizedNamespace === "" ? this.stripNamespace() : "".concat(localizedNamespace.split(" ").join("_"), ":").concat(this.stripNamespace()); |
|||
return this.value; |
|||
} |
|||
} |
|||
this.value = null; |
|||
return null; |
|||
} |
|||
// Return canonical, localized namespace |
|||
namespace() { |
|||
return mw.config.get("wgFormattedNamespaces")[this.namespaceId()]; |
|||
} |
|||
namespaceId() { |
|||
const n = this.value.indexOf(":"); |
|||
if (n === -1) { |
|||
return 0; |
|||
} |
|||
const namespaceId = mw.config.get("wgNamespaceIds")[this.value.slice(0, Math.max(0, n)).split(" ").join("_").toLowerCase()]; |
|||
if (namespaceId === void 0) { |
|||
return 0; |
|||
} |
|||
return namespaceId; |
|||
} |
|||
talkPage() { |
|||
const t = new Title(this.value); |
|||
t.toTalkPage(); |
|||
if (t.value) { |
|||
return t; |
|||
} |
|||
return null; |
|||
} |
|||
isTalkPage() { |
|||
if (this.talkPage() === null) { |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
toArticleFromTalkPage() { |
|||
if (this.value === null) { |
|||
return null; |
|||
} |
|||
const namespaceId = this.namespaceId(); |
|||
if (namespaceId >= 0 && namespaceId % 2 === 1) { |
|||
const localizedNamespace = mw.config.get("wgFormattedNamespaces")[namespaceId - 1]; |
|||
if (localizedNamespace !== void 0) { |
|||
this.value = localizedNamespace === "" ? this.stripNamespace() : "".concat(localizedNamespace.split(" ").join("_"), ":").concat(this.stripNamespace()); |
|||
return this.value; |
|||
} |
|||
} |
|||
this.value = null; |
|||
return null; |
|||
} |
|||
articleFromTalkPage() { |
|||
const t = new Title(this.value); |
|||
t.toArticleFromTalkPage(); |
|||
if (t.value) { |
|||
return t; |
|||
} |
|||
return null; |
|||
} |
|||
articleFromTalkOrArticle() { |
|||
const t = new Title(this.value); |
|||
if (t.toArticleFromTalkPage()) { |
|||
return t; |
|||
} |
|||
return this; |
|||
} |
|||
isIpUser() { |
|||
return pg.re.ipUser.test(this.userName()); |
|||
} |
|||
stripNamespace() { |
|||
const n = this.value.indexOf(":"); |
|||
if (n === -1) { |
|||
return this.value; |
|||
} |
|||
const namespaceId = this.namespaceId(); |
|||
if (namespaceId === pg.nsMainspaceId) { |
|||
return this.value; |
|||
} |
|||
return this.value.slice(Math.max(0, n + 1)); |
|||
} |
|||
setUtf(value) { |
|||
if (!value) { |
|||
this.value = ""; |
|||
return; |
|||
} |
|||
const anch = value.indexOf("#"); |
|||
if (anch === -1) { |
|||
this.value = value.split("_").join(" "); |
|||
this.anchor = ""; |
|||
return; |
|||
} |
|||
this.value = value.slice(0, Math.max(0, anch)).split("_").join(" "); |
|||
this.anchor = value.slice(Math.max(0, anch + 1)); |
|||
this.ns = null; |
|||
} |
|||
setUrl(urlfrag) { |
|||
const anch = urlfrag.indexOf("#"); |
|||
this.value = safeDecodeURI(urlfrag.slice(0, Math.max(0, anch))); |
|||
this.anchor = this.value.slice(Math.max(0, anch + 1)); |
|||
} |
|||
append(x) { |
|||
this.setUtf(this.value + x); |
|||
} |
|||
urlString(x) { |
|||
x || (x = {}); |
|||
let v = this.toString(true); |
|||
if (!x.omitAnchor && this.anchor) { |
|||
v += "#".concat(this.urlAnchor()); |
|||
} |
|||
if (!x.keepSpaces) { |
|||
v = v.split(" ").join("_"); |
|||
} |
|||
return encodeURI(v).split("&").join("%26").split("?").join("%3F").split("+").join("%2B"); |
|||
} |
|||
removeAnchor() { |
|||
return new Title(this.toString(true)); |
|||
} |
|||
toUrl() { |
|||
return pg.wiki.titlebase + this.urlString(); |
|||
} |
|||
} |
|||
Title.fromURL = (h) => { |
|||
return new Title().fromURL(h); |
|||
}; |
|||
Title.fromAnchor = (a) => { |
|||
return new Title().fromAnchor(a); |
|||
}; |
|||
Title.fromWikiText = (txt) => { |
|||
return new Title().fromWikiText(txt); |
|||
}; |
|||
const parseParams = (url) => { |
|||
const specialDiff = pg.re.specialdiff.exec(url); |
|||
if (specialDiff) { |
|||
const split = specialDiff[1].split("/"); |
|||
if (split.length === 1) { |
|||
return { |
|||
oldid: split[0], |
|||
diff: "prev" |
|||
}; |
|||
} else if (split.length === 2) { |
|||
return { |
|||
oldid: split[0], |
|||
diff: split[1] |
|||
}; |
|||
} |
|||
} |
|||
const ret = {}; |
|||
if (!url.includes("?")) { |
|||
return ret; |
|||
} |
|||
[url] = url.split("#"); |
|||
const s = url.split("?").slice(1).join(","); |
|||
const t = s.split("&"); |
|||
var _iterator3 = _createForOfIteratorHelper(t), _step3; |
|||
try { |
|||
for (_iterator3.s(); !(_step3 = _iterator3.n()).done; ) { |
|||
const element = _step3.value; |
|||
const z = element.split("="); |
|||
z.push(null); |
|||
[, ret[z[0]]] = z; |
|||
} |
|||
} catch (err) { |
|||
_iterator3.e(err); |
|||
} finally { |
|||
_iterator3.f(); |
|||
} |
|||
if (ret.diff && ret.oldid === void 0) { |
|||
ret.oldid = "prev"; |
|||
} |
|||
if (ret.oldid && (ret.oldid === "prev" || ret.oldid === "next" || ret.oldid === "cur")) { |
|||
const helper = ret.diff; |
|||
ret.diff = ret.oldid; |
|||
ret.oldid = helper; |
|||
} |
|||
return ret; |
|||
}; |
|||
const myDecodeURI = (str) => { |
|||
let ret; |
|||
try { |
|||
ret = decodeURI(str.toString()); |
|||
} catch { |
|||
return str; |
|||
} |
|||
for (let i = 0; i < pg.misc.decodeExtras.length; ++i) { |
|||
const { |
|||
from |
|||
} = pg.misc.decodeExtras[i]; |
|||
const { |
|||
to |
|||
} = pg.misc.decodeExtras[i]; |
|||
ret = ret.split(from).join(to); |
|||
} |
|||
return ret; |
|||
}; |
|||
const safeDecodeURI = (str) => { |
|||
const ret = myDecodeURI(str); |
|||
return ret || str; |
|||
}; |
|||
const isDisambig = (data, article) => { |
|||
if (!getValueOf("popupAllDabsStubs") && article.namespace()) { |
|||
return false; |
|||
} |
|||
return !article.isTalkPage() && pg.re.disambig.test(data); |
|||
}; |
|||
const stubCount = (data, article) => { |
|||
if (!getValueOf("popupAllDabsStubs") && article.namespace()) { |
|||
return false; |
|||
} |
|||
let sectStub = 0; |
|||
let realStub = 0; |
|||
if (pg.re.stub.test(data)) { |
|||
const s = data.split(pg.re.stub); |
|||
for (let i = 1; i < s.length; i += 2) { |
|||
if (s[i]) { |
|||
++sectStub; |
|||
} else { |
|||
++realStub; |
|||
} |
|||
} |
|||
} |
|||
return { |
|||
real: realStub, |
|||
sect: sectStub |
|||
}; |
|||
}; |
|||
const isValidImageName = (str) => { |
|||
return !str.includes("{"); |
|||
}; |
|||
const isInStrippableNamespace = (article) => { |
|||
return article.namespaceId() !== 0; |
|||
}; |
|||
const isInMainNamespace = (article) => { |
|||
return article.namespaceId() === 0; |
|||
}; |
|||
const anchorContainsImage = (a) => { |
|||
if (a === null) { |
|||
return false; |
|||
} |
|||
const kids = a.childNodes; |
|||
var _iterator4 = _createForOfIteratorHelper(kids), _step4; |
|||
try { |
|||
for (_iterator4.s(); !(_step4 = _iterator4.n()).done; ) { |
|||
const kid = _step4.value; |
|||
if (kid.nodeName === "IMG") { |
|||
return true; |
|||
} |
|||
} |
|||
} catch (err) { |
|||
_iterator4.e(err); |
|||
} finally { |
|||
_iterator4.f(); |
|||
} |
|||
return false; |
|||
}; |
|||
const isPopupLink = (a) => { |
|||
if (!markNopopupSpanLinks.done) { |
|||
markNopopupSpanLinks(); |
|||
} |
|||
if (a.inNopopupSpan) { |
|||
return false; |
|||
} |
|||
if (a.onmousedown || a.getAttribute("nopopup")) { |
|||
return false; |
|||
} |
|||
const h = a.href; |
|||
if (h === "".concat(document.location.href, "#")) { |
|||
return false; |
|||
} |
|||
if (!pg.re.basenames.test(h)) { |
|||
return false; |
|||
} |
|||
if (!pg.re.urlNoPopup.test(h)) { |
|||
return true; |
|||
} |
|||
return (pg.re.email.test(h) || pg.re.contribs.test(h) || pg.re.backlinks.test(h) || pg.re.specialdiff.test(h)) && !h.includes("&limit="); |
|||
}; |
|||
const markNopopupSpanLinks = function markNopopupSpanLinks2() { |
|||
if (!getValueOf("popupOnlyArticleLinks")) { |
|||
fixVectorMenuPopups(); |
|||
} |
|||
const $body = $("body"); |
|||
const s = $body.find(".nopopups").toArray(); |
|||
var _iterator5 = _createForOfIteratorHelper(s), _step5; |
|||
try { |
|||
for (_iterator5.s(); !(_step5 = _iterator5.n()).done; ) { |
|||
const element = _step5.value; |
|||
const as = element.querySelectorAll("a"); |
|||
var _iterator6 = _createForOfIteratorHelper(as), _step6; |
|||
try { |
|||
for (_iterator6.s(); !(_step6 = _iterator6.n()).done; ) { |
|||
const a = _step6.value; |
|||
a.inNopopupSpan = true; |
|||
} |
|||
} catch (err) { |
|||
_iterator6.e(err); |
|||
} finally { |
|||
_iterator6.f(); |
|||
} |
|||
} |
|||
} catch (err) { |
|||
_iterator5.e(err); |
|||
} finally { |
|||
_iterator5.f(); |
|||
} |
|||
markNopopupSpanLinks2.done = true; |
|||
}; |
|||
const fixVectorMenuPopups = () => { |
|||
const $body = $("body"); |
|||
$body.find("nav.vector-menu h3:first a:first").prop("inNopopupSpan", true); |
|||
}; |
|||
const getPageWithCaching = (url, onComplete, owner) => { |
|||
log("getPageWithCaching, url=".concat(url)); |
|||
const i = findInPageCache(url); |
|||
let d; |
|||
if (i > -1) { |
|||
d = fakeDownload(url, owner.idNumber, onComplete, pg.cache.pages[i].data, pg.cache.pages[i].lastModified, owner); |
|||
} else { |
|||
d = getPage(url, onComplete, owner); |
|||
if (d && owner && owner.addDownload) { |
|||
owner.addDownload(d); |
|||
d.owner = owner; |
|||
} |
|||
} |
|||
}; |
|||
const getPage = (url, onComplete, owner) => { |
|||
log("getPage"); |
|||
const callback = (d) => { |
|||
if (!d.aborted) { |
|||
addPageToCache(d); |
|||
onComplete(d); |
|||
} |
|||
}; |
|||
return startDownload(url, owner.idNumber, callback); |
|||
}; |
|||
const findInPageCache = (url) => { |
|||
for (let i = 0; i < pg.cache.pages.length; ++i) { |
|||
if (url === pg.cache.pages[i].url) { |
|||
return i; |
|||
} |
|||
} |
|||
return -1; |
|||
}; |
|||
const addPageToCache = (download) => { |
|||
log("addPageToCache ".concat(download.url)); |
|||
const page = { |
|||
url: download.url, |
|||
data: download.data, |
|||
lastModified: download.lastModified |
|||
}; |
|||
return pg.cache.pages.push(page); |
|||
}; |
|||
const getJsObj = (json) => { |
|||
try { |
|||
const json_ret = JSON.parse(json); |
|||
if (json_ret.warnings) { |
|||
for (let w = 0; w < json_ret.warnings.length; w++) { |
|||
if (json_ret.warnings[w]["*"]) { |
|||
log(json_ret.warnings[w]["*"]); |
|||
} else { |
|||
log(json_ret.warnings[w].warnings); |
|||
} |
|||
} |
|||
} else if (json_ret.error) { |
|||
errlog("".concat(json_ret.error.code, ": ").concat(json_ret.error.info)); |
|||
} |
|||
return json_ret; |
|||
} catch { |
|||
errlog("Something went wrong with getJsObj, json=".concat(json)); |
|||
return 1; |
|||
} |
|||
}; |
|||
const anyChild = (obj) => { |
|||
for (const p in obj) { |
|||
if (!Object.hasOwn(obj, p)) { |
|||
continue; |
|||
} |
|||
return obj[p]; |
|||
} |
|||
return null; |
|||
}; |
|||
const upcaseFirst = (str) => { |
|||
if (typeof str !== "string" || str === "") { |
|||
return; |
|||
} |
|||
return str.charAt(0).toUpperCase() + str.slice(1); |
|||
}; |
|||
const findInArray = (arr, foo) => { |
|||
if (!arr || arr.length === 0) { |
|||
return -1; |
|||
} |
|||
const len = arr.length; |
|||
for (let i = 0; i < len; ++i) { |
|||
if (arr[i] === foo) { |
|||
return i; |
|||
} |
|||
} |
|||
return -1; |
|||
}; |
|||
const nextOne = (array, value) => { |
|||
const i = findInArray(array, value); |
|||
if (i < 0) { |
|||
return null; |
|||
} |
|||
return array[i + 1]; |
|||
}; |
|||
const literalizeRegex = (str) => { |
|||
return mw.util.escapeRegExp(str); |
|||
}; |
|||
String.prototype.entify = function() { |
|||
return this.split("&").join("&").split("<").join("<").split(">").join( |
|||
">" |
|||
/* +shy */ |
|||
).split('"').join("""); |
|||
}; |
|||
const removeNulls = (val) => { |
|||
return val !== null; |
|||
}; |
|||
const joinPath = (list) => { |
|||
return list.filter(removeNulls).join("/"); |
|||
}; |
|||
const simplePrintf = (str, subs) => { |
|||
if (!str || !subs) { |
|||
return str; |
|||
} |
|||
const ret = []; |
|||
const s = str.split(/(%s|\$\d+)/); |
|||
let i = 0; |
|||
do { |
|||
ret.push(s.shift()); |
|||
if (s.length === 0) { |
|||
break; |
|||
} |
|||
const cmd = s.shift(); |
|||
if (cmd === "%s") { |
|||
if (i < subs.length) { |
|||
ret.push(subs[i]); |
|||
} else { |
|||
ret.push(cmd); |
|||
} |
|||
++i; |
|||
} else { |
|||
const j = Number.parseInt(cmd.replace("$", ""), 10) - 1; |
|||
if (j > -1 && j < subs.length) { |
|||
ret.push(subs[j]); |
|||
} else { |
|||
ret.push(cmd); |
|||
} |
|||
} |
|||
} while (s.length > 0); |
|||
return ret.join(""); |
|||
}; |
|||
const isString = (x) => { |
|||
return typeof x === "string" || x instanceof String; |
|||
}; |
|||
const isNumber = (x) => { |
|||
return typeof x === "number" || x instanceof Number; |
|||
}; |
|||
const isRegExp = (x) => { |
|||
return x instanceof RegExp; |
|||
}; |
|||
const isArray = (x) => { |
|||
return Array.isArray(x); |
|||
}; |
|||
const isObject = (x) => { |
|||
return x instanceof Object; |
|||
}; |
|||
const isFunction = (x) => { |
|||
return !isRegExp(x) && (typeof x === "function" || x instanceof Function); |
|||
}; |
|||
const repeatString = (s, mult) => { |
|||
let ret = ""; |
|||
for (let i = 0; i < mult; ++i) { |
|||
ret += s; |
|||
} |
|||
return ret; |
|||
}; |
|||
const zeroFill = (s, min) => { |
|||
min || (min = 2); |
|||
const t = s.toString(); |
|||
return repeatString("0", min - t.length) + t; |
|||
}; |
|||
const map = (f, o) => { |
|||
if (isArray(o)) { |
|||
return map_array(f, o); |
|||
} |
|||
return map_object(f, o); |
|||
}; |
|||
const map_array = (f, o) => { |
|||
const ret = []; |
|||
var _iterator7 = _createForOfIteratorHelper(o), _step7; |
|||
try { |
|||
for (_iterator7.s(); !(_step7 = _iterator7.n()).done; ) { |
|||
const element = _step7.value; |
|||
ret.push(f(element)); |
|||
} |
|||
} catch (err) { |
|||
_iterator7.e(err); |
|||
} finally { |
|||
_iterator7.f(); |
|||
} |
|||
return ret; |
|||
}; |
|||
const map_object = (f, o) => { |
|||
const ret = {}; |
|||
for (const i in o) { |
|||
if (!Object.hasOwn(o, i)) { |
|||
continue; |
|||
} |
|||
ret[o] = f(o[i]); |
|||
} |
|||
return ret; |
|||
}; |
|||
pg.escapeQuotesHTML = (text) => { |
|||
return text.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">"); |
|||
}; |
|||
pg.unescapeQuotesHTML = (html) => { |
|||
const txt = document.createElement("textarea"); |
|||
txt.innerHTML = html; |
|||
return txt.value; |
|||
}; |
|||
const retargetDab = (newTarget, oldTarget, friendlyCurrentArticleName, titleToEdit) => { |
|||
log("retargetDab: newTarget=".concat(newTarget, " oldTarget=").concat(oldTarget)); |
|||
return changeLinkTargetLink({ |
|||
newTarget, |
|||
text: newTarget.split(" ").join(" "), |
|||
hint: tprintf("disambigHint", [newTarget]), |
|||
summary: simplePrintf(getValueOf("popupFixDabsSummary"), [friendlyCurrentArticleName, newTarget]), |
|||
clickButton: getValueOf("popupDabsAutoClick"), |
|||
minor: true, |
|||
oldTarget, |
|||
watch: getValueOf("popupWatchDisambiggedPages"), |
|||
title: titleToEdit |
|||
}); |
|||
}; |
|||
const listLinks = (wikitext, oldTarget, titleToEdit) => { |
|||
const reg = /\[\[([^|]*?) *(\||]])/gi; |
|||
let ret = []; |
|||
const splitted = wikitext.split(reg); |
|||
const omitRegex = /^[a-z]*:|^[Ss]pecial:|^[Ii]mage|^[Cc]ategory/; |
|||
const friendlyCurrentArticleName = oldTarget.toString(); |
|||
const wikPos = getValueOf("popupDabWiktionary"); |
|||
for (let i = 1; i < splitted.length; i += 3) { |
|||
if (typeof splitted[i] === "string" && splitted[i].length > 0 && !omitRegex.test(splitted[i])) { |
|||
ret.push(retargetDab(splitted[i], oldTarget, friendlyCurrentArticleName, titleToEdit)); |
|||
} |
|||
} |
|||
ret = rmDupesFromSortedList(ret.sort()); |
|||
if (wikPos) { |
|||
const wikTarget = "wiktionary:".concat(friendlyCurrentArticleName.replace(/^(.+)\s+\([^)]+\)\s*$/, "$1")); |
|||
const meth = wikPos.toLowerCase() === "first" ? "unshift" : "push"; |
|||
ret[meth](retargetDab(wikTarget, oldTarget, friendlyCurrentArticleName, titleToEdit)); |
|||
} |
|||
ret.push(changeLinkTargetLink({ |
|||
newTarget: null, |
|||
text: popupString("remove this link").split(" ").join(" "), |
|||
hint: popupString("remove all links to this disambig page from this article"), |
|||
clickButton: getValueOf("popupDabsAutoClick"), |
|||
oldTarget, |
|||
summary: simplePrintf(getValueOf("popupRmDabLinkSummary"), [friendlyCurrentArticleName]), |
|||
watch: getValueOf("popupWatchDisambiggedPages"), |
|||
title: titleToEdit |
|||
})); |
|||
return ret; |
|||
}; |
|||
const rmDupesFromSortedList = (list) => { |
|||
const ret = []; |
|||
var _iterator8 = _createForOfIteratorHelper(list), _step8; |
|||
try { |
|||
for (_iterator8.s(); !(_step8 = _iterator8.n()).done; ) { |
|||
const element = _step8.value; |
|||
if (ret.length === 0 || element !== ret.at(-1)) { |
|||
ret.push(element); |
|||
} |
|||
} |
|||
} catch (err) { |
|||
_iterator8.e(err); |
|||
} finally { |
|||
_iterator8.f(); |
|||
} |
|||
return ret; |
|||
}; |
|||
const makeFixDab = (data, navpop) => { |
|||
const titleToEdit = navpop.parentPopup && navpop.parentPopup.article.toString(); |
|||
const list = listLinks(data, navpop.originalArticle, titleToEdit); |
|||
if (list.length === 0) { |
|||
log("listLinks returned empty list"); |
|||
return null; |
|||
} |
|||
let html = "<hr>".concat(popupString("Click to disambiguate this link to:"), "<br>"); |
|||
html += list.join(", "); |
|||
return html; |
|||
}; |
|||
const makeFixDabs = (wikiText, navpop) => { |
|||
if (getValueOf("popupFixDabs") && isDisambig(wikiText, navpop.article) && Title.fromURL(location.href).namespaceId() !== pg.nsSpecialId && navpop.article.talkPage()) { |
|||
setPopupHTML(makeFixDab(wikiText, navpop), "popupFixDab", navpop.idNumber); |
|||
} |
|||
}; |
|||
const popupRedlinkHTML = (article) => { |
|||
return changeLinkTargetLink({ |
|||
newTarget: null, |
|||
text: popupString("remove this link").split(" ").join(" "), |
|||
hint: popupString("remove all links to this page from this article"), |
|||
clickButton: getValueOf("popupRedlinkAutoClick"), |
|||
oldTarget: article.toString(), |
|||
summary: simplePrintf(getValueOf("popupRedlinkSummary"), [article.toString()]) |
|||
}); |
|||
}; |
|||
const setPopupHTML = function setPopupHTML2(str, elementId, popupId, onSuccess, append) { |
|||
if (popupId === void 0) { |
|||
popupId = pg.idNumber; |
|||
} |
|||
const popupElement = document.getElementById("".concat(elementId).concat(popupId)); |
|||
if (popupElement) { |
|||
if (!append) { |
|||
popupElement.innerHTML = ""; |
|||
} |
|||
if (isString(str)) { |
|||
popupElement.innerHTML += str; |
|||
} else { |
|||
popupElement.append(str); |
|||
} |
|||
if (onSuccess) { |
|||
onSuccess(); |
|||
} |
|||
setTimeout(checkPopupPosition, 100); |
|||
return true; |
|||
} |
|||
setTimeout(() => { |
|||
setPopupHTML2(str, elementId, popupId, onSuccess); |
|||
}, 600); |
|||
return null; |
|||
}; |
|||
const setPopupTrailer = (str, id) => { |
|||
return setPopupHTML(str, "popupData", id); |
|||
}; |
|||
const fillEmptySpans = (args) => { |
|||
let redir = true; |
|||
let rcid; |
|||
if (typeof args !== "object" || args.redir === void 0 || !args.redir) { |
|||
redir = false; |
|||
} |
|||
const a = args.navpopup.parentAnchor; |
|||
let article; |
|||
let hint; |
|||
let oldid; |
|||
let params = {}; |
|||
if (redir && typeof args.redirTarget === typeof {}) { |
|||
article = args.redirTarget; |
|||
} else { |
|||
article = new Title().fromAnchor(a); |
|||
hint = a.originalTitle || article.hintValue(); |
|||
params = parseParams(a.href); |
|||
oldid = getValueOf("popupHistoricalLinks") ? params.oldid : null; |
|||
({ |
|||
rcid |
|||
} = params); |
|||
} |
|||
const x = { |
|||
article, |
|||
hint, |
|||
oldid, |
|||
rcid, |
|||
navpop: args.navpopup, |
|||
params |
|||
}; |
|||
const structure = pg.structures[getValueOf("popupStructure")]; |
|||
if (typeof structure !== "object") { |
|||
setPopupHTML("popupError", "Unknown structure (this should never happen): ".concat(pg.option.popupStructure), args.navpopup.idNumber); |
|||
return; |
|||
} |
|||
const spans = flatten(pg.misc.layout); |
|||
const numspans = spans.length; |
|||
const redirs = pg.misc.redirSpans; |
|||
for (let i = 0; i < numspans; ++i) { |
|||
const found = redirs && redirs.includes(spans[i]); |
|||
if (found && !redir || !found && redir) { |
|||
continue; |
|||
} |
|||
const structurefn = structure[spans[i]]; |
|||
if (structurefn === void 0) { |
|||
continue; |
|||
} |
|||
let setfn = setPopupHTML; |
|||
if (getValueOf("popupActiveNavlinks") && (spans[i].indexOf("popupTopLinks") === 0 || spans[i].indexOf("popupRedirTopLinks") === 0)) { |
|||
setfn = setPopupTipsAndHTML; |
|||
} |
|||
switch (typeof structurefn) { |
|||
case "function": |
|||
log("running ".concat(spans[i], "({\n article:").concat(x.article, ", hint:").concat(x.hint, ", oldid: ").concat(x.oldid, "})")); |
|||
setfn(structurefn(x), spans[i], args.navpopup.idNumber); |
|||
break; |
|||
case "string": |
|||
setfn(structurefn, spans[i], args.navpopup.idNumber); |
|||
break; |
|||
default: |
|||
errlog("unknown thing with label ".concat(spans[i], " (span index was ").concat(i, ")")); |
|||
break; |
|||
} |
|||
} |
|||
}; |
|||
const flatten = function flatten2(list, start) { |
|||
const ret = []; |
|||
if (start === void 0) { |
|||
start = 0; |
|||
} |
|||
for (let i = start; i < list.length; ++i) { |
|||
if (typeof list[i] === typeof []) { |
|||
return [...ret, ...flatten2(list[i]), ...flatten2(list, i + 1)]; |
|||
} |
|||
ret.push(list[i]); |
|||
} |
|||
return ret; |
|||
}; |
|||
const popupHTML = function popupHTML2(a) { |
|||
getValueOf("popupStructure"); |
|||
const structure = pg.structures[pg.option.popupStructure]; |
|||
if (typeof structure !== "object") { |
|||
pg.option.popupStructure = pg.optionDefault.popupStructure; |
|||
return popupHTML2(a); |
|||
} |
|||
if (typeof structure.popupLayout !== "function") { |
|||
return "Bad layout"; |
|||
} |
|||
pg.misc.layout = structure.popupLayout(); |
|||
pg.misc.redirSpans = typeof structure.popupRedirSpans === "function" ? structure.popupRedirSpans() : []; |
|||
return makeEmptySpans(pg.misc.layout, a.navpopup); |
|||
}; |
|||
const makeEmptySpans = function makeEmptySpans2(list, navpop) { |
|||
let ret = ""; |
|||
var _iterator9 = _createForOfIteratorHelper(list), _step9; |
|||
try { |
|||
for (_iterator9.s(); !(_step9 = _iterator9.n()).done; ) { |
|||
const element = _step9.value; |
|||
if (typeof element === "string") { |
|||
ret += emptySpanHTML(element, navpop.idNumber, "div"); |
|||
} else if (typeof element === typeof [] && element.length > 0) { |
|||
ret = ret.split(/(<\/[^>]*?>$)/).join(makeEmptySpans2(element, navpop)); |
|||
} else if (typeof element === typeof {} && element.nodeType) { |
|||
ret += emptySpanHTML(element.name, navpop.idNumber, element.nodeType); |
|||
} |
|||
} |
|||
} catch (err) { |
|||
_iterator9.e(err); |
|||
} finally { |
|||
_iterator9.f(); |
|||
} |
|||
return ret; |
|||
}; |
|||
const emptySpanHTML = function emptySpanHTML2(name, id, tag, classname) { |
|||
tag || (tag = "span"); |
|||
classname || (classname = emptySpanHTML2.classAliases[name]); |
|||
classname || (classname = name); |
|||
if (name === getValueOf("popupDragHandle")) { |
|||
classname += " popupDragHandle"; |
|||
} |
|||
return simplePrintf('<%s id="%s" class="%s"></%s>', [tag, name + id, classname, tag]); |
|||
}; |
|||
emptySpanHTML.classAliases = { |
|||
popupSecondPreview: "popupPreview" |
|||
}; |
|||
const imageHTML = (_article, idNumber) => { |
|||
return simplePrintf('<a id="popupImageLink$1"><img align="right" valign="top" id="popupImg$1" style="display:none"></img></a>', [idNumber]); |
|||
}; |
|||
const popTipsSoonFn = (id, when, popData) => { |
|||
when || (when = 250); |
|||
const popTips = () => { |
|||
setupTooltips(document.getElementById("".concat(id)), false, true, popData); |
|||
}; |
|||
return () => { |
|||
setTimeout(popTips, when, popData); |
|||
}; |
|||
}; |
|||
const setPopupTipsAndHTML = (html, divname, idnumber, popData) => { |
|||
setPopupHTML(html, divname, idnumber, getValueOf("popupSubpopups") ? popTipsSoonFn(divname + idnumber, null, popData) : null); |
|||
}; |
|||
const fuzzyCursorOffMenus = (_x, _y, _fuzz, parent) => { |
|||
if (!parent) { |
|||
return null; |
|||
} |
|||
const uls = parent.querySelectorAll("ul"); |
|||
var _iterator0 = _createForOfIteratorHelper(uls), _step0; |
|||
try { |
|||
for (_iterator0.s(); !(_step0 = _iterator0.n()).done; ) { |
|||
const ul = _step0.value; |
|||
if (ul.className === "popup_menu" && ul.offsetWidth > 0) { |
|||
return false; |
|||
} |
|||
} |
|||
} catch (err) { |
|||
_iterator0.e(err); |
|||
} finally { |
|||
_iterator0.f(); |
|||
} |
|||
return true; |
|||
}; |
|||
const checkPopupPosition = () => { |
|||
if (pg.current.link && pg.current.link.navpopup) { |
|||
pg.current.link.navpopup.limitHorizontalPosition(); |
|||
} |
|||
}; |
|||
const mouseOutWikiLink = function mouseOutWikiLink2() { |
|||
const self2 = this; |
|||
removeModifierKeyListener(self2); |
|||
if (self2.navpopup === null || self2.navpopup === void 0) { |
|||
return; |
|||
} |
|||
if (!self2.navpopup.isVisible()) { |
|||
self2.navpopup.banish(); |
|||
return; |
|||
} |
|||
restoreTitle(self2); |
|||
Navpopup.tracker.addHook(posCheckerHook(self2.navpopup)); |
|||
}; |
|||
const posCheckerHook = (navpop) => { |
|||
return () => { |
|||
if (!navpop.isVisible()) { |
|||
return true; |
|||
} |
|||
if (Navpopup.tracker.dirty) { |
|||
return false; |
|||
} |
|||
const { |
|||
x |
|||
} = Navpopup.tracker; |
|||
const { |
|||
y |
|||
} = Navpopup.tracker; |
|||
const mouseOverNavpop = navpop.isWithin(x, y, navpop.fuzz, navpop.mainDiv) || !fuzzyCursorOffMenus(x, y, navpop.fuzz, navpop.mainDiv); |
|||
let t = getValueOf("popupHideDelay"); |
|||
if (t) { |
|||
t *= 1e3; |
|||
} |
|||
if (!t) { |
|||
if (!mouseOverNavpop) { |
|||
if (navpop.parentAnchor) { |
|||
restoreTitle(navpop.parentAnchor); |
|||
} |
|||
navpop.banish(); |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
const d = Date.now(); |
|||
if (!navpop.mouseLeavingTime) { |
|||
navpop.mouseLeavingTime = d; |
|||
return false; |
|||
} |
|||
if (mouseOverNavpop) { |
|||
navpop.mouseLeavingTime = null; |
|||
return false; |
|||
} |
|||
if (d - navpop.mouseLeavingTime > t) { |
|||
navpop.mouseLeavingTime = null; |
|||
navpop.banish(); |
|||
return true; |
|||
} |
|||
return false; |
|||
}; |
|||
}; |
|||
const runStopPopupTimer = (navpop) => { |
|||
if (!navpop.stopPopupTimer) { |
|||
navpop.stopPopupTimer = setInterval(posCheckerHook(navpop), 500); |
|||
navpop.addHook(() => { |
|||
clearInterval(navpop.stopPopupTimer); |
|||
}, "hide", "before"); |
|||
} |
|||
}; |
|||
class Previewmaker { |
|||
constructor(wikiText, baseUrl, owner) { |
|||
this.originalData = wikiText; |
|||
this.baseUrl = baseUrl; |
|||
this.owner = owner; |
|||
this.maxCharacters = getValueOf("popupMaxPreviewCharacters"); |
|||
this.maxSentences = getValueOf("popupMaxPreviewSentences"); |
|||
this.setData(); |
|||
} |
|||
setData() { |
|||
const maxSize = Math.max(1e4, 2 * this.maxCharacters); |
|||
this.data = this.originalData.slice(0, Math.max(0, maxSize)); |
|||
} |
|||
/** |
|||
* Remove HTML comments |
|||
* |
|||
* @private |
|||
*/ |
|||
killComments() { |
|||
this.data = this.data.replace(/^<!--[^$]*?-->\n|\n<!--[^$]*?-->(?=\n)|<!--[^$]*?-->/g, ""); |
|||
} |
|||
/** |
|||
* @private |
|||
*/ |
|||
killDivs() { |
|||
this.data = this.data.replace(/< *div[^>]* *>[\S\s]*?< *\/ *div *>/gi, ""); |
|||
} |
|||
/** |
|||
* @private |
|||
*/ |
|||
killGalleries() { |
|||
this.data = this.data.replace(/< *gallery[^>]* *>[\S\s]*?< *\/ *gallery *>/gi, ""); |
|||
} |
|||
/** |
|||
* @param {Object} opening |
|||
* @param {Object} closing |
|||
* @param {Object} subopening |
|||
* @param {Object} subclosing |
|||
* @param {Object} repl |
|||
* @private |
|||
*/ |
|||
kill(opening, closing, subopening, subclosing, repl) { |
|||
let oldk = this.data; |
|||
let k = Previewmaker.killStuff(this.data, opening, closing, subopening, subclosing, repl); |
|||
while (k.length < oldk.length) { |
|||
oldk = k; |
|||
k = Previewmaker.killStuff(k, opening, closing, subopening, subclosing, repl); |
|||
} |
|||
this.data = k; |
|||
} |
|||
/** |
|||
* @param {Object} txt |
|||
* @param {Object} opening |
|||
* @param {Object} closing |
|||
* @param {Object} subopening |
|||
* @param {Object} subclosing |
|||
* @param {Object} repl |
|||
* @private |
|||
*/ |
|||
static killStuff(txt, opening, closing, subopening, subclosing, repl) { |
|||
const op = Previewmaker.makeRegexp(opening); |
|||
const cl = Previewmaker.makeRegexp(closing, "^"); |
|||
const sb = subopening ? Previewmaker.makeRegexp(subopening, "^") : null; |
|||
const sc = subclosing ? Previewmaker.makeRegexp(subclosing, "^") : cl; |
|||
if (!op || !cl) { |
|||
void mw.notify("Navigation Popups error: op or cl is null! something is wrong.", { |
|||
tag: "popups", |
|||
type: "error" |
|||
}); |
|||
return; |
|||
} |
|||
if (!op.test(txt)) { |
|||
return txt; |
|||
} |
|||
let ret = ""; |
|||
const opResult = op.exec(txt); |
|||
ret = txt.slice(0, Math.max(0, opResult.index)); |
|||
txt = txt.slice(Math.max(0, opResult.index + opResult[0].length)); |
|||
let depth = 1; |
|||
while (txt.length > 0) { |
|||
let removal = 0; |
|||
if (depth === 1 && cl.test(txt)) { |
|||
depth--; |
|||
removal = cl.exec(txt)[0].length; |
|||
} else if (depth > 1 && sc.test(txt)) { |
|||
depth--; |
|||
removal = sc.exec(txt)[0].length; |
|||
} else if (sb && sb.test(txt)) { |
|||
depth++; |
|||
removal = sb.exec(txt)[0].length; |
|||
} |
|||
removal || (removal = 1); |
|||
txt = txt.slice(Math.max(0, removal)); |
|||
if (depth === 0) { |
|||
break; |
|||
} |
|||
} |
|||
return ret + (repl || "") + txt; |
|||
} |
|||
/** |
|||
* @param {string|RegExp} x |
|||
* @param {string|RegExp} prefix |
|||
* @param {string|RegExp} suffix |
|||
* @private |
|||
*/ |
|||
static makeRegexp(x, prefix, suffix) { |
|||
prefix || (prefix = ""); |
|||
suffix || (suffix = ""); |
|||
let reStr = ""; |
|||
let flags = ""; |
|||
if (isString(x)) { |
|||
reStr = prefix + literalizeRegex(x) + suffix; |
|||
} else if (isRegExp(x)) { |
|||
let s = x.toString().slice(1); |
|||
const sp = s.split("/"); |
|||
flags = sp.at(-1); |
|||
sp[sp.length - 1] = ""; |
|||
s = sp.join("/"); |
|||
s = s.slice(0, Math.max(0, s.length - 1)); |
|||
reStr = prefix + s + suffix; |
|||
} else { |
|||
log("makeRegexp failed"); |
|||
} |
|||
log("makeRegexp: got reStr=".concat(reStr, ", flags=").concat(flags)); |
|||
return new RegExp(reStr, flags); |
|||
} |
|||
/** |
|||
* @private |
|||
*/ |
|||
killBoxTemplates() { |
|||
this.kill(/{{[^\s{|}]*?(float|box)[ _](begin|start)/i, /}}\s*/, "{{"); |
|||
this.kill(/{{[^\s{|}]*?(infobox|elementbox|frame)[ _]/i, /}}\s*/, "{{"); |
|||
} |
|||
/** |
|||
* @private |
|||
*/ |
|||
killTemplates() { |
|||
this.kill("{{", "}}", "{", "}", " "); |
|||
} |
|||
/** |
|||
* @private |
|||
*/ |
|||
killTables() { |
|||
this.kill("{|", /\|}\s*/, "{|"); |
|||
this.kill(/<table.*?>/i, /<\/table.*?>/i, /<table.*?>/i); |
|||
this.data = this.data.replace(/^\|.*$/gm, ""); |
|||
} |
|||
/** |
|||
* @private |
|||
*/ |
|||
killImages() { |
|||
const forbiddenNamespaceAliases = []; |
|||
for (var _i = 0, _Object$entries = Object.entries(mw.config.get("wgNamespaceIds")); _i < _Object$entries.length; _i++) { |
|||
const [localizedNamespaceLc, namespaceId] = _Object$entries[_i]; |
|||
if (namespaceId !== pg.nsImageId && namespaceId !== pg.nsCategoryId) { |
|||
return; |
|||
} |
|||
forbiddenNamespaceAliases.push(localizedNamespaceLc.split(" ").join("[ _]")); |
|||
} |
|||
this.kill(new RegExp("[[][[]\\s*(".concat(forbiddenNamespaceAliases.join("|"), ")\\s*:"), "i"), /]]\s*/, "[", "]"); |
|||
} |
|||
/** |
|||
* @private |
|||
*/ |
|||
killHTML() { |
|||
this.kill(/<ref\b[^/>]*?>/i, /<\/ref>/i); |
|||
this.data = this.data.replace(/(^|\n) *<.*/g, "\n"); |
|||
const splitted = this.data.split(/(<[\W\w]*?(?:>|$|(?=<)))/); |
|||
const len = splitted.length; |
|||
for (let i = 1; i < len; i += 2) { |
|||
switch (splitted[i]) { |
|||
case "<no".concat("wiki", ">"): |
|||
case "</no".concat("wiki", ">"): |
|||
case "<block".concat("quote", ">"): |
|||
case "</block".concat("quote", ">"): |
|||
break; |
|||
default: |
|||
splitted[i] = ""; |
|||
} |
|||
} |
|||
this.data = splitted.join(""); |
|||
} |
|||
/** |
|||
* @private |
|||
*/ |
|||
killChunks() { |
|||
const italicChunkRegex = /((^|\n)\s*:*\s*''[^']([^']|'''|'[^']){20}(.|\n[^\n])*''[\s!.?]*\n)+/g; |
|||
this.data = this.data.replace(italicChunkRegex, "\n"); |
|||
} |
|||
/** |
|||
* @private |
|||
*/ |
|||
mopup() { |
|||
this.data = this.data.replace(/^-{4,}/gm, ""); |
|||
this.data = this.data.replace(/(^|\n) *:[^\n]*/g, ""); |
|||
this.data = this.data.replace(/^__[_a-z]*__ *$/gim, ""); |
|||
} |
|||
/** |
|||
* @private |
|||
*/ |
|||
firstBit() { |
|||
let d = this.data; |
|||
if (getValueOf("popupPreviewCutHeadings")) { |
|||
this.data = this.data.replace(/\s*(==+[^=]*==+)\s*/g, "\n\n$1 "); |
|||
this.data = this.data.replace(/([:;]) *\n{2,}/g, "$1\n"); |
|||
this.data = this.data.replace(/^\s*/, ""); |
|||
const stuff = /^([^\n]|\n\S)*/.exec(this.data); |
|||
if (stuff) { |
|||
[d] = stuff; |
|||
} |
|||
if (!getValueOf("popupPreviewFirstParOnly")) { |
|||
d = this.data; |
|||
} |
|||
d = d.replace(/(==+[^=]*==+)\s*/g, "$1\n\n"); |
|||
} |
|||
d = d.split(/([!.?]+["']*\s)/g); |
|||
d[0] = d[0].replace(/^\s*/, ""); |
|||
const notSentenceEnds = /([^.][a-z]\. *[a-z]|etc|sic|dr|mr|mrs|ms|st|no|op|cit|\[[^\]]*|\s[a-z])$/i; |
|||
d = this.fixSentenceEnds(d, notSentenceEnds); |
|||
this.fullLength = d.join("").length; |
|||
let n = this.maxSentences; |
|||
let dd = Previewmaker.firstSentences(d, n); |
|||
do { |
|||
dd = Previewmaker.firstSentences(d, n); |
|||
--n; |
|||
} while (dd.length > this.maxCharacters && n !== 0); |
|||
this.data = dd; |
|||
} |
|||
/** |
|||
* @param {string} strs |
|||
* @param {RegExp} reg |
|||
* @private |
|||
*/ |
|||
fixSentenceEnds(strs, reg) { |
|||
for (let i = 0; i < strs.length - 2; ++i) { |
|||
if (reg.test(strs[i])) { |
|||
const a = []; |
|||
for (let j = 0; j < strs.length; ++j) { |
|||
if (j < i) { |
|||
a[j] = strs[j]; |
|||
} |
|||
if (j === i) { |
|||
a[i] = strs[i] + strs[i + 1] + strs[i + 2]; |
|||
} |
|||
if (j > i + 2) { |
|||
a[j - 2] = strs[j]; |
|||
} |
|||
} |
|||
return this.fixSentenceEnds(a, reg); |
|||
} |
|||
} |
|||
return strs; |
|||
} |
|||
/** |
|||
* @param {string[]} strs |
|||
* @param {number} howmany |
|||
* @private |
|||
*/ |
|||
static firstSentences(strs, howmany) { |
|||
const t = strs.slice(0, 2 * howmany); |
|||
return t.join(""); |
|||
} |
|||
/** |
|||
* @private |
|||
*/ |
|||
killBadWhitespace() { |
|||
this.data = this.data.replace(/^ *'+ *$/gm, ""); |
|||
} |
|||
/** |
|||
* Runs the various methods to generate the preview. |
|||
* The preview is stored in the <code>html</html> field. |
|||
* |
|||
* @private |
|||
*/ |
|||
makePreview() { |
|||
if (this.owner.article.namespaceId() !== pg.nsTemplateId && this.owner.article.namespaceId() !== pg.nsImageId) { |
|||
this.killComments(); |
|||
this.killDivs(); |
|||
this.killGalleries(); |
|||
this.killBoxTemplates(); |
|||
if (getValueOf("popupPreviewKillTemplates")) { |
|||
this.killTemplates(); |
|||
} else { |
|||
this.killMultilineTemplates(); |
|||
} |
|||
this.killTables(); |
|||
this.killImages(); |
|||
this.killHTML(); |
|||
this.killChunks(); |
|||
this.mopup(); |
|||
this.firstBit(); |
|||
this.killBadWhitespace(); |
|||
} else { |
|||
this.killHTML(); |
|||
} |
|||
this.html = wiki2html(this.data, this.baseUrl); |
|||
this.fixHTML(); |
|||
this.stripLongTemplates(); |
|||
} |
|||
/** |
|||
* @param {string} data |
|||
* @private |
|||
*/ |
|||
static esWiki2HtmlPart(data) { |
|||
const reLinks = /(?:\[\[([^\]|]*)(?:\|([^\]|]*))*]]([a-z]*))/gi; |
|||
reLinks.lastIndex = 0; |
|||
let match; |
|||
let result = ""; |
|||
let postfixIndex = 0; |
|||
while ((match = reLinks.exec(data)) !== null) { |
|||
var _match$; |
|||
result += "".concat(pg.escapeQuotesHTML(data.substring(postfixIndex, match.index)), '<a href="').concat(Insta.conf.paths.articles).concat(pg.escapeQuotesHTML(match[1]), '">').concat(pg.escapeQuotesHTML(((_match$ = match[2]) !== null && _match$ !== void 0 ? _match$ : match[1]) + match[3]), "</a>"); |
|||
postfixIndex = reLinks.lastIndex; |
|||
} |
|||
result += pg.escapeQuotesHTML(data.slice(Math.max(0, postfixIndex))); |
|||
return result; |
|||
} |
|||
editSummaryPreview() { |
|||
const reAes = /\/\* *(.*?) *\*\//g; |
|||
reAes.lastIndex = 0; |
|||
const match = reAes.exec(this.data); |
|||
if (match) { |
|||
const prefix = this.data.slice(0, Math.max(0, match.index - 1)); |
|||
const [, section] = match; |
|||
const postfix = this.data.slice(Math.max(0, reAes.lastIndex)); |
|||
let start = "<span class='autocomment'>"; |
|||
let end = "</span>"; |
|||
if (prefix.length > 0) { |
|||
start = "".concat(Previewmaker.esWiki2HtmlPart(prefix), " ").concat(start, "- "); |
|||
} |
|||
if (postfix.length > 0) { |
|||
end = ": ".concat(end).concat(Previewmaker.esWiki2HtmlPart(postfix)); |
|||
} |
|||
const t = new Title().fromURL(this.baseUrl); |
|||
t.anchorFromUtf(section); |
|||
const sectionLink = "".concat(Insta.conf.paths.articles + pg.escapeQuotesHTML(t.toString(true)), "#").concat(pg.escapeQuotesHTML(t.anchor)); |
|||
return "".concat(start, '<a href="').concat(sectionLink, '">→</a> ').concat(pg.escapeQuotesHTML(section)).concat(end); |
|||
} |
|||
return Previewmaker.esWiki2HtmlPart(this.data); |
|||
} |
|||
/** |
|||
* Works around livepreview bugs. |
|||
* |
|||
* @private |
|||
*/ |
|||
fixHTML() { |
|||
if (!this.html) { |
|||
return; |
|||
} |
|||
let ret = this.html; |
|||
ret = ret.replace(new RegExp('(<a href="'.concat(pg.wiki.articlePath, '/[^"]*)[?](.*?")'), "g"), "$1%3F$2"); |
|||
ret = ret.replace(new RegExp("(<a href='".concat(pg.wiki.articlePath, "/[^']*)[?](.*?')"), "g"), "$1%3F$2"); |
|||
this.html = ret; |
|||
} |
|||
/** |
|||
* Generates the preview and displays it in the current popup. |
|||
* Does nothing if the generated preview is invalid or consists of whitespace only. |
|||
* Also activates wikilinks in the preview for subpopups if the popupSubpopups option is true. |
|||
*/ |
|||
showPreview() { |
|||
this.makePreview(); |
|||
if (typeof this.html !== "string") { |
|||
return; |
|||
} |
|||
if (/^\s*$/.test(this.html)) { |
|||
return; |
|||
} |
|||
setPopupHTML("<hr>", "popupPrePreviewSep", this.owner.idNumber); |
|||
setPopupTipsAndHTML(this.html, "popupPreview", this.owner.idNumber, { |
|||
owner: this.owner |
|||
}); |
|||
const more = this.fullLength > this.data.length ? this.moreLink() : ""; |
|||
setPopupHTML(more, "popupPreviewMore", this.owner.idNumber); |
|||
} |
|||
/** |
|||
* @private |
|||
*/ |
|||
moreLink() { |
|||
const a = document.createElement("a"); |
|||
a.className = "popupMoreLink"; |
|||
a.innerHTML = popupString("more..."); |
|||
const self2 = this; |
|||
a.onclick = () => { |
|||
self2.maxCharacters += 2e3; |
|||
self2.maxSentences += 20; |
|||
self2.setData(); |
|||
self2.showPreview(); |
|||
}; |
|||
return a; |
|||
} |
|||
/** |
|||
* @private |
|||
*/ |
|||
stripLongTemplates() { |
|||
this.html = this.html.replace(/^.{0,1000}{{[^}]*?(<(p|br)( \/)?>\s*){2,}([^{}]*?}})?/gi, ""); |
|||
this.html = this.html.split("\n").join(" "); |
|||
this.html = this.html.replace(/{{[^}]*<pre>[^}]*}}/gi, ""); |
|||
} |
|||
/** |
|||
* @private |
|||
*/ |
|||
killMultilineTemplates() { |
|||
this.kill("{{{", "}}}"); |
|||
this.kill(/\s*{{[^{}]*\n/, "}}", "{{"); |
|||
} |
|||
} |
|||
const loadAPIPreview = (queryType, article, navpop) => { |
|||
const art = new Title(article).urlString(); |
|||
let url = "".concat(pg.wiki.apiwikibase, "?format=json&formatversion=2&action=query&"); |
|||
let htmlGenerator = () => { |
|||
void mw.notify("invalid html generator", { |
|||
tag: "popups", |
|||
type: "error" |
|||
}); |
|||
}; |
|||
let usernameart = ""; |
|||
switch (queryType) { |
|||
case "history": |
|||
url += "titles=".concat(art, "&prop=revisions&rvlimit=").concat(getValueOf("popupHistoryPreviewLimit")); |
|||
htmlGenerator = APIhistoryPreviewHTML; |
|||
break; |
|||
case "category": |
|||
url += "list=categorymembers&cmtitle=".concat(art); |
|||
htmlGenerator = APIcategoryPreviewHTML; |
|||
break; |
|||
case "userinfo": { |
|||
const username = new Title(article).userName(); |
|||
usernameart = encodeURIComponent(username); |
|||
url += pg.re.ipUser.test(username) ? "list=blocks&bkprop=range|restrictions&bkip=".concat(usernameart) : "list=users|usercontribs&usprop=blockinfo|groups|editcount|registration|gender&ususers=".concat(usernameart, "&meta=globaluserinfo&guiprop=groups|unattached&guiuser=").concat(usernameart, "&uclimit=1&ucprop=timestamp&ucuser=").concat(usernameart); |
|||
htmlGenerator = APIuserInfoPreviewHTML; |
|||
break; |
|||
} |
|||
case "contribs": |
|||
usernameart = encodeURIComponent(new Title(article).userName()); |
|||
url += "list=usercontribs&ucuser=".concat(usernameart, "&uclimit=").concat(getValueOf("popupContribsPreviewLimit")); |
|||
htmlGenerator = APIcontribsPreviewHTML; |
|||
break; |
|||
case "imagepagepreview": { |
|||
let trail = ""; |
|||
if (getValueOf("popupImageLinks")) { |
|||
trail = "&list=imageusage&iutitle=".concat(art); |
|||
} |
|||
url += "titles=".concat(art, "&prop=revisions|imageinfo&rvprop=content").concat(trail); |
|||
htmlGenerator = APIimagepagePreviewHTML; |
|||
break; |
|||
} |
|||
case "backlinks": |
|||
url += "list=backlinks&bltitle=".concat(art); |
|||
htmlGenerator = APIbacklinksPreviewHTML; |
|||
break; |
|||
case "revision": |
|||
url += article.oldid ? "revids=".concat(article.oldid) : "titles=".concat(article.removeAnchor().urlString()); |
|||
url += "&prop=revisions|pageprops|info|images|categories&rvprop=ids|timestamp|flags|comment|user|content&cllimit=max&imlimit=max"; |
|||
htmlGenerator = APIrevisionPreviewHTML; |
|||
break; |
|||
} |
|||
pendingNavpopTask(navpop); |
|||
const callback = (d) => { |
|||
log("callback of API functions was hit"); |
|||
if (queryType === "userinfo") { |
|||
fetchUserGroupNames(d.data).then(() => { |
|||
showAPIPreview(queryType, htmlGenerator(article, d, navpop), navpop.idNumber, navpop, d); |
|||
}); |
|||
return; |
|||
} |
|||
showAPIPreview(queryType, htmlGenerator(article, d, navpop), navpop.idNumber, navpop, d); |
|||
}; |
|||
const go = () => { |
|||
getPageWithCaching(url, callback, navpop); |
|||
return true; |
|||
}; |
|||
if (navpop.visible || !getValueOf("popupLazyDownloads")) { |
|||
go(); |
|||
} else { |
|||
navpop.addHook(go, "unhide", "before", "DOWNLOAD_".concat(queryType, "_QUERY_DATA")); |
|||
} |
|||
}; |
|||
const linkList = (list) => { |
|||
list.sort((x, y) => { |
|||
return x === y ? 0 : x < y ? -1 : 1; |
|||
}); |
|||
const buf = []; |
|||
var _iterator1 = _createForOfIteratorHelper(list), _step1; |
|||
try { |
|||
for (_iterator1.s(); !(_step1 = _iterator1.n()).done; ) { |
|||
const element = _step1.value; |
|||
buf.push(wikiLink({ |
|||
article: new Title(element), |
|||
text: element.split(" ").join(" "), |
|||
action: "view" |
|||
})); |
|||
} |
|||
} catch (err) { |
|||
_iterator1.e(err); |
|||
} finally { |
|||
_iterator1.f(); |
|||
} |
|||
return buf.join(", "); |
|||
}; |
|||
const getTimeOffset = () => { |
|||
const tz = mw.user.options.get("timecorrection"); |
|||
if (tz && tz.includes("|")) { |
|||
return Number.parseInt(tz.split("|")[1], 10); |
|||
} |
|||
return 0; |
|||
}; |
|||
const getTimeZone = () => { |
|||
if (!pg.user.timeZone) { |
|||
const tz = mw.user.options.get("timecorrection"); |
|||
pg.user.timeZone = "UTC"; |
|||
if (tz) { |
|||
const tzComponents = tz.split("|"); |
|||
if (tzComponents.length === 3 && tzComponents[0] === "ZoneInfo") { |
|||
[, , pg.user.timeZone] = tzComponents; |
|||
} else { |
|||
errlog("Unexpected timezone information: ".concat(tz)); |
|||
} |
|||
} |
|||
} |
|||
return pg.user.timeZone; |
|||
}; |
|||
const useTimeOffset = () => { |
|||
if (Intl.DateTimeFormat.prototype.formatToParts === void 0) { |
|||
return true; |
|||
} |
|||
const tz = mw.user.options.get("timecorrection"); |
|||
if (tz && !tz.includes("ZoneInfo|")) { |
|||
return true; |
|||
} |
|||
return false; |
|||
}; |
|||
const getLocales = () => { |
|||
if (!pg.user.locales) { |
|||
let userLanguage = document.querySelector("html").getAttribute("lang"); |
|||
if (getValueOf("popupLocale")) { |
|||
userLanguage = getValueOf("popupLocale"); |
|||
} else if (userLanguage === "en") { |
|||
userLanguage = getMWDateFormat() === "mdy" ? "en-US" : "en-GB"; |
|||
} |
|||
pg.user.locales = Intl.DateTimeFormat.supportedLocalesOf([userLanguage, navigator.language]); |
|||
} |
|||
return pg.user.locales; |
|||
}; |
|||
const getMWDateFormat = () => { |
|||
return mw.user.options.get("date"); |
|||
}; |
|||
const editPreviewTable = (article, h, reallyContribs) => { |
|||
let html = ["<table>"]; |
|||
let day; |
|||
let curart = article; |
|||
let page; |
|||
let makeFirstColumnLinks; |
|||
if (reallyContribs) { |
|||
makeFirstColumnLinks = (currentRevision) => { |
|||
let result = "("; |
|||
result += '<a href="'.concat(pg.wiki.titlebase).concat(new Title(currentRevision.title).urlString(), "&diff=prev&oldid=").concat(currentRevision.revid, '">').concat(popupString("diff"), "</a>"); |
|||
result += " | "; |
|||
result += '<a href="'.concat(pg.wiki.titlebase).concat(new Title(currentRevision.title).urlString(), '&action=history">').concat(popupString("hist"), "</a>"); |
|||
result += ")"; |
|||
return result; |
|||
}; |
|||
} else { |
|||
const firstRevid = h[0].revid; |
|||
makeFirstColumnLinks = (currentRevision) => { |
|||
let result = "("; |
|||
result += '<a href="'.concat(pg.wiki.titlebase).concat(new Title(curart).urlString(), "&diff=").concat(firstRevid, "&oldid=").concat(currentRevision.revid, '">').concat(popupString("cur"), "</a>"); |
|||
result += " | "; |
|||
result += '<a href="'.concat(pg.wiki.titlebase).concat(new Title(curart).urlString(), "&diff=prev&oldid=").concat(currentRevision.revid, '">').concat(popupString("last"), "</a>"); |
|||
result += ")"; |
|||
return result; |
|||
}; |
|||
} |
|||
var _iterator10 = _createForOfIteratorHelper(h.entries()), _step10; |
|||
try { |
|||
for (_iterator10.s(); !(_step10 = _iterator10.n()).done; ) { |
|||
const [i, element] = _step10.value; |
|||
if (reallyContribs) { |
|||
page = element.title; |
|||
curart = new Title(page); |
|||
} |
|||
const minor = element.minor ? "<b>m </b>" : ""; |
|||
const editDate = new Date(element.timestamp); |
|||
let thisDay = formattedDate(editDate); |
|||
const thisTime = formattedTime(editDate); |
|||
if (thisDay === day) { |
|||
thisDay = ""; |
|||
} else { |
|||
day = thisDay; |
|||
} |
|||
if (thisDay) { |
|||
html.push('<tr><td colspan=3><span class="popup_history_date">'.concat(thisDay, "</span></td></tr>")); |
|||
} |
|||
html.push('<tr class="popup_history_row_'.concat(i % 2 ? "odd" : "even", '">'), "<td>".concat(makeFirstColumnLinks(element), "</td>"), '<td><a href="'.concat(pg.wiki.titlebase).concat(new Title(curart).urlString(), "&oldid=").concat(element.revid, '">').concat(thisTime, "</a></td>")); |
|||
let col3url = ""; |
|||
let col3txt = ""; |
|||
if (reallyContribs) { |
|||
col3url = pg.wiki.titlebase + curart.urlString(); |
|||
col3txt = pg.escapeQuotesHTML(page); |
|||
} else { |
|||
const { |
|||
user |
|||
} = element; |
|||
if (element.userhidden) { |
|||
col3url = getValueOf("popupRevDelUrl"); |
|||
col3txt = pg.escapeQuotesHTML(popupString("revdel")); |
|||
} else { |
|||
col3url = pg.re.ipUser.test(user) ? "".concat(pg.wiki.titlebase + mw.config.get("wgFormattedNamespaces")[pg.nsSpecialId], ":Contributions&target=").concat(new Title(user).urlString()) : "".concat(pg.wiki.titlebase + mw.config.get("wgFormattedNamespaces")[pg.nsUserId], ":").concat(new Title(user).urlString()); |
|||
col3txt = pg.escapeQuotesHTML(user); |
|||
} |
|||
} |
|||
html.push("<td>".concat(reallyContribs ? minor : "", '<a href="').concat(col3url, '">').concat(col3txt, "</a></td>")); |
|||
let comment = ""; |
|||
const c = element.comment || element.content; |
|||
if (c) { |
|||
comment = new Previewmaker(c, new Title(curart).toUrl()).editSummaryPreview(); |
|||
} else if (element.commenthidden) { |
|||
comment = popupString("revdel"); |
|||
} |
|||
html.push("<td>".concat(reallyContribs ? "" : minor).concat(comment, "</td>"), "</tr>"); |
|||
html = [html.join("")]; |
|||
} |
|||
} catch (err) { |
|||
_iterator10.e(err); |
|||
} finally { |
|||
_iterator10.f(); |
|||
} |
|||
html.push("</table>"); |
|||
return html.join(""); |
|||
}; |
|||
const adjustDate = (d, offset) => { |
|||
const o = offset * 60 * 1e3; |
|||
return new Date(+d + o); |
|||
}; |
|||
const convertTimeZone = (date, timeZone) => { |
|||
return new Date(date.toLocaleString("en-US", { |
|||
timeZone |
|||
})); |
|||
}; |
|||
const formattedDateTime = (date) => { |
|||
if (useTimeOffset()) { |
|||
return "".concat(formattedDate(date), " ").concat(formattedTime(date)); |
|||
} |
|||
if (getMWDateFormat() === "ISO 8601") { |
|||
const d2 = convertTimeZone(date, getTimeZone()); |
|||
return "".concat(map(zeroFill, [d2.getFullYear(), d2.getMonth() + 1, d2.getDate()]).join("-"), "T").concat(map(zeroFill, [d2.getHours(), d2.getMinutes(), d2.getSeconds()]).join(":")); |
|||
} |
|||
const options = getValueOf("popupDateTimeFormatterOptions"); |
|||
options.timeZone = getTimeZone(); |
|||
return date.toLocaleString(getLocales(), options); |
|||
}; |
|||
const formattedDate = (date) => { |
|||
let d2; |
|||
if (useTimeOffset()) { |
|||
d2 = adjustDate(date, getTimeOffset()); |
|||
return map(zeroFill, [d2.getUTCFullYear(), d2.getUTCMonth() + 1, d2.getUTCDate()]).join("-"); |
|||
} |
|||
if (getMWDateFormat() === "ISO 8601") { |
|||
d2 = convertTimeZone(date, getTimeZone()); |
|||
return map(zeroFill, [d2.getFullYear(), d2.getMonth() + 1, d2.getDate()]).join("-"); |
|||
} |
|||
const options = getValueOf("popupDateFormatterOptions"); |
|||
options.timeZone = getTimeZone(); |
|||
return date.toLocaleDateString(getLocales(), options); |
|||
}; |
|||
const formattedTime = (date) => { |
|||
let d2; |
|||
if (useTimeOffset()) { |
|||
d2 = adjustDate(date, getTimeOffset()); |
|||
return map(zeroFill, [d2.getUTCHours(), d2.getUTCMinutes(), d2.getUTCSeconds()]).join(":"); |
|||
} |
|||
if (getMWDateFormat() === "ISO 8601") { |
|||
d2 = convertTimeZone(date, getTimeZone()); |
|||
return map(zeroFill, [d2.getHours(), d2.getMinutes(), d2.getSeconds()]).join(":"); |
|||
} |
|||
const options = getValueOf("popupTimeFormatterOptions"); |
|||
options.timeZone = getTimeZone(); |
|||
return date.toLocaleTimeString(getLocales(), options); |
|||
}; |
|||
const fetchUserGroupNames = (userinfoResponse) => { |
|||
const queryObj = getJsObj(userinfoResponse).query; |
|||
const user = anyChild(queryObj.users); |
|||
const messages = []; |
|||
if (user.groups) { |
|||
var _iterator11 = _createForOfIteratorHelper(user.groups), _step11; |
|||
try { |
|||
for (_iterator11.s(); !(_step11 = _iterator11.n()).done; ) { |
|||
const groupName = _step11.value; |
|||
if (!["*", "user", "autoconfirmed"].includes(groupName)) { |
|||
messages.push("group-".concat(groupName, "-member")); |
|||
} |
|||
} |
|||
} catch (err) { |
|||
_iterator11.e(err); |
|||
} finally { |
|||
_iterator11.f(); |
|||
} |
|||
} |
|||
if (queryObj.globaluserinfo && queryObj.globaluserinfo.groups) { |
|||
var _iterator12 = _createForOfIteratorHelper(queryObj.globaluserinfo.groups), _step12; |
|||
try { |
|||
for (_iterator12.s(); !(_step12 = _iterator12.n()).done; ) { |
|||
const groupName = _step12.value; |
|||
messages.push("group-".concat(groupName, "-member")); |
|||
} |
|||
} catch (err) { |
|||
_iterator12.e(err); |
|||
} finally { |
|||
_iterator12.f(); |
|||
} |
|||
} |
|||
return getMwApi().loadMessagesIfMissing(messages); |
|||
}; |
|||
const showAPIPreview = (queryType, html, id, navpop, download) => { |
|||
let target = "popupPreview"; |
|||
completedNavpopTask(navpop); |
|||
switch (queryType) { |
|||
case "imagelinks": |
|||
case "category": |
|||
target = "popupPostPreview"; |
|||
break; |
|||
case "userinfo": |
|||
target = "popupUserData"; |
|||
break; |
|||
case "revision": |
|||
insertPreview(download); |
|||
return; |
|||
} |
|||
setPopupTipsAndHTML(html, target, id); |
|||
}; |
|||
const APIrevisionPreviewHTML = (_article, download) => { |
|||
try { |
|||
const jsObj = getJsObj(download.data); |
|||
const page = anyChild(jsObj.query.pages); |
|||
if (page.missing) { |
|||
download.owner = null; |
|||
return; |
|||
} |
|||
const content = page && page.revisions && page.revisions[0] && page.revisions[0].content ? page.revisions[0].content : null; |
|||
if (typeof content === "string") { |
|||
download.data = content; |
|||
download.lastModified = new Date(page.revisions[0].timestamp); |
|||
} |
|||
} catch { |
|||
return "Revision preview failed :("; |
|||
} |
|||
}; |
|||
const APIbacklinksPreviewHTML = (_article, download) => { |
|||
try { |
|||
const jsObj = getJsObj(download.data); |
|||
const list = jsObj.query.backlinks; |
|||
let html = []; |
|||
if (!list) { |
|||
return popupString("No backlinks found"); |
|||
} |
|||
var _iterator13 = _createForOfIteratorHelper(list), _step13; |
|||
try { |
|||
for (_iterator13.s(); !(_step13 = _iterator13.n()).done; ) { |
|||
const element = _step13.value; |
|||
const t = new Title(element.title); |
|||
html.push('<a href="'.concat(pg.wiki.titlebase).concat(t.urlString(), '">').concat(t.toString().entify(), "</a>")); |
|||
} |
|||
} catch (err) { |
|||
_iterator13.e(err); |
|||
} finally { |
|||
_iterator13.f(); |
|||
} |
|||
html = html.join(", "); |
|||
if (jsObj.continue && jsObj.continue.blcontinue) { |
|||
html += popupString(" and more"); |
|||
} |
|||
return html; |
|||
} catch { |
|||
return "backlinksPreviewHTML went wonky"; |
|||
} |
|||
}; |
|||
pg.fn.APIsharedImagePagePreviewHTML = (obj) => { |
|||
log("APIsharedImagePagePreviewHTML"); |
|||
const popupid = obj.requestid; |
|||
if (obj.query && obj.query.pages) { |
|||
const page = anyChild(obj.query.pages); |
|||
const content = page && page.revisions && page.revisions[0].contentmodel === "wikitext" ? page.revisions[0].content : null; |
|||
if (typeof content === "string" && pg && pg.current && pg.current.link && pg.current.link.navpopup) { |
|||
const p = new Previewmaker(content, pg.current.link.navpopup.article, pg.current.link.navpopup); |
|||
p.makePreview(); |
|||
setPopupHTML(p.html, "popupSecondPreview", popupid); |
|||
} |
|||
} |
|||
}; |
|||
const APIimagepagePreviewHTML = (article, download, navpop) => { |
|||
try { |
|||
const jsObj = getJsObj(download.data); |
|||
const page = anyChild(jsObj.query.pages); |
|||
const content = page && page.revisions && page.revisions[0].contentmodel === "wikitext" ? page.revisions[0].content : null; |
|||
let ret = ""; |
|||
let alt = ""; |
|||
try { |
|||
[{ |
|||
alt |
|||
}] = navpop.parentAnchor.childNodes; |
|||
} catch { |
|||
} |
|||
if (alt) { |
|||
ret = "".concat(ret, "<hr><b>").concat(popupString("Alt text:"), "</b> ").concat(pg.escapeQuotesHTML(alt)); |
|||
} |
|||
if (typeof content === "string") { |
|||
const p = prepPreviewmaker(content, article, navpop); |
|||
p.makePreview(); |
|||
if (p.html) { |
|||
ret += "<hr>".concat(p.html); |
|||
} |
|||
if (getValueOf("popupSummaryData")) { |
|||
const info = getPageInfo(content, download); |
|||
log(info); |
|||
setPopupTrailer(info, navpop.idNumber); |
|||
} |
|||
} |
|||
if (page && page.imagerepository === "shared") { |
|||
const art = new Title(article); |
|||
const encart = encodeURIComponent("File:".concat(art.stripNamespace())); |
|||
const shared_url = "".concat(pg.wiki.apicommonsbase, "?format=json&formatversion=2&callback=pg.fn.APIsharedImagePagePreviewHTML&requestid=").concat(navpop.idNumber, "&action=query&prop=revisions&rvprop=content&titles=").concat(encart); |
|||
ret = "".concat(ret, "<hr>").concat(popupString("Image from Commons"), ': <a href="').concat(pg.wiki.commonsbase, "?title=").concat(encart, '">').concat(popupString("Description page"), "</a>"); |
|||
mw.loader.load(shared_url); |
|||
} |
|||
showAPIPreview("imagelinks", APIimagelinksPreviewHTML(article, download), navpop.idNumber, download); |
|||
return ret; |
|||
} catch { |
|||
return "API imagepage preview failed :("; |
|||
} |
|||
}; |
|||
const APIimagelinksPreviewHTML = (_article, download) => { |
|||
try { |
|||
const jsobj = getJsObj(download.data); |
|||
const list = jsobj.query.imageusage; |
|||
if (list) { |
|||
const ret = []; |
|||
var _iterator14 = _createForOfIteratorHelper(list), _step14; |
|||
try { |
|||
for (_iterator14.s(); !(_step14 = _iterator14.n()).done; ) { |
|||
const element = _step14.value; |
|||
ret.push(element.title); |
|||
} |
|||
} catch (err) { |
|||
_iterator14.e(err); |
|||
} finally { |
|||
_iterator14.f(); |
|||
} |
|||
if (ret.length === 0) { |
|||
return popupString("No image links found"); |
|||
} |
|||
return "<h2>".concat(popupString("File links"), "</h2>").concat(linkList(ret)); |
|||
} |
|||
return popupString("No image links found"); |
|||
} catch { |
|||
return "Image links preview generation failed :("; |
|||
} |
|||
}; |
|||
const APIcategoryPreviewHTML = (_article, download) => { |
|||
try { |
|||
const jsobj = getJsObj(download.data); |
|||
const list = jsobj.query.categorymembers; |
|||
let ret = []; |
|||
var _iterator15 = _createForOfIteratorHelper(list), _step15; |
|||
try { |
|||
for (_iterator15.s(); !(_step15 = _iterator15.n()).done; ) { |
|||
const element = _step15.value; |
|||
ret.push(element.title); |
|||
} |
|||
} catch (err) { |
|||
_iterator15.e(err); |
|||
} finally { |
|||
_iterator15.f(); |
|||
} |
|||
if (ret.length === 0) { |
|||
return popupString("Empty category"); |
|||
} |
|||
ret = "<h2>".concat(tprintf("Category members (%s shown)", [ret.length]), "</h2>").concat(linkList(ret)); |
|||
if (jsobj.continue && jsobj.continue.cmcontinue) { |
|||
ret += popupString(" and more"); |
|||
} |
|||
return ret; |
|||
} catch { |
|||
return "Category preview failed :("; |
|||
} |
|||
}; |
|||
const APIuserInfoPreviewHTML = (_article, download) => { |
|||
let ret = []; |
|||
let queryobj = {}; |
|||
try { |
|||
queryobj = getJsObj(download.data).query; |
|||
} catch { |
|||
return "Userinfo preview failed :("; |
|||
} |
|||
const user = anyChild(queryobj.users); |
|||
if (user) { |
|||
const { |
|||
globaluserinfo |
|||
} = queryobj; |
|||
if (user.invalid === "") { |
|||
ret.push(popupString("Invalid user")); |
|||
} else if (user.missing === "") { |
|||
ret.push(popupString("Not a registered username")); |
|||
} |
|||
if (user.blockedby) { |
|||
if (user.blockpartial) { |
|||
ret.push("<b>".concat(popupString("Has blocks"), "</b>")); |
|||
} else { |
|||
ret.push("<b>".concat(popupString("BLOCKED"), "</b>")); |
|||
} |
|||
} |
|||
if (globaluserinfo && ("locked" in globaluserinfo || "hidden" in globaluserinfo)) { |
|||
let lockedSulAccountIsAttachedToThis = true; |
|||
for (let i = 0; globaluserinfo.unattached && i < globaluserinfo.unattached.length; i++) { |
|||
if (globaluserinfo.unattached[i].wiki === mw.config.get("wgDBname")) { |
|||
lockedSulAccountIsAttachedToThis = false; |
|||
break; |
|||
} |
|||
} |
|||
if (lockedSulAccountIsAttachedToThis) { |
|||
if ("locked" in globaluserinfo) { |
|||
ret.push("<b><i>".concat(popupString("LOCKED"), "</i></b>")); |
|||
} |
|||
if ("hidden" in globaluserinfo) { |
|||
ret.push("<b><i>".concat(popupString("HIDDEN"), "</i></b>")); |
|||
} |
|||
} |
|||
} |
|||
if (getValueOf("popupShowGender") && user.gender) { |
|||
switch (user.gender) { |
|||
case "male": |
|||
ret.push("".concat(popupString("he/him"), " · ")); |
|||
break; |
|||
case "female": |
|||
ret.push("".concat(popupString("she/her"), " · ")); |
|||
break; |
|||
} |
|||
} |
|||
if (user.groups) { |
|||
var _iterator16 = _createForOfIteratorHelper(user.groups), _step16; |
|||
try { |
|||
for (_iterator16.s(); !(_step16 = _iterator16.n()).done; ) { |
|||
const groupName = _step16.value; |
|||
if (!["*", "user", "autoconfirmed"].includes(groupName)) { |
|||
ret.push(pg.escapeQuotesHTML(mw.message("group-".concat(groupName, "-member"), user.gender).text())); |
|||
} |
|||
} |
|||
} catch (err) { |
|||
_iterator16.e(err); |
|||
} finally { |
|||
_iterator16.f(); |
|||
} |
|||
} |
|||
if (globaluserinfo && globaluserinfo.groups) { |
|||
var _iterator17 = _createForOfIteratorHelper(globaluserinfo.groups), _step17; |
|||
try { |
|||
for (_iterator17.s(); !(_step17 = _iterator17.n()).done; ) { |
|||
const groupName = _step17.value; |
|||
ret.push( |
|||
// Messages that can be used here: |
|||
// * see [[Special:PrefixIndex/MediaWiki:Group-]] |
|||
// * for more information |
|||
"<i>".concat(pg.escapeQuotesHTML(mw.message("group-".concat(groupName, "-member"), user.gender).text()), "</i>") |
|||
); |
|||
} |
|||
} catch (err) { |
|||
_iterator17.e(err); |
|||
} finally { |
|||
_iterator17.f(); |
|||
} |
|||
} |
|||
if (user.registration) { |
|||
var _user$editcount; |
|||
ret.push(pg.escapeQuotesHTML(((_user$editcount = user.editcount) !== null && _user$editcount !== void 0 ? _user$editcount : "0") + popupString(" edits since: ") + (user.registration ? formattedDate(new Date(user.registration)) : ""))); |
|||
} |
|||
} |
|||
if (queryobj.usercontribs && queryobj.usercontribs.length > 0) { |
|||
ret.push(popupString("last edit on ") + formattedDate(new Date(queryobj.usercontribs[0].timestamp))); |
|||
} |
|||
if (queryobj.blocks) { |
|||
ret.push(popupString("IP user")); |
|||
for (let l = 0; l < queryobj.blocks.length; l++) { |
|||
let rbstr = queryobj.blocks[l].rangestart === queryobj.blocks[l].rangeend ? "BLOCK" : "RANGEBLOCK"; |
|||
rbstr = Array.isArray(queryobj.blocks[l].restrictions) ? "".concat(rbstr, "ED") : "Has ".concat(rbstr.toLowerCase(), "s"); |
|||
ret.push("<b>".concat(popupString(rbstr), "</b>")); |
|||
} |
|||
} |
|||
for (let m = 0; m < ret.length - 1; m++) { |
|||
if (ret[m].length > 3 && ret[m].slice(Math.max(0, ret[m].length - 3)) === " · ") { |
|||
ret[m] += ret[m + 1]; |
|||
ret.splice(m + 1, 1); |
|||
m--; |
|||
} |
|||
} |
|||
ret = "<hr>".concat(ret.join(", ")); |
|||
return ret; |
|||
}; |
|||
const APIcontribsPreviewHTML = (article, download, navpop) => { |
|||
return APIhistoryPreviewHTML(article, download, navpop, true); |
|||
}; |
|||
const APIhistoryPreviewHTML = (article, download, _navpop, reallyContribs) => { |
|||
try { |
|||
const jsobj = getJsObj(download.data); |
|||
let edits = []; |
|||
edits = reallyContribs ? jsobj.query.usercontribs : anyChild(jsobj.query.pages).revisions; |
|||
const ret = editPreviewTable(article, edits, reallyContribs); |
|||
return ret; |
|||
} catch { |
|||
return "History preview failed :-("; |
|||
} |
|||
}; |
|||
const setupDebugging = () => { |
|||
if (window.popupDebug) { |
|||
window.log = (x) => { |
|||
console.log(x); |
|||
}; |
|||
window.errlog = (x) => { |
|||
console.error("[Popups] ".concat(x)); |
|||
}; |
|||
log("Initializing logger"); |
|||
} else { |
|||
window.log = () => { |
|||
}; |
|||
window.errlog = () => { |
|||
}; |
|||
} |
|||
}; |
|||
const loadImage = (image, navpop) => { |
|||
if (typeof image.stripNamespace !== "function") { |
|||
void mw.notify("loadImages bad", { |
|||
tag: "popups", |
|||
type: "error" |
|||
}); |
|||
} |
|||
if (!getValueOf("popupImages")) { |
|||
return; |
|||
} |
|||
if (!isValidImageName(image.toString())) { |
|||
return false; |
|||
} |
|||
const art = image.urlString(); |
|||
let url = "".concat(pg.wiki.apiwikibase, "?format=json&formatversion=2&action=query"); |
|||
url += "&prop=imageinfo&iiprop=url|mime&iiurlwidth=".concat(getValueOf("popupImageSizeLarge")); |
|||
url += "&titles=".concat(art); |
|||
pendingNavpopTask(navpop); |
|||
const callback = (d) => { |
|||
popupsInsertImage(navpop.idNumber, navpop, d); |
|||
}; |
|||
const go = () => { |
|||
getPageWithCaching(url, callback, navpop); |
|||
return true; |
|||
}; |
|||
if (navpop.visible || !getValueOf("popupLazyDownloads")) { |
|||
go(); |
|||
} else { |
|||
navpop.addHook(go, "unhide", "after", "DOWNLOAD_IMAGE_QUERY_DATA"); |
|||
} |
|||
}; |
|||
const popupsInsertImage = (id, _navpop, download) => { |
|||
log("popupsInsertImage"); |
|||
let imageinfo; |
|||
try { |
|||
const jsObj = getJsObj(download.data); |
|||
const imagepage = anyChild(jsObj.query.pages); |
|||
if (imagepage.imageinfo === void 0) { |
|||
return; |
|||
} |
|||
[imageinfo] = imagepage.imageinfo; |
|||
} catch { |
|||
log("popupsInsertImage failed :("); |
|||
return; |
|||
} |
|||
const popupImage = document.querySelector("#popupImg".concat(id)); |
|||
if (!popupImage) { |
|||
log("could not find insertion point for image"); |
|||
return; |
|||
} |
|||
popupImage.width = getValueOf("popupImageSize"); |
|||
popupImage.style.display = "inline"; |
|||
if (imageinfo.thumburl) { |
|||
popupImage.src = imageinfo.thumburl; |
|||
} else if (imageinfo.mime.indexOf("image") === 0) { |
|||
popupImage.src = imageinfo.url; |
|||
log("a thumb could not be found, using original image"); |
|||
} else { |
|||
log("fullsize imagethumb, but not sure if it's an image"); |
|||
} |
|||
const a = document.querySelector("#popupImageLink".concat(id)); |
|||
if (a === null) { |
|||
return null; |
|||
} |
|||
switch (getValueOf("popupThumbAction")) { |
|||
case "imagepage": |
|||
if (pg.current.article.namespaceId() !== pg.nsImageId) { |
|||
a.href = imageinfo.descriptionurl; |
|||
popTipsSoonFn("popupImage".concat(id))(); |
|||
break; |
|||
} |
|||
/* falls through */ |
|||
case "sizetoggle": |
|||
a.onclick = toggleSize; |
|||
a.title = popupString("Toggle image size"); |
|||
return; |
|||
case "linkfull": |
|||
a.href = imageinfo.url; |
|||
a.title = popupString("Open full-size image"); |
|||
} |
|||
}; |
|||
const toggleSize = function toggleSize2() { |
|||
const self2 = this; |
|||
if (!self2) { |
|||
void mw.notify("self is null :/", { |
|||
tag: "popups", |
|||
type: "error" |
|||
}); |
|||
return; |
|||
} |
|||
const img = self2.firstChild; |
|||
if (!img) { |
|||
void mw.notify("img is null :/", { |
|||
tag: "popups", |
|||
type: "error" |
|||
}); |
|||
return; |
|||
} |
|||
img.style.width = !img.style.width || img.style.width === "" ? "100%" : ""; |
|||
}; |
|||
const getValidImageFromWikiText = (wikiText) => { |
|||
let matched; |
|||
let match; |
|||
const t = removeMatchesUnless(wikiText, /(<!--[\S\s]*?-->)/, 1, /^<!--[^[]*popup/i); |
|||
while ((match = pg.re.image.exec(t)) !== null) { |
|||
const m = match[2] || match[6]; |
|||
if (isValidImageName(m)) { |
|||
matched = m; |
|||
break; |
|||
} |
|||
} |
|||
pg.re.image.lastIndex = 0; |
|||
if (!matched) { |
|||
return null; |
|||
} |
|||
return "".concat(mw.config.get("wgFormattedNamespaces")[pg.nsImageId], ":").concat(upcaseFirst(matched)); |
|||
}; |
|||
const removeMatchesUnless = (str, re1, parencount, re2) => { |
|||
const split = str.split(re1); |
|||
const c = parencount + 1; |
|||
for (let i = 0; i < split.length; ++i) { |
|||
if (i % c === 0 || re2.test(split[i])) { |
|||
continue; |
|||
} |
|||
split[i] = ""; |
|||
} |
|||
return split.join(""); |
|||
}; |
|||
const setNamespaces = () => { |
|||
pg.nsSpecialId = -1; |
|||
pg.nsMainspaceId = 0; |
|||
pg.nsImageId = 6; |
|||
pg.nsUserId = 2; |
|||
pg.nsUsertalkId = 3; |
|||
pg.nsCategoryId = 14; |
|||
pg.nsTemplateId = 10; |
|||
}; |
|||
const setRedirs = () => { |
|||
const r = "redirect"; |
|||
const R = "REDIRECT"; |
|||
const redirLists = { |
|||
ar: [R, "تحويل"], |
|||
be: [r, "перанакіраваньне"], |
|||
bg: [r, "пренасочване", "виж"], |
|||
bs: [r, "Preusmjeri", "preusmjeri", "PREUSMJERI"], |
|||
bn: [R, "পুনর্নির্দেশ"], |
|||
cs: [R, "PŘESMĚRUJ"], |
|||
cy: [r, "ail-cyfeirio"], |
|||
de: [R, "WEITERLEITUNG"], |
|||
el: [R, "ΑΝΑΚΑΤΕΥΘΥΝΣΗ"], |
|||
eo: [R, "ALIDIREKTU", "ALIDIREKTI"], |
|||
es: [R, "REDIRECCIÓN"], |
|||
et: [r, "suuna"], |
|||
ga: [r, "athsheoladh"], |
|||
gl: [r, "REDIRECCIÓN", "REDIRECIONAMENTO"], |
|||
he: [R, "הפניה"], |
|||
hu: [R, "ÁTIRÁNYÍTÁS"], |
|||
is: [r, "tilvísun", "TILVÍSUN"], |
|||
it: [R, "RINVIA", "Rinvia"], |
|||
ja: [R, "転送"], |
|||
mk: [r, "пренасочување", "види"], |
|||
nds: [r, "wiederleiden"], |
|||
"nds-nl": [R, "DEURVERWIEZING", "DUURVERWIEZING"], |
|||
nl: [R, "DOORVERWIJZING"], |
|||
nn: [r, "omdiriger"], |
|||
pl: [R, "PATRZ", "PRZEKIERUJ", "TAM"], |
|||
pt: [R, "redir"], |
|||
ru: [R, "ПЕРЕНАПРАВЛЕНИЕ", "ПЕРЕНАПР"], |
|||
sk: [r, "presmeruj"], |
|||
sr: [r, "Преусмери", "преусмери", "ПРЕУСМЕРИ", "Preusmeri", "preusmeri", "PREUSMERI"], |
|||
tt: [R, "yünältü", "перенаправление", "перенапр"], |
|||
uk: [R, "ПЕРЕНАПРАВЛЕННЯ", "ПЕРЕНАПР"], |
|||
vi: [r, "đổi"], |
|||
yi: [R, "ווייטערפירן"], |
|||
zh: [R, "重定向"] |
|||
// no comma |
|||
}; |
|||
const redirList = redirLists[pg.wiki.lang] || [r, R]; |
|||
pg.re.redirect = new RegExp("^\\s*[#](".concat(redirList.join("|"), ").*?\\[{2}([^\\|\\]]*)(|[^\\]]*)?\\]{2}\\s*(.*)"), "i"); |
|||
}; |
|||
const setInterwiki = () => { |
|||
if (pg.wiki.wikimedia) { |
|||
pg.wiki.interwiki = "aa|ab|ace|af|ak|als|am|an|ang|ar|arc|arz|as|ast|av|ay|az|ba|bar|bat-smg|bcl|be|be-x-old|bg|bh|bi|bjn|bm|bn|bo|bpy|br|bs|bug|bxr|ca|cbk-zam|cdo|ce|ceb|ch|cho|chr|chy|ckb|co|cr|crh|cs|csb|cu|cv|cy|da|de|diq|dsb|dv|dz|ee|el|eml|en|eo|es|et|eu|ext|fa|ff|fi|fiu-vro|fj|fo|fr|frp|frr|fur|fy|ga|gag|gan|gd|gl|glk|gn|got|gu|gv|ha|hak|haw|he|hi|hif|ho|hr|hsb|ht|hu|hy|hz|ia|id|ie|ig|ii|ik|ilo|io|is|it|iu|ja|jbo|jv|ka|kaa|kab|kbd|kg|ki|kj|kk|kl|km|kn|ko|koi|kr|krc|ks|ksh|ku|kv|kw|ky|la|lad|lb|lbe|lg|li|lij|lmo|ln|lo|lt|ltg|lv|map-bms|mdf|mg|mh|mhr|mi|mk|ml|mn|mo|mr|mrj|ms|mt|mus|mwl|my|myv|mzn|na|nah|nap|nds|nds-nl|ne|new|ng|nl|nn|no|nov|nrm|nv|ny|oc|om|or|os|pa|pag|pam|pap|pcd|pdc|pfl|pi|pih|pl|pms|pnb|pnt|ps|pt|qu|rm|rmy|rn|ro|roa-rup|roa-tara|ru|rue|rw|sa|sah|sc|scn|sco|sd|se|sg|sh|si|simple|sk|sl|sm|sn|so|sq|sr|srn|ss|st|stq|su|sv|sw|szl|ta|te|tet|tg|th|ti|tk|tl|tn|to|tpi|tr|ts|tt|tum|tw|ty|udm|ug|uk|ur|uz|ve|vec|vi|vls|vo|wa|war|wo|wuu|xal|xh|yi|yo|za|zea|zh|zh-classical|zh-min-nan|zh-yue|zu"; |
|||
pg.re.interwiki = new RegExp("^".concat(pg.wiki.interwiki, ":")); |
|||
} else { |
|||
pg.wiki.interwiki = null; |
|||
pg.re.interwiki = /^$/; |
|||
} |
|||
}; |
|||
const nsRe = (namespaceId) => { |
|||
const imageNamespaceVariants = []; |
|||
for (var _i2 = 0, _Object$entries2 = Object.entries(mw.config.get("wgNamespaceIds")); _i2 < _Object$entries2.length; _i2++) { |
|||
const [_localizedNamespaceLc, _namespaceId] = _Object$entries2[_i2]; |
|||
if (_namespaceId !== namespaceId) { |
|||
continue; |
|||
} |
|||
const localizedNamespaceLc = upcaseFirst(_localizedNamespaceLc); |
|||
imageNamespaceVariants.push(mw.util.escapeRegExp(localizedNamespaceLc).split(" ").join("[ _]"), mw.util.escapeRegExp(encodeURI(localizedNamespaceLc))); |
|||
} |
|||
return "(?:".concat(imageNamespaceVariants.join("|"), ")"); |
|||
}; |
|||
const nsReImage = () => { |
|||
return nsRe(pg.nsImageId); |
|||
}; |
|||
const getEditboxSelection = () => { |
|||
let editbox; |
|||
try { |
|||
editbox = document.editform.wpTextbox1; |
|||
} catch { |
|||
return; |
|||
} |
|||
if (document.selection) { |
|||
return document.selection.createRange().text; |
|||
} |
|||
const selStart = editbox.selectionStart; |
|||
const selEnd = editbox.selectionEnd; |
|||
return editbox.value.substring(selStart, selEnd); |
|||
}; |
|||
const doSelectionPopup = () => { |
|||
const sel = getEditboxSelection(); |
|||
const open = sel.indexOf("[["); |
|||
const pipe = sel.indexOf("|"); |
|||
const close = sel.indexOf("]]"); |
|||
if (open === -1 || pipe === -1 && close === -1) { |
|||
return; |
|||
} |
|||
if (pipe !== -1 && open > pipe || close !== -1 && open > close) { |
|||
return; |
|||
} |
|||
const article = new Title(sel.substring(open + 2, pipe < 0 ? close : pipe)); |
|||
if (getValueOf("popupOnEditSelection") === "boxpreview") { |
|||
return doSeparateSelectionPopup(sel, article); |
|||
} |
|||
if (close > 0 && sel.slice(Math.max(0, close + 2)).includes("[[")) { |
|||
return; |
|||
} |
|||
const a = document.createElement("a"); |
|||
a.href = pg.wiki.titlebase + article.urlString(); |
|||
mouseOverWikiLink2(a); |
|||
if (a.navpopup) { |
|||
a.navpopup.addHook(() => { |
|||
runStopPopupTimer(a.navpopup); |
|||
}, "unhide", "after"); |
|||
} |
|||
}; |
|||
const doSeparateSelectionPopup = (str, article) => { |
|||
let div = document.querySelector("#selectionPreview"); |
|||
if (!div) { |
|||
div = document.createElement("div"); |
|||
div.id = "selectionPreview"; |
|||
try { |
|||
const box = document.editform.wpTextbox1; |
|||
box.parentNode.insertBefore(div, box); |
|||
} catch { |
|||
return; |
|||
} |
|||
} |
|||
const p = prepPreviewmaker(str, article, newNavpopup(document.createElement("a"), article)); |
|||
p.makePreview(); |
|||
if (p.html) { |
|||
div.innerHTML = p.html; |
|||
} |
|||
div.ranSetupTooltipsAlready = false; |
|||
popTipsSoonFn("selectionPreview")(); |
|||
}; |
|||
class Mousetracker { |
|||
constructor() { |
|||
this.loopDelay = 400; |
|||
this.timer = null; |
|||
this.active = false; |
|||
this.dirty = true; |
|||
this.hooks = []; |
|||
} |
|||
/** |
|||
* Adds a hook, to be called when we get events. |
|||
* |
|||
* @param {Function} f A function which is called as |
|||
* <code>f(x,y)</code>. It should return <code>true</code> when it |
|||
* wants to be removed, and <code>false</code> otherwise. |
|||
*/ |
|||
addHook(f) { |
|||
this.hooks.push(f); |
|||
} |
|||
/** |
|||
* Runs hooks, passing them the x |
|||
* and y coords of the mouse. Hook functions that return true are |
|||
* passed to {@source Mousetracker#removeHooks} for removal. |
|||
* |
|||
* @private |
|||
*/ |
|||
runHooks() { |
|||
if (!this.hooks || this.hooks.length === 0) { |
|||
return; |
|||
} |
|||
let remove = false; |
|||
const removeObj = {}; |
|||
const { |
|||
x |
|||
} = this; |
|||
const { |
|||
y |
|||
} = this; |
|||
const len = this.hooks.length; |
|||
for (let i = 0; i < len; ++i) { |
|||
if (this.hooks[i](x, y) === true) { |
|||
remove = true; |
|||
removeObj[i] = true; |
|||
} |
|||
} |
|||
if (remove) { |
|||
this.removeHooks(removeObj); |
|||
} |
|||
} |
|||
/** |
|||
* Removes hooks. |
|||
* |
|||
* @private |
|||
* @param {Object} removeObj An object whose keys are the index |
|||
* numbers of functions for removal, with values that evaluate to true |
|||
*/ |
|||
removeHooks(removeObj) { |
|||
const newHooks = []; |
|||
const len = this.hooks.length; |
|||
for (let i = 0; i < len; ++i) { |
|||
if (!removeObj[i]) { |
|||
newHooks.push(this.hooks[i]); |
|||
} |
|||
} |
|||
this.hooks = newHooks; |
|||
} |
|||
/** |
|||
* Event listener for mouse wiggles. |
|||
* We simply grab the event, set x and y and run the hooks. |
|||
* This makes the cpu all hot and bothered :-( |
|||
* |
|||
* @private |
|||
* @param {Event} e Mousemove event |
|||
*/ |
|||
track(e) { |
|||
e || (e = window.event); |
|||
let x; |
|||
let y; |
|||
if (e) { |
|||
if (e.pageX) { |
|||
x = e.pageX; |
|||
y = e.pageY; |
|||
} else if (e.clientX === void 0) { |
|||
return; |
|||
} else { |
|||
let left; |
|||
let top; |
|||
const docElt = document.documentElement; |
|||
if (docElt) { |
|||
left = docElt.scrollLeft; |
|||
} |
|||
left || (left = document.querySelector("body").scrollLeft || document.scrollLeft || 0); |
|||
if (docElt) { |
|||
top = docElt.scrollTop; |
|||
} |
|||
top || (top = document.querySelector("body").scrollTop || document.scrollTop || 0); |
|||
x = e.clientX + left; |
|||
y = e.clientY + top; |
|||
} |
|||
this.setPosition(x, y); |
|||
} |
|||
} |
|||
/** |
|||
* Sets the x and y coordinates stored and takes appropriate action, |
|||
* running hooks as appropriate. |
|||
* |
|||
* @param {Integer} x, y Screen coordinates to set |
|||
* @param {number} x |
|||
* @param {number} y |
|||
*/ |
|||
setPosition(x, y) { |
|||
this.x = x; |
|||
this.y = y; |
|||
if (this.dirty || this.hooks.length === 0) { |
|||
this.dirty = false; |
|||
return; |
|||
} |
|||
if (typeof this.lastHook_x !== "number") { |
|||
this.lastHook_x = -100; |
|||
this.lastHook_y = -100; |
|||
} |
|||
let diff2 = (this.lastHook_x - x) * (this.lastHook_y - y); |
|||
diff2 = diff2 >= 0 ? diff2 : -diff2; |
|||
if (diff2 > 1) { |
|||
this.lastHook_x = x; |
|||
this.lastHook_y = y; |
|||
if (this.dirty) { |
|||
this.dirty = false; |
|||
} else { |
|||
this.runHooks(); |
|||
} |
|||
} |
|||
} |
|||
/** |
|||
* Sets things in motion, unless they are already that is, registering an event listener on |
|||
* <code>document.onmousemove</code>. A half-hearted attempt is made to preserve the old event |
|||
* listener if there is one. |
|||
*/ |
|||
enable() { |
|||
if (this.active) { |
|||
return; |
|||
} |
|||
this.active = true; |
|||
this.savedListener = document.onmousemove; |
|||
const self2 = this; |
|||
document.onmousemove = (e) => { |
|||
self2.track(e); |
|||
}; |
|||
if (this.loopDelay) { |
|||
this.timer = setInterval(() => { |
|||
self2.runHooks(); |
|||
}, this.loopDelay); |
|||
} |
|||
} |
|||
/** |
|||
* Disables the tracker, removing the event listener. |
|||
*/ |
|||
disable() { |
|||
if (!this.active) { |
|||
return; |
|||
} |
|||
if (typeof this.savedListener === "function") { |
|||
document.onmousemove = this.savedListener; |
|||
} else { |
|||
delete document.onmousemove; |
|||
} |
|||
if (this.timer) { |
|||
clearInterval(this.timer); |
|||
} |
|||
this.active = false; |
|||
} |
|||
} |
|||
class Navpopup { |
|||
constructor() { |
|||
this.uid = Navpopup.uid++; |
|||
this.visible = false; |
|||
this.noshow = false; |
|||
this.hooks = { |
|||
create: [], |
|||
unhide: [], |
|||
hide: [] |
|||
}; |
|||
this.hookIds = {}; |
|||
this.downloads = []; |
|||
this.pending = null; |
|||
this.fuzz = 5; |
|||
this.constrained = true; |
|||
this.width = 0; |
|||
this.height = 0; |
|||
this.mainDiv = null; |
|||
this.createMainDiv(); |
|||
} |
|||
/** |
|||
* Retrieves the {@source #visible} attribute, indicating whether the popup is currently visible. |
|||
* |
|||
* @type boolean |
|||
*/ |
|||
isVisible() { |
|||
return this.visible; |
|||
} |
|||
/** |
|||
* Repositions popup using CSS style. |
|||
* |
|||
* @private |
|||
* @param {integer} x x-coordinate (px) |
|||
* @param {integer} y y-coordinate (px) |
|||
* @param {boolean} noLimitHor Don't call {@source #limitHorizontalPosition} |
|||
*/ |
|||
reposition(x, y, noLimitHor) { |
|||
log("reposition(".concat(x, ",").concat(y, ",").concat(noLimitHor, ")")); |
|||
if (x !== void 0 && x !== null) { |
|||
this.left = x; |
|||
} |
|||
if (y !== void 0 && y !== null) { |
|||
this.top = y; |
|||
} |
|||
if (this.left !== void 0 && this.top !== void 0) { |
|||
this.mainDiv.style.left = "".concat(this.left, "px"); |
|||
this.mainDiv.style.top = "".concat(this.top, "px"); |
|||
} |
|||
if (!noLimitHor) { |
|||
this.limitHorizontalPosition(); |
|||
} |
|||
} |
|||
/** |
|||
* Prevents popups from being in silly locations. Hopefully. |
|||
* Should not be run if {@source #constrained} is true. |
|||
* |
|||
* @private |
|||
*/ |
|||
limitHorizontalPosition() { |
|||
if (!this.constrained || this.tooWide) { |
|||
return; |
|||
} |
|||
this.updateDimensions(); |
|||
const x = this.left; |
|||
const w = this.width; |
|||
const cWidth = document.querySelector("body").clientWidth; |
|||
if (x + w >= cWidth || x > 0 && this.maxWidth && this.width < this.maxWidth && this.height > this.width && x > cWidth - this.maxWidth) { |
|||
this.mainDiv.style.left = "-10000px"; |
|||
this.mainDiv.style.width = "".concat(this.maxWidth, "px"); |
|||
const naturalWidth = Number.parseInt(this.mainDiv.offsetWidth, 10); |
|||
let newLeft = cWidth - naturalWidth - 1; |
|||
if (newLeft < 0) { |
|||
newLeft = 0; |
|||
this.tooWide = true; |
|||
} |
|||
log("limitHorizontalPosition: moving to (".concat(newLeft, ",").concat(this.top, "); naturalWidth=").concat(naturalWidth, ", clientWidth=").concat(cWidth)); |
|||
this.reposition(newLeft, null, true); |
|||
} |
|||
} |
|||
/** |
|||
* Brings popup to the top of the z-order. |
|||
* We increment the {@source #highest} property of the contructor here. |
|||
* |
|||
* @private |
|||
*/ |
|||
raise() { |
|||
this.mainDiv.style.zIndex = Navpopup.highest + 1; |
|||
++Navpopup.highest; |
|||
} |
|||
/** |
|||
* Shows the popup provided {@source #noshow} is not true. |
|||
* Updates the position, brings the popup to the top of the z-order and unhides it. |
|||
*/ |
|||
show() { |
|||
if (this.noshow) { |
|||
return; |
|||
} |
|||
this.reposition(); |
|||
this.raise(); |
|||
this.unhide(); |
|||
} |
|||
/** |
|||
* Checks to see if the mouse pointer has |
|||
* stabilised (checking every <code>time</code>/2 milliseconds) and runs the |
|||
* {@source #show} method if it has. |
|||
* |
|||
* @param {integer} time The minimum time (ms) before the popup may be shown. |
|||
*/ |
|||
showSoonIfStable(time) { |
|||
log("showSoonIfStable, time=".concat(time)); |
|||
if (this.visible) { |
|||
return; |
|||
} |
|||
this.noshow = false; |
|||
this.stable_x = -1e4; |
|||
this.stable_y = -1e4; |
|||
const stableShow = () => { |
|||
log("stableShow called"); |
|||
const new_x = Navpopup.tracker.x; |
|||
const new_y = Navpopup.tracker.y; |
|||
const dx = self2.stable_x - new_x; |
|||
const dy = self2.stable_y - new_y; |
|||
const fuzz2 = 0; |
|||
if (dx * dx <= fuzz2 && dy * dy <= fuzz2) { |
|||
log("mouse is stable"); |
|||
clearInterval(self2.showSoonStableTimer); |
|||
self2.reposition(new_x + 2, new_y + 2); |
|||
self2.show(); |
|||
self2.limitHorizontalPosition(); |
|||
return; |
|||
} |
|||
self2.stable_x = new_x; |
|||
self2.stable_y = new_y; |
|||
}; |
|||
const self2 = this; |
|||
this.showSoonStableTimer = setInterval(stableShow, time / 2); |
|||
} |
|||
/** |
|||
* Sets the {@source #noshow} flag and hides the popup. This should be called |
|||
* when the mouse leaves the link before |
|||
* (or after) it's actually been displayed. |
|||
*/ |
|||
banish() { |
|||
log("banish called"); |
|||
this.noshow = true; |
|||
if (this.showSoonStableTimer) { |
|||
log("clearing showSoonStableTimer"); |
|||
clearInterval(this.showSoonStableTimer); |
|||
} |
|||
this.hide(); |
|||
} |
|||
/** |
|||
* Runs hooks added with {@source #addHook}. |
|||
* |
|||
* @private |
|||
* @param {string} key Key name of the {@source #hooks} array - one of 'create', 'unhide', 'hide' |
|||
* @param {string} when Controls exactly when the hook is run: either 'before' or 'after' |
|||
*/ |
|||
runHooks(key, when) { |
|||
if (!this.hooks[key]) { |
|||
return; |
|||
} |
|||
const keyHooks = this.hooks[key]; |
|||
const len = keyHooks.length; |
|||
for (let i = 0; i < len; ++i) { |
|||
if (keyHooks[i] && keyHooks[i].when === when && Reflect.apply(keyHooks[i].hook, this, [])) { |
|||
if (keyHooks[i].hookId) { |
|||
delete this.hookIds[keyHooks[i].hookId]; |
|||
} |
|||
keyHooks[i] = null; |
|||
} |
|||
} |
|||
} |
|||
/** |
|||
* Adds a hook to the popup. Hook functions are run with <code>this</code> set to refer to the |
|||
* Navpopup instance, and no arguments. |
|||
* |
|||
* @param {Function} hook The hook function. Functions that return true are deleted. |
|||
* @param {string} key Key name of the {@source #hooks} array - one of 'create', 'unhide', 'hide' |
|||
* @param {string} when Controls exactly when the hook is run: either 'before' or 'after' |
|||
* @param {string} uid A truthy string identifying the hook function; if it matches another hook |
|||
* in this position, it won't be added again. |
|||
*/ |
|||
addHook(hook, key, when, uid) { |
|||
when || (when = "after"); |
|||
if (!this.hooks[key]) { |
|||
return; |
|||
} |
|||
let hookId; |
|||
if (uid) { |
|||
hookId = [key, when, uid].join("|"); |
|||
if (this.hookIds[hookId]) { |
|||
return; |
|||
} |
|||
this.hookIds[hookId] = true; |
|||
} |
|||
this.hooks[key].push({ |
|||
hook, |
|||
when, |
|||
hookId |
|||
}); |
|||
} |
|||
/** |
|||
* Creates the main DIV element, which contains all the actual popup content. |
|||
* Runs hooks with key 'create'. |
|||
* |
|||
* @private |
|||
*/ |
|||
createMainDiv() { |
|||
var _this$className; |
|||
if (this.mainDiv) { |
|||
return; |
|||
} |
|||
this.runHooks("create", "before"); |
|||
const mainDiv = document.createElement("div"); |
|||
const self2 = this; |
|||
mainDiv.onclick = (e) => { |
|||
self2.onclickListener(e); |
|||
}; |
|||
mainDiv.className = (_this$className = this.className) !== null && _this$className !== void 0 ? _this$className : "navpopup_maindiv"; |
|||
mainDiv.id = mainDiv.className + this.uid; |
|||
mainDiv.style.position = "absolute"; |
|||
mainDiv.style.minWidth = "350px"; |
|||
mainDiv.style.display = "none"; |
|||
mainDiv.className = "navpopup"; |
|||
mainDiv.navpopup = this; |
|||
this.mainDiv = mainDiv; |
|||
document.querySelector("body").append(mainDiv); |
|||
this.runHooks("create", "after"); |
|||
} |
|||
/** |
|||
* Calls the {@source #raise} method. |
|||
* |
|||
* @private |
|||
*/ |
|||
onclickListener() { |
|||
this.raise(); |
|||
} |
|||
/** |
|||
* Makes the popup draggable, using a {@source Drag} object. |
|||
* |
|||
* @param {string} handleName |
|||
* @private |
|||
*/ |
|||
makeDraggable(handleName) { |
|||
if (!this.mainDiv) { |
|||
this.createMainDiv(); |
|||
} |
|||
const drag = new Drag(); |
|||
if (!handleName) { |
|||
drag.startCondition = (e) => { |
|||
try { |
|||
if (!e.shiftKey) { |
|||
return false; |
|||
} |
|||
} catch { |
|||
return false; |
|||
} |
|||
return true; |
|||
}; |
|||
} |
|||
let dragHandle; |
|||
if (handleName) { |
|||
dragHandle = document.getElementById("".concat(handleName)); |
|||
} |
|||
dragHandle || (dragHandle = this.mainDiv); |
|||
const self2 = this; |
|||
drag.endHook = (x, y) => { |
|||
Navpopup.tracker.dirty = true; |
|||
self2.reposition(x, y); |
|||
}; |
|||
drag.init(dragHandle, this.mainDiv); |
|||
} |
|||
/** |
|||
* Hides the popup using CSS. Runs hooks with key 'hide'. |
|||
* Sets {@source #visible} appropriately. |
|||
* {@source #banish} should be called externally instead of this method. |
|||
* |
|||
* @private |
|||
*/ |
|||
hide() { |
|||
this.runHooks("hide", "before"); |
|||
this.abortDownloads(); |
|||
if (this.visible !== void 0 && this.visible) { |
|||
this.mainDiv.style.display = "none"; |
|||
this.visible = false; |
|||
} |
|||
this.runHooks("hide", "after"); |
|||
} |
|||
/** |
|||
* Shows the popup using CSS. Runs hooks with key 'unhide'. |
|||
* Sets {@source #visible} appropriately. {@source #show} should be called externally instead of this method. |
|||
* |
|||
* @private |
|||
*/ |
|||
unhide() { |
|||
this.runHooks("unhide", "before"); |
|||
if (this.visible !== void 0 && !this.visible) { |
|||
this.mainDiv.style.display = "inline"; |
|||
this.visible = true; |
|||
} |
|||
this.runHooks("unhide", "after"); |
|||
} |
|||
/** |
|||
* Sets the <code>innerHTML</code> attribute of the main div containing the popup content. |
|||
* |
|||
* @param {string} html The HTML to set. |
|||
*/ |
|||
setInnerHTML(html) { |
|||
this.mainDiv.innerHTML = html; |
|||
} |
|||
/** |
|||
* Updates the {@source #width} and {@source #height} attributes with the CSS properties. |
|||
* |
|||
* @private |
|||
*/ |
|||
updateDimensions() { |
|||
this.width = Number.parseInt(this.mainDiv.offsetWidth, 10); |
|||
this.height = Number.parseInt(this.mainDiv.offsetHeight, 10); |
|||
} |
|||
/** |
|||
* Checks if the point (x,y) is within {@source #fuzz} of the |
|||
* {@source #mainDiv}. |
|||
* |
|||
* @param {integer} x x-coordinate (px) |
|||
* @param {integer} y y-coordinate (px) |
|||
* @type boolean |
|||
*/ |
|||
isWithin(x, y) { |
|||
if (!this.visible) { |
|||
return false; |
|||
} |
|||
this.updateDimensions(); |
|||
const fuzz = this.fuzz || 0; |
|||
return x + fuzz >= this.left && x - fuzz <= this.left + this.width && y + fuzz >= this.top && y - fuzz <= this.top + this.height; |
|||
} |
|||
/** |
|||
* Adds a download to {@source #downloads}. |
|||
* |
|||
* @param {Downloader} download |
|||
*/ |
|||
addDownload(download) { |
|||
if (!download) { |
|||
return; |
|||
} |
|||
this.downloads.push(download); |
|||
} |
|||
/** |
|||
* Aborts the downloads listed in {@source #downloads}. |
|||
* |
|||
* @see Downloader#abort |
|||
*/ |
|||
abortDownloads() { |
|||
var _iterator18 = _createForOfIteratorHelper(this.downloads), _step18; |
|||
try { |
|||
for (_iterator18.s(); !(_step18 = _iterator18.n()).done; ) { |
|||
const d = _step18.value; |
|||
if (d && d.abort) { |
|||
d.abort(); |
|||
} |
|||
} |
|||
} catch (err) { |
|||
_iterator18.e(err); |
|||
} finally { |
|||
_iterator18.f(); |
|||
} |
|||
this.downloads = []; |
|||
} |
|||
} |
|||
Navpopup.uid = 0; |
|||
Navpopup.highest = 1e3; |
|||
Navpopup.tracker = new Mousetracker(); |
|||
const delFmt = (x) => { |
|||
if (x.length === 0) { |
|||
return ""; |
|||
} |
|||
return "<del class='popupDiff'>".concat(x.join(""), "</del>"); |
|||
}; |
|||
const insFmt = (x) => { |
|||
if (x.length === 0) { |
|||
return ""; |
|||
} |
|||
return "<ins class='popupDiff'>".concat(x.join(""), "</ins>"); |
|||
}; |
|||
const countCrossings = (a, b, i, eject) => { |
|||
if (!b[i].row && b[i].row !== 0) { |
|||
return -1; |
|||
} |
|||
let count = 0; |
|||
var _iterator19 = _createForOfIteratorHelper(a.entries()), _step19; |
|||
try { |
|||
for (_iterator19.s(); !(_step19 = _iterator19.n()).done; ) { |
|||
const [j, element] = _step19.value; |
|||
if (!element.row && element.row !== 0) { |
|||
continue; |
|||
} |
|||
if ((j - b[i].row) * (i - element.row) > 0) { |
|||
if (eject) { |
|||
return true; |
|||
} |
|||
count++; |
|||
} |
|||
} |
|||
} catch (err) { |
|||
_iterator19.e(err); |
|||
} finally { |
|||
_iterator19.f(); |
|||
} |
|||
return count; |
|||
}; |
|||
const shortenDiffString = function shortenDiffString2(str, context) { |
|||
const re = /(<del[\S\s]*?<\/del>|<ins[\S\s]*?<\/ins>)/; |
|||
const splitted = str.split(re); |
|||
let ret = [""]; |
|||
for (let i = 0; i < splitted.length; i += 2) { |
|||
if (splitted[i].length < 2 * context) { |
|||
ret[ret.length - 1] += splitted[i]; |
|||
if (i + 1 < splitted.length) { |
|||
ret[ret.length - 1] += splitted[i + 1]; |
|||
} |
|||
continue; |
|||
} else { |
|||
if (i > 0) { |
|||
ret[ret.length - 1] += splitted[i].slice(0, Math.max(0, context)); |
|||
} |
|||
if (i + 1 < splitted.length) { |
|||
ret.push(splitted[i].slice(Math.max(0, splitted[i].length - context)) + splitted[i + 1]); |
|||
} |
|||
} |
|||
} |
|||
while (ret.length > 0 && !ret[0]) { |
|||
ret = ret.slice(1); |
|||
} |
|||
return ret; |
|||
}; |
|||
const diffString = (o, n) => { |
|||
let i; |
|||
const oSplitted = o.split(/\b/); |
|||
const nSplitted = n.split(/\b/); |
|||
for (i = 0; i < oSplitted.length; ++i) { |
|||
oSplitted[i] = oSplitted[i].entify(); |
|||
} |
|||
for (i = 0; i < nSplitted.length; ++i) { |
|||
nSplitted[i] = nSplitted[i].entify(); |
|||
} |
|||
const out = diff(oSplitted, nSplitted); |
|||
let str = ""; |
|||
let acc = []; |
|||
let maxOutputPair = 0; |
|||
for (i = 0; i < out.n.length; ++i) { |
|||
if (out.n[i].paired) { |
|||
if (maxOutputPair > out.n[i].row) { |
|||
out.o[out.n[i].row] = out.o[out.n[i].row].text; |
|||
out.n[i] = out.n[i].text; |
|||
} |
|||
if (maxOutputPair < out.n[i].row) { |
|||
maxOutputPair = out.n[i].row; |
|||
} |
|||
} |
|||
} |
|||
for (i = 0; i < out.o.length && !out.o[i].paired; ++i) { |
|||
acc.push(out.o[i]); |
|||
} |
|||
str += delFmt(acc); |
|||
acc = []; |
|||
for (i = 0; i < out.n.length; ++i) { |
|||
while (i < out.n.length && !out.n[i].paired) { |
|||
acc.push(out.n[i++]); |
|||
} |
|||
str += insFmt(acc); |
|||
acc = []; |
|||
if (i < out.n.length) { |
|||
str += out.n[i].text; |
|||
let m = out.n[i].row + 1; |
|||
while (m < out.o.length && !out.o[m].paired) { |
|||
acc.push(out.o[m++]); |
|||
} |
|||
str += delFmt(acc); |
|||
acc = []; |
|||
} |
|||
} |
|||
return str; |
|||
}; |
|||
const jsReservedProperties = new RegExp("^(constructor|prototype|__((define|lookup)[GS]etter)__|eval|hasOwnProperty|propertyIsEnumerable|to(Source|String|LocaleString)|(un)?watch|valueOf)$"); |
|||
const diffBugAlert = function diffBugAlert2(word) { |
|||
if (!diffBugAlert2.list[word]) { |
|||
diffBugAlert2.list[word] = 1; |
|||
void mw.notify("Bad word: ".concat(word, "\n\nPlease report this bug."), { |
|||
tag: "popups", |
|||
type: "error" |
|||
}); |
|||
} |
|||
}; |
|||
diffBugAlert.list = {}; |
|||
const makeDiffHashtable = (src) => { |
|||
const ret = {}; |
|||
for (let i = 0; i < src.length; i++) { |
|||
var _src$i, _ret$_src$i; |
|||
if (jsReservedProperties.test(src[i])) { |
|||
src[i] += "<!-- -->"; |
|||
} |
|||
(_ret$_src$i = ret[_src$i = src[i]]) !== null && _ret$_src$i !== void 0 ? _ret$_src$i : ret[_src$i] = []; |
|||
try { |
|||
ret[src[i]].push(i); |
|||
} catch { |
|||
diffBugAlert(src[i]); |
|||
} |
|||
} |
|||
return ret; |
|||
}; |
|||
const diff = (o, n) => { |
|||
const ns = makeDiffHashtable(n); |
|||
const os = makeDiffHashtable(o); |
|||
let i; |
|||
for (i in ns) { |
|||
if (ns[i].length === 1 && os[i] && os[i].length === 1) { |
|||
n[ns[i][0]] = { |
|||
text: n[ns[i][0]], |
|||
row: os[i][0], |
|||
paired: true |
|||
}; |
|||
o[os[i][0]] = { |
|||
text: o[os[i][0]], |
|||
row: ns[i][0], |
|||
paired: true |
|||
}; |
|||
} |
|||
} |
|||
for (i = 0; i < n.length - 1; i++) { |
|||
if (n[i].paired && !n[i + 1].paired && n[i].row + 1 < o.length && !o[n[i].row + 1].paired && n[i + 1] === o[n[i].row + 1]) { |
|||
n[i + 1] = { |
|||
text: n[i + 1], |
|||
row: n[i].row + 1, |
|||
paired: true |
|||
}; |
|||
o[n[i].row + 1] = { |
|||
text: o[n[i].row + 1], |
|||
row: i + 1, |
|||
paired: true |
|||
}; |
|||
} |
|||
} |
|||
for (i = n.length - 1; i > 0; i--) { |
|||
if (n[i].paired && !n[i - 1].paired && n[i].row > 0 && !o[n[i].row - 1].paired && n[i - 1] === o[n[i].row - 1]) { |
|||
n[i - 1] = { |
|||
text: n[i - 1], |
|||
row: n[i].row - 1, |
|||
paired: true |
|||
}; |
|||
o[n[i].row - 1] = { |
|||
text: o[n[i].row - 1], |
|||
row: i - 1, |
|||
paired: true |
|||
}; |
|||
} |
|||
} |
|||
return { |
|||
o, |
|||
n |
|||
}; |
|||
}; |
|||
const setSiteInfo = () => { |
|||
if (window.popupLocalDebug) { |
|||
pg.wiki.hostname = "en.wikipedia.org"; |
|||
} else { |
|||
pg.wiki.hostname = location.hostname; |
|||
} |
|||
pg.wiki.wikimedia = /(wiki([mp]edia|source|books|news|quote|versity|species|voyage|data)|metawiki|wiktionary|mediawiki)\.org/.test(pg.wiki.hostname); |
|||
pg.wiki.wikia = /\.wikia\.com$/i.test(pg.wiki.hostname); |
|||
pg.wiki.isLocal = pg.wiki.hostname.startsWith("localhost"); |
|||
pg.wiki.commons = pg.wiki.wikimedia && pg.wiki.hostname !== "commons.wikimedia.org" ? "commons.wikimedia.org" : null; |
|||
pg.wiki.lang = mw.config.get("wgContentLanguage"); |
|||
const port = location.port ? ":".concat(location.port) : ""; |
|||
pg.wiki.sitebase = pg.wiki.hostname + port; |
|||
}; |
|||
const setUserInfo = () => { |
|||
const params = { |
|||
action: "query", |
|||
list: "users", |
|||
ususers: mw.config.get("wgUserName"), |
|||
usprop: "rights" |
|||
}; |
|||
pg.user.canReview = false; |
|||
if (getValueOf("popupReview")) { |
|||
getMwApi().get(params).done((data) => { |
|||
const [{ |
|||
rights |
|||
}] = data.query.users; |
|||
pg.user.canReview = rights.includes("review"); |
|||
}); |
|||
} |
|||
}; |
|||
const fetchSpecialPageNames = () => { |
|||
const params = { |
|||
action: "query", |
|||
format: "json", |
|||
formatversion: "2", |
|||
meta: "siteinfo", |
|||
siprop: "specialpagealiases", |
|||
uselang: "content", |
|||
// cache for an hour |
|||
smaxage: 3600, |
|||
maxage: 3600 |
|||
}; |
|||
return getMwApi().get(params).then((data) => { |
|||
pg.wiki.specialpagealiases = data.query.specialpagealiases; |
|||
}); |
|||
}; |
|||
const setTitleBase = () => { |
|||
const protocol = window.popupLocalDebug ? "http:" : location.protocol; |
|||
pg.wiki.articlePath = mw.config.get("wgArticlePath").replace(/\/\$1/, ""); |
|||
pg.wiki.botInterfacePath = mw.config.get("wgScript"); |
|||
pg.wiki.APIPath = "".concat(mw.config.get("wgScriptPath"), "/api.php"); |
|||
const titletail = "".concat(pg.wiki.botInterfacePath, "?title="); |
|||
pg.wiki.titlebase = "".concat(protocol, "//").concat(pg.wiki.sitebase).concat(titletail); |
|||
pg.wiki.wikibase = "".concat(protocol, "//").concat(pg.wiki.sitebase).concat(pg.wiki.botInterfacePath); |
|||
pg.wiki.apiwikibase = "".concat(protocol, "//").concat(pg.wiki.sitebase).concat(pg.wiki.APIPath); |
|||
pg.wiki.articlebase = "".concat(protocol, "//").concat(pg.wiki.sitebase).concat(pg.wiki.articlePath); |
|||
pg.wiki.commonsbase = "".concat(protocol, "//").concat(pg.wiki.commons).concat(pg.wiki.botInterfacePath); |
|||
pg.wiki.apicommonsbase = "".concat(protocol, "//").concat(pg.wiki.commons).concat(pg.wiki.APIPath); |
|||
pg.re.basenames = new RegExp("^(".concat(map(literalizeRegex, [pg.wiki.titlebase, pg.wiki.articlebase]).join("|"), ")")); |
|||
}; |
|||
const setMainRegex = () => { |
|||
const reStart = "[^:]*://"; |
|||
let preTitles = "".concat(literalizeRegex(mw.config.get("wgScriptPath")), "/(?:index[.]php|wiki[.]phtml)[?]title="); |
|||
preTitles += "|".concat(literalizeRegex("".concat(pg.wiki.articlePath, "/"))); |
|||
const reEnd = "(".concat(preTitles, ")([^&?#]*)[^#]*(?:#(.+))?"); |
|||
pg.re.main = new RegExp(reStart + literalizeRegex(pg.wiki.sitebase) + reEnd); |
|||
}; |
|||
const buildSpecialPageGroup = (specialPageObj) => { |
|||
const variants = []; |
|||
variants.push(mw.util.escapeRegExp(specialPageObj.realname), mw.util.escapeRegExp(encodeURI(specialPageObj.realname))); |
|||
var _iterator20 = _createForOfIteratorHelper(specialPageObj.aliases), _step20; |
|||
try { |
|||
for (_iterator20.s(); !(_step20 = _iterator20.n()).done; ) { |
|||
const alias = _step20.value; |
|||
variants.push(mw.util.escapeRegExp(alias), mw.util.escapeRegExp(encodeURI(alias))); |
|||
} |
|||
} catch (err) { |
|||
_iterator20.e(err); |
|||
} finally { |
|||
_iterator20.f(); |
|||
} |
|||
return variants.join("|"); |
|||
}; |
|||
const setRegexps = () => { |
|||
setMainRegex(); |
|||
const sp = nsRe(pg.nsSpecialId); |
|||
pg.re.urlNoPopup = new RegExp("((title=|/)".concat(sp, "(?:%3A|:)|section=[0-9]|^#$)")); |
|||
var _iterator21 = _createForOfIteratorHelper(pg.wiki.specialpagealiases), _step21; |
|||
try { |
|||
for (_iterator21.s(); !(_step21 = _iterator21.n()).done; ) { |
|||
const specialpage = _step21.value; |
|||
switch (specialpage.realname) { |
|||
case "Contributions": |
|||
pg.re.contribs = new RegExp("(title=|/)".concat(sp, "(?:%3A|:)(?:").concat(buildSpecialPageGroup(specialpage), ")(&target=|/|/").concat(nsRe(pg.nsUserId), ":)(.*)"), "i"); |
|||
break; |
|||
case "Diff": |
|||
pg.re.specialdiff = new RegExp("/".concat(sp, "(?:%3A|:)(?:").concat(buildSpecialPageGroup(specialpage), ")/([^?#]*)"), "i"); |
|||
break; |
|||
case "Emailuser": |
|||
pg.re.email = new RegExp("(title=|/)".concat(sp, "(?:%3A|:)(?:").concat(buildSpecialPageGroup(specialpage), ")(&target=|/|/(?:").concat(nsRe(pg.nsUserId), ":)?)(.*)"), "i"); |
|||
break; |
|||
case "Whatlinkshere": |
|||
pg.re.backlinks = new RegExp("(title=|/)".concat(sp, "(?:%3A|:)(?:").concat(buildSpecialPageGroup(specialpage), ")(&target=|/)([^&]*)"), "i"); |
|||
break; |
|||
} |
|||
} |
|||
} catch (err) { |
|||
_iterator21.e(err); |
|||
} finally { |
|||
_iterator21.f(); |
|||
} |
|||
const im = nsReImage(); |
|||
pg.re.image = new RegExp("(^|\\[\\[)".concat(im, ": *([^|\\]]*[^|\\] ])").concat(String.raw(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral(["([^0-9]]*([0-9]+) *px)?|(?:\n *[|]?|[|]) *"], ["([^0-9\\]]*([0-9]+) *px)?|(?:\\n *[|]?|[|]) *"]))), "(").concat(getValueOf("popupImageVarsRegexp"), ") *= *(?:\\[\\[ *)?(?:").concat(im, ":)?").concat(String.raw(_templateObject5 || (_templateObject5 = _taggedTemplateLiteral(["([^|]*?)(?:]])? *[|]? *\n"], ["([^|]*?)(?:\\]\\])? *[|]? *\\n"])))), "img"); |
|||
pg.re.imageBracketCount = 6; |
|||
pg.re.category = new RegExp("\\[\\[".concat(nsRe(pg.nsCategoryId), ": *([^|\\]]*[^|\\] ]) *"), "i"); |
|||
pg.re.categoryBracketCount = 1; |
|||
pg.re.ipUser = /^(?::(?::|(?::[\dA-Fa-f]{1,4}){1,7})|[\dA-Fa-f]{1,4}(?::[\dA-Fa-f]{1,4}){0,6}::|[\dA-Fa-f]{1,4}(?::[\dA-Fa-f]{1,4}){7})|(((25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)\.){3}(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d))$/; |
|||
pg.re.stub = new RegExp(getValueOf("popupStubRegexp"), "im"); |
|||
pg.re.disambig = new RegExp(getValueOf("popupDabRegexp"), "im"); |
|||
pg.re.oldid = /[&?]oldid=([^&]*)/; |
|||
pg.re.diff = /[&?]diff=([^&]*)/; |
|||
}; |
|||
const setupCache = () => { |
|||
pg.cache.pages = []; |
|||
}; |
|||
const setMisc = () => { |
|||
pg.current.link = null; |
|||
pg.current.links = []; |
|||
pg.current.linksHash = {}; |
|||
setupCache(); |
|||
pg.timer.checkPopupPosition = null; |
|||
pg.counter.loop = 0; |
|||
pg.idNumber = 0; |
|||
pg.misc.decodeExtras = [ |
|||
{ |
|||
from: "%2C", |
|||
to: "," |
|||
}, |
|||
{ |
|||
from: "_", |
|||
to: " " |
|||
}, |
|||
{ |
|||
from: "%24", |
|||
to: "$" |
|||
}, |
|||
{ |
|||
from: "%26", |
|||
to: "&" |
|||
} |
|||
// no , |
|||
]; |
|||
}; |
|||
const getMwApi = () => { |
|||
if (!pg.api.client) { |
|||
pg.api.userAgent = "Navigation popups/1.0"; |
|||
pg.api.client = api; |
|||
} |
|||
return pg.api.client; |
|||
}; |
|||
const setupPopups = function setupPopups2(callback) { |
|||
if (setupPopups2.completed) { |
|||
if (typeof callback === "function") { |
|||
callback(); |
|||
} |
|||
return; |
|||
} |
|||
fetchSpecialPageNames().then(() => { |
|||
setupDebugging(); |
|||
setSiteInfo(); |
|||
setTitleBase(); |
|||
setOptions(); |
|||
setUserInfo(); |
|||
setNamespaces(); |
|||
setInterwiki(); |
|||
setRegexps(); |
|||
setRedirs(); |
|||
setMisc(); |
|||
setupLivePreview(); |
|||
setupTooltips(); |
|||
log("In setupPopups(), just called setupTooltips()"); |
|||
Navpopup.tracker.enable(); |
|||
setupPopups2.completed = true; |
|||
if (typeof callback === "function") { |
|||
callback(); |
|||
} |
|||
}); |
|||
}; |
|||
const defaultNavlinkSpec = () => { |
|||
let str = ""; |
|||
str += "<b><<mainlink|shortcut= >></b>"; |
|||
if (getValueOf("popupLastEditLink")) { |
|||
str += "*<<lastEdit|shortcut=/>>|<<lastContrib>>|<<sinceMe>>if(oldid){|<<oldEdit>>|<<diffCur>>}"; |
|||
} |
|||
str += "if(user){<br><<contribs|shortcut=c>>*<<userlog|shortcut=L|log>>"; |
|||
str += "if(ipuser){*<<arin>>}if(wikimedia){*<<count|shortcut=#>>}"; |
|||
str += "if(ipuser){}else{*<<email|shortcut=E>>}if(admin){*<<block|shortcut=b>>|<<blocklog|log>>}}"; |
|||
const editstr = "<<edit|shortcut=e>>"; |
|||
const editOldidStr = "if(oldid){<<editOld|shortcut=e>>|<<revert|shortcut=v|rv>>|<<edit|cur>>}else{".concat(editstr, "}"); |
|||
const historystr = "<<history|shortcut=h>>|<<editors|shortcut=E|>>"; |
|||
const watchstr = "<<unwatch|unwatchShort>>|<<watch|shortcut=w|watchThingy>>"; |
|||
str += "<br>if(talk){".concat(editOldidStr, "|<<new|shortcut=+>>*").concat(historystr, "*").concat(watchstr, "*<b><<article|shortcut=a>></b>|<<editArticle|edit>>}else{").concat( |
|||
// not a talk page |
|||
editOldidStr, |
|||
"*" |
|||
).concat(historystr, "*").concat(watchstr, "*<b><<talk|shortcut=t>></b>|<<editTalk|edit>>|<<newTalk|shortcut=+|new>>}"); |
|||
str += "<br><<whatLinksHere|shortcut=l>>*<<relatedChanges|shortcut=r>>*<<move|shortcut=m>>"; |
|||
str += "if(admin){<br><<unprotect|unprotectShort>>|<<protect|shortcut=p>>|<<protectlog|log>>*<<undelete|undeleteShort>>|<<delete|shortcut=d>>|<<deletelog|log>>}"; |
|||
return str; |
|||
}; |
|||
const navLinksHTML = (article, _hint, params) => { |
|||
const str = '<span class="popupNavLinks">'.concat(defaultNavlinkSpec(), "</span>"); |
|||
return navlinkStringToHTML(str, article, params); |
|||
}; |
|||
const expandConditionalNavlinkString = function expandConditionalNavlinkString2(s, article, z, recursionCount) { |
|||
const { |
|||
oldid |
|||
} = z; |
|||
const { |
|||
rcid |
|||
} = z; |
|||
const { |
|||
diff: diff2 |
|||
} = z; |
|||
if (typeof recursionCount !== "number") { |
|||
recursionCount = 0; |
|||
} |
|||
const conditionalSplitRegex = /(;?\s*if\s*\(\s*(\w*)\s*\)\s*{([^{}]*)}(\s*else\s*{([^{}]*?)}|))/i; |
|||
const splitted = s.split(conditionalSplitRegex); |
|||
const numParens = 5; |
|||
let [ret] = splitted; |
|||
for (let i = 1; i < splitted.length; i = i + numParens + 1) { |
|||
const testString = splitted[i + 2 - 1]; |
|||
const trueString = splitted[i + 3 - 1]; |
|||
let falseString = splitted[i + 5 - 1]; |
|||
if (falseString === void 0 || !falseString) { |
|||
falseString = ""; |
|||
} |
|||
let testResult; |
|||
switch (testString) { |
|||
case "user": |
|||
testResult = !!article.userName(); |
|||
break; |
|||
case "talk": |
|||
testResult = !article.talkPage(); |
|||
break; |
|||
case "admin": |
|||
testResult = !!getValueOf("popupAdminLinks"); |
|||
break; |
|||
case "oldid": |
|||
testResult = !!(oldid !== void 0 && oldid); |
|||
break; |
|||
case "rcid": |
|||
testResult = !!(rcid !== void 0 && rcid); |
|||
break; |
|||
case "ipuser": |
|||
testResult = !!article.isIpUser(); |
|||
break; |
|||
case "mainspace_en": |
|||
testResult = isInMainNamespace(article) && pg.wiki.hostname === "en.wikipedia.org"; |
|||
break; |
|||
case "wikimedia": |
|||
testResult = !!pg.wiki.wikimedia; |
|||
break; |
|||
case "diff": |
|||
testResult = !!(diff2 !== void 0 && diff2); |
|||
break; |
|||
} |
|||
switch (testResult) { |
|||
case null: |
|||
ret += splitted[i]; |
|||
break; |
|||
case true: |
|||
ret += trueString; |
|||
break; |
|||
case false: |
|||
ret += falseString; |
|||
break; |
|||
} |
|||
ret += splitted[i + numParens]; |
|||
} |
|||
if (conditionalSplitRegex.test(ret) && recursionCount < 10) { |
|||
return expandConditionalNavlinkString2(ret, article, z, recursionCount + 1); |
|||
} |
|||
return ret; |
|||
}; |
|||
const navlinkStringToArray = (s, article, params) => { |
|||
s = expandConditionalNavlinkString(s, article, params); |
|||
const splitted = s.split(/<<(.*?)>>/); |
|||
const ret = []; |
|||
var _iterator22 = _createForOfIteratorHelper(splitted.entries()), _step22; |
|||
try { |
|||
for (_iterator22.s(); !(_step22 = _iterator22.n()).done; ) { |
|||
const [i, element] = _step22.value; |
|||
if (i % 2) { |
|||
const t = new navlinkTag(); |
|||
const ss = element.split("|"); |
|||
[t.id] = ss; |
|||
for (let j = 1; j < ss.length; ++j) { |
|||
const sss = ss[j].split("="); |
|||
if (sss.length > 1) { |
|||
[, t[sss[0]]] = sss; |
|||
} else { |
|||
t.text = popupString(sss[0]); |
|||
} |
|||
} |
|||
t.article = article; |
|||
const { |
|||
oldid |
|||
} = params; |
|||
const { |
|||
rcid |
|||
} = params; |
|||
const { |
|||
diff: diff2 |
|||
} = params; |
|||
if (oldid !== void 0 && oldid !== null) { |
|||
t.oldid = oldid; |
|||
} |
|||
if (rcid !== void 0 && rcid !== null) { |
|||
t.rcid = rcid; |
|||
} |
|||
if (diff2 !== void 0 && diff2 !== null) { |
|||
t.diff = diff2; |
|||
} |
|||
if (!t.text && t.id !== "mainlink") { |
|||
t.text = popupString(t.id); |
|||
} |
|||
ret.push(t); |
|||
} else { |
|||
ret.push(element); |
|||
} |
|||
} |
|||
} catch (err) { |
|||
_iterator22.e(err); |
|||
} finally { |
|||
_iterator22.f(); |
|||
} |
|||
return ret; |
|||
}; |
|||
const navlinkSubstituteHTML = (s) => { |
|||
return s.split("*").join(getValueOf("popupNavLinkSeparator")).split("<menurow>").join('<li class="popup_menu_row">').split("</menurow>").join("</li>").split("<menu>").join('<ul class="popup_menu">').split("</menu>").join("</ul>"); |
|||
}; |
|||
const navlinkDepth = (magic, s) => { |
|||
return s.split("<".concat(magic, ">")).length - s.split("</".concat(magic, ">")).length; |
|||
}; |
|||
const navlinkStringToHTML = (s, article, params) => { |
|||
const p = navlinkStringToArray(s, article, params); |
|||
let html = ""; |
|||
let menudepth = 0; |
|||
let menurowdepth = 0; |
|||
var _iterator23 = _createForOfIteratorHelper(p), _step23; |
|||
try { |
|||
for (_iterator23.s(); !(_step23 = _iterator23.n()).done; ) { |
|||
const element = _step23.value; |
|||
if (typeof element === "string") { |
|||
html += navlinkSubstituteHTML(element); |
|||
menudepth += navlinkDepth("menu", element); |
|||
menurowdepth += navlinkDepth("menurow", element); |
|||
} else if (element.type !== void 0 && element.type === "navlinkTag") { |
|||
html += menudepth > 0 && menurowdepth === 0 ? '<li class="popup_menu_item">'.concat(element.html(), "</li>") : element.html(); |
|||
} |
|||
} |
|||
} catch (err) { |
|||
_iterator23.e(err); |
|||
} finally { |
|||
_iterator23.f(); |
|||
} |
|||
return html; |
|||
}; |
|||
class navlinkTag { |
|||
constructor() { |
|||
this.type = "navlinkTag"; |
|||
} |
|||
html() { |
|||
this.getNewWin(); |
|||
this.getPrintFunction(); |
|||
let html = ""; |
|||
let opening; |
|||
let closing; |
|||
const tagType = "span"; |
|||
if (tagType) { |
|||
opening = "<".concat(tagType, ' class="popup_').concat(this.id, '">'); |
|||
closing = "</".concat(tagType, ">"); |
|||
} else { |
|||
opening = ""; |
|||
closing = ""; |
|||
} |
|||
if (typeof this.print === "function") { |
|||
html = this.print(this); |
|||
if (typeof html !== "string") { |
|||
html = ""; |
|||
} else if (this.shortcut !== void 0) { |
|||
html = addPopupShortcut(html, this.shortcut); |
|||
} |
|||
} else { |
|||
errlog("Oh dear - invalid print function for a navlinkTag, id=".concat(this.id)); |
|||
} |
|||
return opening + html + closing; |
|||
} |
|||
getNewWin() { |
|||
getValueOf("popupLinksNewWindow"); |
|||
if (pg.option.popupLinksNewWindow[this.id] === void 0) { |
|||
this.newWin = null; |
|||
} |
|||
this.newWin = pg.option.popupLinksNewWindow[this.id]; |
|||
} |
|||
getPrintFunction() { |
|||
if (typeof this.id !== "string" || typeof this.article !== typeof {}) { |
|||
return; |
|||
} |
|||
this.noPopup = 1; |
|||
switch (this.id) { |
|||
case "contribs": |
|||
case "history": |
|||
case "whatLinksHere": |
|||
case "userPage": |
|||
case "userTalk": |
|||
case "talk": |
|||
case "article": |
|||
case "lastEdit": |
|||
this.noPopup = null; |
|||
} |
|||
switch (this.id) { |
|||
case "email": |
|||
case "contribs": |
|||
case "block": |
|||
case "unblock": |
|||
case "userlog": |
|||
case "userSpace": |
|||
case "deletedContribs": |
|||
this.article = this.article.userName(); |
|||
} |
|||
switch (this.id) { |
|||
case "userTalk": |
|||
case "newUserTalk": |
|||
case "editUserTalk": |
|||
case "userPage": |
|||
case "blocklog": |
|||
this.article = this.article.userName(true); |
|||
/* falls through */ |
|||
case "pagelog": |
|||
case "deletelog": |
|||
case "protectlog": |
|||
delete this.oldid; |
|||
} |
|||
if (this.id !== "mainlink") { |
|||
this.article = this.article.removeAnchor(); |
|||
} |
|||
switch (this.id) { |
|||
case "undelete": |
|||
this.print = specialLink; |
|||
this.specialpage = "Undelete"; |
|||
this.sep = "/"; |
|||
break; |
|||
case "whatLinksHere": |
|||
this.print = specialLink; |
|||
this.specialpage = "Whatlinkshere"; |
|||
break; |
|||
case "relatedChanges": |
|||
this.print = specialLink; |
|||
this.specialpage = "Recentchangeslinked"; |
|||
break; |
|||
case "move": |
|||
this.print = specialLink; |
|||
this.specialpage = "Movepage"; |
|||
break; |
|||
case "contribs": |
|||
this.print = specialLink; |
|||
this.specialpage = "Contributions"; |
|||
break; |
|||
case "deletedContribs": |
|||
this.print = specialLink; |
|||
this.specialpage = "Deletedcontributions"; |
|||
break; |
|||
case "email": |
|||
this.print = specialLink; |
|||
this.specialpage = "EmailUser"; |
|||
this.sep = "/"; |
|||
break; |
|||
case "block": |
|||
this.print = specialLink; |
|||
this.specialpage = "Blockip"; |
|||
this.sep = "&ip="; |
|||
break; |
|||
case "unblock": |
|||
this.print = specialLink; |
|||
this.specialpage = "Ipblocklist"; |
|||
this.sep = "&action=unblock&ip="; |
|||
break; |
|||
case "userlog": |
|||
this.print = specialLink; |
|||
this.specialpage = "Log"; |
|||
this.sep = "&user="; |
|||
break; |
|||
case "blocklog": |
|||
this.print = specialLink; |
|||
this.specialpage = "Log"; |
|||
this.sep = "&type=block&page="; |
|||
break; |
|||
case "pagelog": |
|||
this.print = specialLink; |
|||
this.specialpage = "Log"; |
|||
this.sep = "&page="; |
|||
break; |
|||
case "protectlog": |
|||
this.print = specialLink; |
|||
this.specialpage = "Log"; |
|||
this.sep = "&type=protect&page="; |
|||
break; |
|||
case "deletelog": |
|||
this.print = specialLink; |
|||
this.specialpage = "Log"; |
|||
this.sep = "&type=delete&page="; |
|||
break; |
|||
case "userSpace": |
|||
this.print = specialLink; |
|||
this.specialpage = "PrefixIndex"; |
|||
this.sep = "&namespace=2&prefix="; |
|||
break; |
|||
case "search": |
|||
this.print = specialLink; |
|||
this.specialpage = "Search"; |
|||
this.sep = "&fulltext=Search&search="; |
|||
break; |
|||
case "thank": |
|||
this.print = specialLink; |
|||
this.specialpage = "Thanks"; |
|||
this.sep = "/"; |
|||
this.article.value = this.diff === "prev" ? this.oldid : this.diff; |
|||
break; |
|||
case "unwatch": |
|||
case "watch": |
|||
this.print = magicWatchLink; |
|||
this.action = "".concat(this.id, "&autowatchlist=1&autoimpl=").concat(popupString("autoedit_version"), "&actoken=").concat(autoClickToken()); |
|||
break; |
|||
case "history": |
|||
case "historyfeed": |
|||
case "unprotect": |
|||
case "protect": |
|||
this.print = wikiLink; |
|||
this.action = this.id; |
|||
break; |
|||
case "delete": |
|||
this.print = wikiLink; |
|||
this.action = "delete"; |
|||
if (this.article.namespaceId() === pg.nsImageId) { |
|||
const img = this.article.stripNamespace(); |
|||
this.action += "&image=".concat(img); |
|||
} |
|||
break; |
|||
case "markpatrolled": |
|||
case "edit": |
|||
delete this.oldid; |
|||
/* falls through */ |
|||
case "view": |
|||
case "purge": |
|||
case "render": |
|||
this.print = wikiLink; |
|||
this.action = this.id; |
|||
break; |
|||
case "raw": |
|||
this.print = wikiLink; |
|||
this.action = "raw"; |
|||
break; |
|||
case "new": |
|||
this.print = wikiLink; |
|||
this.action = "edit§ion=new"; |
|||
break; |
|||
case "mainlink": |
|||
if (this.text === void 0) { |
|||
this.text = this.article.toString().entify(); |
|||
} |
|||
if (getValueOf("popupSimplifyMainLink") && isInStrippableNamespace(this.article)) { |
|||
const s = this.text.split("/"); |
|||
this.text = s.at(-1); |
|||
if (this.text === "" && s.length > 1) { |
|||
this.text = s.at(-2); |
|||
} |
|||
} |
|||
this.print = titledWikiLink; |
|||
if (this.title === void 0 && pg.current.link && pg.current.link.href !== void 0) { |
|||
var _pg$current$link$orig; |
|||
this.title = safeDecodeURI((_pg$current$link$orig = pg.current.link.originalTitle) !== null && _pg$current$link$orig !== void 0 ? _pg$current$link$orig : this.article); |
|||
if (this.oldid !== void 0 && this.oldid) { |
|||
this.title = tprintf("Revision %s of %s", [this.oldid, this.title]); |
|||
} |
|||
} |
|||
this.action = "view"; |
|||
break; |
|||
case "userPage": |
|||
case "article": |
|||
case "editArticle": |
|||
delete this.oldid; |
|||
this.article = this.article.articleFromTalkOrArticle(); |
|||
this.print = wikiLink; |
|||
this.action = this.id.indexOf("edit") === 0 ? "edit" : "view"; |
|||
break; |
|||
case "userTalk": |
|||
case "talk": |
|||
this.article = this.article.talkPage(); |
|||
delete this.oldid; |
|||
this.print = wikiLink; |
|||
this.action = "view"; |
|||
break; |
|||
case "arin": |
|||
this.print = arinLink; |
|||
break; |
|||
case "count": |
|||
this.print = editCounterLink; |
|||
break; |
|||
case "editors": |
|||
this.print = editorListLink; |
|||
break; |
|||
case "lastEdit": |
|||
this.print = titledDiffLink; |
|||
this.title = popupString("Show the last edit"); |
|||
this.from = "prev"; |
|||
this.to = "cur"; |
|||
break; |
|||
case "oldEdit": |
|||
this.print = titledDiffLink; |
|||
this.title = "".concat(popupString("Show the edit made to get revision"), " ").concat(this.oldid); |
|||
this.from = "prev"; |
|||
this.to = this.oldid; |
|||
break; |
|||
case "editOld": |
|||
this.print = wikiLink; |
|||
this.action = "edit"; |
|||
break; |
|||
case "undo": |
|||
this.print = wikiLink; |
|||
this.action = "edit&undo="; |
|||
break; |
|||
case "revert": |
|||
this.print = wikiLink; |
|||
this.action = "revert"; |
|||
break; |
|||
case "nullEdit": |
|||
this.print = wikiLink; |
|||
this.action = "nullEdit"; |
|||
break; |
|||
case "diffCur": |
|||
this.print = titledDiffLink; |
|||
this.title = tprintf("Show changes since revision %s", [this.oldid]); |
|||
this.from = this.oldid; |
|||
this.to = "cur"; |
|||
break; |
|||
case "editUserTalk": |
|||
case "editTalk": |
|||
delete this.oldid; |
|||
this.article = this.article.talkPage(); |
|||
this.action = "edit"; |
|||
this.print = wikiLink; |
|||
break; |
|||
case "newUserTalk": |
|||
case "newTalk": |
|||
this.article = this.article.talkPage(); |
|||
this.action = "edit§ion=new"; |
|||
this.print = wikiLink; |
|||
break; |
|||
case "lastContrib": |
|||
case "sinceMe": |
|||
this.print = magicHistoryLink; |
|||
break; |
|||
case "togglePreviews": |
|||
this.text = popupString(pg.option.simplePopups ? "enable previews" : "disable previews"); |
|||
/* falls through */ |
|||
case "disablePopups": |
|||
case "purgePopups": |
|||
this.print = popupMenuLink; |
|||
break; |
|||
default: |
|||
this.print = function() { |
|||
return "Unknown navlink type: ".concat(this.id); |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
const popupHandleKeypress = function popupHandleKeypress2(evt) { |
|||
var _evt$keyCode; |
|||
const keyCode = window.event ? window.event.keyCode : (_evt$keyCode = evt.keyCode) !== null && _evt$keyCode !== void 0 ? _evt$keyCode : evt.which; |
|||
if (!keyCode || !pg.current.link || !pg.current.link.navpopup) { |
|||
return; |
|||
} |
|||
if (keyCode === 27) { |
|||
killPopup(); |
|||
return false; |
|||
} |
|||
const letter = String.fromCodePoint(keyCode); |
|||
const links = pg.current.link.navpopup.mainDiv.querySelectorAll("A"); |
|||
let startLink = 0; |
|||
let i; |
|||
let j; |
|||
if (popupHandleKeypress2.lastPopupLinkSelected) { |
|||
for (i = 0; i < links.length; ++i) { |
|||
if (links[i] === popupHandleKeypress2.lastPopupLinkSelected) { |
|||
startLink = i; |
|||
} |
|||
} |
|||
} |
|||
for (j = 0; j < links.length; ++j) { |
|||
i = (startLink + j + 1) % links.length; |
|||
if (links[i].getAttribute("popupkey") === letter) { |
|||
if (evt && evt.preventDefault) { |
|||
evt.preventDefault(); |
|||
} |
|||
links[i].focus(); |
|||
popupHandleKeypress2.lastPopupLinkSelected = links[i]; |
|||
return false; |
|||
} |
|||
} |
|||
if (document.oldPopupOnkeypress) { |
|||
return document.oldPopupOnkeypress(evt); |
|||
} |
|||
return true; |
|||
}; |
|||
const addPopupShortcuts = () => { |
|||
if (document.onkeypress !== popupHandleKeypress) { |
|||
document.oldPopupOnkeypress = document.onkeypress; |
|||
} |
|||
document.onkeypress = popupHandleKeypress; |
|||
}; |
|||
const rmPopupShortcuts = () => { |
|||
popupHandleKeypress.lastPopupLinkSelected = null; |
|||
try { |
|||
if (document.oldPopupOnkeypress && document.oldPopupOnkeypress === popupHandleKeypress) { |
|||
document.onkeypress = null; |
|||
return; |
|||
} |
|||
document.onkeypress = document.oldPopupOnkeypress; |
|||
} catch { |
|||
} |
|||
}; |
|||
const addLinkProperty = (html, property) => { |
|||
const i = html.indexOf(">"); |
|||
if (i === -1) { |
|||
return html; |
|||
} |
|||
return "".concat(html.slice(0, Math.max(0, i)), " ").concat(property).concat(html.slice(Math.max(0, i))); |
|||
}; |
|||
const addPopupShortcut = (html, key) => { |
|||
if (!getValueOf("popupShortcutKeys")) { |
|||
return html; |
|||
} |
|||
const ret = addLinkProperty(html, 'popupkey="'.concat(key, '"')); |
|||
if (key === " ") { |
|||
key = popupString("spacebar"); |
|||
} |
|||
return ret.replace(/^(.*?)(title=")(.*?)(".*)$/i, "$1$2$3 [".concat(key, "]$4")); |
|||
}; |
|||
const loadDiff = (article, oldid, diff2, navpop) => { |
|||
navpop.diffData = { |
|||
oldRev: {}, |
|||
newRev: {} |
|||
}; |
|||
const api2 = getMwApi(); |
|||
const params = { |
|||
action: "compare", |
|||
prop: ["ids", "title"], |
|||
smaxage: 600, |
|||
maxage: 600 |
|||
}; |
|||
if (article.title) { |
|||
params.fromtitle = article.title; |
|||
} |
|||
switch (diff2) { |
|||
case "cur": |
|||
switch (oldid) { |
|||
case null: |
|||
case "": |
|||
case "prev": |
|||
params.torelative = "prev"; |
|||
break; |
|||
default: |
|||
params.fromrev = oldid; |
|||
params.torelative = "cur"; |
|||
break; |
|||
} |
|||
break; |
|||
case "prev": |
|||
if (oldid) { |
|||
params.fromrev = oldid; |
|||
} |
|||
params.torelative = "prev"; |
|||
break; |
|||
case "next": |
|||
params.fromrev = oldid || 0; |
|||
params.torelative = "next"; |
|||
break; |
|||
default: |
|||
params.fromrev = oldid || 0; |
|||
params.torev = diff2 || 0; |
|||
break; |
|||
} |
|||
api2.get(params).then((data) => { |
|||
navpop.diffData.oldRev.revid = data.compare.fromrevid; |
|||
navpop.diffData.newRev.revid = data.compare.torevid; |
|||
addReviewLink(navpop, "popupMiscTools"); |
|||
const go = () => { |
|||
pendingNavpopTask(navpop); |
|||
let url = "".concat(pg.wiki.apiwikibase, "?format=json&formatversion=2&action=query&"); |
|||
url += "revids=".concat(navpop.diffData.oldRev.revid, "|").concat(navpop.diffData.newRev.revid); |
|||
url += "&prop=revisions&rvprop=ids|timestamp|content"; |
|||
getPageWithCaching(url, doneDiff, navpop); |
|||
return true; |
|||
}; |
|||
if (navpop.visible || !getValueOf("popupLazyDownloads")) { |
|||
go(); |
|||
} else { |
|||
navpop.addHook(go, "unhide", "before", "DOWNLOAD_DIFFS"); |
|||
} |
|||
}); |
|||
}; |
|||
const addReviewLink = (navpop, target) => { |
|||
if (!pg.user.canReview) { |
|||
return; |
|||
} |
|||
if (navpop.diffData.newRev.revid <= navpop.diffData.oldRev.revid) { |
|||
return; |
|||
} |
|||
const params = { |
|||
action: "query", |
|||
format: "json", |
|||
formatversion: "2", |
|||
prop: ["info", "flagged"], |
|||
revids: navpop.diffData.oldRev.revid |
|||
}; |
|||
getMwApi().get(params).then((data) => { |
|||
const stable_revid = data.query.pages[0].flagged && data.query.pages[0].flagged.stable_revid || 0; |
|||
if (stable_revid === navpop.diffData.oldRev.revid) { |
|||
const a = document.createElement("a"); |
|||
a.innerHTML = popupString("mark patrolled"); |
|||
a.title = popupString("markpatrolledHint"); |
|||
a.onclick = () => { |
|||
const params2 = { |
|||
action: "review", |
|||
comment: tprintf("defaultpopupReviewedSummary", [navpop.diffData.oldRev.revid, navpop.diffData.newRev.revid]), |
|||
revid: navpop.diffData.newRev.revid |
|||
}; |
|||
getMwApi().postWithToken("csrf", params2).done(() => { |
|||
a.style.display = "none"; |
|||
}).fail(() => { |
|||
void mw.notify(popupString("Could not marked this edit as patrolled"), { |
|||
tag: "popups", |
|||
type: "error" |
|||
}); |
|||
}); |
|||
}; |
|||
setPopupHTML(a, target, navpop.idNumber, null, true); |
|||
} |
|||
}); |
|||
}; |
|||
const doneDiff = (download) => { |
|||
if (!download.owner || !download.owner.diffData) { |
|||
return; |
|||
} |
|||
const navpop = download.owner; |
|||
completedNavpopTask(navpop); |
|||
let pages; |
|||
let revisions = []; |
|||
try { |
|||
({ |
|||
pages |
|||
} = getJsObj(download.data).query); |
|||
var _iterator24 = _createForOfIteratorHelper(pages), _step24; |
|||
try { |
|||
for (_iterator24.s(); !(_step24 = _iterator24.n()).done; ) { |
|||
const page = _step24.value; |
|||
revisions = [...revisions, ...page.revisions]; |
|||
} |
|||
} catch (err) { |
|||
_iterator24.e(err); |
|||
} finally { |
|||
_iterator24.f(); |
|||
} |
|||
for (var _i3 = 0, _revisions = revisions; _i3 < _revisions.length; _i3++) { |
|||
const revision = _revisions[_i3]; |
|||
if (revision.revid === navpop.diffData.oldRev.revid) { |
|||
navpop.diffData.oldRev.revision = revision; |
|||
} else if (revision.revid === navpop.diffData.newRev.revid) { |
|||
navpop.diffData.newRev.revision = revision; |
|||
} |
|||
} |
|||
} catch { |
|||
errlog("Could not get diff"); |
|||
} |
|||
insertDiff(navpop); |
|||
}; |
|||
const rmBoringLines = (a, b, context) => { |
|||
if (context === void 0) { |
|||
context = 2; |
|||
} |
|||
const aa = []; |
|||
const aaa = []; |
|||
const bb = []; |
|||
const bbb = []; |
|||
let i; |
|||
let j; |
|||
for (i = 0; i < a.length; ++i) { |
|||
if (!a[i].paired) { |
|||
aa[i] = 1; |
|||
} else if (countCrossings(b, a, i, true)) { |
|||
aa[i] = 1; |
|||
bb[a[i].row] = 1; |
|||
} |
|||
} |
|||
for (i = 0; i < b.length; ++i) { |
|||
if (bb[i] === 1) { |
|||
continue; |
|||
} |
|||
if (!b[i].paired) { |
|||
bb[i] = 1; |
|||
} |
|||
} |
|||
for (i = 0; i < b.length; ++i) { |
|||
if (bb[i] === 1) { |
|||
for (j = Math.max(0, i - context); j < Math.min(b.length, i + context); ++j) { |
|||
if (!bb[j]) { |
|||
bb[j] = 1; |
|||
aa[b[j].row] = 0.5; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
for (i = 0; i < a.length; ++i) { |
|||
if (aa[i] === 1) { |
|||
for (j = Math.max(0, i - context); j < Math.min(a.length, i + context); ++j) { |
|||
if (!aa[j]) { |
|||
aa[j] = 1; |
|||
bb[a[j].row] = 0.5; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
for (i = 0; i < bb.length; ++i) { |
|||
if (bb[i] > 0) { |
|||
if (b[i].paired) { |
|||
bbb.push(b[i].text); |
|||
} else { |
|||
bbb.push(b[i]); |
|||
} |
|||
} |
|||
} |
|||
for (i = 0; i < aa.length; ++i) { |
|||
if (aa[i] > 0) { |
|||
if (a[i].paired) { |
|||
aaa.push(a[i].text); |
|||
} else { |
|||
aaa.push(a[i]); |
|||
} |
|||
} |
|||
} |
|||
return { |
|||
a: aaa, |
|||
b: bbb |
|||
}; |
|||
}; |
|||
const stripOuterCommonLines = (a, b, context) => { |
|||
let i = 0; |
|||
while (i < a.length && i < b.length && a[i] === b[i]) { |
|||
++i; |
|||
} |
|||
let j = a.length - 1; |
|||
let k = b.length - 1; |
|||
while (j >= 0 && k >= 0 && a[j] === b[k]) { |
|||
--j; |
|||
--k; |
|||
} |
|||
return { |
|||
a: a.slice(Math.max(0, i - 1 - context), Math.min(a.length + 1, j + context + 1)), |
|||
b: b.slice(Math.max(0, i - 1 - context), Math.min(b.length + 1, k + context + 1)) |
|||
}; |
|||
}; |
|||
const insertDiff = (navpop) => { |
|||
let oldlines = navpop.diffData.oldRev.revision.content.split("\n"); |
|||
let newlines = navpop.diffData.newRev.revision.content.split("\n"); |
|||
let inner = stripOuterCommonLines(oldlines, newlines, getValueOf("popupDiffContextLines")); |
|||
oldlines = inner.a; |
|||
newlines = inner.b; |
|||
let truncated = false; |
|||
getValueOf("popupDiffMaxLines"); |
|||
if (oldlines.length > pg.option.popupDiffMaxLines || newlines.length > pg.option.popupDiffMaxLines) { |
|||
truncated = true; |
|||
inner = stripOuterCommonLines(oldlines.slice(0, pg.option.popupDiffMaxLines), newlines.slice(0, pg.option.popupDiffMaxLines), pg.option.popupDiffContextLines); |
|||
oldlines = inner.a; |
|||
newlines = inner.b; |
|||
} |
|||
const lineDiff = diff(oldlines, newlines); |
|||
const lines2 = rmBoringLines(lineDiff.o, lineDiff.n); |
|||
const oldlines2 = lines2.a; |
|||
const newlines2 = lines2.b; |
|||
let html = "<hr>"; |
|||
if (getValueOf("popupDiffDates")) { |
|||
html += diffDatesTable(navpop); |
|||
html += "<hr>"; |
|||
} |
|||
html += shortenDiffString(diffString(oldlines2.join("\n"), newlines2.join("\n")), getValueOf("popupDiffContextCharacters")).join("<hr>"); |
|||
setPopupTipsAndHTML(html.split("\n").join("<br>") + (truncated ? "<hr><b>".concat(popupString("Diff truncated for performance reasons"), "</b>") : ""), "popupPreview", navpop.idNumber); |
|||
}; |
|||
const diffDatesTable = (navpop) => { |
|||
let html = '<table class="popup_diff_dates">'; |
|||
html += diffDatesTableRow(navpop.diffData.newRev.revision, tprintf("New revision")); |
|||
html += diffDatesTableRow(navpop.diffData.oldRev.revision, tprintf("Old revision")); |
|||
html += "</table>"; |
|||
return html; |
|||
}; |
|||
const diffDatesTableRow = (revision, label) => { |
|||
let txt = ""; |
|||
const lastModifiedDate = new Date(revision.timestamp); |
|||
txt = formattedDateTime(lastModifiedDate); |
|||
const revlink = generalLink({ |
|||
url: "".concat(mw.config.get("wgScript"), "?oldid=").concat(revision.revid), |
|||
text: label, |
|||
title: label |
|||
}); |
|||
return simplePrintf("<tr><td>%s</td><td>%s</td></tr>", [revlink, txt]); |
|||
}; |
|||
const titledDiffLink = (l) => { |
|||
return titledWikiLink({ |
|||
article: l.article, |
|||
action: "".concat(l.to, "&oldid=").concat(l.from), |
|||
newWin: l.newWin, |
|||
noPopup: l.noPopup, |
|||
text: l.text, |
|||
title: l.title, |
|||
/* hack: no oldid here */ |
|||
actionName: "diff" |
|||
}); |
|||
}; |
|||
const wikiLink = (l) => { |
|||
if (!(typeof l.article === typeof {} && typeof l.action === "string" && typeof l.text === "string")) { |
|||
return null; |
|||
} |
|||
if (l.oldid === void 0) { |
|||
l.oldid = null; |
|||
} |
|||
const savedOldid = l.oldid; |
|||
if (!/^(edit|view|revert|render)$|^raw/.test(l.action)) { |
|||
l.oldid = null; |
|||
} |
|||
let hint = popupString("".concat(l.action, "Hint")); |
|||
const oldidData = [l.oldid, safeDecodeURI(l.article)]; |
|||
let revisionString = tprintf("revision %s of %s", oldidData); |
|||
log("revisionString=".concat(revisionString)); |
|||
switch (l.action) { |
|||
case "edit§ion=new": |
|||
hint = popupString("newSectionHint"); |
|||
break; |
|||
case "edit&undo=": |
|||
if (l.diff && l.diff !== "prev" && savedOldid) { |
|||
l.action += "".concat(l.diff, "&undoafter=").concat(savedOldid); |
|||
} else if (savedOldid) { |
|||
l.action += savedOldid; |
|||
} |
|||
hint = popupString("undoHint"); |
|||
break; |
|||
case "raw&ctype=text/css": |
|||
hint = popupString("rawHint"); |
|||
break; |
|||
case "revert": { |
|||
const p = parseParams(pg.current.link.href); |
|||
l.action = "edit&autoclick=wpSave&actoken=".concat(autoClickToken(), "&autoimpl=").concat(popupString("autoedit_version"), "&autosummary=").concat(revertSummary(l.oldid, p.diff)); |
|||
if (p.diff === "prev") { |
|||
l.action += "&direction=prev"; |
|||
revisionString = tprintf("the revision prior to revision %s of %s", oldidData); |
|||
} |
|||
if (getValueOf("popupRevertSummaryPrompt")) { |
|||
l.action += "&autosummaryprompt=true"; |
|||
} |
|||
if (getValueOf("popupMinorReverts")) { |
|||
l.action += "&autominor=true"; |
|||
} |
|||
log("revisionString is now ".concat(revisionString)); |
|||
break; |
|||
} |
|||
case "nullEdit": |
|||
l.action = "edit&autoclick=wpSave&actoken=".concat(autoClickToken(), "&autoimpl=").concat(popupString("autoedit_version"), "&autosummary=null"); |
|||
break; |
|||
case "historyfeed": |
|||
l.action = "history&feed=rss"; |
|||
break; |
|||
case "markpatrolled": |
|||
l.action = "markpatrolled&rcid=".concat(l.rcid); |
|||
} |
|||
if (hint) { |
|||
hint = l.oldid ? simplePrintf(hint, [revisionString]) : simplePrintf(hint, [safeDecodeURI(l.article)]); |
|||
} else { |
|||
hint = safeDecodeURI("".concat(l.article, "&action=").concat(l.action)) + l.oldid ? "&oldid=".concat(l.oldid) : ""; |
|||
} |
|||
return titledWikiLink({ |
|||
article: l.article, |
|||
action: l.action, |
|||
text: l.text, |
|||
newWin: l.newWin, |
|||
title: hint, |
|||
oldid: l.oldid, |
|||
noPopup: l.noPopup, |
|||
onclick: l.onclick |
|||
}); |
|||
}; |
|||
const revertSummary = (oldid, diff2) => { |
|||
let ret = ""; |
|||
ret = diff2 === "prev" ? getValueOf("popupQueriedRevertToPreviousSummary") : getValueOf("popupQueriedRevertSummary"); |
|||
return "".concat(ret, "&autorv=").concat(oldid); |
|||
}; |
|||
const titledWikiLink = (l) => { |
|||
if (l.article === void 0 || l.action === void 0) { |
|||
errlog("got undefined article or action in titledWikiLink"); |
|||
return null; |
|||
} |
|||
const base = pg.wiki.titlebase + l.article.urlString(); |
|||
let url = base; |
|||
if (l.actionName === void 0 || !l.actionName) { |
|||
l.actionName = "action"; |
|||
} |
|||
if (l.action !== "view") { |
|||
url = "".concat(base, "&").concat(l.actionName, "=").concat(l.action); |
|||
} |
|||
if (l.oldid !== void 0 && l.oldid) { |
|||
url += "&oldid=".concat(l.oldid); |
|||
} |
|||
let cssClass = pg.misc.defaultNavlinkClassname; |
|||
if (l.className !== void 0 && l.className) { |
|||
cssClass = l.className; |
|||
} |
|||
return generalNavLink({ |
|||
url, |
|||
newWin: l.newWin, |
|||
title: l.title === void 0 ? null : l.title, |
|||
text: l.text === void 0 ? null : l.text, |
|||
className: cssClass, |
|||
noPopup: l.noPopup, |
|||
onclick: l.onclick |
|||
}); |
|||
}; |
|||
pg.fn.getLastContrib = (wikipage, newWin) => { |
|||
getHistoryInfo(wikipage, (x) => { |
|||
processLastContribInfo(x, { |
|||
page: wikipage, |
|||
newWin |
|||
}); |
|||
}); |
|||
}; |
|||
const processLastContribInfo = (info, stuff) => { |
|||
if (!info.edits || info.edits.length === 0) { |
|||
void mw.notify("Popups: an odd thing happened. Please retry.", { |
|||
tag: "popups", |
|||
type: "error" |
|||
}); |
|||
return; |
|||
} |
|||
if (!info.firstNewEditor) { |
|||
void mw.notify(tprintf("Only found one editor: %s made %s edits", [info.edits[0].editor, info.edits.length]), { |
|||
tag: "popups", |
|||
type: "error" |
|||
}); |
|||
return; |
|||
} |
|||
const newUrl = "".concat(pg.wiki.titlebase + new Title(stuff.page).urlString(), "&diff=cur&oldid=").concat(info.firstNewEditor.oldid); |
|||
displayUrl(newUrl, stuff.newWin); |
|||
}; |
|||
pg.fn.getDiffSinceMyEdit = (wikipage, newWin) => { |
|||
getHistoryInfo(wikipage, (x) => { |
|||
processDiffSinceMyEdit(x, { |
|||
page: wikipage, |
|||
newWin |
|||
}); |
|||
}); |
|||
}; |
|||
const processDiffSinceMyEdit = (info, stuff) => { |
|||
if (!info.edits || info.edits.length === 0) { |
|||
void mw.notify("Popups: something fishy happened. Please try again.", { |
|||
tag: "popups", |
|||
type: "error" |
|||
}); |
|||
return; |
|||
} |
|||
const friendlyName = stuff.page.split("_").join(" "); |
|||
if (!info.myLastEdit) { |
|||
void mw.notify(tprintf("Couldn't find an edit by %s\nin the last %s edits to\n%s", [info.userName, getValueOf("popupHistoryLimit"), friendlyName]), { |
|||
tag: "popups", |
|||
type: "error" |
|||
}); |
|||
return; |
|||
} |
|||
if (info.myLastEdit.index === 0) { |
|||
void mw.notify(tprintf("%s seems to be the last editor to the page %s", [info.userName, friendlyName]), { |
|||
type: "error" |
|||
}); |
|||
return; |
|||
} |
|||
const newUrl = "".concat(pg.wiki.titlebase + new Title(stuff.page).urlString(), "&diff=cur&oldid=").concat(info.myLastEdit.oldid); |
|||
displayUrl(newUrl, stuff.newWin); |
|||
}; |
|||
const displayUrl = (url, newWin) => { |
|||
if (newWin) { |
|||
window.open(url); |
|||
} else { |
|||
document.location = url; |
|||
} |
|||
}; |
|||
pg.fn.purgePopups = () => { |
|||
processAllPopups(true); |
|||
setupCache(); |
|||
pg.option = {}; |
|||
abortAllDownloads(); |
|||
}; |
|||
const processAllPopups = (nullify, banish) => { |
|||
for (let i = 0; pg.current.links && i < pg.current.links.length; ++i) { |
|||
if (!pg.current.links[i].navpopup) { |
|||
continue; |
|||
} |
|||
if (nullify || banish) { |
|||
pg.current.links[i].navpopup.banish(); |
|||
} |
|||
pg.current.links[i].simpleNoMore = false; |
|||
if (nullify) { |
|||
pg.current.links[i].navpopup = null; |
|||
} |
|||
} |
|||
}; |
|||
pg.fn.disablePopups = () => { |
|||
processAllPopups(false, true); |
|||
setupTooltips(null, true); |
|||
}; |
|||
pg.fn.togglePreviews = () => { |
|||
processAllPopups(true, true); |
|||
pg.option.simplePopups = !pg.option.simplePopups; |
|||
abortAllDownloads(); |
|||
}; |
|||
const magicWatchLink = function magicWatchLink2(l) { |
|||
l.onclick = simplePrintf("pg.fn.modifyWatchlist('%s','%s');return false;", [l.article.toString(true).split("\\").join("\\\\").split("'").join(String.raw(_templateObject6 || (_templateObject6 = _taggedTemplateLiteral(["'"], ["\\'"])))), this.id]); |
|||
return wikiLink(l); |
|||
}; |
|||
pg.fn.modifyWatchlist = /* @__PURE__ */ (function() { |
|||
var _ref = _asyncToGenerator(function* (title, action) { |
|||
const reqData = { |
|||
action: "watch", |
|||
formatversion: "2", |
|||
titles: title, |
|||
uselang: mw.config.get("wgUserLanguage") |
|||
}; |
|||
if (action === "unwatch") { |
|||
reqData.unwatch = true; |
|||
} |
|||
const mwTitle = mw.Title.newFromText(title); |
|||
let messageName; |
|||
if (mwTitle && mwTitle.getNamespaceId() > 0 && mwTitle.getNamespaceId() % 2 === 1) { |
|||
messageName = action === "watch" ? "addedwatchtext-talk" : "removedwatchtext-talk"; |
|||
} else { |
|||
messageName = action === "watch" ? "addedwatchtext" : "removedwatchtext"; |
|||
} |
|||
yield getMwApi().postWithToken("watch", reqData); |
|||
yield getMwApi().loadMessagesIfMissing([messageName]); |
|||
void mw.notify(mw.message(messageName, title).parseDom(), { |
|||
tag: "popups" |
|||
}); |
|||
}); |
|||
return function(_x2, _x3) { |
|||
return _ref.apply(this, arguments); |
|||
}; |
|||
})(); |
|||
const magicHistoryLink = (l) => { |
|||
let title = ""; |
|||
let onClick = ""; |
|||
switch (l.id) { |
|||
case "lastContrib": |
|||
onClick = simplePrintf("pg.fn.getLastContrib('%s',%s)", [l.article.toString(true).split("\\").join("\\\\").split("'").join(String.raw(_templateObject7 || (_templateObject7 = _taggedTemplateLiteral(["'"], ["\\'"])))), l.newWin]); |
|||
title = popupString("lastContribHint"); |
|||
break; |
|||
case "sinceMe": |
|||
onClick = simplePrintf("pg.fn.getDiffSinceMyEdit('%s',%s)", [l.article.toString(true).split("\\").join("\\\\").split("'").join(String.raw(_templateObject8 || (_templateObject8 = _taggedTemplateLiteral(["'"], ["\\'"])))), l.newWin]); |
|||
title = popupString("sinceMeHint"); |
|||
break; |
|||
} |
|||
onClick += ";return false;"; |
|||
return generalNavLink({ |
|||
newWin: false, |
|||
title, |
|||
text: l.text, |
|||
noPopup: l.noPopup, |
|||
onclick: onClick |
|||
}); |
|||
}; |
|||
const popupMenuLink = (l) => { |
|||
const title = popupString(simplePrintf("%sHint", [l.id])); |
|||
const onClick = simplePrintf("pg.fn.%s();return false;", [l.id]); |
|||
return generalNavLink({ |
|||
newWin: false, |
|||
title, |
|||
text: l.text, |
|||
noPopup: l.noPopup, |
|||
onclick: onClick |
|||
}); |
|||
}; |
|||
const specialLink = (l) => { |
|||
var _l$sep; |
|||
if (l.specialpage === void 0 || !l.specialpage) { |
|||
return null; |
|||
} |
|||
const base = "".concat(pg.wiki.titlebase + mw.config.get("wgFormattedNamespaces")[pg.nsSpecialId], ":").concat(l.specialpage); |
|||
(_l$sep = l.sep) !== null && _l$sep !== void 0 ? _l$sep : l.sep = "&target="; |
|||
let article = l.article.urlString({ |
|||
keepSpaces: l.specialpage === "Search" |
|||
}); |
|||
let hint = popupString("".concat(l.specialpage, "Hint")); |
|||
switch (l.specialpage) { |
|||
case "Log": |
|||
switch (l.sep) { |
|||
case "&user=": |
|||
hint = popupString("userLogHint"); |
|||
break; |
|||
case "&type=block&page=": |
|||
hint = popupString("blockLogHint"); |
|||
break; |
|||
case "&page=": |
|||
hint = popupString("pageLogHint"); |
|||
break; |
|||
case "&type=protect&page=": |
|||
hint = popupString("protectLogHint"); |
|||
break; |
|||
case "&type=delete&page=": |
|||
hint = popupString("deleteLogHint"); |
|||
break; |
|||
default: |
|||
log("Unknown log type, sep=".concat(l.sep)); |
|||
hint = "Missing hint (FIXME)"; |
|||
} |
|||
break; |
|||
case "PrefixIndex": |
|||
article += "/"; |
|||
break; |
|||
} |
|||
hint = hint ? simplePrintf(hint, [safeDecodeURI(l.article)]) : safeDecodeURI("".concat(l.specialpage, ":").concat(l.article)); |
|||
const url = base + l.sep + article; |
|||
return generalNavLink({ |
|||
url, |
|||
title: hint, |
|||
text: l.text, |
|||
newWin: l.newWin, |
|||
noPopup: l.noPopup |
|||
}); |
|||
}; |
|||
const generalLink = (l) => { |
|||
let ret = "<a"; |
|||
if (l.url) { |
|||
const url = l.url.split('"').join("%22"); |
|||
ret += ' href="'.concat(url, '"'); |
|||
} |
|||
if (l.title !== void 0 && l.title) { |
|||
ret += ' title="'.concat(pg.escapeQuotesHTML(l.title), '"'); |
|||
} |
|||
if (l.onclick !== void 0 && l.onclick) { |
|||
ret += ' onclick="'.concat(pg.escapeQuotesHTML(l.onclick), '"'); |
|||
} |
|||
if (l.noPopup) { |
|||
ret += " noPopup=1"; |
|||
} |
|||
let newWin; |
|||
if (l.newWin === void 0 || l.newWin === null) { |
|||
newWin = getValueOf("popupNewWindows"); |
|||
} else { |
|||
({ |
|||
newWin |
|||
} = l); |
|||
} |
|||
if (newWin) { |
|||
ret += ' rel="noopener" target="_blank"'; |
|||
} |
|||
if (l.className !== void 0 && l.className) { |
|||
ret += ' class="'.concat(l.className, '"'); |
|||
} |
|||
ret += ">"; |
|||
if (typeof l.text === "string") { |
|||
ret += pg.escapeQuotesHTML(pg.unescapeQuotesHTML(l.text)); |
|||
} |
|||
ret += "</a>"; |
|||
return ret; |
|||
}; |
|||
const appendParamsToLink = (linkstr, params) => { |
|||
const sp = linkstr.split(/(href="[^"]+?)"/i); |
|||
if (sp.length < 2) { |
|||
return null; |
|||
} |
|||
let ret = sp.shift() + sp.shift(); |
|||
ret += "&".concat(params, '"'); |
|||
ret += sp.join(""); |
|||
return ret; |
|||
}; |
|||
const changeLinkTargetLink = (x) => { |
|||
if (x.newTarget) { |
|||
log("changeLinkTargetLink: newTarget=".concat(x.newTarget)); |
|||
} |
|||
if (x.oldTarget !== decodeURIComponent(x.oldTarget)) { |
|||
log("This might be an input problem: ".concat(x.oldTarget)); |
|||
} |
|||
const cA = mw.util.escapeRegExp(x.oldTarget); |
|||
let chs = cA.charAt(0).toUpperCase(); |
|||
chs = "[".concat(chs).concat(chs.toLowerCase(), "]"); |
|||
let currentArticleRegexBit = chs + cA.slice(1); |
|||
currentArticleRegexBit = currentArticleRegexBit.split(/[ _]+|%20/g).join("(?:[_ ]+|%20)").split(String.raw(_templateObject9 || (_templateObject9 = _taggedTemplateLiteral(["("], ["\\("])))).join(String.raw(_templateObject0 || (_templateObject0 = _taggedTemplateLiteral(["(?:%28|()"], ["(?:%28|\\()"])))).split(String.raw(_templateObject1 || (_templateObject1 = _taggedTemplateLiteral([")"], ["\\)"])))).join(String.raw(_templateObject10 || (_templateObject10 = _taggedTemplateLiteral(["(?:%29|))"], ["(?:%29|\\))"])))); |
|||
currentArticleRegexBit = "\\s*(".concat(currentArticleRegexBit, "(?:#[^\\[\\|]*)?)\\s*"); |
|||
const title = x.title || mw.config.get("wgPageName").split("_").join(" "); |
|||
const lk = titledWikiLink({ |
|||
article: new Title(title), |
|||
newWin: x.newWin, |
|||
action: "edit", |
|||
text: x.text, |
|||
title: x.hint, |
|||
className: "popup_change_title_link" |
|||
}); |
|||
let cmd = ""; |
|||
if (x.newTarget) { |
|||
const t = x.newTarget; |
|||
const s = mw.util.escapeRegExp(x.newTarget); |
|||
if (x.alsoChangeLabel) { |
|||
cmd += "s~\\[\\[".concat(currentArticleRegexBit, "\\]\\]~[[").concat(t, "]]~g;"); |
|||
cmd += "s~\\[\\[".concat(currentArticleRegexBit, "[|]~[[").concat(t, "|~g;"); |
|||
cmd += "s~\\[\\[".concat(s, "\\|").concat(s, "\\]\\]~[[").concat(t, "]]~g"); |
|||
} else { |
|||
cmd += "s~\\[\\[".concat(currentArticleRegexBit, "\\]\\]~[[").concat(t, "|$1]]~g;"); |
|||
cmd += "s~\\[\\[".concat(currentArticleRegexBit, "[|]~[[").concat(t, "|~g;"); |
|||
cmd += "s~\\[\\[".concat(s, "\\|").concat(s, "\\]\\]~[[").concat(t, "]]~g"); |
|||
} |
|||
} else { |
|||
cmd += "s~\\[\\[".concat(currentArticleRegexBit, "\\]\\]~$1~g;"); |
|||
cmd += "s~\\[\\[".concat(currentArticleRegexBit, "[|](.*?)\\]\\]~$2~g"); |
|||
} |
|||
cmd = "autoedit=".concat(encodeURIComponent(cmd)); |
|||
cmd += "&autoclick=".concat(encodeURIComponent(x.clickButton), "&actoken=").concat(encodeURIComponent(autoClickToken())); |
|||
cmd += x.minor === null ? "" : "&autominor=".concat(encodeURIComponent(x.minor)); |
|||
cmd += x.watch === null ? "" : "&autowatch=".concat(encodeURIComponent(x.watch)); |
|||
cmd += "&autosummary=".concat(encodeURIComponent(x.summary)); |
|||
cmd += "&autoimpl=".concat(encodeURIComponent(popupString("autoedit_version"))); |
|||
return appendParamsToLink(lk, cmd); |
|||
}; |
|||
const redirLink = (redirMatch, article) => { |
|||
let ret = ""; |
|||
if (getValueOf("popupAppendRedirNavLinks") && getValueOf("popupNavLinks")) { |
|||
ret += "<hr>"; |
|||
if (getValueOf("popupFixRedirs") && autoEdit !== void 0 && autoEdit) { |
|||
ret += popupString("Redirects to: (Fix "); |
|||
log("redirLink: newTarget=".concat(redirMatch)); |
|||
ret += addPopupShortcut(changeLinkTargetLink({ |
|||
newTarget: redirMatch, |
|||
text: popupString("target"), |
|||
hint: popupString("Fix this redirect, changing just the link target"), |
|||
summary: simplePrintf(getValueOf("popupFixRedirsSummary"), [article.toString(), redirMatch]), |
|||
oldTarget: article.toString(), |
|||
clickButton: getValueOf("popupRedirAutoClick"), |
|||
minor: true, |
|||
watch: getValueOf("popupWatchRedirredPages") |
|||
}), "R"); |
|||
ret += popupString(" or "); |
|||
ret += addPopupShortcut(changeLinkTargetLink({ |
|||
newTarget: redirMatch, |
|||
text: popupString("target & label"), |
|||
hint: popupString("Fix this redirect, changing the link target and label"), |
|||
summary: simplePrintf(getValueOf("popupFixRedirsSummary"), [article.toString(), redirMatch]), |
|||
oldTarget: article.toString(), |
|||
clickButton: getValueOf("popupRedirAutoClick"), |
|||
minor: true, |
|||
watch: getValueOf("popupWatchRedirredPages"), |
|||
alsoChangeLabel: true |
|||
}), "R"); |
|||
ret += popupString(")"); |
|||
} else { |
|||
ret += popupString("Redirects") + popupString(" to "); |
|||
} |
|||
return ret; |
|||
} |
|||
return "<br> ".concat(popupString("Redirects")).concat(popupString(" to ")).concat(titledWikiLink({ |
|||
article: new Title().fromWikiText(redirMatch), |
|||
action: "view", |
|||
text: safeDecodeURI(redirMatch), |
|||
title: popupString("Bypass redirect") |
|||
})); |
|||
}; |
|||
const arinLink = (l) => { |
|||
if (!saneLinkCheck(l)) { |
|||
return null; |
|||
} |
|||
if (!l.article.isIpUser() || !pg.wiki.wikimedia) { |
|||
return null; |
|||
} |
|||
const uN = l.article.userName(); |
|||
return generalNavLink({ |
|||
url: "http://ws.arin.net/cgi-bin/whois.pl?queryinput=".concat(encodeURIComponent(uN)), |
|||
newWin: l.newWin, |
|||
title: tprintf("Look up %s in ARIN whois database", [uN]), |
|||
text: l.text, |
|||
noPopup: 1 |
|||
}); |
|||
}; |
|||
const toolDbName = (cookieStyle) => { |
|||
let ret = mw.config.get("wgDBname"); |
|||
if (!cookieStyle) { |
|||
ret += "_p"; |
|||
} |
|||
return ret; |
|||
}; |
|||
const saneLinkCheck = (l) => { |
|||
if (typeof l.article !== typeof {} || typeof l.text !== "string") { |
|||
return false; |
|||
} |
|||
return true; |
|||
}; |
|||
const editCounterLink = (l) => { |
|||
if (!saneLinkCheck(l)) { |
|||
return null; |
|||
} |
|||
if (!pg.wiki.wikimedia) { |
|||
return null; |
|||
} |
|||
const uN = l.article.userName(); |
|||
const tool = getValueOf("popupEditCounterTool"); |
|||
let url; |
|||
const defaultToolUrl = "//tools.wmflabs.org/supercount/index.php?user=$1&project=$2.$3"; |
|||
switch (tool) { |
|||
case "custom": |
|||
url = simplePrintf(getValueOf("popupEditCounterUrl"), [encodeURIComponent(uN), toolDbName()]); |
|||
break; |
|||
default: { |
|||
const theWiki = pg.wiki.hostname.split("."); |
|||
url = simplePrintf(defaultToolUrl, [encodeURIComponent(uN), theWiki[0], theWiki[1]]); |
|||
} |
|||
} |
|||
return generalNavLink({ |
|||
url, |
|||
title: tprintf("editCounterLinkHint", [uN]), |
|||
newWin: l.newWin, |
|||
text: l.text, |
|||
noPopup: 1 |
|||
}); |
|||
}; |
|||
const editorListLink = (l) => { |
|||
if (!saneLinkCheck(l)) { |
|||
return null; |
|||
} |
|||
const article = l.article.articleFromTalkPage() || l.article; |
|||
const url = "https://xtools.wmflabs.org/articleinfo/".concat(encodeURI(pg.wiki.hostname), "/").concat(article.urlString(), "?uselang=").concat(mw.config.get("wgUserLanguage")); |
|||
return generalNavLink({ |
|||
url, |
|||
title: tprintf("editorListHint", [article]), |
|||
newWin: l.newWin, |
|||
text: l.text, |
|||
noPopup: 1 |
|||
}); |
|||
}; |
|||
const generalNavLink = (l) => { |
|||
l.className = l.className === null ? "popupNavLink" : l.className; |
|||
return generalLink(l); |
|||
}; |
|||
const getHistoryInfo = (wikipage, whatNext) => { |
|||
log("getHistoryInfo"); |
|||
getHistory(wikipage, whatNext ? (d) => { |
|||
whatNext(processHistory(d)); |
|||
} : processHistory); |
|||
}; |
|||
const getHistory = (wikipage, onComplete) => { |
|||
log("getHistory"); |
|||
const url = "".concat(pg.wiki.apiwikibase, "?format=json&formatversion=2&action=query&prop=revisions&titles=").concat(new Title(wikipage).urlString(), "&rvlimit=").concat(getValueOf("popupHistoryLimit")); |
|||
log("getHistory: url=".concat(url)); |
|||
return startDownload(url, "".concat(pg.idNumber, "history"), onComplete); |
|||
}; |
|||
const processHistory = (download) => { |
|||
const jsobj = getJsObj(download.data); |
|||
try { |
|||
const { |
|||
revisions |
|||
} = anyChild(jsobj.query.pages); |
|||
const edits = []; |
|||
var _iterator25 = _createForOfIteratorHelper(revisions), _step25; |
|||
try { |
|||
for (_iterator25.s(); !(_step25 = _iterator25.n()).done; ) { |
|||
const revision = _step25.value; |
|||
edits.push({ |
|||
oldid: revision.revid, |
|||
editor: revision.user |
|||
}); |
|||
} |
|||
} catch (err) { |
|||
_iterator25.e(err); |
|||
} finally { |
|||
_iterator25.f(); |
|||
} |
|||
log("processed ".concat(edits.length, " edits")); |
|||
return finishProcessHistory(edits, mw.config.get("wgUserName")); |
|||
} catch { |
|||
log("Something went wrong with JSON business"); |
|||
return finishProcessHistory([]); |
|||
} |
|||
}; |
|||
const finishProcessHistory = (edits, userName) => { |
|||
const histInfo = {}; |
|||
histInfo.edits = edits; |
|||
histInfo.userName = userName; |
|||
for (let i = 0; i < edits.length; ++i) { |
|||
if (histInfo.myLastEdit === void 0 && userName && edits[i].editor === userName) { |
|||
histInfo.myLastEdit = { |
|||
index: i, |
|||
oldid: edits[i].oldid, |
|||
previd: i === 0 ? null : edits[i - 1].oldid |
|||
}; |
|||
} |
|||
if (histInfo.firstNewEditor === void 0 && edits[i].editor !== edits[0].editor) { |
|||
histInfo.firstNewEditor = { |
|||
index: i, |
|||
oldid: edits[i].oldid, |
|||
previd: i === 0 ? null : edits[i - 1].oldid |
|||
}; |
|||
} |
|||
} |
|||
return histInfo; |
|||
}; |
|||
const defaultize = (x) => { |
|||
var _pg$option, _pg$option$x; |
|||
(_pg$option$x = (_pg$option = pg.option)[x]) !== null && _pg$option$x !== void 0 ? _pg$option$x : _pg$option[x] = window[x] === void 0 ? pg.optionDefault[x] : window[x]; |
|||
}; |
|||
const newOption = (x, def) => { |
|||
pg.optionDefault[x] = def; |
|||
}; |
|||
const setDefault = (x, def) => { |
|||
return newOption(x, def); |
|||
}; |
|||
const getValueOf = (varName) => { |
|||
defaultize(varName); |
|||
return pg.option[varName]; |
|||
}; |
|||
const setOptions = () => { |
|||
let userIsSysop = false; |
|||
if (mw.config.get("wgUserGroups")) { |
|||
for (let g = 0; g < mw.config.get("wgUserGroups").length; ++g) { |
|||
if (mw.config.get("wgUserGroups")[g] === "sysop") { |
|||
userIsSysop = true; |
|||
} |
|||
if (mw.config.get("wgUserGroups")[g] === "steward") { |
|||
userIsSysop = true; |
|||
} |
|||
} |
|||
} |
|||
newOption("popupDelay", 0.5); |
|||
newOption("popupHideDelay", 0.5); |
|||
newOption("simplePopups", false); |
|||
newOption("popupStructure", "shortmenus"); |
|||
newOption("popupActionsMenu", true); |
|||
newOption("popupSetupMenu", true); |
|||
newOption("popupAdminLinks", userIsSysop); |
|||
newOption("popupShortcutKeys", false); |
|||
newOption("popupHistoricalLinks", true); |
|||
newOption("popupOnlyArticleLinks", true); |
|||
newOption("removeTitles", true); |
|||
newOption("popupMaxWidth", 350); |
|||
newOption("popupSimplifyMainLink", true); |
|||
newOption("popupAppendRedirNavLinks", true); |
|||
newOption("popupTocLinks", false); |
|||
newOption("popupSubpopups", true); |
|||
newOption( |
|||
"popupDragHandle", |
|||
false |
|||
/* 'popupTopLinks' */ |
|||
); |
|||
newOption("popupLazyPreviews", true); |
|||
newOption("popupLazyDownloads", true); |
|||
newOption("popupAllDabsStubs", false); |
|||
newOption("popupDebugging", false); |
|||
newOption("popupActiveNavlinks", true); |
|||
newOption("popupModifier", false); |
|||
newOption("popupModifierAction", "enable"); |
|||
newOption("popupDraggable", true); |
|||
newOption("popupReview", false); |
|||
newOption("popupLocale", false); |
|||
newOption("popupDateTimeFormatterOptions", { |
|||
year: "numeric", |
|||
month: "long", |
|||
day: "numeric", |
|||
hour12: false, |
|||
hour: "2-digit", |
|||
minute: "2-digit", |
|||
second: "2-digit" |
|||
}); |
|||
newOption("popupDateFormatterOptions", { |
|||
year: "numeric", |
|||
month: "long", |
|||
day: "numeric" |
|||
}); |
|||
newOption("popupTimeFormatterOptions", { |
|||
hour12: false, |
|||
hour: "2-digit", |
|||
minute: "2-digit", |
|||
second: "2-digit" |
|||
}); |
|||
newOption("popupImages", true); |
|||
newOption("imagePopupsForImages", true); |
|||
newOption("popupNeverGetThumbs", false); |
|||
newOption("popupThumbAction", "imagepage"); |
|||
newOption("popupImageSize", 60); |
|||
newOption("popupImageSizeLarge", 200); |
|||
newOption("popupFixRedirs", false); |
|||
newOption("popupRedirAutoClick", "wpDiff"); |
|||
newOption("popupFixDabs", false); |
|||
newOption("popupDabsAutoClick", "wpDiff"); |
|||
newOption("popupRevertSummaryPrompt", false); |
|||
newOption("popupMinorReverts", false); |
|||
newOption("popupRedlinkRemoval", false); |
|||
newOption("popupRedlinkAutoClick", "wpDiff"); |
|||
newOption("popupWatchDisambiggedPages", null); |
|||
newOption("popupWatchRedirredPages", null); |
|||
newOption("popupDabWiktionary", "last"); |
|||
newOption("popupNavLinks", true); |
|||
newOption("popupNavLinkSeparator", " ⋅ "); |
|||
newOption("popupLastEditLink", true); |
|||
newOption("popupEditCounterTool", "supercount"); |
|||
newOption("popupEditCounterUrl", ""); |
|||
newOption("popupPreviews", true); |
|||
newOption("popupSummaryData", true); |
|||
newOption("popupMaxPreviewSentences", 5); |
|||
newOption("popupMaxPreviewCharacters", 600); |
|||
newOption("popupLastModified", true); |
|||
newOption("popupPreviewKillTemplates", true); |
|||
newOption("popupPreviewRawTemplates", true); |
|||
newOption("popupPreviewFirstParOnly", true); |
|||
newOption("popupPreviewCutHeadings", true); |
|||
newOption("popupPreviewButton", false); |
|||
newOption("popupPreviewButtonEvent", "click"); |
|||
newOption("popupPreviewDiffs", true); |
|||
newOption("popupDiffMaxLines", 100); |
|||
newOption("popupDiffContextLines", 2); |
|||
newOption("popupDiffContextCharacters", 40); |
|||
newOption("popupDiffDates", true); |
|||
newOption("popupDiffDatePrinter", "toLocaleString"); |
|||
newOption("popupReviewedSummary", popupString("defaultpopupReviewedSummary")); |
|||
newOption("popupFixDabsSummary", popupString("defaultpopupFixDabsSummary")); |
|||
newOption("popupExtendedRevertSummary", popupString("defaultpopupExtendedRevertSummary")); |
|||
newOption("popupRevertSummary", popupString("defaultpopupRevertSummary")); |
|||
newOption("popupRevertToPreviousSummary", popupString("defaultpopupRevertToPreviousSummary")); |
|||
newOption("popupQueriedRevertSummary", popupString("defaultpopupQueriedRevertSummary")); |
|||
newOption("popupQueriedRevertToPreviousSummary", popupString("defaultpopupQueriedRevertToPreviousSummary")); |
|||
newOption("popupFixRedirsSummary", popupString("defaultpopupFixRedirsSummary")); |
|||
newOption("popupRedlinkSummary", popupString("defaultpopupRedlinkSummary")); |
|||
newOption("popupRmDabLinkSummary", popupString("defaultpopupRmDabLinkSummary")); |
|||
newOption("popupHistoryLimit", 50); |
|||
newOption("popupFilters", [popupFilterStubDetect, popupFilterDisambigDetect, popupFilterPageSize, popupFilterCountLinks, popupFilterCountImages, popupFilterCountCategories, popupFilterLastModified]); |
|||
newOption("extraPopupFilters", []); |
|||
newOption("popupOnEditSelection", "cursor"); |
|||
newOption("popupPreviewHistory", true); |
|||
newOption("popupImageLinks", true); |
|||
newOption("popupCategoryMembers", true); |
|||
newOption("popupUserInfo", true); |
|||
newOption("popupHistoryPreviewLimit", 25); |
|||
newOption("popupContribsPreviewLimit", 25); |
|||
newOption("popupRevDelUrl", "//en.wikipedia.org/wiki/Wikipedia:Revision_deletion"); |
|||
newOption("popupShowGender", true); |
|||
newOption("popupNewWindows", false); |
|||
newOption("popupLinksNewWindow", { |
|||
lastContrib: true, |
|||
sinceMe: true |
|||
}); |
|||
newOption("popupDabRegexp", String.raw(_templateObject11 || (_templateObject11 = _taggedTemplateLiteral(["{{s*(d(ab|isamb(ig(uation)?)?)|(((geo|hn|road?|school|number)dis)|[234][lc][acw]|(road|ship)index))s*(|[^}]*)?}}|is a .*disambiguation.*page"], ["\\{\\{\\s*(d(ab|isamb(ig(uation)?)?)|(((geo|hn|road?|school|number)dis)|[234][lc][acw]|(road|ship)index))\\s*(\\|[^}]*)?\\}\\}|is a .*disambiguation.*page"])))); |
|||
newOption("popupAnchorRegexp", "anchors?"); |
|||
newOption("popupStubRegexp", "(sect)?stub[}][}]|This .*-related article is a .*stub"); |
|||
newOption("popupImageVarsRegexp", "image|image_(?:file|skyline|name|flag|seal)|cover|badge|logo"); |
|||
}; |
|||
pg.string = { |
|||
// summary data, searching etc. |
|||
article: "article", |
|||
category: "category", |
|||
categories: "categories", |
|||
image: "image", |
|||
images: "images", |
|||
stub: "stub", |
|||
"section stub": "section stub", |
|||
"Empty page": "Empty page", |
|||
kB: "kB", |
|||
bytes: "bytes", |
|||
day: "day", |
|||
days: "days", |
|||
hour: "hour", |
|||
hours: "hours", |
|||
minute: "minute", |
|||
minutes: "minutes", |
|||
second: "second", |
|||
seconds: "seconds", |
|||
week: "week", |
|||
weeks: "weeks", |
|||
search: "search", |
|||
SearchHint: "Find English Wikipedia articles containing %s", |
|||
web: "web", |
|||
global: "global", |
|||
// article-related actions and info |
|||
// (some actions also apply to user pages) |
|||
actions: "actions", |
|||
popupsMenu: "popups", |
|||
togglePreviewsHint: "Toggle preview generation in popups on this page", |
|||
"enable previews": "enable previews", |
|||
"disable previews": "disable previews", |
|||
"toggle previews": "toggle previews", |
|||
"show preview": "show preview", |
|||
reset: "reset", |
|||
"more...": "more...", |
|||
disable: "disable popups", |
|||
disablePopupsHint: "Disable popups on this page. Reload page to re-enable.", |
|||
historyfeedHint: "RSS feed of recent changes to this page", |
|||
purgePopupsHint: "Reset popups, clearing all cached popup data.", |
|||
PopupsHint: "Reset popups, clearing all cached popup data.", |
|||
spacebar: "space", |
|||
view: "view", |
|||
"view article": "view article", |
|||
viewHint: "Go to %s", |
|||
talk: "talk", |
|||
"talk page": "talk page", |
|||
"this revision": "this revision", |
|||
"revision %s of %s": "revision %s of %s", |
|||
"Revision %s of %s": "Revision %s of %s", |
|||
"the revision prior to revision %s of %s": "the revision prior to revision %s of %s", |
|||
"Toggle image size": "Click to toggle image size", |
|||
del: "del", |
|||
delete: "delete", |
|||
deleteHint: "Delete %s", |
|||
undeleteShort: "un", |
|||
UndeleteHint: "Show the deletion history for %s", |
|||
protect: "protect", |
|||
protectHint: "Restrict editing rights to %s", |
|||
unprotectShort: "un", |
|||
unprotectHint: "Allow %s to be edited by anyone again", |
|||
"send thanks": "send thanks", |
|||
ThanksHint: "Send a thank you notification to this user", |
|||
move: "move", |
|||
"move page": "move page", |
|||
MovepageHint: "Change the title of %s", |
|||
edit: "edit", |
|||
"edit article": "edit article", |
|||
editHint: "Change the content of %s", |
|||
"edit talk": "edit talk", |
|||
new: "new", |
|||
"new topic": "new topic", |
|||
newSectionHint: "Start a new section on %s", |
|||
"null edit": "null edit", |
|||
nullEditHint: "Submit an edit to %s, making no changes ", |
|||
hist: "hist", |
|||
history: "history", |
|||
historyHint: "List the changes made to %s", |
|||
last: "prev", |
|||
lastEdit: "lastEdit", |
|||
"mark patrolled": "mark patrolled", |
|||
markpatrolledHint: "Mark this edit as patrolled", |
|||
"Could not marked this edit as patrolled": "Could not marked this edit as patrolled", |
|||
"show last edit": "most recent edit", |
|||
"Show the last edit": "Show the effects of the most recent change", |
|||
lastContrib: "lastContrib", |
|||
"last set of edits": "latest edits", |
|||
lastContribHint: "Show the net effect of changes made by the last editor", |
|||
cur: "cur", |
|||
diffCur: "diffCur", |
|||
"Show changes since revision %s": "Show changes since revision %s", |
|||
"%s old": "%s old", |
|||
oldEdit: "oldEdit", |
|||
purge: "purge", |
|||
purgeHint: "Demand a fresh copy of %s", |
|||
raw: "source", |
|||
rawHint: "Download the source of %s", |
|||
render: "simple", |
|||
renderHint: "Show a plain HTML version of %s", |
|||
"Show the edit made to get revision": "Show the edit made to get revision", |
|||
sinceMe: "sinceMe", |
|||
"changes since mine": "diff my edit", |
|||
sinceMeHint: "Show changes since my last edit", |
|||
"Couldn't find an edit by %s\nin the last %s edits to\n%s": "Couldn't find an edit by %s\nin the last %s edits to\n%s", |
|||
eds: "eds", |
|||
editors: "editors", |
|||
editorListHint: "List the users who have edited %s", |
|||
related: "related", |
|||
relatedChanges: "relatedChanges", |
|||
"related changes": "related changes", |
|||
RecentchangeslinkedHint: "Show changes in articles related to %s", |
|||
editOld: "editOld", |
|||
rv: "rv", |
|||
revert: "revert", |
|||
revertHint: "Revert to %s", |
|||
defaultpopupReviewedSummary: "Accepted by reviewing the [[Special:diff/%s/%s|difference]] between this version and previously accepted version using [[:enwiki:Wikipedia:Tools/Navigation_popups|popups]]", |
|||
defaultpopupRedlinkSummary: "Removing link to empty page [[%s]] using [[:enwiki:Wikipedia:Tools/Navigation_popups|popups]]", |
|||
defaultpopupFixDabsSummary: "Disambiguate [[%s]] to [[%s]] using [[:enwiki:Wikipedia:Tools/Navigation_popups|popups]]", |
|||
defaultpopupFixRedirsSummary: "Redirect bypass from [[%s]] to [[%s]] using [[:enwiki:Wikipedia:Tools/Navigation_popups|popups]]", |
|||
defaultpopupExtendedRevertSummary: "Revert to revision dated %s by %s, oldid %s using [[:enwiki:Wikipedia:Tools/Navigation_popups|popups]]", |
|||
defaultpopupRevertToPreviousSummary: "Revert to the revision prior to revision %s using [[:enwiki:Wikipedia:Tools/Navigation_popups|popups]]", |
|||
defaultpopupRevertSummary: "Revert to revision %s using [[:enwiki:Wikipedia:Tools/Navigation_popups|popups]]", |
|||
defaultpopupQueriedRevertToPreviousSummary: "Revert to the revision prior to revision $1 dated $2 by $3 using [[:enwiki:Wikipedia:Tools/Navigation_popups|popups]]", |
|||
defaultpopupQueriedRevertSummary: "Revert to revision $1 dated $2 by $3 using [[:enwiki:Wikipedia:Tools/Navigation_popups|popups]]", |
|||
defaultpopupRmDabLinkSummary: "Remove link to dab page [[%s]] using [[:enwiki:Wikipedia:Tools/Navigation_popups|popups]]", |
|||
Redirects: "Redirects", |
|||
" to ": " to ", |
|||
"Bypass redirect": "Bypass redirect", |
|||
"Fix this redirect": "Fix this redirect", |
|||
disambig: "disambig", |
|||
disambigHint: "Disambiguate this link to [[%s]]", |
|||
"Click to disambiguate this link to:": "Click to disambiguate this link to:", |
|||
"remove this link": "remove this link", |
|||
"remove all links to this page from this article": "remove all links to this page from this article", |
|||
"remove all links to this disambig page from this article": "remove all links to this disambig page from this article", |
|||
mainlink: "mainlink", |
|||
wikiLink: "wikiLink", |
|||
wikiLinks: "wikiLinks", |
|||
"links here": "links here", |
|||
whatLinksHere: "whatLinksHere", |
|||
"what links here": "what links here", |
|||
WhatlinkshereHint: "List the pages that are hyperlinked to %s", |
|||
unwatchShort: "un", |
|||
watchThingy: "watch", |
|||
watchHint: "Add %s to my watchlist", |
|||
unwatchHint: "Remove %s from my watchlist", |
|||
"Only found one editor: %s made %s edits": "Only found one editor: %s made %s edits", |
|||
"%s seems to be the last editor to the page %s": "%s seems to be the last editor to the page %s", |
|||
rss: "rss", |
|||
// diff previews |
|||
"Diff truncated for performance reasons": "Diff truncated for performance reasons", |
|||
"Old revision": "Old revision", |
|||
"New revision": "New revision", |
|||
"Something went wrong :-(": "Something went wrong :-(", |
|||
"Empty revision, maybe non-existent": "Empty revision, maybe non-existent", |
|||
"Unknown date": "Unknown date", |
|||
// other special previews |
|||
"Empty category": "Empty category", |
|||
"Category members (%s shown)": "Category members (%s shown)", |
|||
"No image links found": "No image links found", |
|||
"File links": "File links", |
|||
"No image found": "No image found", |
|||
"Image from Commons": "Image from Commons", |
|||
"Description page": "Description page", |
|||
"Alt text:": "Alt text:", |
|||
revdel: "Hidden revision", |
|||
// user-related actions and info |
|||
user: "user", |
|||
"user page": "user page", |
|||
"user talk": "user talk", |
|||
"edit user talk": "edit user talk", |
|||
"leave comment": "leave comment", |
|||
email: "email", |
|||
"email user": "email user", |
|||
EmailuserHint: "Send an email to %s", |
|||
space: "space", |
|||
PrefixIndexHint: "Show pages in the userspace of %s", |
|||
count: "count", |
|||
"edit counter": "edit counter", |
|||
editCounterLinkHint: "Count the contributions made by %s", |
|||
contribs: "contribs", |
|||
contributions: "contributions", |
|||
deletedContribs: "deleted contributions", |
|||
DeletedcontributionsHint: "List deleted edits made by %s", |
|||
ContributionsHint: "List the contributions made by %s", |
|||
log: "log", |
|||
"user log": "user log", |
|||
userLogHint: "Show %s's user log", |
|||
arin: "ARIN lookup", |
|||
"Look up %s in ARIN whois database": "Look up %s in the ARIN whois database", |
|||
unblockShort: "un", |
|||
block: "block", |
|||
"block user": "block user", |
|||
IpblocklistHint: "Unblock %s", |
|||
BlockipHint: "Prevent %s from editing", |
|||
"block log": "block log", |
|||
blockLogHint: "Show the block log for %s", |
|||
protectLogHint: "Show the protection log for %s", |
|||
pageLogHint: "Show the page log for %s", |
|||
deleteLogHint: "Show the deletion log for %s", |
|||
"Invalid %s %s": "The option %s is invalid: %s", |
|||
"No backlinks found": "No backlinks found", |
|||
" and more": " and more", |
|||
undo: "undo", |
|||
undoHint: "undo this edit", |
|||
"Download preview data": "Download preview data", |
|||
"Invalid or IP user": "Invalid or IP user", |
|||
"Not a registered username": "Not a registered username", |
|||
BLOCKED: "BLOCKED", |
|||
"Has blocks": "Has blocks", |
|||
" edits since: ": " edits since: ", |
|||
"last edit on ": "last edit on ", |
|||
"he/him": "he/him", |
|||
"she/her": "she/her", |
|||
// Autoediting |
|||
"Enter a non-empty edit summary or press cancel to abort": "Enter a non-empty edit summary or press cancel to abort", |
|||
"Failed to get revision information, please edit manually.\n\n": "Failed to get revision information, please edit manually.\n\n", |
|||
"The %s button has been automatically clicked. Please wait for the next page to load.": "The %s button has been automatically clicked. Please wait for the next page to load.", |
|||
"Could not find button %s. Please check the settings in your javascript file.": "Could not find button %s. Please check the settings in your javascript file.", |
|||
// Popups setup |
|||
"Open full-size image": "Open full-size image", |
|||
autoedit_version: "np20140416" |
|||
}; |
|||
const popupString = (str) => { |
|||
if (message !== void 0 && message && message[str]) { |
|||
return message[str]; |
|||
} |
|||
if (pg.string[str]) { |
|||
return pg.string[str]; |
|||
} |
|||
return str; |
|||
}; |
|||
const tprintf = (str, subs) => { |
|||
if (typeof subs !== typeof []) { |
|||
subs = [subs]; |
|||
} |
|||
return simplePrintf(popupString(str), subs); |
|||
}; |
|||
if (document.readyState === "complete") { |
|||
autoEdit(); |
|||
} else { |
|||
$(window).on("load", autoEdit); |
|||
} |
|||
(() => { |
|||
let once = true; |
|||
const dynamicContentHandler = ($content) => { |
|||
if ($content.attr("id") === "mw-content-text" && once) { |
|||
once = false; |
|||
return; |
|||
} |
|||
const registerHooksForVisibleNavpops = () => { |
|||
for (let i = 0; pg.current.links && i < pg.current.links.length; i++) { |
|||
const navpop = pg.current.links[i].navpopup; |
|||
if (!navpop || !navpop.isVisible()) { |
|||
continue; |
|||
} |
|||
Navpopup.tracker.addHook(posCheckerHook(navpop)); |
|||
} |
|||
}; |
|||
const doIt = () => { |
|||
registerHooksForVisibleNavpops(); |
|||
$content.each((_index, element) => { |
|||
element.ranSetupTooltipsAlready = false; |
|||
setupTooltips(element); |
|||
}); |
|||
}; |
|||
setupPopups(doIt); |
|||
}; |
|||
mw.hook("wikipage.content").add(dynamicContentHandler); |
|||
mw.hook("ext.echo.overlay.beforeShowingOverlay").add(($overlay) => { |
|||
dynamicContentHandler($overlay.find(".mw-echo-state")); |
|||
}); |
|||
})(); |
|||
}; |
|||
//! src/Navigation_popups/Navigation_popups.ts |
|||
$(popups); |
|||
})(); |
|||
nx = x + (ex - o.lastMouseX) * (o.hmode ? 1 : -1); |
|||
ny = y + (ey - o.lastMouseY) * (o.vmode ? 1 : -1); |
|||
/* </nowiki> */ |
|||
this.obj.root.style[o.hmode ? 'left' : 'right'] = nx + 'px'; |
|||
this.obj.root.style[o.vmode ? 'top' : 'bottom'] = ny + 'px'; |
|||
this.obj.lastMouseX = ex; |
|||
this.obj.lastMouseY = ey; |
|||
this.obj.root.onthis(nx, ny); |
|||
return false; |
|||
}; |
|||
/** |
|||
* Ends the drag. |
|||
* |
|||
* @private |
|||
*/ |
|||
Drag.prototype.end = function () { |
|||
document.onmousemove = this.obj.onmousemoveDefault; |
|||
document.onmouseup = null; |
|||
this.obj.dragging = false; |
|||
if (this.endHook) { |
|||
this.endHook( |
|||
parseInt(this.obj.root.style[this.obj.hmode ? 'left' : 'right'], 10), |
|||
parseInt(this.obj.root.style[this.obj.vmode ? 'top' : 'bottom'], 10) |
|||
); |
|||
} |
|||
}; |
|||
// ENDFILE: domdrag.js |
|||
// STARTFILE: structures.js |
|||
pg.structures.original = {}; |
|||
pg.structures.original.popupLayout = function () { |
|||
return [ |
|||
'popupError', |
|||
'popupImage', |
|||
'popupTopLinks', |
|||
'popupTitle', |
|||
'popupUserData', |
|||
'popupData', |
|||
'popupOtherLinks', |
|||
'popupRedir', |
|||
[ |
|||
'popupWarnRedir', |
|||
'popupRedirTopLinks', |
|||
'popupRedirTitle', |
|||
'popupRedirData', |
|||
'popupRedirOtherLinks', |
|||
], |
|||
'popupMiscTools', |
|||
['popupRedlink'], |
|||
'popupPrePreviewSep', |
|||
'popupPreview', |
|||
'popupSecondPreview', |
|||
'popupPreviewMore', |
|||
'popupPostPreview', |
|||
'popupFixDab', |
|||
]; |
|||
}; |
|||
pg.structures.original.popupRedirSpans = function () { |
|||
return [ |
|||
'popupRedir', |
|||
'popupWarnRedir', |
|||
'popupRedirTopLinks', |
|||
'popupRedirTitle', |
|||
'popupRedirData', |
|||
'popupRedirOtherLinks', |
|||
]; |
|||
}; |
|||
pg.structures.original.popupTitle = function (x) { |
|||
log('defaultstructure.popupTitle'); |
|||
if (!getValueOf('popupNavLinks')) { |
|||
return navlinkStringToHTML('<b><<mainlink>></b>', x.article, x.params); |
|||
} |
|||
return ''; |
|||
}; |
|||
pg.structures.original.popupTopLinks = function (x) { |
|||
log('defaultstructure.popupTopLinks'); |
|||
if (getValueOf('popupNavLinks')) { |
|||
return navLinksHTML(x.article, x.hint, x.params); |
|||
} |
|||
return ''; |
|||
}; |
|||
pg.structures.original.popupImage = function (x) { |
|||
log('original.popupImage, x.article=' + x.article + ', x.navpop.idNumber=' + x.navpop.idNumber); |
|||
return imageHTML(x.article, x.navpop.idNumber); |
|||
}; |
|||
pg.structures.original.popupRedirTitle = pg.structures.original.popupTitle; |
|||
pg.structures.original.popupRedirTopLinks = pg.structures.original.popupTopLinks; |
|||
function copyStructure(oldStructure, newStructure) { |
|||
pg.structures[newStructure] = {}; |
|||
for (const prop in pg.structures[oldStructure]) { |
|||
pg.structures[newStructure][prop] = pg.structures[oldStructure][prop]; |
|||
} |
|||
} |
|||
copyStructure('original', 'nostalgia'); |
|||
pg.structures.nostalgia.popupTopLinks = function (x) { |
|||
let str = ''; |
|||
str += '<b><<mainlink|shortcut= >></b>'; |
|||
// user links |
|||
// contribs - log - count - email - block |
|||
// count only if applicable; block only if popupAdminLinks |
|||
str += 'if(user){<br><<contribs|shortcut=c>>'; |
|||
str += 'if(wikimedia){*<<count|shortcut=#>>}'; |
|||
str += 'if(ipuser){}else{*<<email|shortcut=E>>}if(admin){*<<block|shortcut=b>>}}'; |
|||
// editing links |
|||
// talkpage -> edit|new - history - un|watch - article|edit |
|||
// other page -> edit - history - un|watch - talk|edit|new |
|||
const editstr = '<<edit|shortcut=e>>'; |
|||
const editOldidStr = |
|||
'if(oldid){<<editOld|shortcut=e>>|<<revert|shortcut=v|rv>>|<<edit|cur>>}else{' + |
|||
editstr + |
|||
'}'; |
|||
const historystr = '<<history|shortcut=h>>'; |
|||
const watchstr = '<<unwatch|unwatchShort>>|<<watch|shortcut=w|watchThingy>>'; |
|||
str += |
|||
'<br>if(talk){' + |
|||
editOldidStr + |
|||
'|<<new|shortcut=+>>' + |
|||
'*' + |
|||
historystr + |
|||
'*' + |
|||
watchstr + |
|||
'*' + |
|||
'<b><<article|shortcut=a>></b>|<<editArticle|edit>>' + |
|||
'}else{' + // not a talk page |
|||
editOldidStr + |
|||
'*' + |
|||
historystr + |
|||
'*' + |
|||
watchstr + |
|||
'*' + |
|||
'<b><<talk|shortcut=t>></b>|<<editTalk|edit>>|<<newTalk|shortcut=+|new>>}'; |
|||
// misc links |
|||
str += '<br><<whatLinksHere|shortcut=l>>*<<relatedChanges|shortcut=r>>'; |
|||
str += 'if(admin){<br>}else{*}<<move|shortcut=m>>'; |
|||
// admin links |
|||
str += |
|||
'if(admin){*<<unprotect|unprotectShort>>|<<protect|shortcut=p>>*' + |
|||
'<<undelete|undeleteShort>>|<<delete|shortcut=d>>}'; |
|||
return navlinkStringToHTML(str, x.article, x.params); |
|||
}; |
|||
pg.structures.nostalgia.popupRedirTopLinks = pg.structures.nostalgia.popupTopLinks; |
|||
/** -- fancy -- */ |
|||
copyStructure('original', 'fancy'); |
|||
pg.structures.fancy.popupTitle = function (x) { |
|||
return navlinkStringToHTML('<font size=+0><<mainlink>></font>', x.article, x.params); |
|||
}; |
|||
pg.structures.fancy.popupTopLinks = function (x) { |
|||
const hist = |
|||
'<<history|shortcut=h|hist>>|<<lastEdit|shortcut=/|last>>|<<editors|shortcut=E|eds>>'; |
|||
const watch = '<<unwatch|unwatchShort>>|<<watch|shortcut=w|watchThingy>>'; |
|||
const move = '<<move|shortcut=m|move>>'; |
|||
return navlinkStringToHTML( |
|||
'if(talk){' + |
|||
'<<edit|shortcut=e>>|<<new|shortcut=+|+>>*' + |
|||
hist + |
|||
'*' + |
|||
'<<article|shortcut=a>>|<<editArticle|edit>>' + |
|||
'*' + |
|||
watch + |
|||
'*' + |
|||
move + |
|||
'}else{<<edit|shortcut=e>>*' + |
|||
hist + |
|||
'*<<talk|shortcut=t|>>|<<editTalk|edit>>|<<newTalk|shortcut=+|new>>' + |
|||
'*' + |
|||
watch + |
|||
'*' + |
|||
move + |
|||
'}<br>', |
|||
x.article, |
|||
x.params |
|||
); |
|||
}; |
|||
pg.structures.fancy.popupOtherLinks = function (x) { |
|||
const admin = |
|||
'<<unprotect|unprotectShort>>|<<protect|shortcut=p>>*<<undelete|undeleteShort>>|<<delete|shortcut=d|del>>'; |
|||
let user = '<<contribs|shortcut=c>>if(wikimedia){|<<count|shortcut=#|#>>}'; |
|||
user += |
|||
'if(ipuser){|<<arin>>}else{*<<email|shortcut=E|' + |
|||
popupString('email') + |
|||
'>>}if(admin){*<<block|shortcut=b>>}'; |
|||
const normal = '<<whatLinksHere|shortcut=l|links here>>*<<relatedChanges|shortcut=r|related>>'; |
|||
return navlinkStringToHTML( |
|||
'<br>if(user){' + user + '*}if(admin){' + admin + 'if(user){<br>}else{*}}' + normal, |
|||
x.article, |
|||
x.params |
|||
); |
|||
}; |
|||
pg.structures.fancy.popupRedirTitle = pg.structures.fancy.popupTitle; |
|||
pg.structures.fancy.popupRedirTopLinks = pg.structures.fancy.popupTopLinks; |
|||
pg.structures.fancy.popupRedirOtherLinks = pg.structures.fancy.popupOtherLinks; |
|||
/** -- fancy2 -- */ |
|||
// hack for [[User:MacGyverMagic]] |
|||
copyStructure('fancy', 'fancy2'); |
|||
pg.structures.fancy2.popupTopLinks = function (x) { |
|||
// hack out the <br> at the end and put one at the beginning |
|||
return '<br>' + pg.structures.fancy.popupTopLinks(x).replace(/<br>$/i, ''); |
|||
}; |
|||
pg.structures.fancy2.popupLayout = function () { |
|||
// move toplinks to after the title |
|||
return [ |
|||
'popupError', |
|||
'popupImage', |
|||
'popupTitle', |
|||
'popupUserData', |
|||
'popupData', |
|||
'popupTopLinks', |
|||
'popupOtherLinks', |
|||
'popupRedir', |
|||
[ |
|||
'popupWarnRedir', |
|||
'popupRedirTopLinks', |
|||
'popupRedirTitle', |
|||
'popupRedirData', |
|||
'popupRedirOtherLinks', |
|||
], |
|||
'popupMiscTools', |
|||
['popupRedlink'], |
|||
'popupPrePreviewSep', |
|||
'popupPreview', |
|||
'popupSecondPreview', |
|||
'popupPreviewMore', |
|||
'popupPostPreview', |
|||
'popupFixDab', |
|||
]; |
|||
}; |
|||
/** -- menus -- */ |
|||
copyStructure('original', 'menus'); |
|||
pg.structures.menus.popupLayout = function () { |
|||
return [ |
|||
'popupError', |
|||
'popupImage', |
|||
'popupTopLinks', |
|||
'popupTitle', |
|||
'popupOtherLinks', |
|||
'popupRedir', |
|||
[ |
|||
'popupWarnRedir', |
|||
'popupRedirTopLinks', |
|||
'popupRedirTitle', |
|||
'popupRedirData', |
|||
'popupRedirOtherLinks', |
|||
], |
|||
'popupUserData', |
|||
'popupData', |
|||
'popupMiscTools', |
|||
['popupRedlink'], |
|||
'popupPrePreviewSep', |
|||
'popupPreview', |
|||
'popupSecondPreview', |
|||
'popupPreviewMore', |
|||
'popupPostPreview', |
|||
'popupFixDab', |
|||
]; |
|||
}; |
|||
pg.structures.menus.popupTopLinks = function (x, shorter) { |
|||
// FIXME maybe this stuff should be cached |
|||
const s = []; |
|||
const dropclass = 'popup_drop'; |
|||
const enddiv = '</div>'; |
|||
let hist = '<<history|shortcut=h>>'; |
|||
if (!shorter) { |
|||
hist = '<menurow>' + hist + '|<<historyfeed|rss>>|<<editors|shortcut=E>></menurow>'; |
|||
} |
|||
const lastedit = '<<lastEdit|shortcut=/|show last edit>>'; |
|||
const thank = 'if(diff){<<thank|send thanks>>}'; |
|||
const jsHistory = '<<lastContrib|last set of edits>><<sinceMe|changes since mine>>'; |
|||
const linkshere = '<<whatLinksHere|shortcut=l|what links here>>'; |
|||
const related = '<<relatedChanges|shortcut=r|related changes>>'; |
|||
const search = |
|||
'<menurow><<search|shortcut=s>>if(wikimedia){|<<globalsearch|shortcut=g|global>>}' + |
|||
'|<<google|shortcut=G|web>></menurow>'; |
|||
const watch = '<menurow><<unwatch|unwatchShort>>|<<watch|shortcut=w|watchThingy>></menurow>'; |
|||
const protect = |
|||
'<menurow><<unprotect|unprotectShort>>|' + |
|||
'<<protect|shortcut=p>>|<<protectlog|log>></menurow>'; |
|||
const del = |
|||
'<menurow><<undelete|undeleteShort>>|<<delete|shortcut=d>>|<<deletelog|log>></menurow>'; |
|||
const move = '<<move|shortcut=m|move page>>'; |
|||
const nullPurge = '<menurow><<nullEdit|shortcut=n|null edit>>|<<purge|shortcut=P>></menurow>'; |
|||
const viewOptions = '<menurow><<view|shortcut=v>>|<<render|shortcut=S>>|<<raw>></menurow>'; |
|||
const editRow = |
|||
'if(oldid){' + |
|||
'<menurow><<edit|shortcut=e>>|<<editOld|shortcut=e|this revision>></menurow>' + |
|||
'<menurow><<revert|shortcut=v>>|<<undo>></menurow>' + |
|||
'}else{<<edit|shortcut=e>>}'; |
|||
const markPatrolled = 'if(rcid){<<markpatrolled|mark patrolled>>}'; |
|||
const newTopic = 'if(talk){<<new|shortcut=+|new topic>>}'; |
|||
const protectDelete = 'if(admin){' + protect + del + '}'; |
|||
if (getValueOf('popupActionsMenu')) { |
|||
s.push('<<mainlink>>*' + menuTitle(dropclass, 'actions')); |
|||
} else { |
|||
s.push('<div class="' + dropclass + '"><<mainlink>>'); |
|||
} |
|||
s.push('<menu>'); |
|||
s.push(editRow + markPatrolled + newTopic + hist + lastedit + thank); |
|||
if (!shorter) { |
|||
s.push(jsHistory); |
|||
} |
|||
s.push(move + linkshere + related); |
|||
if (!shorter) { |
|||
s.push(nullPurge + search); |
|||
} |
|||
if (!shorter) { |
|||
s.push(viewOptions); |
|||
} |
|||
s.push('<hr />' + watch + protectDelete); |
|||
s.push( |
|||
'<hr />' + |
|||
'if(talk){<<article|shortcut=a|view article>><<editArticle|edit article>>}' + |
|||
'else{<<talk|shortcut=t|talk page>><<editTalk|edit talk>>' + |
|||
'<<newTalk|shortcut=+|new topic>>}</menu>' + |
|||
enddiv |
|||
); |
|||
// user menu starts here |
|||
const email = '<<email|shortcut=E|email user>>'; |
|||
const contribs = |
|||
'if(wikimedia){<menurow>}<<contribs|shortcut=c|contributions>>if(wikimedia){</menurow>}' + |
|||
'if(admin){<menurow><<deletedContribs>></menurow>}'; |
|||
s.push('if(user){*' + menuTitle(dropclass, 'user')); |
|||
s.push('<menu>'); |
|||
s.push('<menurow><<userPage|shortcut=u|user page>>|<<userSpace|space>></menurow>'); |
|||
s.push( |
|||
'<<userTalk|shortcut=t|user talk>><<editUserTalk|edit user talk>>' + |
|||
'<<newUserTalk|shortcut=+|leave comment>>' |
|||
); |
|||
if (!shorter) { |
|||
s.push('if(ipuser){<<arin>>}else{' + email + '}'); |
|||
} else { |
|||
s.push('if(ipuser){}else{' + email + '}'); |
|||
} |
|||
s.push('<hr />' + contribs + '<<userlog|shortcut=L|user log>>'); |
|||
s.push('if(wikimedia){<<count|shortcut=#|edit counter>>}'); |
|||
s.push( |
|||
'if(admin){<menurow><<unblock|unblockShort>>|<<block|shortcut=b|block user>></menurow>}' |
|||
); |
|||
s.push('<<blocklog|shortcut=B|block log>>'); |
|||
s.push('</menu>' + enddiv + '}'); |
|||
// popups menu starts here |
|||
if (getValueOf('popupSetupMenu') && !x.navpop.hasPopupMenu /* FIXME: hack */) { |
|||
x.navpop.hasPopupMenu = true; |
|||
s.push('*' + menuTitle(dropclass, 'popupsMenu') + '<menu>'); |
|||
s.push('<<togglePreviews|toggle previews>>'); |
|||
s.push('<<purgePopups|reset>>'); |
|||
s.push('<<disablePopups|disable>>'); |
|||
s.push('</menu>' + enddiv); |
|||
} |
|||
return navlinkStringToHTML(s.join(''), x.article, x.params); |
|||
}; |
|||
function menuTitle(dropclass, s) { |
|||
const text = popupString(s); // i18n |
|||
const len = text.length; |
|||
return '<div class="' + dropclass + '" style="--navpop-m-len:' + len + 'ch"><a href="#" noPopup=1>' + text + '</a>'; |
|||
} |
|||
pg.structures.menus.popupRedirTitle = pg.structures.menus.popupTitle; |
|||
pg.structures.menus.popupRedirTopLinks = pg.structures.menus.popupTopLinks; |
|||
copyStructure('menus', 'shortmenus'); |
|||
pg.structures.shortmenus.popupTopLinks = function (x) { |
|||
return pg.structures.menus.popupTopLinks(x, true); |
|||
}; |
|||
pg.structures.shortmenus.popupRedirTopLinks = pg.structures.shortmenus.popupTopLinks; |
|||
pg.structures.lite = {}; |
|||
pg.structures.lite.popupLayout = function () { |
|||
return ['popupTitle', 'popupPreview']; |
|||
}; |
|||
pg.structures.lite.popupTitle = function (x) { |
|||
log(x.article + ': structures.lite.popupTitle'); |
|||
//return navlinkStringToHTML('<b><<mainlink>></b>',x.article,x.params); |
|||
return '<div><span class="popup_mainlink"><b>' + x.article.toString() + '</b></span></div>'; |
|||
}; |
|||
// ENDFILE: structures.js |
|||
// STARTFILE: autoedit.js |
|||
function substitute(data, cmdBody) { |
|||
// alert('sub\nfrom: '+cmdBody.from+'\nto: '+cmdBody.to+'\nflags: '+cmdBody.flags); |
|||
const fromRe = RegExp(cmdBody.from, cmdBody.flags); |
|||
return data.replace(fromRe, cmdBody.to); |
|||
} |
|||
function execCmds(data, cmdList) { |
|||
for (let i = 0; i < cmdList.length; ++i) { |
|||
data = cmdList[i].action(data, cmdList[i]); |
|||
} |
|||
return data; |
|||
} |
|||
function parseCmd(str) { |
|||
// returns a list of commands |
|||
if (!str.length) { |
|||
return []; |
|||
} |
|||
let p = false; |
|||
switch (str.charAt(0)) { |
|||
case 's': |
|||
p = parseSubstitute(str); |
|||
break; |
|||
default: |
|||
return false; |
|||
} |
|||
if (p) { |
|||
return [p].concat(parseCmd(p.remainder)); |
|||
} |
|||
return false; |
|||
} |
|||
// FIXME: Only used once here, confusing with native (and more widely-used) unescape, should probably be replaced |
|||
// Then again, unescape is semi-soft-deprecated, so we should look into replacing that too |
|||
function unEscape(str, sep) { |
|||
return str |
|||
.split('\\\\') |
|||
.join('\\') |
|||
.split('\\' + sep) |
|||
.join(sep) |
|||
.split('\\n') |
|||
.join('\n'); |
|||
} |
|||
function parseSubstitute(str) { |
|||
// takes a string like s/a/b/flags;othercmds and parses it |
|||
let from, to, flags, tmp; |
|||
if (str.length < 4) { |
|||
return false; |
|||
} |
|||
const sep = str.charAt(1); |
|||
str = str.substring(2); |
|||
tmp = skipOver(str, sep); |
|||
if (tmp) { |
|||
from = tmp.segment; |
|||
str = tmp.remainder; |
|||
} else { |
|||
return false; |
|||
} |
|||
tmp = skipOver(str, sep); |
|||
if (tmp) { |
|||
to = tmp.segment; |
|||
str = tmp.remainder; |
|||
} else { |
|||
return false; |
|||
} |
|||
flags = ''; |
|||
if (str.length) { |
|||
tmp = skipOver(str, ';') || skipToEnd(str, ';'); |
|||
if (tmp) { |
|||
flags = tmp.segment; |
|||
str = tmp.remainder; |
|||
} |
|||
} |
|||
return { |
|||
action: substitute, |
|||
from: from, |
|||
to: to, |
|||
flags: flags, |
|||
remainder: str, |
|||
}; |
|||
} |
|||
function skipOver(str, sep) { |
|||
const endSegment = findNext(str, sep); |
|||
if (endSegment < 0) { |
|||
return false; |
|||
} |
|||
const segment = unEscape(str.substring(0, endSegment), sep); |
|||
return { segment: segment, remainder: str.substring(endSegment + 1) }; |
|||
} |
|||
/*eslint-disable*/ |
|||
function skipToEnd(str, sep) { |
|||
return { segment: str, remainder: '' }; |
|||
} |
|||
/*eslint-enable */ |
|||
function findNext(str, ch) { |
|||
for (let i = 0; i < str.length; ++i) { |
|||
if (str.charAt(i) == '\\') { |
|||
i += 2; |
|||
} |
|||
if (str.charAt(i) == ch) { |
|||
return i; |
|||
} |
|||
} |
|||
return -1; |
|||
} |
|||
function setCheckbox(param, box) { |
|||
const val = mw.util.getParamValue(param); |
|||
if (val) { |
|||
switch (val) { |
|||
case '1': |
|||
case 'yes': |
|||
case 'true': |
|||
box.checked = true; |
|||
break; |
|||
case '0': |
|||
case 'no': |
|||
case 'false': |
|||
box.checked = false; |
|||
} |
|||
} |
|||
} |
|||
function autoEdit() { |
|||
setupPopups(() => { |
|||
if (mw.util.getParamValue('autoimpl') !== popupString('autoedit_version')) { |
|||
return false; |
|||
} |
|||
if ( |
|||
mw.util.getParamValue('autowatchlist') && |
|||
mw.util.getParamValue('actoken') === autoClickToken() |
|||
) { |
|||
pg.fn.modifyWatchlist(mw.util.getParamValue('title'), mw.util.getParamValue('action')); |
|||
} |
|||
if (!document.editform) { |
|||
return false; |
|||
} |
|||
if (autoEdit.alreadyRan) { |
|||
return false; |
|||
} |
|||
autoEdit.alreadyRan = true; |
|||
const cmdString = mw.util.getParamValue('autoedit'); |
|||
if (cmdString) { |
|||
try { |
|||
const editbox = document.editform.wpTextbox1; |
|||
const cmdList = parseCmd(cmdString); |
|||
const input = editbox.value; |
|||
const output = execCmds(input, cmdList); |
|||
editbox.value = output; |
|||
} catch (dang) { |
|||
return; |
|||
} |
|||
// wikEd user script compatibility |
|||
if (typeof wikEdUseWikEd != 'undefined') { |
|||
if (wikEdUseWikEd === true) { |
|||
WikEdUpdateFrame(); |
|||
} |
|||
} |
|||
} |
|||
setCheckbox('autominor', document.editform.wpMinoredit); |
|||
setCheckbox('autowatch', document.editform.wpWatchthis); |
|||
const rvid = mw.util.getParamValue('autorv'); |
|||
if (rvid) { |
|||
const url = |
|||
pg.wiki.apiwikibase + |
|||
'?action=query&format=json&formatversion=2&prop=revisions&revids=' + |
|||
rvid; |
|||
startDownload(url, null, autoEdit2); |
|||
} else { |
|||
autoEdit2(); |
|||
} |
|||
}); |
|||
} |
|||
function autoEdit2(d) { |
|||
let summary = mw.util.getParamValue('autosummary'); |
|||
let summaryprompt = mw.util.getParamValue('autosummaryprompt'); |
|||
let summarynotice = ''; |
|||
if (d && d.data && mw.util.getParamValue('autorv')) { |
|||
const s = getRvSummary(summary, d.data); |
|||
if (s === false) { |
|||
summaryprompt = true; |
|||
summarynotice = popupString( |
|||
'Failed to get revision information, please edit manually.\n\n' |
|||
); |
|||
summary = simplePrintf(summary, [ |
|||
mw.util.getParamValue('autorv'), |
|||
'(unknown)', |
|||
'(unknown)', |
|||
]); |
|||
} else { |
|||
summary = s; |
|||
} |
|||
} |
|||
if (summaryprompt) { |
|||
const txt = |
|||
summarynotice + popupString('Enter a non-empty edit summary or press cancel to abort'); |
|||
const response = prompt(txt, summary); |
|||
if (response) { |
|||
summary = response; |
|||
} else { |
|||
return; |
|||
} |
|||
} |
|||
if (summary) { |
|||
document.editform.wpSummary.value = summary; |
|||
} |
|||
// Attempt to avoid possible premature clicking of the save button |
|||
// (maybe delays in updates to the DOM are to blame?? or a red herring) |
|||
setTimeout(autoEdit3, 100); |
|||
} |
|||
function autoClickToken() { |
|||
return mw.user.sessionId(); |
|||
} |
|||
function autoEdit3() { |
|||
if (mw.util.getParamValue('actoken') != autoClickToken()) { |
|||
return; |
|||
} |
|||
const btn = mw.util.getParamValue('autoclick'); |
|||
if (btn) { |
|||
if (document.editform && document.editform[btn]) { |
|||
const button = document.editform[btn]; |
|||
const msg = tprintf( |
|||
'The %s button has been automatically clicked. Please wait for the next page to load.', |
|||
[button.value] |
|||
); |
|||
bannerMessage(msg); |
|||
document.title = '(' + document.title + ')'; |
|||
button.click(); |
|||
} else { |
|||
alert( |
|||
tprintf('Could not find button %s. Please check the settings in your javascript file.', [ |
|||
btn, |
|||
]) |
|||
); |
|||
} |
|||
} |
|||
} |
|||
function bannerMessage(s) { |
|||
const headings = document.getElementsByTagName('h1'); |
|||
if (headings) { |
|||
const div = document.createElement('div'); |
|||
div.innerHTML = '<font size=+1><b>' + pg.escapeQuotesHTML(s) + '</b></font>'; |
|||
headings[0].parentNode.insertBefore(div, headings[0]); |
|||
} |
|||
} |
|||
function getRvSummary(template, json) { |
|||
try { |
|||
const o = getJsObj(json); |
|||
const edit = anyChild(o.query.pages).revisions[0]; |
|||
const timestamp = edit.timestamp |
|||
.split(/[A-Z]/g) |
|||
.join(' ') |
|||
.replace(/^ *| *$/g, ''); |
|||
return simplePrintf(template, [ |
|||
edit.revid, |
|||
timestamp, |
|||
edit.userhidden ? '(hidden)' : edit.user, |
|||
]); |
|||
} catch (badness) { |
|||
return false; |
|||
} |
|||
} |
|||
// ENDFILE: autoedit.js |
|||
// STARTFILE: downloader.js |
|||
/** |
|||
* @file |
|||
* {@link Downloader}, a xmlhttprequest wrapper, and helper functions. |
|||
*/ |
|||
/** |
|||
* Creates a new Downloader |
|||
* |
|||
* @constructor |
|||
* @class The Downloader class. Create a new instance of this class to download stuff. |
|||
* @param {string} url The url to download. This can be omitted and supplied later. |
|||
*/ |
|||
function Downloader(url) { |
|||
if (typeof XMLHttpRequest != 'undefined') { |
|||
this.http = new XMLHttpRequest(); |
|||
} |
|||
/** |
|||
* The url to download |
|||
* |
|||
* @type {string} |
|||
*/ |
|||
this.url = url; |
|||
/** |
|||
* A universally unique ID number |
|||
* |
|||
* @type {number} |
|||
*/ |
|||
this.id = null; |
|||
/** |
|||
* Modification date, to be culled from the incoming headers |
|||
* |
|||
* @type {Date} |
|||
* @private |
|||
*/ |
|||
this.lastModified = null; |
|||
/** |
|||
* What to do when the download completes successfully |
|||
* |
|||
* @type {Function} |
|||
* @private |
|||
*/ |
|||
this.callbackFunction = null; |
|||
/** |
|||
* What to do on failure |
|||
* |
|||
* @type {Function} |
|||
* @private |
|||
*/ |
|||
this.onFailure = null; |
|||
/** |
|||
* Flag set on <code>abort</code> |
|||
* |
|||
* @type {boolean} |
|||
*/ |
|||
this.aborted = false; |
|||
/** |
|||
* HTTP method. See https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html for |
|||
* possibilities. |
|||
* |
|||
* @type {string} |
|||
*/ |
|||
this.method = 'GET'; |
|||
/** |
|||
* Async flag. |
|||
* |
|||
* @type {boolean} |
|||
*/ |
|||
this.async = true; |
|||
} |
|||
new Downloader(); |
|||
/** Submits the http request. */ |
|||
Downloader.prototype.send = function (x) { |
|||
if (!this.http) { |
|||
return null; |
|||
} |
|||
return this.http.send(x); |
|||
}; |
|||
/** Aborts the download, setting the <code>aborted</code> field to true. */ |
|||
Downloader.prototype.abort = function () { |
|||
if (!this.http) { |
|||
return null; |
|||
} |
|||
this.aborted = true; |
|||
return this.http.abort(); |
|||
}; |
|||
/** Returns the downloaded data. */ |
|||
Downloader.prototype.getData = function () { |
|||
if (!this.http) { |
|||
return null; |
|||
} |
|||
return this.http.responseText; |
|||
}; |
|||
/** Prepares the download. */ |
|||
Downloader.prototype.setTarget = function () { |
|||
if (!this.http) { |
|||
return null; |
|||
} |
|||
this.http.open(this.method, this.url, this.async); |
|||
this.http.setRequestHeader('Api-User-Agent', pg.api.userAgent); |
|||
}; |
|||
/** Gets the state of the download. */ |
|||
Downloader.prototype.getReadyState = function () { |
|||
if (!this.http) { |
|||
return null; |
|||
} |
|||
return this.http.readyState; |
|||
}; |
|||
pg.misc.downloadsInProgress = {}; |
|||
/** |
|||
* Starts the download. |
|||
* Note that setTarget {@link Downloader#setTarget} must be run first |
|||
*/ |
|||
Downloader.prototype.start = function () { |
|||
if (!this.http) { |
|||
return; |
|||
} |
|||
pg.misc.downloadsInProgress[this.id] = this; |
|||
this.http.send(null); |
|||
}; |
|||
/** |
|||
* Gets the 'Last-Modified' date from the download headers. |
|||
* Should be run after the download completes. |
|||
* Returns <code>null</code> on failure. |
|||
* |
|||
* @return {Date} |
|||
*/ |
|||
Downloader.prototype.getLastModifiedDate = function () { |
|||
if (!this.http) { |
|||
return null; |
|||
} |
|||
let lastmod = null; |
|||
try { |
|||
lastmod = this.http.getResponseHeader('Last-Modified'); |
|||
} catch (err) {} |
|||
if (lastmod) { |
|||
return new Date(lastmod); |
|||
} |
|||
return null; |
|||
}; |
|||
/** |
|||
* Sets the callback function. |
|||
* |
|||
* @param {Function} f callback function, called as <code>f(this)</code> on success |
|||
*/ |
|||
Downloader.prototype.setCallback = function (f) { |
|||
if (!this.http) { |
|||
return; |
|||
} |
|||
this.http.onreadystatechange = f; |
|||
}; |
|||
Downloader.prototype.getStatus = function () { |
|||
if (!this.http) { |
|||
return null; |
|||
} |
|||
return this.http.status; |
|||
}; |
|||
////////////////////////////////////////////////// |
|||
// helper functions |
|||
/** |
|||
* Creates a new {@link Downloader} and prepares it for action. |
|||
* |
|||
* @param {string} url The url to download |
|||
* @param {number} id The ID of the {@link Downloader} object |
|||
* @param {Function} callback The callback function invoked on success |
|||
* @return {string|Downloader} the {@link Downloader} object created, or 'ohdear' if an unsupported browser |
|||
*/ |
|||
function newDownload(url, id, callback, onfailure) { |
|||
const d = new Downloader(url); |
|||
if (!d.http) { |
|||
return 'ohdear'; |
|||
} |
|||
d.id = id; |
|||
d.setTarget(); |
|||
if (!onfailure) { |
|||
onfailure = 2; |
|||
} |
|||
const f = function () { |
|||
if (d.getReadyState() == 4) { |
|||
delete pg.misc.downloadsInProgress[this.id]; |
|||
try { |
|||
if (d.getStatus() == 200) { |
|||
d.data = d.getData(); |
|||
d.lastModified = d.getLastModifiedDate(); |
|||
callback(d); |
|||
} else if (typeof onfailure == typeof 1) { |
|||
if (onfailure > 0) { |
|||
// retry |
|||
newDownload(url, id, callback, onfailure - 1); |
|||
} |
|||
} else if (typeof onfailure === 'function') { |
|||
onfailure(d, url, id, callback); |
|||
} |
|||
} catch (somerr) { |
|||
/* ignore it */ |
|||
} |
|||
} |
|||
}; |
|||
d.setCallback(f); |
|||
return d; |
|||
} |
|||
/** |
|||
* Simulates a download from cached data. |
|||
* The supplied data is put into a {@link Downloader} as if it had downloaded it. |
|||
* |
|||
* @param {string} url The url. |
|||
* @param {number} id The ID. |
|||
* @param {Function} callback The callback, which is invoked immediately as <code>callback(d)</code>, |
|||
* where <code>d</code> is the new {@link Downloader}. |
|||
* @param {string} data The (cached) data. |
|||
* @param {Date} lastModified The (cached) last modified date. |
|||
*/ |
|||
function fakeDownload(url, id, callback, data, lastModified, owner) { |
|||
const d = newDownload(url, callback); |
|||
d.owner = owner; |
|||
d.id = id; |
|||
d.data = data; |
|||
d.lastModified = lastModified; |
|||
return callback(d); |
|||
} |
|||
/** |
|||
* Starts a download. |
|||
* |
|||
* @param {string} url The url to download |
|||
* @param {number} id The ID of the {@link Downloader} object |
|||
* @param {Function} callback The callback function invoked on success |
|||
* @return {string|Downloader} the {@link Downloader} object created, or 'ohdear' if an unsupported browser |
|||
*/ |
|||
function startDownload(url, id, callback) { |
|||
const d = newDownload(url, id, callback); |
|||
if (typeof d == typeof '') { |
|||
return d; |
|||
} |
|||
d.start(); |
|||
return d; |
|||
} |
|||
/** |
|||
* Aborts all downloads which have been started. |
|||
*/ |
|||
function abortAllDownloads() { |
|||
for (const x in pg.misc.downloadsInProgress) { |
|||
try { |
|||
pg.misc.downloadsInProgress[x].aborted = true; |
|||
pg.misc.downloadsInProgress[x].abort(); |
|||
delete pg.misc.downloadsInProgress[x]; |
|||
} catch (e) {} |
|||
} |
|||
} |
|||
// ENDFILE: downloader.js |
|||
// STARTFILE: livepreview.js |
|||
// TODO: location is often not correct (eg relative links in previews) |
|||
// NOTE: removed md5 and image and math parsing. was broken, lots of bytes. |
|||
/** |
|||
* InstaView - a Mediawiki to HTML converter in JavaScript |
|||
* Version 0.6.1 |
|||
* Copyright (C) Pedro Fayolle 2005-2006 |
|||
* https://en.wikipedia.org/wiki/User:Pilaf |
|||
* Distributed under the BSD license |
|||
* |
|||
* Changelog: |
|||
* |
|||
* 0.6.1 |
|||
* - Fixed problem caused by \r characters |
|||
* - Improved inline formatting parser |
|||
* |
|||
* 0.6 |
|||
* - Changed name to InstaView |
|||
* - Some major code reorganizations and factored out some common functions |
|||
* - Handled conversion of relative links (i.e. [[/foo]]) |
|||
* - Fixed misrendering of adjacent definition list items |
|||
* - Fixed bug in table headings handling |
|||
* - Changed date format in signatures to reflect Mediawiki's |
|||
* - Fixed handling of [[:Image:...]] |
|||
* - Updated MD5 function (hopefully it will work with UTF-8) |
|||
* - Fixed bug in handling of links inside images |
|||
* |
|||
* To do: |
|||
* - Better support for math tags |
|||
* - Full support for <nowiki> |
|||
* - Parser-based (as opposed to RegExp-based) inline wikicode handling (make it one-pass and |
|||
* bullet-proof) |
|||
* - Support for templates (through AJAX) |
|||
* - Support for coloured links (AJAX) |
|||
*/ |
|||
const Insta = {}; |
|||
function setupLivePreview() { |
|||
// options |
|||
Insta.conf = { |
|||
baseUrl: '', |
|||
user: {}, |
|||
wiki: { |
|||
lang: pg.wiki.lang, |
|||
interwiki: pg.wiki.interwiki, |
|||
default_thumb_width: 180, |
|||
}, |
|||
paths: { |
|||
articles: pg.wiki.articlePath + '/', |
|||
// Only used for Insta previews with images. (not in popups) |
|||
math: '/math/', |
|||
images: '//upload.wikimedia.org/wikipedia/en/', // FIXME getImageUrlStart(pg.wiki.hostname), |
|||
images_fallback: '//upload.wikimedia.org/wikipedia/commons/', |
|||
}, |
|||
locale: { |
|||
user: mw.config.get('wgFormattedNamespaces')[pg.nsUserId], |
|||
image: mw.config.get('wgFormattedNamespaces')[pg.nsImageId], |
|||
category: mw.config.get('wgFormattedNamespaces')[pg.nsCategoryId], |
|||
// shouldn't be used in popup previews, i think |
|||
months: [ |
|||
'Jan', |
|||
'Feb', |
|||
'Mar', |
|||
'Apr', |
|||
'May', |
|||
'Jun', |
|||
'Jul', |
|||
'Aug', |
|||
'Sep', |
|||
'Oct', |
|||
'Nov', |
|||
'Dec', |
|||
], |
|||
}, |
|||
}; |
|||
// options with default values or backreferences |
|||
Insta.conf.user.name = Insta.conf.user.name || 'Wikipedian'; |
|||
Insta.conf.user.signature = |
|||
'[[' + |
|||
Insta.conf.locale.user + |
|||
':' + |
|||
Insta.conf.user.name + |
|||
'|' + |
|||
Insta.conf.user.name + |
|||
']]'; |
|||
//Insta.conf.paths.images = '//upload.wikimedia.org/wikipedia/' + Insta.conf.wiki.lang + '/'; |
|||
// define constants |
|||
Insta.BLOCK_IMAGE = new RegExp( |
|||
'^\\[\\[(?:File|Image|' + |
|||
Insta.conf.locale.image + |
|||
'):.*?\\|.*?(?:frame|thumbnail|thumb|none|right|left|center)', |
|||
'i' |
|||
); |
|||
} |
|||
Insta.dump = function (from, to) { |
|||
if (typeof from == 'string') { |
|||
from = document.getElementById(from); |
|||
} |
|||
if (typeof to == 'string') { |
|||
to = document.getElementById(to); |
|||
} |
|||
to.innerHTML = this.convert(from.value); |
|||
}; |
|||
Insta.convert = function (wiki) { |
|||
let ll = typeof wiki == 'string' ? wiki.replace(/\r/g, '').split(/\n/) : wiki, // lines of wikicode |
|||
o = '', // output |
|||
p = 0, // para flag |
|||
r; // result of passing a regexp to compareLineStringOrReg() |
|||
// some shorthands |
|||
function remain() { |
|||
return ll.length; |
|||
} |
|||
function sh() { |
|||
return ll.shift(); |
|||
} // shift |
|||
function ps(s) { |
|||
o += s; |
|||
} // push |
|||
// similar to C's printf, uses ? as placeholders, ?? to escape question marks |
|||
function f() { |
|||
let i = 1, |
|||
a = arguments, |
|||
f = a[0], |
|||
o = '', |
|||
c, |
|||
p; |
|||
for (; i < a.length; i++) { |
|||
if ((p = f.indexOf('?')) + 1) { |
|||
// allow character escaping |
|||
i -= c = f.charAt(p + 1) == '?' ? 1 : 0; |
|||
o += f.substring(0, p) + (c ? '?' : a[i]); |
|||
f = f.substr(p + 1 + c); |
|||
} else { |
|||
break; |
|||
} |
|||
} |
|||
return o + f; |
|||
} |
|||
function html_entities(s) { |
|||
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); |
|||
} |
|||
// Wiki text parsing to html is a nightmare. |
|||
// The below functions deliberately don't escape the ampersand since this would make it more |
|||
// difficult, and we don't absolutely need to for how we need it. This means that any |
|||
// unescaped ampersands in wikitext will remain unescaped and can cause invalid HTML. |
|||
// Browsers should all be able to handle it though. We also escape significant wikimarkup |
|||
// characters to prevent further matching on the processed text. |
|||
function htmlescape_text(s) { |
|||
return s |
|||
.replace(/</g, '<') |
|||
.replace(/>/g, '>') |
|||
.replace(/:/g, ':') |
|||
.replace(/\[/g, '[') |
|||
.replace(/]/g, ']'); |
|||
} |
|||
function htmlescape_attr(s) { |
|||
return htmlescape_text(s).replace(/'/g, ''').replace(/"/g, '"'); |
|||
} |
|||
// return the first non matching character position between two strings |
|||
function str_imatch(a, b) { |
|||
for (var i = 0, l = Math.min(a.length, b.length); i < l; i++) { |
|||
if (a.charAt(i) != b.charAt(i)) { |
|||
break; |
|||
} |
|||
} |
|||
return i; |
|||
} |
|||
// compare current line against a string or regexp |
|||
// if passed a string it will compare only the first string.length characters |
|||
// if passed a regexp the result is stored in r |
|||
function compareLineStringOrReg(c) { |
|||
return typeof c == 'string' ? |
|||
ll[0] && ll[0].substr(0, c.length) == c : |
|||
(r = ll[0] && ll[0].match(c)); |
|||
} |
|||
function compareLineString(c) { |
|||
return ll[0] == c; |
|||
} // compare current line against a string |
|||
function charAtPoint(p) { |
|||
return ll[0].charAt(p); |
|||
} // return char at pos p |
|||
function endl(s) { |
|||
ps(s); |
|||
sh(); |
|||
} |
|||
function parse_list() { |
|||
let prev = ''; |
|||
while (remain() && compareLineStringOrReg(/^([*#:;]+)(.*)$/)) { |
|||
const l_match = r; |
|||
sh(); |
|||
const ipos = str_imatch(prev, l_match[1]); |
|||
// close uncontinued lists |
|||
for (let prevPos = prev.length - 1; prevPos >= ipos; prevPos--) { |
|||
const pi = prev.charAt(prevPos); |
|||
if (pi == '*') { |
|||
ps('</ul>'); |
|||
} else if (pi == '#') { |
|||
ps('</ol>'); |
|||
} |
|||
// close a dl only if the new item is not a dl item (:, ; or empty) |
|||
else if ($.inArray(l_match[1].charAt(prevPos), ['', '*', '#'])) { |
|||
ps('</dl>'); |
|||
} |
|||
} |
|||
// open new lists |
|||
for (let matchPos = ipos; matchPos < l_match[1].length; matchPos++) { |
|||
const li = l_match[1].charAt(matchPos); |
|||
if (li == '*') { |
|||
ps('<ul>'); |
|||
} else if (li == '#') { |
|||
ps('<ol>'); |
|||
} |
|||
// open a new dl only if the prev item is not a dl item (:, ; or empty) |
|||
else if ($.inArray(prev.charAt(matchPos), ['', '*', '#'])) { |
|||
ps('<dl>'); |
|||
} |
|||
} |
|||
switch (l_match[1].charAt(l_match[1].length - 1)) { |
|||
case '*': |
|||
case '#': |
|||
ps('<li>' + parse_inline_nowiki(l_match[2])); |
|||
break; |
|||
case ';': |
|||
ps('<dt>'); |
|||
var dt_match = l_match[2].match(/(.*?)(:.*?)$/); |
|||
// handle ;dt :dd format |
|||
if (dt_match) { |
|||
ps(parse_inline_nowiki(dt_match[1])); |
|||
ll.unshift(dt_match[2]); |
|||
} else { |
|||
ps(parse_inline_nowiki(l_match[2])); |
|||
} |
|||
break; |
|||
case ':': |
|||
ps('<dd>' + parse_inline_nowiki(l_match[2])); |
|||
} |
|||
prev = l_match[1]; |
|||
} |
|||
// close remaining lists |
|||
for (let i = prev.length - 1; i >= 0; i--) { |
|||
ps(f('</?>', prev.charAt(i) == '*' ? 'ul' : prev.charAt(i) == '#' ? 'ol' : 'dl')); |
|||
} |
|||
} |
|||
function parse_table() { |
|||
endl(f('<table>', compareLineStringOrReg(/^\{\|( .*)$/) ? r[1] : '')); |
|||
for (; remain(); ) { |
|||
if (compareLineStringOrReg('|')) { |
|||
switch (charAtPoint(1)) { |
|||
case '}': |
|||
endl('</table>'); |
|||
return; |
|||
case '-': |
|||
endl(f('<tr>', compareLineStringOrReg(/\|-*(.*)/)[1])); |
|||
break; |
|||
default: |
|||
parse_table_data(); |
|||
} |
|||
} else if (compareLineStringOrReg('!')) { |
|||
parse_table_data(); |
|||
} else { |
|||
sh(); |
|||
} |
|||
} |
|||
} |
|||
function parse_table_data() { |
|||
let td_line, match_i; |
|||
// 1: "|+", '|' or '+' |
|||
// 2: ?? |
|||
// 3: attributes ?? |
|||
// TODO: finish commenting this regexp |
|||
const td_match = sh().match(/^(\|\+|\||!)((?:([^[|]*?)\|(?!\|))?(.*))$/); |
|||
if (td_match[1] == '|+') { |
|||
ps('<caption'); |
|||
} else { |
|||
ps('<t' + (td_match[1] == '|' ? 'd' : 'h')); |
|||
} |
|||
if (typeof td_match[3] != 'undefined') { |
|||
//ps(' ' + td_match[3]) |
|||
match_i = 4; |
|||
} else { |
|||
match_i = 2; |
|||
} |
|||
ps('>'); |
|||
if (td_match[1] != '|+') { |
|||
// use || or !! as a cell separator depending on context |
|||
// NOTE: when split() is passed a regexp make sure to use non-capturing brackets |
|||
td_line = td_match[match_i].split(td_match[1] == '|' ? '||' : /(?:\|\||!!)/); |
|||
ps(parse_inline_nowiki(td_line.shift())); |
|||
while (td_line.length) { |
|||
ll.unshift(td_match[1] + td_line.pop()); |
|||
} |
|||
} else { |
|||
ps(parse_inline_nowiki(td_match[match_i])); |
|||
} |
|||
let tc = 0, |
|||
td = []; |
|||
while (remain()) { |
|||
td.push(sh()); |
|||
if (compareLineStringOrReg('|')) { |
|||
if (!tc) { |
|||
break; |
|||
} |
|||
// we're at the outer-most level (no nested tables), skip to td parse |
|||
else if (charAtPoint(1) == '}') { |
|||
tc--; |
|||
} |
|||
} else if (!tc && compareLineStringOrReg('!')) { |
|||
break; |
|||
} else if (compareLineStringOrReg('{|')) { |
|||
tc++; |
|||
} |
|||
} |
|||
if (td.length) { |
|||
ps(Insta.convert(td)); |
|||
} |
|||
} |
|||
function parse_pre() { |
|||
ps('<pre>'); |
|||
do { |
|||
endl(parse_inline_nowiki(ll[0].substring(1)) + '\n'); |
|||
} while (remain() && compareLineStringOrReg(' ')); |
|||
ps('</pre>'); |
|||
} |
|||
function parse_block_image() { |
|||
ps(parse_image(sh())); |
|||
} |
|||
function parse_image(str) { |
|||
// get what's in between "[[Image:" and "]]" |
|||
let tag = str.substring(str.indexOf(':') + 1, str.length - 2); |
|||
let width; |
|||
let attr = [], |
|||
filename, |
|||
caption = ''; |
|||
let thumb = 0, |
|||
frame = 0, |
|||
center = 0; |
|||
let align = ''; |
|||
if (tag.match(/\|/)) { |
|||
// manage nested links |
|||
let nesting = 0; |
|||
let last_attr; |
|||
for (let i = tag.length - 1; i > 0; i--) { |
|||
if (tag.charAt(i) == '|' && !nesting) { |
|||
last_attr = tag.substr(i + 1); |
|||
tag = tag.substring(0, i); |
|||
break; |
|||
} else { |
|||
switch (tag.substr(i - 1, 2)) { |
|||
case ']]': |
|||
nesting++; |
|||
i--; |
|||
break; |
|||
case '[[': |
|||
nesting--; |
|||
i--; |
|||
} |
|||
} |
|||
} |
|||
attr = tag.split(/\s*\|\s*/); |
|||
attr.push(last_attr); |
|||
filename = attr.shift(); |
|||
let w_match; |
|||
for (; attr.length; attr.shift()) { |
|||
w_match = attr[0].match(/^(\d*)(?:[px]*\d*)?px$/); |
|||
if (w_match) { |
|||
width = w_match[1]; |
|||
} else { |
|||
switch (attr[0]) { |
|||
case 'thumb': |
|||
case 'thumbnail': |
|||
thumb = true; |
|||
frame = true; |
|||
break; |
|||
case 'frame': |
|||
frame = true; |
|||
break; |
|||
case 'none': |
|||
case 'right': |
|||
case 'left': |
|||
center = false; |
|||
align = attr[0]; |
|||
break; |
|||
case 'center': |
|||
center = true; |
|||
align = 'none'; |
|||
break; |
|||
default: |
|||
if (attr.length == 1) { |
|||
caption = attr[0]; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} else { |
|||
filename = tag; |
|||
} |
|||
return ''; |
|||
} |
|||
function parse_inline_nowiki(str) { |
|||
let start, |
|||
lastend = 0; |
|||
let substart = 0, |
|||
nestlev = 0, |
|||
open, |
|||
close, |
|||
subloop; |
|||
let html = ''; |
|||
while ((start = str.indexOf('<nowiki>', substart)) != -1) { |
|||
html += parse_inline_wiki(str.substring(lastend, start)); |
|||
start += 8; |
|||
substart = start; |
|||
subloop = true; |
|||
do { |
|||
open = str.indexOf('<nowiki>', substart); |
|||
close = str.indexOf('</nowiki>', substart); |
|||
if (close <= open || open == -1) { |
|||
if (close == -1) { |
|||
return html + html_entities(str.substr(start)); |
|||
} |
|||
substart = close + 9; |
|||
if (nestlev) { |
|||
nestlev--; |
|||
} else { |
|||
lastend = substart; |
|||
html += html_entities(str.substring(start, lastend - 9)); |
|||
subloop = false; |
|||
} |
|||
} else { |
|||
substart = open + 8; |
|||
nestlev++; |
|||
} |
|||
} while (subloop); |
|||
} |
|||
return html + parse_inline_wiki(str.substr(lastend)); |
|||
} |
|||
function parse_inline_images(str) { |
|||
let start, |
|||
substart = 0, |
|||
nestlev = 0; |
|||
let loop, close, open, wiki, html; |
|||
while ((start = str.indexOf('[[', substart)) != -1) { |
|||
if ( |
|||
str.substr(start + 2).match(RegExp('^(Image|File|' + Insta.conf.locale.image + '):', 'i')) |
|||
) { |
|||
loop = true; |
|||
substart = start; |
|||
do { |
|||
substart += 2; |
|||
close = str.indexOf(']]', substart); |
|||
open = str.indexOf('[[', substart); |
|||
if (close <= open || open == -1) { |
|||
if (close == -1) { |
|||
return str; |
|||
} |
|||
substart = close; |
|||
if (nestlev) { |
|||
nestlev--; |
|||
} else { |
|||
wiki = str.substring(start, close + 2); |
|||
html = parse_image(wiki); |
|||
str = str.replace(wiki, html); |
|||
substart = start + html.length; |
|||
loop = false; |
|||
} |
|||
} else { |
|||
substart = open; |
|||
nestlev++; |
|||
} |
|||
} while (loop); |
|||
} else { |
|||
break; |
|||
} |
|||
} |
|||
return str; |
|||
} |
|||
// the output of this function doesn't respect the FILO structure of HTML |
|||
// but since most browsers can handle it I'll save myself the hassle |
|||
function parse_inline_formatting(str) { |
|||
let italic, |
|||
bold, |
|||
i, |
|||
li, |
|||
o = ''; |
|||
while ((i = str.indexOf("''", li)) + 1) { |
|||
o += str.substring(li, i); |
|||
li = i + 2; |
|||
if (str.charAt(i + 2) == "'") { |
|||
li++; |
|||
bold = !bold; |
|||
o += bold ? '<b>' : '</b>'; |
|||
} else { |
|||
italic = !italic; |
|||
o += italic ? '<i>' : '</i>'; |
|||
} |
|||
} |
|||
return o + str.substr(li); |
|||
} |
|||
function parse_inline_wiki(str) { |
|||
str = parse_inline_images(str); |
|||
// math |
|||
str = str.replace(/<(?:)math>(.*?)<\/math>/gi, ''); |
|||
// Build a Mediawiki-formatted date string |
|||
let date = new Date(); |
|||
let minutes = date.getUTCMinutes(); |
|||
if (minutes < 10) { |
|||
minutes = '0' + minutes; |
|||
} |
|||
date = f( |
|||
'?:?, ? ? ? (UTC)', |
|||
date.getUTCHours(), |
|||
minutes, |
|||
date.getUTCDate(), |
|||
Insta.conf.locale.months[date.getUTCMonth()], |
|||
date.getUTCFullYear() |
|||
); |
|||
// text formatting |
|||
str = |
|||
str |
|||
// signatures |
|||
.replace(/~{5}(?!~)/g, date) |
|||
.replace(/~{4}(?!~)/g, Insta.conf.user.name + ' ' + date) |
|||
.replace(/~{3}(?!~)/g, Insta.conf.user.name) |
|||
// [[:Category:...]], [[:Image:...]], etc... |
|||
.replace( |
|||
RegExp( |
|||
'\\[\\[:((?:' + |
|||
Insta.conf.locale.category + |
|||
'|Image|File|' + |
|||
Insta.conf.locale.image + |
|||
'|' + |
|||
Insta.conf.wiki.interwiki + |
|||
'):[^|]*?)\\]\\](\\w*)', |
|||
'gi' |
|||
), |
|||
($0, $1, $2) => f( |
|||
"<a href='?'>?</a>", |
|||
Insta.conf.paths.articles + htmlescape_attr($1), |
|||
htmlescape_text($1) + htmlescape_text($2) |
|||
) |
|||
) |
|||
// remove straight category and interwiki tags |
|||
.replace( |
|||
RegExp( |
|||
'\\[\\[(?:' + |
|||
Insta.conf.locale.category + |
|||
'|' + |
|||
Insta.conf.wiki.interwiki + |
|||
'):.*?\\]\\]', |
|||
'gi' |
|||
), |
|||
'' |
|||
) |
|||
// [[:Category:...|Links]], [[:Image:...|Links]], etc... |
|||
.replace( |
|||
RegExp( |
|||
'\\[\\[:((?:' + |
|||
Insta.conf.locale.category + |
|||
'|Image|File|' + |
|||
Insta.conf.locale.image + |
|||
'|' + |
|||
Insta.conf.wiki.interwiki + |
|||
'):.*?)\\|([^\\]]+?)\\]\\](\\w*)', |
|||
'gi' |
|||
), |
|||
($0, $1, $2, $3) => f( |
|||
"<a href='?'>?</a>", |
|||
Insta.conf.paths.articles + htmlescape_attr($1), |
|||
htmlescape_text($2) + htmlescape_text($3) |
|||
) |
|||
) |
|||
// [[/Relative links]] |
|||
.replace(/\[\[(\/[^|]*?)\]\]/g, ($0, $1) => f( |
|||
"<a href='?'>?</a>", |
|||
Insta.conf.baseUrl + htmlescape_attr($1), |
|||
htmlescape_text($1) |
|||
)) |
|||
// [[/Replaced|Relative links]] |
|||
.replace(/\[\[(\/.*?)\|(.+?)\]\]/g, ($0, $1, $2) => f( |
|||
"<a href='?'>?</a>", |
|||
Insta.conf.baseUrl + htmlescape_attr($1), |
|||
htmlescape_text($2) |
|||
)) |
|||
// [[Common links]] |
|||
.replace(/\[\[([^[|]*?)\]\](\w*)/g, ($0, $1, $2) => f( |
|||
"<a href='?'>?</a>", |
|||
Insta.conf.paths.articles + htmlescape_attr($1), |
|||
htmlescape_text($1) + htmlescape_text($2) |
|||
)) |
|||
// [[Replaced|Links]] |
|||
.replace(/\[\[([^[]*?)\|([^\]]+?)\]\](\w*)/g, ($0, $1, $2, $3) => f( |
|||
"<a href='?'>?</a>", |
|||
Insta.conf.paths.articles + htmlescape_attr($1), |
|||
htmlescape_text($2) + htmlescape_text($3) |
|||
)) |
|||
// [[Stripped:Namespace|Namespace]] |
|||
.replace(/\[\[([^\]]*?:)?(.*?)( *\(.*?\))?\|\]\]/g, ($0, $1, $2, $3) => f( |
|||
"<a href='?'>?</a>", |
|||
Insta.conf.paths.articles + |
|||
htmlescape_attr($1) + |
|||
htmlescape_attr($2) + |
|||
htmlescape_attr($3), |
|||
htmlescape_text($2) |
|||
)) |
|||
// External links |
|||
.replace( |
|||
/\[(https?|news|ftp|mailto|gopher|irc):(\/*)([^\]]*?) (.*?)\]/g, |
|||
($0, $1, $2, $3, $4) => f( |
|||
"<a class='external' href='?:?'>?</a>", |
|||
htmlescape_attr($1), |
|||
htmlescape_attr($2) + htmlescape_attr($3), |
|||
htmlescape_text($4) |
|||
) |
|||
) |
|||
.replace(/\[http:\/\/(.*?)\]/g, ($0, $1) => f("<a class='external' href='http://?'>[#]</a>", htmlescape_attr($1))) |
|||
.replace(/\[(news|ftp|mailto|gopher|irc):(\/*)(.*?)\]/g, ($0, $1, $2, $3) => f( |
|||
"<a class='external' href='?:?'>?:?</a>", |
|||
htmlescape_attr($1), |
|||
htmlescape_attr($2) + htmlescape_attr($3), |
|||
htmlescape_text($1), |
|||
htmlescape_text($2) + htmlescape_text($3) |
|||
)) |
|||
.replace( |
|||
/(^| )(https?|news|ftp|mailto|gopher|irc):(\/*)([^ $]*[^.,!?;: $])/g, |
|||
($0, $1, $2, $3, $4) => f( |
|||
"?<a class='external' href='?:?'>?:?</a>", |
|||
htmlescape_text($1), |
|||
htmlescape_attr($2), |
|||
htmlescape_attr($3) + htmlescape_attr($4), |
|||
htmlescape_text($2), |
|||
htmlescape_text($3) + htmlescape_text($4) |
|||
) |
|||
) |
|||
.replace('__NOTOC__', '') |
|||
.replace('__NOINDEX__', '') |
|||
.replace('__INDEX__', '') |
|||
.replace('__NOEDITSECTION__', ''); |
|||
return parse_inline_formatting(str); |
|||
} |
|||
// begin parsing |
|||
for (; remain(); ) { |
|||
if (compareLineStringOrReg(/^(={1,6})(.*)\1(.*)$/)) { |
|||
p = 0; |
|||
endl(f('<h?>?</h?>?', r[1].length, parse_inline_nowiki(r[2]), r[1].length, r[3])); |
|||
} else if (compareLineStringOrReg(/^[*#:;]/)) { |
|||
p = 0; |
|||
parse_list(); |
|||
} else if (compareLineStringOrReg(' ')) { |
|||
p = 0; |
|||
parse_pre(); |
|||
} else if (compareLineStringOrReg('{|')) { |
|||
p = 0; |
|||
parse_table(); |
|||
} else if (compareLineStringOrReg(/^----+$/)) { |
|||
p = 0; |
|||
endl('<hr />'); |
|||
} else if (compareLineStringOrReg(Insta.BLOCK_IMAGE)) { |
|||
p = 0; |
|||
parse_block_image(); |
|||
} else { |
|||
// handle paragraphs |
|||
if (compareLineString('')) { |
|||
p = remain() > 1 && ll[1] === ''; |
|||
if (p) { |
|||
endl('<p><br>'); |
|||
} |
|||
} else { |
|||
if (!p) { |
|||
ps('<p>'); |
|||
p = 1; |
|||
} |
|||
ps(parse_inline_nowiki(ll[0]) + ' '); |
|||
} |
|||
sh(); |
|||
} |
|||
} |
|||
return o; |
|||
}; |
|||
function wiki2html(txt, baseurl) { |
|||
Insta.conf.baseUrl = baseurl; |
|||
return Insta.convert(txt); |
|||
} |
|||
// ENDFILE: livepreview.js |
|||
// STARTFILE: pageinfo.js |
|||
function popupFilterPageSize(data) { |
|||
return formatBytes(data.length); |
|||
} |
|||
function popupFilterCountLinks(data) { |
|||
const num = countLinks(data); |
|||
return String(num) + ' ' + (num != 1 ? popupString('wikiLinks') : popupString('wikiLink')); |
|||
} |
|||
function popupFilterCountImages(data) { |
|||
const num = countImages(data); |
|||
return String(num) + ' ' + (num != 1 ? popupString('images') : popupString('image')); |
|||
} |
|||
function popupFilterCountCategories(data) { |
|||
const num = countCategories(data); |
|||
return ( |
|||
String(num) + ' ' + (num != 1 ? popupString('categories') : popupString('category')) |
|||
); |
|||
} |
|||
function popupFilterLastModified(data, download) { |
|||
const lastmod = download.lastModified; |
|||
const now = new Date(); |
|||
const age = now - lastmod; |
|||
if (lastmod && getValueOf('popupLastModified')) { |
|||
return tprintf('%s old', [formatAge(age)]).replace(/ /g, ' '); |
|||
} |
|||
return ''; |
|||
} |
|||
function popupFilterWikibaseItem(data, download) { |
|||
return download.wikibaseItem ? |
|||
tprintf('<a href="%s">%s</a>', [ |
|||
download.wikibaseRepo.replace(/\$1/g, download.wikibaseItem), |
|||
download.wikibaseItem, |
|||
]) : |
|||
''; |
|||
} |
|||
function formatAge(age) { |
|||
// coerce into a number |
|||
let a = 0 + age, |
|||
aa = a; |
|||
const seclen = 1000; |
|||
const minlen = 60 * seclen; |
|||
const hourlen = 60 * minlen; |
|||
const daylen = 24 * hourlen; |
|||
const weeklen = 7 * daylen; |
|||
const numweeks = (a - (a % weeklen)) / weeklen; |
|||
a = a - numweeks * weeklen; |
|||
const sweeks = addunit(numweeks, 'week'); |
|||
const numdays = (a - (a % daylen)) / daylen; |
|||
a = a - numdays * daylen; |
|||
const sdays = addunit(numdays, 'day'); |
|||
const numhours = (a - (a % hourlen)) / hourlen; |
|||
a = a - numhours * hourlen; |
|||
const shours = addunit(numhours, 'hour'); |
|||
const nummins = (a - (a % minlen)) / minlen; |
|||
a = a - nummins * minlen; |
|||
const smins = addunit(nummins, 'minute'); |
|||
const numsecs = (a - (a % seclen)) / seclen; |
|||
a = a - numsecs * seclen; |
|||
const ssecs = addunit(numsecs, 'second'); |
|||
if (aa > 4 * weeklen) { |
|||
return sweeks; |
|||
} |
|||
if (aa > weeklen) { |
|||
return sweeks + ' ' + sdays; |
|||
} |
|||
if (aa > daylen) { |
|||
return sdays + ' ' + shours; |
|||
} |
|||
if (aa > 6 * hourlen) { |
|||
return shours; |
|||
} |
|||
if (aa > hourlen) { |
|||
return shours + ' ' + smins; |
|||
} |
|||
if (aa > 10 * minlen) { |
|||
return smins; |
|||
} |
|||
if (aa > minlen) { |
|||
return smins + ' ' + ssecs; |
|||
} |
|||
return ssecs; |
|||
} |
|||
function addunit(num, str) { |
|||
return String(num) + ' ' + (num != 1 ? popupString(str + 's') : popupString(str)); |
|||
} |
|||
function runPopupFilters(list, data, download) { |
|||
const ret = []; |
|||
for (let i = 0; i < list.length; ++i) { |
|||
if (list[i] && typeof list[i] == 'function') { |
|||
const s = list[i](data, download, download.owner.article); |
|||
if (s) { |
|||
ret.push(s); |
|||
} |
|||
} |
|||
} |
|||
return ret; |
|||
} |
|||
function getPageInfo(data, download) { |
|||
if (!data || data.length === 0) { |
|||
return popupString('Empty page'); |
|||
} |
|||
const popupFilters = getValueOf('popupFilters') || []; |
|||
const extraPopupFilters = getValueOf('extraPopupFilters') || []; |
|||
const pageInfoArray = runPopupFilters(popupFilters.concat(extraPopupFilters), data, download); |
|||
let pageInfo = pageInfoArray.join(', '); |
|||
if (pageInfo !== '') { |
|||
pageInfo = upcaseFirst(pageInfo); |
|||
} |
|||
return pageInfo; |
|||
} |
|||
// this could be improved! |
|||
function countLinks(wikiText) { |
|||
return wikiText.split('[[').length - 1; |
|||
} |
|||
// if N = # matches, n = # brackets, then |
|||
// String.parenSplit(regex) intersperses the N+1 split elements |
|||
// with Nn other elements. So total length is |
|||
// L= N+1 + Nn = N(n+1)+1. So N=(L-1)/(n+1). |
|||
function countImages(wikiText) { |
|||
return (wikiText.parenSplit(pg.re.image).length - 1) / (pg.re.imageBracketCount + 1); |
|||
} |
|||
function countCategories(wikiText) { |
|||
return (wikiText.parenSplit(pg.re.category).length - 1) / (pg.re.categoryBracketCount + 1); |
|||
} |
|||
function popupFilterStubDetect(data, download, article) { |
|||
const counts = stubCount(data, article); |
|||
if (counts.real) { |
|||
return popupString('stub'); |
|||
} |
|||
if (counts.sect) { |
|||
return popupString('section stub'); |
|||
} |
|||
return ''; |
|||
} |
|||
function popupFilterDisambigDetect(data, download, article) { |
|||
if (!getValueOf('popupAllDabsStubs') && article.namespace()) { |
|||
return ''; |
|||
} |
|||
return isDisambig(data, article) ? popupString('disambig') : ''; |
|||
} |
|||
function formatBytes(num) { |
|||
return num > 949 ? |
|||
Math.round(num / 100) / 10 + popupString('kB') : |
|||
num + ' ' + popupString('bytes'); |
|||
} |
|||
// ENDFILE: pageinfo.js |
|||
// STARTFILE: titles.js |
|||
/** |
|||
* @file Defines the {@link Title} class, and associated crufty functions. |
|||
* |
|||
* <code>Title</code> deals with article titles and their various |
|||
* forms. {@link Stringwrapper} is the parent class of |
|||
* <code>Title</code>, which exists simply to make things a little |
|||
* neater. |
|||
*/ |
|||
/** |
|||
* Creates a new Stringwrapper. |
|||
* |
|||
* @constructor |
|||
* |
|||
* @class the Stringwrapper class. This base class is not really |
|||
* useful on its own; it just wraps various common string operations. |
|||
*/ |
|||
function Stringwrapper() { |
|||
/** |
|||
* Wrapper for this.toString().indexOf() |
|||
* |
|||
* @param {string} x |
|||
* @type {number} |
|||
*/ |
|||
this.indexOf = function (x) { |
|||
return this.toString().indexOf(x); |
|||
}; |
|||
/** |
|||
* Returns this.value. |
|||
* |
|||
* @type {string} |
|||
*/ |
|||
this.toString = function () { |
|||
return this.value; |
|||
}; |
|||
/** |
|||
* Wrapper for {@link String#parenSplit} applied to this.toString() |
|||
* |
|||
* @param {RegExp} x |
|||
* @type {Array} |
|||
*/ |
|||
this.parenSplit = function (x) { |
|||
return this.toString().parenSplit(x); |
|||
}; |
|||
/** |
|||
* Wrapper for this.toString().substring() |
|||
* |
|||
* @param {string} x |
|||
* @param {string} y (optional) |
|||
* @type {string} |
|||
*/ |
|||
this.substring = function (x, y) { |
|||
if (typeof y == 'undefined') { |
|||
return this.toString().substring(x); |
|||
} |
|||
return this.toString().substring(x, y); |
|||
}; |
|||
/** |
|||
* Wrapper for this.toString().split() |
|||
* |
|||
* @param {string} x |
|||
* @type {Array} |
|||
*/ |
|||
this.split = function (x) { |
|||
return this.toString().split(x); |
|||
}; |
|||
/** |
|||
* Wrapper for this.toString().replace() |
|||
* |
|||
* @param {string} x |
|||
* @param {string} y |
|||
* @type {string} |
|||
*/ |
|||
this.replace = function (x, y) { |
|||
return this.toString().replace(x, y); |
|||
}; |
|||
} |
|||
/** |
|||
* Creates a new <code>Title</code>. |
|||
* |
|||
* @constructor |
|||
* |
|||
* @class The Title class. Holds article titles and converts them into |
|||
* various forms. Also deals with anchors, by which we mean the bits |
|||
* of the article URL after a # character, representing locations |
|||
* within an article. |
|||
* |
|||
* @param {string} value The initial value to assign to the |
|||
* article. This must be the canonical title (see {@link |
|||
* Title#value}. Omit this in the constructor and use another function |
|||
* to set the title if this is unavailable. |
|||
*/ |
|||
function Title(val) { |
|||
/** |
|||
* The canonical article title. This must be in UTF-8 with no |
|||
* entities, escaping or nasties. Also, underscores should be |
|||
* replaced with spaces. |
|||
* |
|||
* @type {string} |
|||
* @private |
|||
*/ |
|||
this.value = null; |
|||
/** |
|||
* The canonical form of the anchor. This should be exactly as |
|||
* it appears in the URL, i.e. with the .C3.0A bits in. |
|||
* |
|||
* @type {string} |
|||
*/ |
|||
this.anchor = ''; |
|||
this.setUtf(val); |
|||
} |
|||
Title.prototype = new Stringwrapper(); |
|||
/** |
|||
* Returns the canonical representation of the article title, optionally without anchor. |
|||
* |
|||
* @param {boolean} omitAnchor |
|||
* @fixme Decide specs for anchor |
|||
* @return String The article title and the anchor. |
|||
*/ |
|||
Title.prototype.toString = function (omitAnchor) { |
|||
return this.value + (!omitAnchor && this.anchor ? '#' + this.anchorString() : ''); |
|||
}; |
|||
Title.prototype.anchorString = function () { |
|||
if (!this.anchor) { |
|||
return ''; |
|||
} |
|||
const split = this.anchor.parenSplit(/((?:[.][0-9A-F]{2})+)/); |
|||
const len = split.length; |
|||
let value; |
|||
for (let j = 1; j < len; j += 2) { |
|||
// FIXME s/decodeURI/decodeURIComponent/g ? |
|||
value = split[j].split('.').join('%'); |
|||
try { |
|||
value = decodeURIComponent(value); |
|||
} catch (e) { |
|||
// cannot decode |
|||
} |
|||
split[j] = value.split('_').join(' '); |
|||
} |
|||
return split.join(''); |
|||
}; |
|||
Title.prototype.urlAnchor = function () { |
|||
const split = this.anchor.parenSplit('/((?:[%][0-9A-F]{2})+)/'); |
|||
const len = split.length; |
|||
for (let j = 1; j < len; j += 2) { |
|||
split[j] = split[j].split('%').join('.'); |
|||
} |
|||
return split.join(''); |
|||
}; |
|||
Title.prototype.anchorFromUtf = function (str) { |
|||
this.anchor = encodeURIComponent(str.split(' ').join('_')) |
|||
.split('%3A') |
|||
.join(':') |
|||
.split("'") |
|||
.join('%27') |
|||
.split('%') |
|||
.join('.'); |
|||
}; |
|||
Title.fromURL = function (h) { |
|||
return new Title().fromURL(h); |
|||
}; |
|||
Title.prototype.fromURL = function (h) { |
|||
if (typeof h != 'string') { |
|||
this.value = null; |
|||
return this; |
|||
} |
|||
// NOTE : playing with decodeURI, encodeURI, escape, unescape, |
|||
// we seem to be able to replicate the IE borked encoding |
|||
// IE doesn't do this new-fangled utf-8 thing. |
|||
// and it's worse than that. |
|||
// IE seems to treat the query string differently to the rest of the url |
|||
// the query is treated as bona-fide utf8, but the first bit of the url is pissed around with |
|||
// we fix up & for all browsers, just in case. |
|||
const splitted = h.split('?'); |
|||
splitted[0] = splitted[0].split('&').join('%26'); |
|||
h = splitted.join('?'); |
|||
const contribs = pg.re.contribs.exec(h); |
|||
if (contribs) { |
|||
if (contribs[1] == 'title=') { |
|||
contribs[3] = contribs[3].split('+').join(' '); |
|||
} |
|||
const u = new Title(contribs[3]); |
|||
this.setUtf( |
|||
this.decodeNasties( |
|||
mw.config.get('wgFormattedNamespaces')[pg.nsUserId] + ':' + u.stripNamespace() |
|||
) |
|||
); |
|||
return this; |
|||
} |
|||
const email = pg.re.email.exec(h); |
|||
if (email) { |
|||
this.setUtf( |
|||
this.decodeNasties( |
|||
mw.config.get('wgFormattedNamespaces')[pg.nsUserId] + |
|||
':' + |
|||
new Title(email[3]).stripNamespace() |
|||
) |
|||
); |
|||
return this; |
|||
} |
|||
const backlinks = pg.re.backlinks.exec(h); |
|||
if (backlinks) { |
|||
this.setUtf(this.decodeNasties(new Title(backlinks[3]))); |
|||
return this; |
|||
} |
|||
//A dummy title object for a Special:Diff link. |
|||
const specialdiff = pg.re.specialdiff.exec(h); |
|||
if (specialdiff) { |
|||
this.setUtf( |
|||
this.decodeNasties( |
|||
new Title(mw.config.get('wgFormattedNamespaces')[pg.nsSpecialId] + ':Diff') |
|||
) |
|||
); |
|||
return this; |
|||
} |
|||
// no more special cases to check -- |
|||
// hopefully it's not a disguised user-related or specially treated special page |
|||
// Includes references |
|||
const m = pg.re.main.exec(h); |
|||
if (m === null) { |
|||
this.value = null; |
|||
} else { |
|||
const fromBotInterface = /[?](.+[&])?title=/.test(h); |
|||
if (fromBotInterface) { |
|||
m[2] = m[2].split('+').join('_'); |
|||
} |
|||
const extracted = m[2] + (m[3] ? '#' + m[3] : ''); |
|||
if (pg.flag.isSafari && /%25[0-9A-Fa-f]{2}/.test(extracted)) { |
|||
// Fix Safari issue |
|||
// Safari sometimes encodes % as %25 in UTF-8 encoded strings like %E5%A3 -> %25E5%25A3. |
|||
this.setUtf(decodeURIComponent(unescape(extracted))); |
|||
} else { |
|||
this.setUtf(this.decodeNasties(extracted)); |
|||
} |
|||
} |
|||
return this; |
|||
}; |
|||
Title.prototype.decodeNasties = function (txt) { |
|||
// myDecodeURI uses decodeExtras, which removes _, |
|||
// thus ruining citations previews, which are formated as "cite_note-1" |
|||
try { |
|||
let ret = decodeURI(this.decodeEscapes(txt)); |
|||
ret = ret.replace(/[_ ]*$/, ''); |
|||
return ret; |
|||
} catch (e) { |
|||
return txt; // cannot decode |
|||
} |
|||
}; |
|||
// Decode valid %-encodings, otherwise escape them |
|||
Title.prototype.decodeEscapes = function (txt) { |
|||
const split = txt.parenSplit(/((?:[%][0-9A-Fa-f]{2})+)/); |
|||
const len = split.length; |
|||
// No %-encoded items found, so replace the literal % |
|||
if (len === 1) { |
|||
return split[0].replace(/%(?![0-9a-fA-F][0-9a-fA-F])/g, '%25'); |
|||
} |
|||
for (let i = 1; i < len; i = i + 2) { |
|||
split[i] = decodeURIComponent(split[i]); |
|||
} |
|||
return split.join(''); |
|||
}; |
|||
Title.fromAnchor = function (a) { |
|||
return new Title().fromAnchor(a); |
|||
}; |
|||
Title.prototype.fromAnchor = function (a) { |
|||
if (!a) { |
|||
this.value = null; |
|||
return this; |
|||
} |
|||
return this.fromURL(a.href); |
|||
}; |
|||
Title.fromWikiText = function (txt) { |
|||
return new Title().fromWikiText(txt); |
|||
}; |
|||
Title.prototype.fromWikiText = function (txt) { |
|||
// FIXME - testing needed |
|||
txt = myDecodeURI(txt); |
|||
this.setUtf(txt); |
|||
return this; |
|||
}; |
|||
Title.prototype.hintValue = function () { |
|||
if (!this.value) { |
|||
return ''; |
|||
} |
|||
return safeDecodeURI(this.value); |
|||
}; |
|||
Title.prototype.toUserName = function (withNs) { |
|||
if (this.namespaceId() != pg.nsUserId && this.namespaceId() != pg.nsUsertalkId) { |
|||
this.value = null; |
|||
return; |
|||
} |
|||
this.value = |
|||
(withNs ? mw.config.get('wgFormattedNamespaces')[pg.nsUserId] + ':' : '') + |
|||
this.stripNamespace().split('/')[0]; |
|||
}; |
|||
Title.prototype.userName = function (withNs) { |
|||
const t = new Title(this.value); |
|||
t.toUserName(withNs); |
|||
if (t.value) { |
|||
return t; |
|||
} |
|||
return null; |
|||
}; |
|||
Title.prototype.toTalkPage = function () { |
|||
// convert article to a talk page, or if we can't, return null |
|||
// In other words: return null if this ALREADY IS a talk page |
|||
// and return the corresponding talk page otherwise |
|||
// |
|||
// Per https://www.mediawiki.org/wiki/Manual:Namespace#Subject_and_talk_namespaces |
|||
// * All discussion namespaces have odd-integer indices |
|||
// * The discussion namespace index for a specific namespace with index n is n + 1 |
|||
if (this.value === null) { |
|||
return null; |
|||
} |
|||
const namespaceId = this.namespaceId(); |
|||
if (namespaceId >= 0 && namespaceId % 2 === 0) { |
|||
//non-special and subject namespace |
|||
const localizedNamespace = mw.config.get('wgFormattedNamespaces')[namespaceId + 1]; |
|||
if (typeof localizedNamespace !== 'undefined') { |
|||
if (localizedNamespace === '') { |
|||
this.value = this.stripNamespace(); |
|||
} else { |
|||
this.value = localizedNamespace.split(' ').join('_') + ':' + this.stripNamespace(); |
|||
} |
|||
return this.value; |
|||
} |
|||
} |
|||
this.value = null; |
|||
return null; |
|||
}; |
|||
// Return canonical, localized namespace |
|||
Title.prototype.namespace = function () { |
|||
return mw.config.get('wgFormattedNamespaces')[this.namespaceId()]; |
|||
}; |
|||
Title.prototype.namespaceId = function () { |
|||
const n = this.value.indexOf(':'); |
|||
if (n < 0) { |
|||
return 0; |
|||
} //mainspace |
|||
const namespaceId = |
|||
mw.config.get('wgNamespaceIds')[ |
|||
this.value.substring(0, n).split(' ').join('_').toLowerCase() |
|||
]; |
|||
if (typeof namespaceId == 'undefined') { |
|||
return 0; |
|||
} //mainspace |
|||
return namespaceId; |
|||
}; |
|||
Title.prototype.talkPage = function () { |
|||
const t = new Title(this.value); |
|||
t.toTalkPage(); |
|||
if (t.value) { |
|||
return t; |
|||
} |
|||
return null; |
|||
}; |
|||
Title.prototype.isTalkPage = function () { |
|||
if (this.talkPage() === null) { |
|||
return true; |
|||
} |
|||
return false; |
|||
}; |
|||
Title.prototype.toArticleFromTalkPage = function () { |
|||
//largely copy/paste from toTalkPage above. |
|||
if (this.value === null) { |
|||
return null; |
|||
} |
|||
const namespaceId = this.namespaceId(); |
|||
if (namespaceId >= 0 && namespaceId % 2 == 1) { |
|||
//non-special and talk namespace |
|||
const localizedNamespace = mw.config.get('wgFormattedNamespaces')[namespaceId - 1]; |
|||
if (typeof localizedNamespace !== 'undefined') { |
|||
if (localizedNamespace === '') { |
|||
this.value = this.stripNamespace(); |
|||
} else { |
|||
this.value = localizedNamespace.split(' ').join('_') + ':' + this.stripNamespace(); |
|||
} |
|||
return this.value; |
|||
} |
|||
} |
|||
this.value = null; |
|||
return null; |
|||
}; |
|||
Title.prototype.articleFromTalkPage = function () { |
|||
const t = new Title(this.value); |
|||
t.toArticleFromTalkPage(); |
|||
if (t.value) { |
|||
return t; |
|||
} |
|||
return null; |
|||
}; |
|||
Title.prototype.articleFromTalkOrArticle = function () { |
|||
const t = new Title(this.value); |
|||
if (t.toArticleFromTalkPage()) { |
|||
return t; |
|||
} |
|||
return this; |
|||
}; |
|||
Title.prototype.isIpUser = function () { |
|||
return pg.re.ipUser.test(this.userName()); |
|||
}; |
|||
Title.prototype.stripNamespace = function () { |
|||
// returns a string, not a Title |
|||
const n = this.value.indexOf(':'); |
|||
if (n < 0) { |
|||
return this.value; |
|||
} |
|||
const namespaceId = this.namespaceId(); |
|||
if (namespaceId === pg.nsMainspaceId) { |
|||
return this.value; |
|||
} |
|||
return this.value.substring(n + 1); |
|||
}; |
|||
Title.prototype.setUtf = function (value) { |
|||
if (!value) { |
|||
this.value = ''; |
|||
return; |
|||
} |
|||
const anch = value.indexOf('#'); |
|||
if (anch < 0) { |
|||
this.value = value.split('_').join(' '); |
|||
this.anchor = ''; |
|||
return; |
|||
} |
|||
this.value = value.substring(0, anch).split('_').join(' '); |
|||
this.anchor = value.substring(anch + 1); |
|||
this.ns = null; // wait until namespace() is called |
|||
}; |
|||
Title.prototype.setUrl = function (urlfrag) { |
|||
const anch = urlfrag.indexOf('#'); |
|||
this.value = safeDecodeURI(urlfrag.substring(0, anch)); |
|||
this.anchor = this.value.substring(anch + 1); |
|||
}; |
|||
Title.prototype.append = function (x) { |
|||
this.setUtf(this.value + x); |
|||
}; |
|||
Title.prototype.urlString = function (x) { |
|||
if (!x) { |
|||
x = {}; |
|||
} |
|||
let v = this.toString(true); |
|||
if (!x.omitAnchor && this.anchor) { |
|||
v += '#' + this.urlAnchor(); |
|||
} |
|||
if (!x.keepSpaces) { |
|||
v = v.split(' ').join('_'); |
|||
} |
|||
return encodeURI(v).split('&').join('%26').split('?').join('%3F').split('+').join('%2B'); |
|||
}; |
|||
Title.prototype.removeAnchor = function () { |
|||
return new Title(this.toString(true)); |
|||
}; |
|||
Title.prototype.toUrl = function () { |
|||
return pg.wiki.titlebase + this.urlString(); |
|||
}; |
|||
function parseParams(url) { |
|||
const specialDiff = pg.re.specialdiff.exec(url); |
|||
if (specialDiff) { |
|||
const split = specialDiff[1].split('/'); |
|||
if (split.length == 1) { |
|||
return { oldid: split[0], diff: 'prev' }; |
|||
} else if (split.length == 2) { |
|||
return { oldid: split[0], diff: split[1] }; |
|||
} |
|||
} |
|||
const ret = {}; |
|||
if (url.indexOf('?') == -1) { |
|||
return ret; |
|||
} |
|||
url = url.split('#')[0]; |
|||
const s = url.split('?').slice(1).join(); |
|||
const t = s.split('&'); |
|||
for (let i = 0; i < t.length; ++i) { |
|||
const z = t[i].split('='); |
|||
z.push(null); |
|||
ret[z[0]] = z[1]; |
|||
} |
|||
//Diff revision with no oldid is interpreted as a diff to the previous revision by MediaWiki |
|||
if (ret.diff && typeof ret.oldid === 'undefined') { |
|||
ret.oldid = 'prev'; |
|||
} |
|||
//Documentation seems to say something different, but oldid can also accept prev/next, and |
|||
//Echo is emitting such URLs. Simple fixup during parameter decoding: |
|||
if (ret.oldid && (ret.oldid === 'prev' || ret.oldid === 'next' || ret.oldid === 'cur')) { |
|||
const helper = ret.diff; |
|||
ret.diff = ret.oldid; |
|||
ret.oldid = helper; |
|||
} |
|||
return ret; |
|||
} |
|||
// (a) myDecodeURI (first standard decodeURI, then pg.re.urlNoPopup) |
|||
// (b) change spaces to underscores |
|||
// (c) encodeURI (just the straight one, no pg.re.urlNoPopup) |
|||
function myDecodeURI(str) { |
|||
let ret; |
|||
// FIXME decodeURIComponent?? |
|||
try { |
|||
ret = decodeURI(str.toString()); |
|||
} catch (summat) { |
|||
return str; |
|||
} |
|||
for (let i = 0; i < pg.misc.decodeExtras.length; ++i) { |
|||
const from = pg.misc.decodeExtras[i].from; |
|||
const to = pg.misc.decodeExtras[i].to; |
|||
ret = ret.split(from).join(to); |
|||
} |
|||
return ret; |
|||
} |
|||
function safeDecodeURI(str) { |
|||
const ret = myDecodeURI(str); |
|||
return ret || str; |
|||
} |
|||
/////////// |
|||
// TESTS // |
|||
/////////// |
|||
function isDisambig(data, article) { |
|||
if (!getValueOf('popupAllDabsStubs') && article.namespace()) { |
|||
return false; |
|||
} |
|||
return !article.isTalkPage() && pg.re.disambig.test(data); |
|||
} |
|||
function stubCount(data, article) { |
|||
if (!getValueOf('popupAllDabsStubs') && article.namespace()) { |
|||
return false; |
|||
} |
|||
let sectStub = 0; |
|||
let realStub = 0; |
|||
if (pg.re.stub.test(data)) { |
|||
const s = data.parenSplit(pg.re.stub); |
|||
for (let i = 1; i < s.length; i = i + 2) { |
|||
if (s[i]) { |
|||
++sectStub; |
|||
} else { |
|||
++realStub; |
|||
} |
|||
} |
|||
} |
|||
return { real: realStub, sect: sectStub }; |
|||
} |
|||
function isValidImageName(str) { |
|||
// extend as needed... |
|||
return str.indexOf('{') == -1; |
|||
} |
|||
function isInStrippableNamespace(article) { |
|||
// Does the namespace allow subpages |
|||
// Note, would be better if we had access to wgNamespacesWithSubpages |
|||
return article.namespaceId() !== 0; |
|||
} |
|||
function isInMainNamespace(article) { |
|||
return article.namespaceId() === 0; |
|||
} |
|||
function anchorContainsImage(a) { |
|||
// iterate over children of anchor a |
|||
// see if any are images |
|||
if (a === null) { |
|||
return false; |
|||
} |
|||
const kids = a.childNodes; |
|||
for (let i = 0; i < kids.length; ++i) { |
|||
if (kids[i].nodeName == 'IMG') { |
|||
return true; |
|||
} |
|||
} |
|||
return false; |
|||
} |
|||
function isPopupLink(a) { |
|||
// NB for performance reasons, TOC links generally return true |
|||
// they should be stripped out later |
|||
if (!markNopopupSpanLinks.done) { |
|||
markNopopupSpanLinks(); |
|||
} |
|||
if (a.inNopopupSpan) { |
|||
return false; |
|||
} |
|||
// FIXME is this faster inline? |
|||
if (a.onmousedown || a.getAttribute('nopopup')) { |
|||
return false; |
|||
} |
|||
const h = a.href; |
|||
if (h === document.location.href + '#') { |
|||
return false; |
|||
} |
|||
if (!pg.re.basenames.test(h)) { |
|||
return false; |
|||
} |
|||
if (!pg.re.urlNoPopup.test(h)) { |
|||
return true; |
|||
} |
|||
return ( |
|||
(pg.re.email.test(h) || |
|||
pg.re.contribs.test(h) || |
|||
pg.re.backlinks.test(h) || |
|||
pg.re.specialdiff.test(h)) && |
|||
h.indexOf('&limit=') == -1 |
|||
); |
|||
} |
|||
function markNopopupSpanLinks() { |
|||
if (!getValueOf('popupOnlyArticleLinks')) { |
|||
fixVectorMenuPopups(); |
|||
} |
|||
const s = $('.nopopups').toArray(); |
|||
for (let i = 0; i < s.length; ++i) { |
|||
const as = s[i].getElementsByTagName('a'); |
|||
for (let j = 0; j < as.length; ++j) { |
|||
as[j].inNopopupSpan = true; |
|||
} |
|||
} |
|||
markNopopupSpanLinks.done = true; |
|||
} |
|||
function fixVectorMenuPopups() { |
|||
$('nav.vector-menu h3:first a:first').prop('inNopopupSpan', true); |
|||
} |
|||
// ENDFILE: titles.js |
|||
// STARTFILE: getpage.js |
|||
////////////////////////////////////////////////// |
|||
// Wiki-specific downloading |
|||
// |
|||
// Schematic for a getWiki call |
|||
// |
|||
// getPageWithCaching |
|||
// | |
|||
// false | true |
|||
// getPage<-[findPictureInCache]->-onComplete(a fake download) |
|||
// \. |
|||
// (async)->addPageToCache(download)->-onComplete(download) |
|||
// check cache to see if page exists |
|||
function getPageWithCaching(url, onComplete, owner) { |
|||
log('getPageWithCaching, url=' + url); |
|||
const i = findInPageCache(url); |
|||
let d; |
|||
if (i > -1) { |
|||
d = fakeDownload( |
|||
url, |
|||
owner.idNumber, |
|||
onComplete, |
|||
pg.cache.pages[i].data, |
|||
pg.cache.pages[i].lastModified, |
|||
owner |
|||
); |
|||
} else { |
|||
d = getPage(url, onComplete, owner); |
|||
if (d && owner && owner.addDownload) { |
|||
owner.addDownload(d); |
|||
d.owner = owner; |
|||
} |
|||
} |
|||
} |
|||
function getPage(url, onComplete, owner) { |
|||
log('getPage'); |
|||
const callback = function (d) { |
|||
if (!d.aborted) { |
|||
addPageToCache(d); |
|||
onComplete(d); |
|||
} |
|||
}; |
|||
return startDownload(url, owner.idNumber, callback); |
|||
} |
|||
function findInPageCache(url) { |
|||
for (let i = 0; i < pg.cache.pages.length; ++i) { |
|||
if (url == pg.cache.pages[i].url) { |
|||
return i; |
|||
} |
|||
} |
|||
return -1; |
|||
} |
|||
function addPageToCache(download) { |
|||
log('addPageToCache ' + download.url); |
|||
const page = { |
|||
url: download.url, |
|||
data: download.data, |
|||
lastModified: download.lastModified, |
|||
}; |
|||
return pg.cache.pages.push(page); |
|||
} |
|||
// ENDFILE: getpage.js |
|||
// STARTFILE: parensplit.js |
|||
////////////////////////////////////////////////// |
|||
// parenSplit |
|||
// String.prototype.parenSplit should do what ECMAscript says String.prototype.split does, |
|||
// interspersing paren matches (regex capturing groups) between the split elements. |
|||
// i.e. 'abc'.split(/(b)/)) should return ['a','b','c'], not ['a','c'] |
|||
if (String('abc'.split(/(b)/)) != 'a,b,c') { |
|||
// broken String.split, e.g. konq, IE < 10 |
|||
String.prototype.parenSplit = function (re) { |
|||
re = nonGlobalRegex(re); |
|||
let s = this; |
|||
let m = re.exec(s); |
|||
let ret = []; |
|||
while (m && s) { |
|||
// without the following loop, we have |
|||
// 'ab'.parenSplit(/a|(b)/) != 'ab'.split(/a|(b)/) |
|||
for (let i = 0; i < m.length; ++i) { |
|||
if (typeof m[i] == 'undefined') { |
|||
m[i] = ''; |
|||
} |
|||
} |
|||
ret.push(s.substring(0, m.index)); |
|||
ret = ret.concat(m.slice(1)); |
|||
s = s.substring(m.index + m[0].length); |
|||
m = re.exec(s); |
|||
} |
|||
ret.push(s); |
|||
return ret; |
|||
}; |
|||
} else { |
|||
String.prototype.parenSplit = function (re) { |
|||
return this.split(re); |
|||
}; |
|||
String.prototype.parenSplit.isNative = true; |
|||
} |
|||
function nonGlobalRegex(re) { |
|||
const s = re.toString(); |
|||
let flags = ''; |
|||
for (var j = s.length; s.charAt(j) != '/'; --j) { |
|||
if (s.charAt(j) != 'g') { |
|||
flags += s.charAt(j); |
|||
} |
|||
} |
|||
const t = s.substring(1, j); |
|||
return RegExp(t, flags); |
|||
} |
|||
// ENDFILE: parensplit.js |
|||
// STARTFILE: tools.js |
|||
// IE madness with encoding |
|||
// ======================== |
|||
// |
|||
// suppose throughout that the page is in utf8, like wikipedia |
|||
// |
|||
// if a is an anchor DOM element and a.href should consist of |
|||
// |
|||
// http://host.name.here/wiki/foo?bar=baz |
|||
// |
|||
// then IE gives foo as "latin1-encoded" utf8; we have foo = decode_utf8(decodeURI(foo_ie)) |
|||
// but IE gives bar=baz correctly as plain utf8 |
|||
// |
|||
// --------------------------------- |
|||
// |
|||
// IE's xmlhttp doesn't understand utf8 urls. Have to use encodeURI here. |
|||
// |
|||
// --------------------------------- |
|||
// |
|||
// summat else |
|||
// Source: http://aktuell.de.selfhtml.org/artikel/javascript/utf8b64/utf8.htm |
|||
function getJsObj(json) { |
|||
try { |
|||
const json_ret = JSON.parse(json); |
|||
if (json_ret.warnings) { |
|||
for (let w = 0; w < json_ret.warnings.length; w++) { |
|||
if (json_ret.warnings[w]['*']) { |
|||
log(json_ret.warnings[w]['*']); |
|||
} else { |
|||
log(json_ret.warnings[w].warnings); |
|||
} |
|||
} |
|||
} else if (json_ret.error) { |
|||
errlog(json_ret.error.code + ': ' + json_ret.error.info); |
|||
} |
|||
return json_ret; |
|||
} catch (someError) { |
|||
errlog('Something went wrong with getJsObj, json=' + json); |
|||
return 1; |
|||
} |
|||
} |
|||
function anyChild(obj) { |
|||
for (const p in obj) { |
|||
return obj[p]; |
|||
} |
|||
return null; |
|||
} |
|||
function upcaseFirst(str) { |
|||
if (typeof str != typeof '' || str === '') { |
|||
return ''; |
|||
} |
|||
return str.charAt(0).toUpperCase() + str.substring(1); |
|||
} |
|||
function findInArray(arr, foo) { |
|||
if (!arr || !arr.length) { |
|||
return -1; |
|||
} |
|||
const len = arr.length; |
|||
for (let i = 0; i < len; ++i) { |
|||
if (arr[i] == foo) { |
|||
return i; |
|||
} |
|||
} |
|||
return -1; |
|||
} |
|||
/* eslint-disable no-unused-vars */ |
|||
function nextOne(array, value) { |
|||
// NB if the array has two consecutive entries equal |
|||
// then this will loop on successive calls |
|||
const i = findInArray(array, value); |
|||
if (i < 0) { |
|||
return null; |
|||
} |
|||
return array[i + 1]; |
|||
} |
|||
/* eslint-enable no-unused-vars */ |
|||
function literalizeRegex(str) { |
|||
return mw.util.escapeRegExp(str); |
|||
} |
|||
String.prototype.entify = function () { |
|||
//var shy='­'; |
|||
return this.split('&') |
|||
.join('&') |
|||
.split('<') |
|||
.join('<') |
|||
.split('>') |
|||
.join('>' /*+shy*/) |
|||
.split('"') |
|||
.join('"'); |
|||
}; |
|||
// Array filter function |
|||
function removeNulls(val) { |
|||
return val !== null; |
|||
} |
|||
function joinPath(list) { |
|||
return list.filter(removeNulls).join('/'); |
|||
} |
|||
function simplePrintf(str, subs) { |
|||
if (!str || !subs) { |
|||
return str; |
|||
} |
|||
const ret = []; |
|||
const s = str.parenSplit(/(%s|\$[0-9]+)/); |
|||
let i = 0; |
|||
do { |
|||
ret.push(s.shift()); |
|||
if (!s.length) { |
|||
break; |
|||
} |
|||
const cmd = s.shift(); |
|||
if (cmd == '%s') { |
|||
if (i < subs.length) { |
|||
ret.push(subs[i]); |
|||
} else { |
|||
ret.push(cmd); |
|||
} |
|||
++i; |
|||
} else { |
|||
const j = parseInt(cmd.replace('$', ''), 10) - 1; |
|||
if (j > -1 && j < subs.length) { |
|||
ret.push(subs[j]); |
|||
} else { |
|||
ret.push(cmd); |
|||
} |
|||
} |
|||
} while (s.length > 0); |
|||
return ret.join(''); |
|||
} |
|||
/* eslint-disable no-unused-vars */ |
|||
function isString(x) { |
|||
return typeof x === 'string' || x instanceof String; |
|||
} |
|||
function isNumber(x) { |
|||
return typeof x === 'number' || x instanceof Number; |
|||
} |
|||
function isRegExp(x) { |
|||
return x instanceof RegExp; |
|||
} |
|||
function isArray(x) { |
|||
return x instanceof Array; |
|||
} |
|||
function isObject(x) { |
|||
return x instanceof Object; |
|||
} |
|||
function isFunction(x) { |
|||
return !isRegExp(x) && (typeof x === 'function' || x instanceof Function); |
|||
} |
|||
/* eslint-enable no-unused-vars */ |
|||
function repeatString(s, mult) { |
|||
let ret = ''; |
|||
for (let i = 0; i < mult; ++i) { |
|||
ret += s; |
|||
} |
|||
return ret; |
|||
} |
|||
function zeroFill(s, min) { |
|||
min = min || 2; |
|||
const t = s.toString(); |
|||
return repeatString('0', min - t.length) + t; |
|||
} |
|||
function map(f, o) { |
|||
if (isArray(o)) { |
|||
return map_array(f, o); |
|||
} |
|||
return map_object(f, o); |
|||
} |
|||
function map_array(f, o) { |
|||
const ret = []; |
|||
for (let i = 0; i < o.length; ++i) { |
|||
ret.push(f(o[i])); |
|||
} |
|||
return ret; |
|||
} |
|||
function map_object(f, o) { |
|||
const ret = {}; |
|||
for (const i in o) { |
|||
ret[o] = f(o[i]); |
|||
} |
|||
return ret; |
|||
} |
|||
pg.escapeQuotesHTML = function (text) { |
|||
return text |
|||
.replace(/&/g, '&') |
|||
.replace(/"/g, '"') |
|||
.replace(/</g, '<') |
|||
.replace(/>/g, '>'); |
|||
}; |
|||
pg.unescapeQuotesHTML = function (html) { |
|||
// From https://stackoverflow.com/a/7394787 |
|||
// This seems to be implemented correctly on all major browsers now, so we |
|||
// don't have to make our own function. |
|||
const txt = document.createElement('textarea'); |
|||
txt.innerHTML = html; |
|||
return txt.value; |
|||
}; |
|||
// ENDFILE: tools.js |
|||
// STARTFILE: dab.js |
|||
////////////////////////////////////////////////// |
|||
// Dab-fixing code |
|||
// |
|||
function retargetDab(newTarget, oldTarget, friendlyCurrentArticleName, titleToEdit) { |
|||
log('retargetDab: newTarget=' + newTarget + ' oldTarget=' + oldTarget); |
|||
return changeLinkTargetLink({ |
|||
newTarget: newTarget, |
|||
text: newTarget.split(' ').join(' '), |
|||
hint: tprintf('disambigHint', [newTarget]), |
|||
summary: simplePrintf(getValueOf('popupFixDabsSummary'), [ |
|||
friendlyCurrentArticleName, |
|||
newTarget, |
|||
]), |
|||
clickButton: getValueOf('popupDabsAutoClick'), |
|||
minor: true, |
|||
oldTarget: oldTarget, |
|||
watch: getValueOf('popupWatchDisambiggedPages'), |
|||
title: titleToEdit, |
|||
}); |
|||
} |
|||
function listLinks(wikitext, oldTarget, titleToEdit) { |
|||
// mediawiki strips trailing spaces, so we do the same |
|||
// testcase: https://en.wikipedia.org/w/index.php?title=Radial&oldid=97365633 |
|||
const reg = /\[\[([^|]*?) *(\||\]\])/gi; |
|||
let ret = []; |
|||
const splitted = wikitext.parenSplit(reg); |
|||
// ^[a-z]+ should match interwiki links, hopefully (case-insensitive) |
|||
// and ^[a-z]* should match those and [[:Category...]] style links too |
|||
const omitRegex = /^[a-z]*:|^[Ss]pecial:|^[Ii]mage|^[Cc]ategory/; |
|||
const friendlyCurrentArticleName = oldTarget.toString(); |
|||
const wikPos = getValueOf('popupDabWiktionary'); |
|||
for (let i = 1; i < splitted.length; i = i + 3) { |
|||
if ( |
|||
typeof splitted[i] == typeof 'string' && |
|||
splitted[i].length > 0 && |
|||
!omitRegex.test(splitted[i]) |
|||
) { |
|||
ret.push(retargetDab(splitted[i], oldTarget, friendlyCurrentArticleName, titleToEdit)); |
|||
} /* if */ |
|||
} /* for loop */ |
|||
ret = rmDupesFromSortedList(ret.sort()); |
|||
if (wikPos) { |
|||
const wikTarget = |
|||
'wiktionary:' + |
|||
friendlyCurrentArticleName.replace(/^(.+)\s+[(][^)]+[)]\s*$/, '$1'); |
|||
let meth; |
|||
if (wikPos.toLowerCase() == 'first') { |
|||
meth = 'unshift'; |
|||
} else { |
|||
meth = 'push'; |
|||
} |
|||
ret[meth](retargetDab(wikTarget, oldTarget, friendlyCurrentArticleName, titleToEdit)); |
|||
} |
|||
ret.push( |
|||
changeLinkTargetLink({ |
|||
newTarget: null, |
|||
text: popupString('remove this link').split(' ').join(' '), |
|||
hint: popupString('remove all links to this disambig page from this article'), |
|||
clickButton: getValueOf('popupDabsAutoClick'), |
|||
oldTarget: oldTarget, |
|||
summary: simplePrintf(getValueOf('popupRmDabLinkSummary'), [friendlyCurrentArticleName]), |
|||
watch: getValueOf('popupWatchDisambiggedPages'), |
|||
title: titleToEdit, |
|||
}) |
|||
); |
|||
return ret; |
|||
} |
|||
function rmDupesFromSortedList(list) { |
|||
const ret = []; |
|||
for (let i = 0; i < list.length; ++i) { |
|||
if (ret.length === 0 || list[i] != ret[ret.length - 1]) { |
|||
ret.push(list[i]); |
|||
} |
|||
} |
|||
return ret; |
|||
} |
|||
function makeFixDab(data, navpop) { |
|||
// grab title from parent popup if there is one; default exists in changeLinkTargetLink |
|||
const titleToEdit = navpop.parentPopup && navpop.parentPopup.article.toString(); |
|||
const list = listLinks(data, navpop.originalArticle, titleToEdit); |
|||
if (list.length === 0) { |
|||
log('listLinks returned empty list'); |
|||
return null; |
|||
} |
|||
let html = '<hr />' + popupString('Click to disambiguate this link to:') + '<br>'; |
|||
html += list.join(', '); |
|||
return html; |
|||
} |
|||
function makeFixDabs(wikiText, navpop) { |
|||
if ( |
|||
getValueOf('popupFixDabs') && |
|||
isDisambig(wikiText, navpop.article) && |
|||
Title.fromURL(location.href).namespaceId() != pg.nsSpecialId && |
|||
navpop.article.talkPage() |
|||
) { |
|||
setPopupHTML(makeFixDab(wikiText, navpop), 'popupFixDab', navpop.idNumber); |
|||
} |
|||
} |
|||
function popupRedlinkHTML(article) { |
|||
return changeLinkTargetLink({ |
|||
newTarget: null, |
|||
text: popupString('remove this link').split(' ').join(' '), |
|||
hint: popupString('remove all links to this page from this article'), |
|||
clickButton: getValueOf('popupRedlinkAutoClick'), |
|||
oldTarget: article.toString(), |
|||
summary: simplePrintf(getValueOf('popupRedlinkSummary'), [article.toString()]), |
|||
}); |
|||
} |
|||
// ENDFILE: dab.js |
|||
// STARTFILE: htmloutput.js |
|||
// this has to use a timer loop as we don't know if the DOM element exists when we want to set the text |
|||
function setPopupHTML(str, elementId, popupId, onSuccess, append) { |
|||
if (typeof popupId === 'undefined') { |
|||
//console.error('popupId is not defined in setPopupHTML, html='+str.substring(0,100)); |
|||
popupId = pg.idNumber; |
|||
} |
|||
const popupElement = document.getElementById(elementId + popupId); |
|||
if (popupElement) { |
|||
if (!append) { |
|||
popupElement.innerHTML = ''; |
|||
} |
|||
if (isString(str)) { |
|||
popupElement.innerHTML += str; |
|||
} else { |
|||
popupElement.appendChild(str); |
|||
} |
|||
if (onSuccess) { |
|||
onSuccess(); |
|||
} |
|||
setTimeout(checkPopupPosition, 100); |
|||
return true; |
|||
} else { |
|||
// call this function again in a little while... |
|||
setTimeout(() => { |
|||
setPopupHTML(str, elementId, popupId, onSuccess); |
|||
}, 600); |
|||
} |
|||
return null; |
|||
} |
|||
function setPopupTrailer(str, id) { |
|||
return setPopupHTML(str, 'popupData', id); |
|||
} |
|||
// args.navpopup is mandatory |
|||
// optional: args.redir, args.redirTarget |
|||
// FIXME: ye gods, this is ugly stuff |
|||
function fillEmptySpans(args) { |
|||
// if redir is present and true then redirTarget is mandatory |
|||
let redir = true; |
|||
let rcid; |
|||
if (typeof args != 'object' || typeof args.redir == 'undefined' || !args.redir) { |
|||
redir = false; |
|||
} |
|||
const a = args.navpopup.parentAnchor; |
|||
let article, |
|||
hint = null, |
|||
oldid = null, |
|||
params = {}; |
|||
if (redir && typeof args.redirTarget == typeof {}) { |
|||
article = args.redirTarget; |
|||
//hint=article.hintValue(); |
|||
} else { |
|||
article = new Title().fromAnchor(a); |
|||
hint = a.originalTitle || article.hintValue(); |
|||
params = parseParams(a.href); |
|||
oldid = getValueOf('popupHistoricalLinks') ? params.oldid : null; |
|||
rcid = params.rcid; |
|||
} |
|||
const x = { |
|||
article: article, |
|||
hint: hint, |
|||
oldid: oldid, |
|||
rcid: rcid, |
|||
navpop: args.navpopup, |
|||
params: params, |
|||
}; |
|||
const structure = pg.structures[getValueOf('popupStructure')]; |
|||
if (typeof structure != 'object') { |
|||
setPopupHTML( |
|||
'popupError', |
|||
'Unknown structure (this should never happen): ' + pg.option.popupStructure, |
|||
args.navpopup.idNumber |
|||
); |
|||
return; |
|||
} |
|||
const spans = flatten(pg.misc.layout); |
|||
const numspans = spans.length; |
|||
const redirs = pg.misc.redirSpans; |
|||
for (let i = 0; i < numspans; ++i) { |
|||
const found = redirs && redirs.indexOf(spans[i]) !== -1; |
|||
//log('redir='+redir+', found='+found+', spans[i]='+spans[i]); |
|||
if ((found && !redir) || (!found && redir)) { |
|||
//log('skipping this set of the loop'); |
|||
continue; |
|||
} |
|||
const structurefn = structure[spans[i]]; |
|||
if (structurefn === undefined) { |
|||
// nothing to do for this structure part |
|||
continue; |
|||
} |
|||
let setfn = setPopupHTML; |
|||
if ( |
|||
getValueOf('popupActiveNavlinks') && |
|||
(spans[i].indexOf('popupTopLinks') === 0 || spans[i].indexOf('popupRedirTopLinks') === 0) |
|||
) { |
|||
setfn = setPopupTipsAndHTML; |
|||
} |
|||
switch (typeof structurefn) { |
|||
case 'function': |
|||
log( |
|||
'running ' + |
|||
spans[i] + |
|||
'({article:' + |
|||
x.article + |
|||
', hint:' + |
|||
x.hint + |
|||
', oldid: ' + |
|||
x.oldid + |
|||
'})' |
|||
); |
|||
setfn(structurefn(x), spans[i], args.navpopup.idNumber); |
|||
break; |
|||
case 'string': |
|||
setfn(structurefn, spans[i], args.navpopup.idNumber); |
|||
break; |
|||
default: |
|||
errlog('unknown thing with label ' + spans[i] + ' (span index was ' + i + ')'); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
// flatten an array |
|||
function flatten(list, start) { |
|||
const ret = []; |
|||
if (typeof start == 'undefined') { |
|||
start = 0; |
|||
} |
|||
for (let i = start; i < list.length; ++i) { |
|||
if (typeof list[i] == typeof []) { |
|||
return ret.concat(flatten(list[i])).concat(flatten(list, i + 1)); |
|||
} else { |
|||
ret.push(list[i]); |
|||
} |
|||
} |
|||
return ret; |
|||
} |
|||
// Generate html for whole popup |
|||
function popupHTML(a) { |
|||
getValueOf('popupStructure'); |
|||
const structure = pg.structures[pg.option.popupStructure]; |
|||
if (typeof structure != 'object') { |
|||
//return 'Unknown structure: '+pg.option.popupStructure; |
|||
// override user choice |
|||
pg.option.popupStructure = pg.optionDefault.popupStructure; |
|||
return popupHTML(a); |
|||
} |
|||
if (typeof structure.popupLayout != 'function') { |
|||
return 'Bad layout'; |
|||
} |
|||
pg.misc.layout = structure.popupLayout(); |
|||
if (typeof structure.popupRedirSpans === 'function') { |
|||
pg.misc.redirSpans = structure.popupRedirSpans(); |
|||
} else { |
|||
pg.misc.redirSpans = []; |
|||
} |
|||
return makeEmptySpans(pg.misc.layout, a.navpopup); |
|||
} |
|||
function makeEmptySpans(list, navpop) { |
|||
let ret = ''; |
|||
for (let i = 0; i < list.length; ++i) { |
|||
if (typeof list[i] == typeof '') { |
|||
ret += emptySpanHTML(list[i], navpop.idNumber, 'div'); |
|||
} else if (typeof list[i] == typeof [] && list[i].length > 0) { |
|||
ret = ret.parenSplit(/(<\/[^>]*?>$)/).join(makeEmptySpans(list[i], navpop)); |
|||
} else if (typeof list[i] == typeof {} && list[i].nodeType) { |
|||
ret += emptySpanHTML(list[i].name, navpop.idNumber, list[i].nodeType); |
|||
} |
|||
} |
|||
return ret; |
|||
} |
|||
function emptySpanHTML(name, id, tag, classname) { |
|||
tag = tag || 'span'; |
|||
if (!classname) { |
|||
classname = emptySpanHTML.classAliases[name]; |
|||
} |
|||
classname = classname || name; |
|||
if (name == getValueOf('popupDragHandle')) { |
|||
classname += ' popupDragHandle'; |
|||
} |
|||
return simplePrintf('<%s id="%s" class="%s"></%s>', [tag, name + id, classname, tag]); |
|||
} |
|||
emptySpanHTML.classAliases = { popupSecondPreview: 'popupPreview' }; |
|||
// generate html for popup image |
|||
// <a id="popupImageLinkn"><img id="popupImagen"> |
|||
// where n=idNumber |
|||
function imageHTML(article, idNumber) { |
|||
return simplePrintf( |
|||
'<a id="popupImageLink$1">' + |
|||
'<img align="right" valign="top" id="popupImg$1" style="display: none;"></img>' + |
|||
'</a>', |
|||
[idNumber] |
|||
); |
|||
} |
|||
function popTipsSoonFn(id, when, popData) { |
|||
if (!when) { |
|||
when = 250; |
|||
} |
|||
const popTips = function () { |
|||
setupTooltips(document.getElementById(id), false, true, popData); |
|||
}; |
|||
return function () { |
|||
setTimeout(popTips, when, popData); |
|||
}; |
|||
} |
|||
function setPopupTipsAndHTML(html, divname, idnumber, popData) { |
|||
setPopupHTML( |
|||
html, |
|||
divname, |
|||
idnumber, |
|||
getValueOf('popupSubpopups') ? popTipsSoonFn(divname + idnumber, null, popData) : null |
|||
); |
|||
} |
|||
// ENDFILE: htmloutput.js |
|||
// STARTFILE: mouseout.js |
|||
////////////////////////////////////////////////// |
|||
// fuzzy checks |
|||
function fuzzyCursorOffMenus(x, y, fuzz, parent) { |
|||
if (!parent) { |
|||
return null; |
|||
} |
|||
const uls = parent.getElementsByTagName('ul'); |
|||
for (let i = 0; i < uls.length; ++i) { |
|||
if (uls[i].className == 'popup_menu') { |
|||
if (uls[i].offsetWidth > 0) { |
|||
return false; |
|||
} |
|||
} // else {document.title+='.';} |
|||
} |
|||
return true; |
|||
} |
|||
function checkPopupPosition() { |
|||
// stop the popup running off the right of the screen |
|||
// FIXME avoid pg.current.link |
|||
if (pg.current.link && pg.current.link.navpopup) { |
|||
pg.current.link.navpopup.limitHorizontalPosition(); |
|||
} |
|||
} |
|||
function mouseOutWikiLink() { |
|||
//console ('mouseOutWikiLink'); |
|||
const a = this; |
|||
removeModifierKeyHandler(a); |
|||
if (a.navpopup === null || typeof a.navpopup === 'undefined') { |
|||
return; |
|||
} |
|||
if (!a.navpopup.isVisible()) { |
|||
a.navpopup.banish(); |
|||
return; |
|||
} |
|||
restoreTitle(a); |
|||
Navpopup.tracker.addHook(posCheckerHook(a.navpopup)); |
|||
} |
|||
function posCheckerHook(navpop) { |
|||
return function () { |
|||
if (!navpop.isVisible()) { |
|||
return true; /* remove this hook */ |
|||
} |
|||
if (Navpopup.tracker.dirty) { |
|||
return false; |
|||
} |
|||
const x = Navpopup.tracker.x, |
|||
y = Navpopup.tracker.y; |
|||
const mouseOverNavpop = |
|||
navpop.isWithin(x, y, navpop.fuzz, navpop.mainDiv) || |
|||
!fuzzyCursorOffMenus(x, y, navpop.fuzz, navpop.mainDiv); |
|||
// FIXME it'd be prettier to do this internal to the Navpopup objects |
|||
let t = getValueOf('popupHideDelay'); |
|||
if (t) { |
|||
t = t * 1000; |
|||
} |
|||
if (!t) { |
|||
if (!mouseOverNavpop) { |
|||
if (navpop.parentAnchor) { |
|||
restoreTitle(navpop.parentAnchor); |
|||
} |
|||
navpop.banish(); |
|||
return true; /* remove this hook */ |
|||
} |
|||
return false; |
|||
} |
|||
// we have a hide delay set |
|||
const d = Date.now(); |
|||
if (!navpop.mouseLeavingTime) { |
|||
navpop.mouseLeavingTime = d; |
|||
return false; |
|||
} |
|||
if (mouseOverNavpop) { |
|||
navpop.mouseLeavingTime = null; |
|||
return false; |
|||
} |
|||
if (d - navpop.mouseLeavingTime > t) { |
|||
navpop.mouseLeavingTime = null; |
|||
navpop.banish(); |
|||
return true; /* remove this hook */ |
|||
} |
|||
return false; |
|||
}; |
|||
} |
|||
function runStopPopupTimer(navpop) { |
|||
// at this point, we should have left the link but remain within the popup |
|||
// so we call this function again until we leave the popup. |
|||
if (!navpop.stopPopupTimer) { |
|||
navpop.stopPopupTimer = setInterval(posCheckerHook(navpop), 500); |
|||
navpop.addHook( |
|||
() => { |
|||
clearInterval(navpop.stopPopupTimer); |
|||
}, |
|||
'hide', |
|||
'before' |
|||
); |
|||
} |
|||
} |
|||
// ENDFILE: mouseout.js |
|||
// STARTFILE: previewmaker.js |
|||
/** |
|||
* @file |
|||
* Defines the {@link Previewmaker} object, which generates short previews from wiki markup. |
|||
*/ |
|||
/** |
|||
* Creates a new Previewmaker |
|||
* |
|||
* @constructor |
|||
* @class The Previewmaker class. Use an instance of this to generate short previews from Wikitext. |
|||
* @param {string} wikiText The Wikitext source of the page we wish to preview. |
|||
* @param {string} baseUrl The url we should prepend when creating relative urls. |
|||
* @param {Navpopup} owner The navpop associated to this preview generator |
|||
*/ |
|||
function Previewmaker(wikiText, baseUrl, owner) { |
|||
/** The wikitext which is manipulated to generate the preview. */ |
|||
this.originalData = wikiText; |
|||
this.baseUrl = baseUrl; |
|||
this.owner = owner; |
|||
this.maxCharacters = getValueOf('popupMaxPreviewCharacters'); |
|||
this.maxSentences = getValueOf('popupMaxPreviewSentences'); |
|||
this.setData(); |
|||
} |
|||
Previewmaker.prototype.setData = function () { |
|||
const maxSize = Math.max(10000, 2 * this.maxCharacters); |
|||
this.data = this.originalData.substring(0, maxSize); |
|||
}; |
|||
/** |
|||
* Remove HTML comments |
|||
* |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.killComments = function () { |
|||
// this also kills one trailing newline, eg [[diamyo]] |
|||
this.data = this.data.replace( |
|||
/^<!--[^$]*?-->\n|\n<!--[^$]*?-->(?=\n)|<!--[^$]*?-->/g, |
|||
'' |
|||
); |
|||
}; |
|||
/** |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.killDivs = function () { |
|||
// say goodbye, divs (can be nested, so use * not *?) |
|||
this.data = this.data.replace(/< *div[^>]* *>[\s\S]*?< *\/ *div *>/gi, ''); |
|||
}; |
|||
/** |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.killGalleries = function () { |
|||
this.data = this.data.replace(/< *gallery[^>]* *>[\s\S]*?< *\/ *gallery *>/gi, ''); |
|||
}; |
|||
/** |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.kill = function (opening, closing, subopening, subclosing, repl) { |
|||
let oldk = this.data; |
|||
let k = this.killStuff(this.data, opening, closing, subopening, subclosing, repl); |
|||
while (k.length < oldk.length) { |
|||
oldk = k; |
|||
k = this.killStuff(k, opening, closing, subopening, subclosing, repl); |
|||
} |
|||
this.data = k; |
|||
}; |
|||
/** |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.killStuff = function ( |
|||
txt, |
|||
opening, |
|||
closing, |
|||
subopening, |
|||
subclosing, |
|||
repl |
|||
) { |
|||
const op = this.makeRegexp(opening); |
|||
const cl = this.makeRegexp(closing, '^'); |
|||
const sb = subopening ? this.makeRegexp(subopening, '^') : null; |
|||
const sc = subclosing ? this.makeRegexp(subclosing, '^') : cl; |
|||
if (!op || !cl) { |
|||
alert('Navigation Popups error: op or cl is null! something is wrong.'); |
|||
return; |
|||
} |
|||
if (!op.test(txt)) { |
|||
return txt; |
|||
} |
|||
let ret = ''; |
|||
const opResult = op.exec(txt); |
|||
ret = txt.substring(0, opResult.index); |
|||
txt = txt.substring(opResult.index + opResult[0].length); |
|||
let depth = 1; |
|||
while (txt.length > 0) { |
|||
let removal = 0; |
|||
if (depth == 1 && cl.test(txt)) { |
|||
depth--; |
|||
removal = cl.exec(txt)[0].length; |
|||
} else if (depth > 1 && sc.test(txt)) { |
|||
depth--; |
|||
removal = sc.exec(txt)[0].length; |
|||
} else if (sb && sb.test(txt)) { |
|||
depth++; |
|||
removal = sb.exec(txt)[0].length; |
|||
} |
|||
if (!removal) { |
|||
removal = 1; |
|||
} |
|||
txt = txt.substring(removal); |
|||
if (depth === 0) { |
|||
break; |
|||
} |
|||
} |
|||
return ret + (repl || '') + txt; |
|||
}; |
|||
/** |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.makeRegexp = function (x, prefix, suffix) { |
|||
prefix = prefix || ''; |
|||
suffix = suffix || ''; |
|||
let reStr = ''; |
|||
let flags = ''; |
|||
if (isString(x)) { |
|||
reStr = prefix + literalizeRegex(x) + suffix; |
|||
} else if (isRegExp(x)) { |
|||
let s = x.toString().substring(1); |
|||
const sp = s.split('/'); |
|||
flags = sp[sp.length - 1]; |
|||
sp[sp.length - 1] = ''; |
|||
s = sp.join('/'); |
|||
s = s.substring(0, s.length - 1); |
|||
reStr = prefix + s + suffix; |
|||
} else { |
|||
log('makeRegexp failed'); |
|||
} |
|||
log('makeRegexp: got reStr=' + reStr + ', flags=' + flags); |
|||
return RegExp(reStr, flags); |
|||
}; |
|||
/** |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.killBoxTemplates = function () { |
|||
// taxobox removal... in fact, there's a saudiprincebox_begin, so let's be more general |
|||
// also, have float_begin, ... float_end |
|||
this.kill(/[{][{][^{}\s|]*?(float|box)[_ ](begin|start)/i, /[}][}]\s*/, '{{'); |
|||
// infoboxes etc |
|||
// from [[User:Zyxw/popups.js]]: kill frames too |
|||
this.kill(/[{][{][^{}\s|]*?(infobox|elementbox|frame)[_ ]/i, /[}][}]\s*/, '{{'); |
|||
}; |
|||
/** |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.killTemplates = function () { |
|||
this.kill('{{', '}}', '{', '}', ' '); |
|||
}; |
|||
/** |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.killTables = function () { |
|||
// tables are bad, too |
|||
// this can be slow, but it's an inprovement over a browser hang |
|||
// torture test: [[Comparison_of_Intel_Central_Processing_Units]] |
|||
this.kill('{|', /[|]}\s*/, '{|'); |
|||
this.kill(/<table.*?>/i, /<\/table.*?>/i, /<table.*?>/i); |
|||
// remove lines starting with a pipe for the hell of it (?) |
|||
this.data = this.data.replace(/^[|].*$/mg, ''); |
|||
}; |
|||
/** |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.killImages = function () { |
|||
const forbiddenNamespaceAliases = []; |
|||
$.each(mw.config.get('wgNamespaceIds'), (_localizedNamespaceLc, _namespaceId) => { |
|||
if (_namespaceId != pg.nsImageId && _namespaceId != pg.nsCategoryId) { |
|||
return; |
|||
} |
|||
forbiddenNamespaceAliases.push(_localizedNamespaceLc.split(' ').join('[ _]')); //todo: escape regexp fragments! |
|||
}); |
|||
// images and categories are a nono |
|||
this.kill( |
|||
RegExp('[[][[]\\s*(' + forbiddenNamespaceAliases.join('|') + ')\\s*:', 'i'), |
|||
/\]\]\s*/, |
|||
'[', |
|||
']' |
|||
); |
|||
}; |
|||
/** |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.killHTML = function () { |
|||
// kill <ref ...>...</ref> |
|||
this.kill(/<ref\b[^/>]*?>/i, /<\/ref>/i); |
|||
// let's also delete entire lines starting with <. it's worth a try. |
|||
this.data = this.data.replace(/(^|\n) *<.*/g, '\n'); |
|||
// and those pesky html tags, but not <nowiki> or <blockquote> |
|||
const splitted = this.data.parenSplit(/(<[\w\W]*?(?:>|$|(?=<)))/); |
|||
const len = splitted.length; |
|||
for (let i = 1; i < len; i = i + 2) { |
|||
switch (splitted[i]) { |
|||
case '<nowiki>': |
|||
case '</nowiki>': |
|||
case '<blockquote>': |
|||
case '</blockquote>': |
|||
break; |
|||
default: |
|||
splitted[i] = ''; |
|||
} |
|||
} |
|||
this.data = splitted.join(''); |
|||
}; |
|||
/** |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.killChunks = function () { |
|||
// heuristics alert |
|||
// chunks of italic text? you crazy, man? |
|||
const italicChunkRegex = /((^|\n)\s*:*\s*''[^']([^']|'''|'[^']){20}(.|\n[^\n])*''[.!?\s]*\n)+/g; |
|||
// keep stuff separated, though, so stick in \n (fixes [[Union Jack]]? |
|||
this.data = this.data.replace(italicChunkRegex, '\n'); |
|||
}; |
|||
/** |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.mopup = function () { |
|||
// we simply *can't* be doing with horizontal rules right now |
|||
this.data = this.data.replace(/^-{4,}/mg, ''); |
|||
// no indented lines |
|||
this.data = this.data.replace(/(^|\n) *:[^\n]*/g, ''); |
|||
// replace __TOC__, __NOTOC__ and whatever else there is |
|||
// this'll probably do |
|||
this.data = this.data.replace(/^__[A-Z_]*__ *$/gmi, ''); |
|||
}; |
|||
/** |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.firstBit = function () { |
|||
// dont't be givin' me no subsequent paragraphs, you hear me? |
|||
/// first we "normalize" section headings, removing whitespace after, adding before |
|||
let d = this.data; |
|||
if (getValueOf('popupPreviewCutHeadings')) { |
|||
this.data = this.data.replace(/\s*(==+[^=]*==+)\s*/g, '\n\n$1 '); |
|||
/// then we want to get rid of paragraph breaks whose text ends badly |
|||
this.data = this.data.replace(/([:;]) *\n{2,}/g, '$1\n'); |
|||
this.data = this.data.replace(/^[\s\n]*/, ''); |
|||
const stuff = /^([^\n]|\n[^\n\s])*/.exec(this.data); |
|||
if (stuff) { |
|||
d = stuff[0]; |
|||
} |
|||
if (!getValueOf('popupPreviewFirstParOnly')) { |
|||
d = this.data; |
|||
} |
|||
/// now put \n\n after sections so that bullets and numbered lists work |
|||
d = d.replace(/(==+[^=]*==+)\s*/g, '$1\n\n'); |
|||
} |
|||
// Split sentences. Superfluous sentences are RIGHT OUT. |
|||
// note: exactly 1 set of parens here needed to make the slice work |
|||
d = d.parenSplit(/([!?.]+["']*\s)/g); |
|||
// leading space is bad, mmkay? |
|||
d[0] = d[0].replace(/^\s*/, ''); |
|||
const notSentenceEnds = /([^.][a-z][.] *[a-z]|etc|sic|Dr|Mr|Mrs|Ms|St|no|op|cit|\[[^\]]*|\s[A-Zvclm])$/i; |
|||
d = this.fixSentenceEnds(d, notSentenceEnds); |
|||
this.fullLength = d.join('').length; |
|||
let n = this.maxSentences; |
|||
let dd = this.firstSentences(d, n); |
|||
do { |
|||
dd = this.firstSentences(d, n); |
|||
--n; |
|||
} while (dd.length > this.maxCharacters && n !== 0); |
|||
this.data = dd; |
|||
}; |
|||
/** |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.fixSentenceEnds = function (strs, reg) { |
|||
// take an array of strings, strs |
|||
// join strs[i] to strs[i+1] & strs[i+2] if strs[i] matches regex reg |
|||
for (let i = 0; i < strs.length - 2; ++i) { |
|||
if (reg.test(strs[i])) { |
|||
const a = []; |
|||
for (let j = 0; j < strs.length; ++j) { |
|||
if (j < i) { |
|||
a[j] = strs[j]; |
|||
} |
|||
if (j == i) { |
|||
a[i] = strs[i] + strs[i + 1] + strs[i + 2]; |
|||
} |
|||
if (j > i + 2) { |
|||
a[j - 2] = strs[j]; |
|||
} |
|||
} |
|||
return this.fixSentenceEnds(a, reg); |
|||
} |
|||
} |
|||
return strs; |
|||
}; |
|||
/** |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.firstSentences = function (strs, howmany) { |
|||
const t = strs.slice(0, 2 * howmany); |
|||
return t.join(''); |
|||
}; |
|||
/** |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.killBadWhitespace = function () { |
|||
// also cleans up isolated '''', eg [[Suntory Sungoliath]] |
|||
this.data = this.data.replace(/^ *'+ *$/gm, ''); |
|||
}; |
|||
/** |
|||
* Runs the various methods to generate the preview. |
|||
* The preview is stored in the <code>html</html> field. |
|||
* |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.makePreview = function () { |
|||
if ( |
|||
this.owner.article.namespaceId() != pg.nsTemplateId && |
|||
this.owner.article.namespaceId() != pg.nsImageId |
|||
) { |
|||
this.killComments(); |
|||
this.killDivs(); |
|||
this.killGalleries(); |
|||
this.killBoxTemplates(); |
|||
if (getValueOf('popupPreviewKillTemplates')) { |
|||
this.killTemplates(); |
|||
} else { |
|||
this.killMultilineTemplates(); |
|||
} |
|||
this.killTables(); |
|||
this.killImages(); |
|||
this.killHTML(); |
|||
this.killChunks(); |
|||
this.mopup(); |
|||
this.firstBit(); |
|||
this.killBadWhitespace(); |
|||
} else { |
|||
this.killHTML(); |
|||
} |
|||
this.html = wiki2html(this.data, this.baseUrl); // needs livepreview |
|||
this.fixHTML(); |
|||
this.stripLongTemplates(); |
|||
}; |
|||
/** |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.esWiki2HtmlPart = function (data) { |
|||
const reLinks = /(?:\[\[([^|\]]*)(?:\|([^|\]]*))*]]([a-z]*))/gi; //match a wikilink |
|||
reLinks.lastIndex = 0; //reset regex |
|||
let match; |
|||
let result = ''; |
|||
let postfixIndex = 0; |
|||
while ((match = reLinks.exec(data))) { |
|||
//match all wikilinks |
|||
//FIXME: the way that link is built here isn't perfect. It is clickable, but popups preview won't recognize it in some cases. |
|||
result += |
|||
pg.escapeQuotesHTML(data.substring(postfixIndex, match.index)) + |
|||
'<a href="' + |
|||
Insta.conf.paths.articles + |
|||
pg.escapeQuotesHTML(match[1]) + |
|||
'">' + |
|||
pg.escapeQuotesHTML((match[2] ? match[2] : match[1]) + match[3]) + |
|||
'</a>'; |
|||
postfixIndex = reLinks.lastIndex; |
|||
} |
|||
//append the rest |
|||
result += pg.escapeQuotesHTML(data.substring(postfixIndex)); |
|||
return result; |
|||
}; |
|||
Previewmaker.prototype.editSummaryPreview = function () { |
|||
const reAes = /\/\* *(.*?) *\*\//g; //match the first section marker |
|||
reAes.lastIndex = 0; //reset regex |
|||
let match; |
|||
match = reAes.exec(this.data); |
|||
if (match) { |
|||
//we have a section link. Split it, process it, combine it. |
|||
const prefix = this.data.substring(0, match.index - 1); |
|||
const section = match[1]; |
|||
const postfix = this.data.substring(reAes.lastIndex); |
|||
let start = "<span class='autocomment'>"; |
|||
let end = '</span>'; |
|||
if (prefix.length > 0) { |
|||
start = this.esWiki2HtmlPart(prefix) + ' ' + start + '- '; |
|||
} |
|||
if (postfix.length > 0) { |
|||
end = ': ' + end + this.esWiki2HtmlPart(postfix); |
|||
} |
|||
const t = new Title().fromURL(this.baseUrl); |
|||
t.anchorFromUtf(section); |
|||
const sectionLink = |
|||
Insta.conf.paths.articles + |
|||
pg.escapeQuotesHTML(t.toString(true)) + |
|||
'#' + |
|||
pg.escapeQuotesHTML(t.anchor); |
|||
return ( |
|||
start + '<a href="' + sectionLink + '">→</a> ' + pg.escapeQuotesHTML(section) + end |
|||
); |
|||
} |
|||
//else there's no section link, htmlify the whole thing. |
|||
return this.esWiki2HtmlPart(this.data); |
|||
}; |
|||
/** Test function for debugging preview problems one step at a time. */ |
|||
/*eslint-disable */ |
|||
function previewSteps(txt) { |
|||
try { |
|||
txt = txt || document.editform.wpTextbox1.value; |
|||
} catch (err) { |
|||
if (pg.cache.pages.length > 0) { |
|||
txt = pg.cache.pages[pg.cache.pages.length - 1].data; |
|||
} else { |
|||
alert('provide text or use an edit page'); |
|||
} |
|||
} |
|||
txt = txt.substring(0, 10000); |
|||
var base = pg.wiki.articlebase + Title.fromURL(document.location.href).urlString(); |
|||
var p = new Previewmaker(txt, base, pg.current.link.navpopup); |
|||
if (this.owner.article.namespaceId() != pg.nsTemplateId) { |
|||
p.killComments(); |
|||
if (!confirm('done killComments(). Continue?\n---\n' + p.data)) { |
|||
return; |
|||
} |
|||
p.killDivs(); |
|||
if (!confirm('done killDivs(). Continue?\n---\n' + p.data)) { |
|||
return; |
|||
} |
|||
p.killGalleries(); |
|||
if (!confirm('done killGalleries(). Continue?\n---\n' + p.data)) { |
|||
return; |
|||
} |
|||
p.killBoxTemplates(); |
|||
if (!confirm('done killBoxTemplates(). Continue?\n---\n' + p.data)) { |
|||
return; |
|||
} |
|||
if (getValueOf('popupPreviewKillTemplates')) { |
|||
p.killTemplates(); |
|||
if (!confirm('done killTemplates(). Continue?\n---\n' + p.data)) { |
|||
return; |
|||
} |
|||
} else { |
|||
p.killMultilineTemplates(); |
|||
if (!confirm('done killMultilineTemplates(). Continue?\n---\n' + p.data)) { |
|||
return; |
|||
} |
|||
} |
|||
p.killTables(); |
|||
if (!confirm('done killTables(). Continue?\n---\n' + p.data)) { |
|||
return; |
|||
} |
|||
p.killImages(); |
|||
if (!confirm('done killImages(). Continue?\n---\n' + p.data)) { |
|||
return; |
|||
} |
|||
p.killHTML(); |
|||
if (!confirm('done killHTML(). Continue?\n---\n' + p.data)) { |
|||
return; |
|||
} |
|||
p.killChunks(); |
|||
if (!confirm('done killChunks(). Continue?\n---\n' + p.data)) { |
|||
return; |
|||
} |
|||
p.mopup(); |
|||
if (!confirm('done mopup(). Continue?\n---\n' + p.data)) { |
|||
return; |
|||
} |
|||
p.firstBit(); |
|||
if (!confirm('done firstBit(). Continue?\n---\n' + p.data)) { |
|||
return; |
|||
} |
|||
p.killBadWhitespace(); |
|||
if (!confirm('done killBadWhitespace(). Continue?\n---\n' + p.data)) { |
|||
return; |
|||
} |
|||
} |
|||
p.html = wiki2html(p.data, base); // needs livepreview |
|||
p.fixHTML(); |
|||
if (!confirm('done fixHTML(). Continue?\n---\n' + p.html)) { |
|||
return; |
|||
} |
|||
p.stripLongTemplates(); |
|||
if (!confirm('done stripLongTemplates(). Continue?\n---\n' + p.html)) { |
|||
return; |
|||
} |
|||
alert('finished preview - end result follows.\n---\n' + p.html); |
|||
} |
|||
/*eslint-enable */ |
|||
/** |
|||
* Works around livepreview bugs. |
|||
* |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.fixHTML = function () { |
|||
if (!this.html) { |
|||
return; |
|||
} |
|||
let ret = this.html; |
|||
// fix question marks in wiki links |
|||
// maybe this'll break some stuff :-( |
|||
ret = ret.replace( |
|||
RegExp('(<a href="' + pg.wiki.articlePath + '/[^"]*)[?](.*?")', 'g'), |
|||
'$1%3F$2' |
|||
); |
|||
ret = ret.replace( |
|||
RegExp("(<a href='" + pg.wiki.articlePath + "/[^']*)[?](.*?')", 'g'), |
|||
'$1%3F$2' |
|||
); |
|||
// FIXME fix up % too |
|||
this.html = ret; |
|||
}; |
|||
/** |
|||
* Generates the preview and displays it in the current popup. |
|||
* |
|||
* Does nothing if the generated preview is invalid or consists of whitespace only. |
|||
* Also activates wikilinks in the preview for subpopups if the popupSubpopups option is true. |
|||
*/ |
|||
Previewmaker.prototype.showPreview = function () { |
|||
this.makePreview(); |
|||
if (typeof this.html != typeof '') { |
|||
return; |
|||
} |
|||
if (/^\s*$/.test(this.html)) { |
|||
return; |
|||
} |
|||
setPopupHTML('<hr />', 'popupPrePreviewSep', this.owner.idNumber); |
|||
setPopupTipsAndHTML(this.html, 'popupPreview', this.owner.idNumber, { |
|||
owner: this.owner, |
|||
}); |
|||
const more = this.fullLength > this.data.length ? this.moreLink() : ''; |
|||
setPopupHTML(more, 'popupPreviewMore', this.owner.idNumber); |
|||
}; |
|||
/** |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.moreLink = function () { |
|||
const a = document.createElement('a'); |
|||
a.className = 'popupMoreLink'; |
|||
a.innerHTML = popupString('more...'); |
|||
const savedThis = this; |
|||
a.onclick = function () { |
|||
savedThis.maxCharacters += 2000; |
|||
savedThis.maxSentences += 20; |
|||
savedThis.setData(); |
|||
savedThis.showPreview(); |
|||
}; |
|||
return a; |
|||
}; |
|||
/** |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.stripLongTemplates = function () { |
|||
// operates on the HTML! |
|||
this.html = this.html.replace( |
|||
/^.{0,1000}[{][{][^}]*?(<(p|br)( \/)?>\s*){2,}([^{}]*?[}][}])?/gi, |
|||
'' |
|||
); |
|||
this.html = this.html.split('\n').join(' '); // workaround for <pre> templates |
|||
this.html = this.html.replace(/[{][{][^}]*<pre>[^}]*[}][}]/gi, ''); |
|||
}; |
|||
/** |
|||
* @private |
|||
*/ |
|||
Previewmaker.prototype.killMultilineTemplates = function () { |
|||
this.kill('{{{', '}}}'); |
|||
this.kill(/\s*[{][{][^{}]*\n/, '}}', '{{'); |
|||
}; |
|||
// ENDFILE: previewmaker.js |
|||
// STARTFILE: querypreview.js |
|||
function loadAPIPreview(queryType, article, navpop) { |
|||
const art = new Title(article).urlString(); |
|||
let url = pg.wiki.apiwikibase + '?format=json&formatversion=2&action=query&'; |
|||
let htmlGenerator = function (/*a, d*/) { |
|||
alert('invalid html generator'); |
|||
}; |
|||
let usernameart = ''; |
|||
switch (queryType) { |
|||
case 'history': |
|||
url += |
|||
'titles=' + art + '&prop=revisions&rvlimit=' + getValueOf('popupHistoryPreviewLimit'); |
|||
htmlGenerator = APIhistoryPreviewHTML; |
|||
break; |
|||
case 'category': |
|||
url += 'list=categorymembers&cmtitle=' + art; |
|||
htmlGenerator = APIcategoryPreviewHTML; |
|||
break; |
|||
case 'userinfo': |
|||
var username = new Title(article).userName(); |
|||
usernameart = encodeURIComponent(username); |
|||
if (pg.re.ipUser.test(username)) { |
|||
url += 'list=blocks&bkprop=range|restrictions&bkip=' + usernameart; |
|||
} else { |
|||
url += |
|||
'list=users|usercontribs&usprop=blockinfo|groups|editcount|registration|gender&ususers=' + |
|||
usernameart + |
|||
'&meta=globaluserinfo&guiprop=groups|unattached&guiuser=' + |
|||
usernameart + |
|||
'&uclimit=1&ucprop=timestamp&ucuser=' + |
|||
usernameart; |
|||
} |
|||
htmlGenerator = APIuserInfoPreviewHTML; |
|||
break; |
|||
case 'contribs': |
|||
usernameart = encodeURIComponent(new Title(article).userName()); |
|||
url += |
|||
'list=usercontribs&ucuser=' + |
|||
usernameart + |
|||
'&uclimit=' + |
|||
getValueOf('popupContribsPreviewLimit'); |
|||
htmlGenerator = APIcontribsPreviewHTML; |
|||
break; |
|||
case 'imagepagepreview': |
|||
var trail = ''; |
|||
if (getValueOf('popupImageLinks')) { |
|||
trail = '&list=imageusage&iutitle=' + art; |
|||
} |
|||
url += 'titles=' + art + '&prop=revisions|imageinfo&rvslots=main&rvprop=content' + trail; |
|||
htmlGenerator = APIimagepagePreviewHTML; |
|||
break; |
|||
case 'backlinks': |
|||
url += 'list=backlinks&bltitle=' + art; |
|||
htmlGenerator = APIbacklinksPreviewHTML; |
|||
break; |
|||
case 'revision': |
|||
if (article.oldid) { |
|||
url += 'revids=' + article.oldid; |
|||
} else { |
|||
url += 'titles=' + article.removeAnchor().urlString(); |
|||
} |
|||
url += |
|||
'&prop=revisions|pageprops|info|images|categories&meta=wikibase&rvslots=main&rvprop=ids|timestamp|flags|comment|user|content&cllimit=max&imlimit=max'; |
|||
htmlGenerator = APIrevisionPreviewHTML; |
|||
break; |
|||
} |
|||
pendingNavpopTask(navpop); |
|||
const callback = function (d) { |
|||
log('callback of API functions was hit'); |
|||
if (queryType === 'userinfo') { |
|||
// We need to do another API request |
|||
fetchUserGroupNames(d.data).then(() => { |
|||
showAPIPreview(queryType, htmlGenerator(article, d, navpop), navpop.idNumber, navpop, d); |
|||
}); |
|||
return; |
|||
} |
|||
showAPIPreview(queryType, htmlGenerator(article, d, navpop), navpop.idNumber, navpop, d); |
|||
}; |
|||
const go = function () { |
|||
getPageWithCaching(url, callback, navpop); |
|||
return true; |
|||
}; |
|||
if (navpop.visible || !getValueOf('popupLazyDownloads')) { |
|||
go(); |
|||
} else { |
|||
navpop.addHook(go, 'unhide', 'before', 'DOWNLOAD_' + queryType + '_QUERY_DATA'); |
|||
} |
|||
} |
|||
function linkList(list) { |
|||
list.sort((x, y) => x == y ? 0 : x < y ? -1 : 1); |
|||
const buf = []; |
|||
for (let i = 0; i < list.length; ++i) { |
|||
buf.push( |
|||
wikiLink({ |
|||
article: new Title(list[i]), |
|||
text: list[i].split(' ').join(' '), |
|||
action: 'view', |
|||
}) |
|||
); |
|||
} |
|||
return buf.join(', '); |
|||
} |
|||
function getTimeOffset() { |
|||
const tz = mw.user.options.get('timecorrection'); |
|||
if (tz) { |
|||
if (tz.indexOf('|') > -1) { |
|||
// New format |
|||
return parseInt(tz.split('|')[1], 10); |
|||
} |
|||
} |
|||
return 0; |
|||
} |
|||
function getTimeZone() { |
|||
if (!pg.user.timeZone) { |
|||
const tz = mw.user.options.get('timecorrection'); |
|||
pg.user.timeZone = 'UTC'; |
|||
if (tz) { |
|||
const tzComponents = tz.split('|'); |
|||
if (tzComponents.length === 3 && tzComponents[0] === 'ZoneInfo') { |
|||
pg.user.timeZone = tzComponents[2]; |
|||
} else { |
|||
errlog('Unexpected timezone information: ' + tz); |
|||
} |
|||
} |
|||
} |
|||
return pg.user.timeZone; |
|||
} |
|||
/** |
|||
* Should we use an offset or can we use proper timezones |
|||
*/ |
|||
function useTimeOffset() { |
|||
if (typeof Intl.DateTimeFormat.prototype.formatToParts === 'undefined') { |
|||
// IE 11 |
|||
return true; |
|||
} |
|||
const tz = mw.user.options.get('timecorrection'); |
|||
if (tz && tz.indexOf('ZoneInfo|') === -1) { |
|||
// System| Default system time, default for users who didn't configure timezone |
|||
// Offset| Manual defined offset by user |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
/** |
|||
* Array of locales for the purpose of javascript locale based formatting |
|||
* Filters down to those supported by the browser. Empty [] === System's default locale |
|||
*/ |
|||
function getLocales() { |
|||
if (!pg.user.locales) { |
|||
let userLanguage = document.querySelector('html').getAttribute('lang'); // make sure we have HTML locale |
|||
if (getValueOf('popupLocale')) { |
|||
userLanguage = getValueOf('popupLocale'); |
|||
} else if (userLanguage === 'en') { |
|||
// en.wp tends to treat this as international english / unspecified |
|||
// but we have more specific settings in user options |
|||
if (getMWDateFormat() === 'mdy') { |
|||
userLanguage = 'en-US'; |
|||
} else { |
|||
userLanguage = 'en-GB'; |
|||
} |
|||
} |
|||
pg.user.locales = Intl.DateTimeFormat.supportedLocalesOf([userLanguage, navigator.language]); |
|||
} |
|||
return pg.user.locales; |
|||
} |
|||
/** |
|||
* Retrieve configured MW date format for this user |
|||
* These can be |
|||
* default |
|||
* dmy: time, dmy |
|||
* mdy: time, mdy |
|||
* ymd: time, ymd |
|||
* dmyt: dmy, time |
|||
* dmyts: dmy, time + seconds |
|||
* ISO 8601: YYYY-MM-DDThh:mm:ss (local time) |
|||
* |
|||
* This isn't too useful for us, as JS doesn't have formatters to match these private specifiers |
|||
*/ |
|||
function getMWDateFormat() { |
|||
return mw.user.options.get('date'); |
|||
} |
|||
/** |
|||
* Creates a HTML table that's shown in the history and user-contribs popups. |
|||
* |
|||
* @param {Object[]} h - a list of revisions, returned from the API |
|||
* @param {boolean} reallyContribs - true only if we're displaying user contributions |
|||
*/ |
|||
function editPreviewTable(article, h, reallyContribs) { |
|||
let html = ['<table>']; |
|||
let day = null; |
|||
let curart = article; |
|||
let page = null; |
|||
let makeFirstColumnLinks; |
|||
if (reallyContribs) { |
|||
// We're showing user contributions, so make (diff | hist) links |
|||
makeFirstColumnLinks = function (currentRevision) { |
|||
let result = '('; |
|||
result += |
|||
'<a href="' + |
|||
pg.wiki.titlebase + |
|||
new Title(currentRevision.title).urlString() + |
|||
'&diff=prev' + |
|||
'&oldid=' + |
|||
currentRevision.revid + |
|||
'">' + |
|||
popupString('diff') + |
|||
'</a>'; |
|||
result += ' | '; |
|||
result += |
|||
'<a href="' + |
|||
pg.wiki.titlebase + |
|||
new Title(currentRevision.title).urlString() + |
|||
'&action=history">' + |
|||
popupString('hist') + |
|||
'</a>'; |
|||
result += ')'; |
|||
return result; |
|||
}; |
|||
} else { |
|||
// It's a regular history page, so make (cur | last) links |
|||
const firstRevid = h[0].revid; |
|||
makeFirstColumnLinks = function (currentRevision) { |
|||
let result = '('; |
|||
result += |
|||
'<a href="' + |
|||
pg.wiki.titlebase + |
|||
new Title(curart).urlString() + |
|||
'&diff=' + |
|||
firstRevid + |
|||
'&oldid=' + |
|||
currentRevision.revid + |
|||
'">' + |
|||
popupString('cur') + |
|||
'</a>'; |
|||
result += ' | '; |
|||
result += |
|||
'<a href="' + |
|||
pg.wiki.titlebase + |
|||
new Title(curart).urlString() + |
|||
'&diff=prev&oldid=' + |
|||
currentRevision.revid + |
|||
'">' + |
|||
popupString('last') + |
|||
'</a>'; |
|||
result += ')'; |
|||
return result; |
|||
}; |
|||
} |
|||
for (let i = 0; i < h.length; ++i) { |
|||
if (reallyContribs) { |
|||
page = h[i].title; |
|||
curart = new Title(page); |
|||
} |
|||
const minor = h[i].minor ? '<b>m </b>' : ''; |
|||
const editDate = new Date(h[i].timestamp); |
|||
let thisDay = formattedDate(editDate); |
|||
const thisTime = formattedTime(editDate); |
|||
if (thisDay == day) { |
|||
thisDay = ''; |
|||
} else { |
|||
day = thisDay; |
|||
} |
|||
if (thisDay) { |
|||
html.push( |
|||
'<tr><td colspan=3><span class="popup_history_date">' + thisDay + '</span></td></tr>' |
|||
); |
|||
} |
|||
html.push('<tr class="popup_history_row_' + (i % 2 ? 'odd' : 'even') + '">'); |
|||
html.push('<td>' + makeFirstColumnLinks(h[i]) + '</td>'); |
|||
html.push( |
|||
'<td>' + |
|||
'<a href="' + |
|||
pg.wiki.titlebase + |
|||
new Title(curart).urlString() + |
|||
'&oldid=' + |
|||
h[i].revid + |
|||
'">' + |
|||
thisTime + |
|||
'</a></td>' |
|||
); |
|||
let col3url = '', |
|||
col3txt = ''; |
|||
if (!reallyContribs) { |
|||
const user = h[i].user; |
|||
if (!h[i].userhidden) { |
|||
if (pg.re.ipUser.test(user)) { |
|||
col3url = |
|||
pg.wiki.titlebase + |
|||
mw.config.get('wgFormattedNamespaces')[pg.nsSpecialId] + |
|||
':Contributions&target=' + |
|||
new Title(user).urlString(); |
|||
} else { |
|||
col3url = |
|||
pg.wiki.titlebase + |
|||
mw.config.get('wgFormattedNamespaces')[pg.nsUserId] + |
|||
':' + |
|||
new Title(user).urlString(); |
|||
} |
|||
col3txt = pg.escapeQuotesHTML(user); |
|||
} else { |
|||
col3url = getValueOf('popupRevDelUrl'); |
|||
col3txt = pg.escapeQuotesHTML(popupString('revdel')); |
|||
} |
|||
} else { |
|||
col3url = pg.wiki.titlebase + curart.urlString(); |
|||
col3txt = pg.escapeQuotesHTML(page); |
|||
} |
|||
html.push( |
|||
'<td>' + |
|||
(reallyContribs ? minor : '') + |
|||
'<a href="' + |
|||
col3url + |
|||
'">' + |
|||
col3txt + |
|||
'</a></td>' |
|||
); |
|||
let comment = ''; |
|||
const c = h[i].comment || ( typeof h[i].slots !== 'undefined' ? h[i].slots.main.content : null ); |
|||
if (c) { |
|||
comment = new Previewmaker(c, new Title(curart).toUrl()).editSummaryPreview(); |
|||
} else if (h[i].commenthidden) { |
|||
comment = popupString('revdel'); |
|||
} |
|||
html.push('<td>' + (!reallyContribs ? minor : '') + comment + '</td>'); |
|||
html.push('</tr>'); |
|||
html = [html.join('')]; |
|||
} |
|||
html.push('</table>'); |
|||
return html.join(''); |
|||
} |
|||
function adjustDate(d, offset) { |
|||
// offset is in minutes |
|||
const o = offset * 60 * 1000; |
|||
return new Date(Number(d) + o); |
|||
} |
|||
/** |
|||
* This relies on the Date parser understanding en-US dates, |
|||
* which is pretty safe assumption, but not perfect. |
|||
*/ |
|||
function convertTimeZone(date, timeZone) { |
|||
return new Date(date.toLocaleString('en-US', { timeZone: timeZone })); |
|||
} |
|||
function formattedDateTime(date) { |
|||
// fallback for IE11 and unknown timezones |
|||
if (useTimeOffset()) { |
|||
return formattedDate(date) + ' ' + formattedTime(date); |
|||
} |
|||
if (getMWDateFormat() === 'ISO 8601') { |
|||
const d2 = convertTimeZone(date, getTimeZone()); |
|||
return ( |
|||
map(zeroFill, [d2.getFullYear(), d2.getMonth() + 1, d2.getDate()]).join('-') + |
|||
'T' + |
|||
map(zeroFill, [d2.getHours(), d2.getMinutes(), d2.getSeconds()]).join(':') |
|||
); |
|||
} |
|||
const options = getValueOf('popupDateTimeFormatterOptions'); |
|||
options.timeZone = getTimeZone(); |
|||
return date.toLocaleString(getLocales(), options); |
|||
} |
|||
function formattedDate(date) { |
|||
// fallback for IE11 and unknown timezones |
|||
if (useTimeOffset()) { |
|||
// we adjust the UTC time, so we print the adjusted UTC, but not really UTC values |
|||
var d2 = adjustDate(date, getTimeOffset()); |
|||
return map(zeroFill, [d2.getUTCFullYear(), d2.getUTCMonth() + 1, d2.getUTCDate()]).join('-'); |
|||
} |
|||
if (getMWDateFormat() === 'ISO 8601') { |
|||
var d2 = convertTimeZone(date, getTimeZone()); |
|||
return map(zeroFill, [d2.getFullYear(), d2.getMonth() + 1, d2.getDate()]).join('-'); |
|||
} |
|||
const options = getValueOf('popupDateFormatterOptions'); |
|||
options.timeZone = getTimeZone(); |
|||
return date.toLocaleDateString(getLocales(), options); |
|||
} |
|||
function formattedTime(date) { |
|||
// fallback for IE11 and unknown timezones |
|||
if (useTimeOffset()) { |
|||
// we adjust the UTC time, so we print the adjusted UTC, but not really UTC values |
|||
var d2 = adjustDate(date, getTimeOffset()); |
|||
return map(zeroFill, [d2.getUTCHours(), d2.getUTCMinutes(), d2.getUTCSeconds()]).join(':'); |
|||
} |
|||
if (getMWDateFormat() === 'ISO 8601') { |
|||
var d2 = convertTimeZone(date, getTimeZone()); |
|||
return map(zeroFill, [d2.getHours(), d2.getMinutes(), d2.getSeconds()]).join(':'); |
|||
} |
|||
const options = getValueOf('popupTimeFormatterOptions'); |
|||
options.timeZone = getTimeZone(); |
|||
return date.toLocaleTimeString(getLocales(), options); |
|||
} |
|||
// Get the proper groupnames for the technicalgroups |
|||
function fetchUserGroupNames(userinfoResponse) { |
|||
const queryObj = getJsObj(userinfoResponse).query; |
|||
const user = anyChild(queryObj.users); |
|||
const messages = []; |
|||
if (user.groups) { |
|||
user.groups.forEach((groupName) => { |
|||
if (['*', 'user', 'autoconfirmed', 'extendedconfirmed', 'oathauth-twofactorauth'].indexOf(groupName) === -1) { |
|||
messages.push('group-' + groupName + '-member'); |
|||
} |
|||
}); |
|||
} |
|||
if (queryObj.globaluserinfo && queryObj.globaluserinfo.groups) { |
|||
queryObj.globaluserinfo.groups.forEach((groupName) => { |
|||
messages.push('group-' + groupName + '-member'); |
|||
}); |
|||
} |
|||
return getMwApi().loadMessagesIfMissing(messages); |
|||
} |
|||
function showAPIPreview(queryType, html, id, navpop, download) { |
|||
// DJ: done |
|||
let target = 'popupPreview'; |
|||
completedNavpopTask(navpop); |
|||
switch (queryType) { |
|||
case 'imagelinks': |
|||
case 'category': |
|||
target = 'popupPostPreview'; |
|||
break; |
|||
case 'userinfo': |
|||
target = 'popupUserData'; |
|||
break; |
|||
case 'revision': |
|||
insertPreview(download); |
|||
return; |
|||
} |
|||
setPopupTipsAndHTML(html, target, id); |
|||
} |
|||
function APIrevisionPreviewHTML(article, download) { |
|||
try { |
|||
const jsObj = getJsObj(download.data); |
|||
const page = anyChild(jsObj.query.pages); |
|||
if (page.missing) { |
|||
// TODO we need to fix this proper later on |
|||
download.owner = null; |
|||
return; |
|||
} |
|||
const content = |
|||
page && page.revisions && page.revisions[0] && |
|||
page.revisions[0].slots && page.revisions[0].slots.main && |
|||
page.revisions[0].slots.main.contentmodel === 'wikitext' ? |
|||
page.revisions[0].slots.main.content : |
|||
null; |
|||
if (typeof content === 'string') { |
|||
download.data = content; |
|||
download.lastModified = new Date(page.revisions[0].timestamp); |
|||
} |
|||
if (page.pageprops.wikibase_item) { |
|||
download.wikibaseItem = page.pageprops.wikibase_item; |
|||
download.wikibaseRepo = jsObj.query.wikibase.repo.url.base + |
|||
jsObj.query.wikibase.repo.url.articlepath; |
|||
} |
|||
} catch (someError) { |
|||
return 'Revision preview failed :('; |
|||
} |
|||
} |
|||
function APIbacklinksPreviewHTML(article, download /*, navpop*/) { |
|||
try { |
|||
const jsObj = getJsObj(download.data); |
|||
const list = jsObj.query.backlinks; |
|||
let html = []; |
|||
if (!list) { |
|||
return popupString('No backlinks found'); |
|||
} |
|||
for (let i = 0; i < list.length; i++) { |
|||
const t = new Title(list[i].title); |
|||
html.push( |
|||
'<a href="' + pg.wiki.titlebase + t.urlString() + '">' + t.toString().entify() + '</a>' |
|||
); |
|||
} |
|||
html = html.join(', '); |
|||
if (jsObj.continue && jsObj.continue.blcontinue) { |
|||
html += popupString(' and more'); |
|||
} |
|||
return html; |
|||
} catch (someError) { |
|||
return 'backlinksPreviewHTML went wonky'; |
|||
} |
|||
} |
|||
pg.fn.APIsharedImagePagePreviewHTML = function APIsharedImagePagePreviewHTML(obj) { |
|||
log('APIsharedImagePagePreviewHTML'); |
|||
const popupid = obj.requestid; |
|||
if (obj.query && obj.query.pages) { |
|||
const page = anyChild(obj.query.pages); |
|||
const content = |
|||
page && page.revisions && page.revisions[0] && |
|||
page.revisions[0].slots && page.revisions[0].slots.main && |
|||
page.revisions[0].slots.main.contentmodel === 'wikitext' ? |
|||
page.revisions[0].slots.main.content : |
|||
null; |
|||
if ( |
|||
typeof content === 'string' && |
|||
pg && |
|||
pg.current && |
|||
pg.current.link && |
|||
pg.current.link.navpopup |
|||
) { |
|||
/* Not entirely safe, but the best we can do */ |
|||
const p = new Previewmaker( |
|||
content, |
|||
pg.current.link.navpopup.article, |
|||
pg.current.link.navpopup |
|||
); |
|||
p.makePreview(); |
|||
setPopupHTML(p.html, 'popupSecondPreview', popupid); |
|||
} |
|||
} |
|||
}; |
|||
function APIimagepagePreviewHTML(article, download, navpop) { |
|||
try { |
|||
const jsObj = getJsObj(download.data); |
|||
const page = anyChild(jsObj.query.pages); |
|||
const content = |
|||
page && page.revisions && page.revisions[0] && |
|||
page.revisions[0].slots && page.revisions[0].slots.main && |
|||
page.revisions[0].slots.main.contentmodel === 'wikitext' ? |
|||
page.revisions[0].slots.main.content : |
|||
null; |
|||
let ret = ''; |
|||
let alt = ''; |
|||
try { |
|||
alt = navpop.parentAnchor.childNodes[0].alt; |
|||
} catch (e) {} |
|||
if (alt) { |
|||
ret = ret + '<hr /><b>' + popupString('Alt text:') + '</b> ' + pg.escapeQuotesHTML(alt); |
|||
} |
|||
if (typeof content === 'string') { |
|||
const p = prepPreviewmaker(content, article, navpop); |
|||
p.makePreview(); |
|||
if (p.html) { |
|||
ret += '<hr />' + p.html; |
|||
} |
|||
if (getValueOf('popupSummaryData')) { |
|||
const info = getPageInfo(content, download); |
|||
log(info); |
|||
setPopupTrailer(info, navpop.idNumber); |
|||
} |
|||
} |
|||
if (page && page.imagerepository == 'shared') { |
|||
const art = new Title(article); |
|||
const encart = encodeURIComponent('File:' + art.stripNamespace()); |
|||
const shared_url = |
|||
pg.wiki.apicommonsbase + |
|||
'?format=json&formatversion=2' + |
|||
'&callback=pg.fn.APIsharedImagePagePreviewHTML' + |
|||
'&requestid=' + |
|||
navpop.idNumber + |
|||
'&action=query&prop=revisions&rvslots=main&rvprop=content&titles=' + |
|||
encart; |
|||
ret = |
|||
ret + |
|||
'<hr />' + |
|||
popupString('Image from Commons') + |
|||
': <a href="' + |
|||
pg.wiki.commonsbase + |
|||
'?title=' + |
|||
encart + |
|||
'">' + |
|||
popupString('Description page') + |
|||
'</a>'; |
|||
mw.loader.load(shared_url); |
|||
} |
|||
showAPIPreview( |
|||
'imagelinks', |
|||
APIimagelinksPreviewHTML(article, download), |
|||
navpop.idNumber, |
|||
download |
|||
); |
|||
return ret; |
|||
} catch (someError) { |
|||
return 'API imagepage preview failed :('; |
|||
} |
|||
} |
|||
function APIimagelinksPreviewHTML(article, download) { |
|||
try { |
|||
const jsobj = getJsObj(download.data); |
|||
const list = jsobj.query.imageusage; |
|||
if (list) { |
|||
const ret = []; |
|||
for (let i = 0; i < list.length; i++) { |
|||
ret.push(list[i].title); |
|||
} |
|||
if (ret.length === 0) { |
|||
return popupString('No image links found'); |
|||
} |
|||
return '<h2>' + popupString('File links') + '</h2>' + linkList(ret); |
|||
} else { |
|||
return popupString('No image links found'); |
|||
} |
|||
} catch (someError) { |
|||
return 'Image links preview generation failed :('; |
|||
} |
|||
} |
|||
function APIcategoryPreviewHTML(article, download) { |
|||
try { |
|||
const jsobj = getJsObj(download.data); |
|||
const list = jsobj.query.categorymembers; |
|||
let ret = []; |
|||
for (let p = 0; p < list.length; p++) { |
|||
ret.push(list[p].title); |
|||
} |
|||
if (ret.length === 0) { |
|||
return popupString('Empty category'); |
|||
} |
|||
ret = '<h2>' + tprintf('Category members (%s shown)', [ret.length]) + '</h2>' + linkList(ret); |
|||
if (jsobj.continue && jsobj.continue.cmcontinue) { |
|||
ret += popupString(' and more'); |
|||
} |
|||
return ret; |
|||
} catch (someError) { |
|||
return 'Category preview failed :('; |
|||
} |
|||
} |
|||
function APIuserInfoPreviewHTML(article, download) { |
|||
let ret = []; |
|||
let queryobj = {}; |
|||
try { |
|||
queryobj = getJsObj(download.data).query; |
|||
} catch (someError) { |
|||
return 'Userinfo preview failed :('; |
|||
} |
|||
const user = anyChild(queryobj.users); |
|||
if (user) { |
|||
const globaluserinfo = queryobj.globaluserinfo; |
|||
if (user.invalid === '') { |
|||
ret.push(popupString('Invalid user')); |
|||
} else if (user.missing === '') { |
|||
ret.push(popupString('Not a registered username')); |
|||
} |
|||
if (user.blockedby) { |
|||
if (user.blockpartial) { |
|||
ret.push('<b>' + popupString('Has blocks') + '</b>'); |
|||
} else { |
|||
ret.push('<b>' + popupString('BLOCKED') + '</b>'); |
|||
} |
|||
} |
|||
if (globaluserinfo && ('locked' in globaluserinfo || 'hidden' in globaluserinfo)) { |
|||
let lockedSulAccountIsAttachedToThis = true; |
|||
for (let i = 0; globaluserinfo.unattached && i < globaluserinfo.unattached.length; i++) { |
|||
if (globaluserinfo.unattached[i].wiki === mw.config.get('wgDBname')) { |
|||
lockedSulAccountIsAttachedToThis = false; |
|||
break; |
|||
} |
|||
} |
|||
if (lockedSulAccountIsAttachedToThis) { |
|||
if ('locked' in globaluserinfo) { |
|||
ret.push('<b><i>' + popupString('LOCKED') + '</i></b>'); |
|||
} |
|||
if ('hidden' in globaluserinfo) { |
|||
ret.push('<b><i>' + popupString('HIDDEN') + '</i></b>'); |
|||
} |
|||
} |
|||
} |
|||
if (getValueOf('popupShowGender') && user.gender) { |
|||
switch (user.gender) { |
|||
case 'male': |
|||
ret.push(popupString('he/him') + ' · '); |
|||
break; |
|||
case 'female': |
|||
ret.push(popupString('she/her') + ' · '); |
|||
break; |
|||
} |
|||
} |
|||
if (user.groups) { |
|||
user.groups.forEach((groupName) => { |
|||
if (['*', 'user', 'autoconfirmed', 'extendedconfirmed', 'oathauth-twofactorauth'].indexOf(groupName) === -1) { |
|||
ret.push( |
|||
pg.escapeQuotesHTML(mw.message('group-' + groupName + '-member', user.gender).text()) |
|||
); |
|||
} |
|||
}); |
|||
} |
|||
if (globaluserinfo && globaluserinfo.groups) { |
|||
globaluserinfo.groups.forEach((groupName) => { |
|||
ret.push( |
|||
'<i>' + |
|||
pg.escapeQuotesHTML( |
|||
mw.message('group-' + groupName + '-member', user.gender).text() |
|||
) + |
|||
'</i>' |
|||
); |
|||
}); |
|||
} |
|||
if (user.registration) { |
|||
ret.push( |
|||
pg.escapeQuotesHTML( |
|||
(user.editcount ? user.editcount : '0') + |
|||
popupString(' edits since: ') + |
|||
(user.registration ? formattedDate(new Date(user.registration)) : '') |
|||
) |
|||
); |
|||
} |
|||
} |
|||
if (queryobj.usercontribs && queryobj.usercontribs.length) { |
|||
ret.push( |
|||
popupString('last edit on ') + formattedDate(new Date(queryobj.usercontribs[0].timestamp)) |
|||
); |
|||
} |
|||
if (queryobj.blocks) { |
|||
ret.push(popupString('IP user')); //we only request list=blocks for IPs |
|||
for (let l = 0; l < queryobj.blocks.length; l++) { |
|||
let rbstr = |
|||
queryobj.blocks[l].rangestart === queryobj.blocks[l].rangeend ? 'BLOCK' : 'RANGEBLOCK'; |
|||
rbstr = !Array.isArray(queryobj.blocks[l].restrictions) ? |
|||
'Has ' + rbstr.toLowerCase() + 's' : |
|||
rbstr + 'ED'; |
|||
ret.push('<b>' + popupString(rbstr) + '</b>'); |
|||
} |
|||
} |
|||
// if any element of ret ends with ' · ', merge it with the next element to avoid |
|||
// the .join(', ') call inserting a comma after it |
|||
for (let m = 0; m < ret.length - 1; m++) { |
|||
if (ret[m].length > 3 && ret[m].substring(ret[m].length - 3) === ' · ') { |
|||
ret[m] = ret[m] + ret[m + 1]; |
|||
ret.splice(m + 1, 1); // delete element at index m+1 |
|||
m--; |
|||
} |
|||
} |
|||
ret = '<hr />' + ret.join(', '); |
|||
return ret; |
|||
} |
|||
function APIcontribsPreviewHTML(article, download, navpop) { |
|||
return APIhistoryPreviewHTML(article, download, navpop, true); |
|||
} |
|||
function APIhistoryPreviewHTML(article, download, navpop, reallyContribs) { |
|||
try { |
|||
const jsobj = getJsObj(download.data); |
|||
let edits = []; |
|||
if (reallyContribs) { |
|||
edits = jsobj.query.usercontribs; |
|||
} else { |
|||
edits = anyChild(jsobj.query.pages).revisions; |
|||
} |
|||
const ret = editPreviewTable(article, edits, reallyContribs); |
|||
return ret; |
|||
} catch (someError) { |
|||
return popupString('History preview failed'); |
|||
} |
|||
} |
|||
// ENDFILE: querypreview.js |
|||
// STARTFILE: debug.js |
|||
//////////////////////////////////////////////////////////////////// |
|||
// Debugging functions |
|||
//////////////////////////////////////////////////////////////////// |
|||
function setupDebugging() { |
|||
if (window.popupDebug) { |
|||
// popupDebug is set from .version |
|||
window.log = function (x) { |
|||
//if(gMsg!='')gMsg += '\n'; gMsg+=time() + ' ' + x; }; |
|||
window.console.log(x); |
|||
}; |
|||
window.errlog = function (x) { |
|||
window.console.error(x); |
|||
}; |
|||
log('Initializing logger'); |
|||
} else { |
|||
window.log = function () {}; |
|||
window.errlog = function () {}; |
|||
} |
|||
} |
|||
// ENDFILE: debug.js |
|||
// STARTFILE: images.js |
|||
// load image of type Title. |
|||
function loadImage(image, navpop) { |
|||
if (typeof image.stripNamespace != 'function') { |
|||
alert('loadImages bad'); |
|||
} |
|||
// API call to retrieve image info. |
|||
if (!getValueOf('popupImages')) { |
|||
return; |
|||
} |
|||
if (!isValidImageName(image)) { |
|||
return false; |
|||
} |
|||
const art = image.urlString(); |
|||
let url = pg.wiki.apiwikibase + '?format=json&formatversion=2&action=query'; |
|||
url += '&prop=imageinfo&iiprop=url|mime&iiurlwidth=' + getValueOf('popupImageSizeLarge'); |
|||
url += '&titles=' + art; |
|||
pendingNavpopTask(navpop); |
|||
const callback = function (d) { |
|||
popupsInsertImage(navpop.idNumber, navpop, d); |
|||
}; |
|||
const go = function () { |
|||
getPageWithCaching(url, callback, navpop); |
|||
return true; |
|||
}; |
|||
if (navpop.visible || !getValueOf('popupLazyDownloads')) { |
|||
go(); |
|||
} else { |
|||
navpop.addHook(go, 'unhide', 'after', 'DOWNLOAD_IMAGE_QUERY_DATA'); |
|||
} |
|||
} |
|||
function popupsInsertImage(id, navpop, download) { |
|||
log('popupsInsertImage'); |
|||
let imageinfo; |
|||
try { |
|||
const jsObj = getJsObj(download.data); |
|||
const imagepage = anyChild(jsObj.query.pages); |
|||
if (typeof imagepage.imageinfo === 'undefined') { |
|||
return; |
|||
} |
|||
imageinfo = imagepage.imageinfo[0]; |
|||
} catch (someError) { |
|||
log('popupsInsertImage failed :('); |
|||
return; |
|||
} |
|||
const popupImage = document.getElementById('popupImg' + id); |
|||
if (!popupImage) { |
|||
log('could not find insertion point for image'); |
|||
return; |
|||
} |
|||
popupImage.width = getValueOf('popupImageSize'); |
|||
popupImage.style.display = 'inline'; |
|||
// Set the source for the image. |
|||
if (imageinfo.thumburl) { |
|||
popupImage.src = imageinfo.thumburl; |
|||
} else if (imageinfo.mime.indexOf('image') === 0) { |
|||
popupImage.src = imageinfo.url; |
|||
log('a thumb could not be found, using original image'); |
|||
} else { |
|||
log("fullsize imagethumb, but not sure if it's an image"); |
|||
} |
|||
const a = document.getElementById('popupImageLink' + id); |
|||
if (a === null) { |
|||
return null; |
|||
} |
|||
// Determine the action of the surrouding imagelink. |
|||
switch (getValueOf('popupThumbAction')) { |
|||
case 'imagepage': |
|||
if (pg.current.article.namespaceId() != pg.nsImageId) { |
|||
a.href = imageinfo.descriptionurl; |
|||
// FIXME: unreliable pg.idNumber |
|||
popTipsSoonFn('popupImage' + id)(); |
|||
break; |
|||
} |
|||
/* falls through */ |
|||
case 'sizetoggle': |
|||
a.onclick = toggleSize; |
|||
a.title = popupString('Toggle image size'); |
|||
return; |
|||
case 'linkfull': |
|||
a.href = imageinfo.url; |
|||
a.title = popupString('Open full-size image'); |
|||
return; |
|||
} |
|||
} |
|||
// Toggles the image between inline small and navpop fullwidth. |
|||
// It's the same image, no actual sizechange occurs, only display width. |
|||
function toggleSize() { |
|||
const imgContainer = this; |
|||
if (!imgContainer) { |
|||
alert('imgContainer is null :/'); |
|||
return; |
|||
} |
|||
const img = imgContainer.firstChild; |
|||
if (!img) { |
|||
alert('img is null :/'); |
|||
return; |
|||
} |
|||
if (!img.style.width || img.style.width === '') { |
|||
img.style.width = '100%'; |
|||
} else { |
|||
img.style.width = ''; |
|||
} |
|||
} |
|||
// Returns one title of an image from wikiText. |
|||
function getValidImageFromWikiText(wikiText) { |
|||
// nb in pg.re.image we're interested in the second bracketed expression |
|||
// this may change if the regex changes :-( |
|||
//var match=pg.re.image.exec(wikiText); |
|||
let matched = null; |
|||
let match; |
|||
// strip html comments, used by evil bots :-( |
|||
const t = removeMatchesUnless( |
|||
wikiText, |
|||
/(<!--[\s\S]*?-->)/, |
|||
1, |
|||
/^<!--[^[]*popup/i |
|||
); |
|||
while ((match = pg.re.image.exec(t))) { |
|||
// now find a sane image name - exclude templates by seeking { |
|||
const m = match[2] || match[6]; |
|||
if (isValidImageName(m)) { |
|||
matched = m; |
|||
break; |
|||
} |
|||
} |
|||
pg.re.image.lastIndex = 0; |
|||
if (!matched) { |
|||
return null; |
|||
} |
|||
return mw.config.get('wgFormattedNamespaces')[pg.nsImageId] + ':' + upcaseFirst(matched); |
|||
} |
|||
function removeMatchesUnless(str, re1, parencount, re2) { |
|||
const split = str.parenSplit(re1); |
|||
const c = parencount + 1; |
|||
for (let i = 0; i < split.length; ++i) { |
|||
if (i % c === 0 || re2.test(split[i])) { |
|||
continue; |
|||
} |
|||
split[i] = ''; |
|||
} |
|||
return split.join(''); |
|||
} |
|||
// ENDFILE: images.js |
|||
// STARTFILE: namespaces.js |
|||
// Set up namespaces and other non-strings.js localization |
|||
// (currently that means redirs too) |
|||
function setNamespaces() { |
|||
pg.nsSpecialId = -1; |
|||
pg.nsMainspaceId = 0; |
|||
pg.nsImageId = 6; |
|||
pg.nsUserId = 2; |
|||
pg.nsUsertalkId = 3; |
|||
pg.nsCategoryId = 14; |
|||
pg.nsTemplateId = 10; |
|||
} |
|||
function setRedirs() { |
|||
const r = 'redirect'; |
|||
const R = 'REDIRECT'; |
|||
const redirLists = { |
|||
ar: [R, 'تحويل'], |
|||
be: [r, 'перанакіраваньне'], |
|||
bg: [r, 'пренасочване', 'виж'], |
|||
bs: [r, 'Preusmjeri', 'preusmjeri', 'PREUSMJERI'], |
|||
bn: [R, 'পুনর্নির্দেশ'], |
|||
cs: [R, 'PŘESMĚRUJ'], |
|||
cy: [r, 'ail-cyfeirio'], |
|||
de: [R, 'WEITERLEITUNG'], |
|||
el: [R, 'ΑΝΑΚΑΤΕΥΘΥΝΣΗ'], |
|||
eo: [R, 'ALIDIREKTU', 'ALIDIREKTI'], |
|||
es: [R, 'REDIRECCIÓN'], |
|||
et: [r, 'suuna'], |
|||
ga: [r, 'athsheoladh'], |
|||
gl: [r, 'REDIRECCIÓN', 'REDIRECIONAMENTO'], |
|||
he: [R, 'הפניה'], |
|||
hu: [R, 'ÁTIRÁNYÍTÁS'], |
|||
is: [r, 'tilvísun', 'TILVÍSUN'], |
|||
it: [R, 'RINVIA', 'Rinvia'], |
|||
ja: [R, '転送'], |
|||
mk: [r, 'пренасочување', 'види'], |
|||
nds: [r, 'wiederleiden'], |
|||
'nds-nl': [R, 'DEURVERWIEZING', 'DUURVERWIEZING'], |
|||
nl: [R, 'DOORVERWIJZING'], |
|||
nn: [r, 'omdiriger'], |
|||
pl: [R, 'PATRZ', 'PRZEKIERUJ', 'TAM'], |
|||
pt: [R, 'redir'], |
|||
ru: [R, 'ПЕРЕНАПРАВЛЕНИЕ', 'ПЕРЕНАПР'], |
|||
sk: [r, 'presmeruj'], |
|||
sr: [r, 'Преусмери', 'преусмери', 'ПРЕУСМЕРИ', 'Preusmeri', 'preusmeri', 'PREUSMERI'], |
|||
tr: [R, 'YÖNLENDİRME', 'yönlendirme', 'YÖNLENDİR', 'yönlendir'], |
|||
tt: [R, 'yünältü', 'перенаправление', 'перенапр'], |
|||
uk: [R, 'ПЕРЕНАПРАВЛЕННЯ', 'ПЕРЕНАПР'], |
|||
vi: [r, 'đổi'], |
|||
yi: [R, 'ווייטערפירן'], |
|||
zh: [R, '重定向'], // no comma |
|||
}; |
|||
const redirList = redirLists[pg.wiki.lang] || [r, R]; |
|||
// Mediawiki is very tolerant about what comes after the #redirect at the start |
|||
pg.re.redirect = RegExp( |
|||
'^\\s*[#](' + redirList.join('|') + ').*?\\[{2}([^\\|\\]]*)(|[^\\]]*)?\\]{2}\\s*(.*)', |
|||
'i' |
|||
); |
|||
} |
|||
function setInterwiki() { |
|||
if (pg.wiki.wikimedia) { |
|||
// From https://meta.wikimedia.org/wiki/List_of_Wikipedias |
|||
//en.wikipedia.org/w/api.php?action=sitematrix&format=json&smtype=language&smlangprop=code&formatversion=2 |
|||
pg.wiki.interwiki = |
|||
'aa|ab|ace|af|ak|als|am|an|ang|ar|arc|arz|as|ast|av|ay|az|ba|bar|bat-smg|bcl|be|be-x-old|bg|bh|bi|bjn|bm|bn|bo|bpy|br|bs|bug|bxr|ca|cbk-zam|cdo|ce|ceb|ch|cho|chr|chy|ckb|co|cr|crh|cs|csb|cu|cv|cy|da|de|diq|dsb|dv|dz|ee|el|eml|en|eo|es|et|eu|ext|fa|ff|fi|fiu-vro|fj|fo|fr|frp|frr|fur|fy|ga|gag|gan|gd|gl|glk|gn|got|gu|gv|ha|hak|haw|he|hi|hif|ho|hr|hsb|ht|hu|hy|hz|ia|id|ie|ig|ii|ik|ilo|io|is|it|iu|ja|jbo|jv|ka|kaa|kab|kbd|kg|ki|kj|kk|kl|km|kn|ko|koi|kr|krc|ks|ksh|ku|kv|kw|ky|la|lad|lb|lbe|lg|li|lij|lmo|ln|lo|lt|ltg|lv|map-bms|mdf|mg|mh|mhr|mi|mk|ml|mn|mo|mr|mrj|ms|mt|mus|mwl|my|myv|mzn|na|nah|nap|nds|nds-nl|ne|new|ng|nl|nn|no|nov|nrm|nv|ny|oc|om|or|os|pa|pag|pam|pap|pcd|pdc|pfl|pi|pih|pl|pms|pnb|pnt|ps|pt|qu|rm|rmy|rn|ro|roa-rup|roa-tara|ru|rue|rw|sa|sah|sc|scn|sco|sd|se|sg|sh|si|simple|sk|sl|sm|sn|so|sq|sr|srn|ss|st|stq|su|sv|sw|szl|ta|te|tet|tg|th|ti|tk|tl|tn|to|tpi|tr|ts|tt|tum|tw|ty|udm|ug|uk|ur|uz|ve|vec|vi|vls|vo|wa|war|wo|wuu|xal|xh|yi|yo|za|zea|zh|zh-classical|zh-min-nan|zh-yue|zu'; |
|||
pg.re.interwiki = RegExp('^' + pg.wiki.interwiki + ':'); |
|||
} else { |
|||
pg.wiki.interwiki = null; |
|||
pg.re.interwiki = /^$/; |
|||
} |
|||
} |
|||
// return a regexp pattern matching all variants to write the given namespace |
|||
function nsRe(namespaceId) { |
|||
const imageNamespaceVariants = []; |
|||
$.each(mw.config.get('wgNamespaceIds'), (_localizedNamespaceLc, _namespaceId) => { |
|||
if (_namespaceId != namespaceId) { |
|||
return; |
|||
} |
|||
_localizedNamespaceLc = upcaseFirst(_localizedNamespaceLc); |
|||
imageNamespaceVariants.push( |
|||
mw.util.escapeRegExp(_localizedNamespaceLc).split(' ').join('[ _]') |
|||
); |
|||
imageNamespaceVariants.push(mw.util.escapeRegExp(encodeURI(_localizedNamespaceLc))); |
|||
}); |
|||
return '(?:' + imageNamespaceVariants.join('|') + ')'; |
|||
} |
|||
function nsReImage() { |
|||
return nsRe(pg.nsImageId); |
|||
} |
|||
// ENDFILE: namespaces.js |
|||
// STARTFILE: selpop.js |
|||
function getEditboxSelection() { |
|||
// see http://www.webgurusforum.com/8/12/0 |
|||
let editbox; |
|||
try { |
|||
editbox = document.editform.wpTextbox1; |
|||
} catch (dang) { |
|||
return; |
|||
} |
|||
// IE, Opera |
|||
if (document.selection) { |
|||
return document.selection.createRange().text; |
|||
} |
|||
// Mozilla |
|||
const selStart = editbox.selectionStart; |
|||
const selEnd = editbox.selectionEnd; |
|||
return editbox.value.substring(selStart, selEnd); |
|||
} |
|||
function doSelectionPopup() { |
|||
// popup if the selection looks like [[foo|anything afterwards at all |
|||
// or [[foo|bar]]text without ']]' |
|||
// or [[foo|bar]] |
|||
const sel = getEditboxSelection(); |
|||
const open = sel.indexOf('[['); |
|||
const pipe = sel.indexOf('|'); |
|||
const close = sel.indexOf(']]'); |
|||
if (open == -1 || (pipe == -1 && close == -1)) { |
|||
return; |
|||
} |
|||
if ((pipe != -1 && open > pipe) || (close != -1 && open > close)) { |
|||
return; |
|||
} |
|||
const article = new Title(sel.substring(open + 2, pipe < 0 ? close : pipe)); |
|||
if (getValueOf('popupOnEditSelection') == 'boxpreview') { |
|||
return doSeparateSelectionPopup(sel, article); |
|||
} |
|||
if (close > 0 && sel.substring(close + 2).indexOf('[[') >= 0) { |
|||
return; |
|||
} |
|||
const a = document.createElement('a'); |
|||
a.href = pg.wiki.titlebase + article.urlString(); |
|||
mouseOverWikiLink2(a); |
|||
if (a.navpopup) { |
|||
a.navpopup.addHook( |
|||
() => { |
|||
runStopPopupTimer(a.navpopup); |
|||
}, |
|||
'unhide', |
|||
'after' |
|||
); |
|||
} |
|||
} |
|||
function doSeparateSelectionPopup(str, article) { |
|||
let div = document.getElementById('selectionPreview'); |
|||
if (!div) { |
|||
div = document.createElement('div'); |
|||
div.id = 'selectionPreview'; |
|||
try { |
|||
const box = document.editform.wpTextbox1; |
|||
box.parentNode.insertBefore(div, box); |
|||
} catch (error) { |
|||
return; |
|||
} |
|||
} |
|||
const p = prepPreviewmaker(str, article, newNavpopup(document.createElement('a'), article)); |
|||
p.makePreview(); |
|||
if (p.html) { |
|||
div.innerHTML = p.html; |
|||
} |
|||
div.ranSetupTooltipsAlready = false; |
|||
popTipsSoonFn('selectionPreview')(); |
|||
} |
|||
// ENDFILE: selpop.js |
|||
// STARTFILE: navpopup.js |
|||
/** |
|||
* @file Defines two classes: {@link Navpopup} and {@link Mousetracker}. |
|||
* |
|||
* <code>Navpopup</code> describes popups: when they appear, where, what |
|||
* they look like and so on. |
|||
* |
|||
* <code>Mousetracker</code> "captures" the mouse using |
|||
* <code>document.onmousemove</code>. |
|||
*/ |
|||
/** |
|||
* Creates a new Mousetracker. |
|||
* |
|||
* @constructor |
|||
* @class The Mousetracker class. This monitors mouse movements and manages associated hooks. |
|||
*/ |
|||
function Mousetracker() { |
|||
/** |
|||
* Interval to regularly run the hooks anyway, in milliseconds. |
|||
* |
|||
* @type {number} |
|||
*/ |
|||
this.loopDelay = 400; |
|||
/** |
|||
* Timer for the loop. |
|||
* |
|||
* @type {Timer} |
|||
*/ |
|||
this.timer = null; |
|||
/** |
|||
* Flag - are we switched on? |
|||
* |
|||
* @type {boolean} |
|||
*/ |
|||
this.active = false; |
|||
/** |
|||
* Flag - are we probably inaccurate, i.e. not reflecting the actual mouse position? |
|||
*/ |
|||
this.dirty = true; |
|||
/** |
|||
* Array of hook functions. |
|||
* |
|||
* @private |
|||
* @type {Array} |
|||
*/ |
|||
this.hooks = []; |
|||
} |
|||
/** |
|||
* Adds a hook, to be called when we get events. |
|||
* |
|||
* @param {Function} f A function which is called as |
|||
* <code>f(x,y)</code>. It should return <code>true</code> when it |
|||
* wants to be removed, and <code>false</code> otherwise. |
|||
*/ |
|||
Mousetracker.prototype.addHook = function (f) { |
|||
this.hooks.push(f); |
|||
}; |
|||
/** |
|||
* Runs hooks, passing them the x |
|||
* and y coords of the mouse. Hook functions that return true are |
|||
* passed to {@link Mousetracker#removeHooks} for removal. |
|||
* |
|||
* @private |
|||
*/ |
|||
Mousetracker.prototype.runHooks = function () { |
|||
if (!this.hooks || !this.hooks.length) { |
|||
return; |
|||
} |
|||
//log('Mousetracker.runHooks; we got some hooks to run'); |
|||
let remove = false; |
|||
const removeObj = {}; |
|||
// this method gets called a LOT - |
|||
// pre-cache some variables |
|||
const x = this.x, |
|||
y = this.y, |
|||
len = this.hooks.length; |
|||
for (let i = 0; i < len; ++i) { |
|||
//~ run the hook function, and remove it if it returns true |
|||
if (this.hooks[i](x, y) === true) { |
|||
remove = true; |
|||
removeObj[i] = true; |
|||
} |
|||
} |
|||
if (remove) { |
|||
this.removeHooks(removeObj); |
|||
} |
|||
}; |
|||
/** |
|||
* Removes hooks. |
|||
* |
|||
* @private |
|||
* @param {Object} removeObj An object whose keys are the index |
|||
* numbers of functions for removal, with values that evaluate to true |
|||
*/ |
|||
Mousetracker.prototype.removeHooks = function (removeObj) { |
|||
const newHooks = []; |
|||
const len = this.hooks.length; |
|||
for (let i = 0; i < len; ++i) { |
|||
if (!removeObj[i]) { |
|||
newHooks.push(this.hooks[i]); |
|||
} |
|||
} |
|||
this.hooks = newHooks; |
|||
}; |
|||
/** |
|||
* Event handler for mouse wiggles. |
|||
* We simply grab the event, set x and y and run the hooks. |
|||
* This makes the cpu all hot and bothered :-( |
|||
* |
|||
* @private |
|||
* @param {Event} e Mousemove event |
|||
*/ |
|||
Mousetracker.prototype.track = function (e) { |
|||
//~ Apparently this is needed in IE. |
|||
e = e || window.event; |
|||
let x, y; |
|||
if (e) { |
|||
if (e.pageX) { |
|||
x = e.pageX; |
|||
y = e.pageY; |
|||
} else if (typeof e.clientX != 'undefined') { |
|||
let left, |
|||
top, |
|||
docElt = document.documentElement; |
|||
if (docElt) { |
|||
left = docElt.scrollLeft; |
|||
} |
|||
left = left || document.body.scrollLeft || document.scrollLeft || 0; |
|||
if (docElt) { |
|||
top = docElt.scrollTop; |
|||
} |
|||
top = top || document.body.scrollTop || document.scrollTop || 0; |
|||
x = e.clientX + left; |
|||
y = e.clientY + top; |
|||
} else { |
|||
return; |
|||
} |
|||
this.setPosition(x, y); |
|||
} |
|||
}; |
|||
/** |
|||
* Sets the x and y coordinates stored and takes appropriate action, |
|||
* running hooks as appropriate. |
|||
* |
|||
* @param {number} x Screen coordinates to set |
|||
* @param {number} y Screen coordinates to set |
|||
*/ |
|||
Mousetracker.prototype.setPosition = function (x, y) { |
|||
this.x = x; |
|||
this.y = y; |
|||
if (this.dirty || this.hooks.length === 0) { |
|||
this.dirty = false; |
|||
return; |
|||
} |
|||
if (typeof this.lastHook_x != 'number') { |
|||
this.lastHook_x = -100; |
|||
this.lastHook_y = -100; |
|||
} |
|||
let diff = (this.lastHook_x - x) * (this.lastHook_y - y); |
|||
diff = diff >= 0 ? diff : -diff; |
|||
if (diff > 1) { |
|||
this.lastHook_x = x; |
|||
this.lastHook_y = y; |
|||
if (this.dirty) { |
|||
this.dirty = false; |
|||
} else { |
|||
this.runHooks(); |
|||
} |
|||
} |
|||
}; |
|||
/** |
|||
* Sets things in motion, unless they are already that is, registering an event handler on |
|||
* <code>document.onmousemove</code>. A half-hearted attempt is made to preserve the old event |
|||
* handler if there is one. |
|||
*/ |
|||
Mousetracker.prototype.enable = function () { |
|||
if (this.active) { |
|||
return; |
|||
} |
|||
this.active = true; |
|||
//~ Save the current handler for mousemove events. This isn't too |
|||
//~ robust, of course. |
|||
this.savedHandler = document.onmousemove; |
|||
//~ Gotta save @tt{this} again for the closure, and use apply for |
|||
//~ the member function. |
|||
const savedThis = this; |
|||
document.onmousemove = function (e) { |
|||
savedThis.track.apply(savedThis, [e]); |
|||
}; |
|||
if (this.loopDelay) { |
|||
this.timer = setInterval(() => { |
|||
//log('loop delay in mousetracker is working'); |
|||
savedThis.runHooks(); |
|||
}, this.loopDelay); |
|||
} |
|||
}; |
|||
/** |
|||
* Disables the tracker, removing the event handler. |
|||
*/ |
|||
Mousetracker.prototype.disable = function () { |
|||
if (!this.active) { |
|||
return; |
|||
} |
|||
if (typeof this.savedHandler === 'function') { |
|||
document.onmousemove = this.savedHandler; |
|||
} else { |
|||
delete document.onmousemove; |
|||
} |
|||
if (this.timer) { |
|||
clearInterval(this.timer); |
|||
} |
|||
this.active = false; |
|||
}; |
|||
/** |
|||
* Creates a new Navpopup. |
|||
* Gets a UID for the popup and |
|||
* |
|||
* @param init Contructor object. If <code>init.draggable</code> is true or absent, the popup becomes draggable. |
|||
* @constructor |
|||
* @class The Navpopup class. This generates popup hints, and does some management of them. |
|||
*/ |
|||
function Navpopup(/*init*/) { |
|||
//alert('new Navpopup(init)'); |
|||
/** |
|||
* UID for each Navpopup instance. |
|||
* Read-only. |
|||
* |
|||
* @type {number} |
|||
*/ |
|||
this.uid = Navpopup.uid++; |
|||
/** |
|||
* Read-only flag for current visibility of the popup. |
|||
* |
|||
* @type {boolean} |
|||
* @private |
|||
*/ |
|||
this.visible = false; |
|||
/** Flag to be set when we want to cancel a previous request to |
|||
* show the popup in a little while. |
|||
* |
|||
* @private |
|||
* @type {boolean} |
|||
*/ |
|||
this.noshow = false; |
|||
/** Categorised list of hooks. |
|||
* @see #runHooks |
|||
* @see #addHook |
|||
* @private |
|||
* @type {Object} |
|||
*/ |
|||
this.hooks = { |
|||
create: [], |
|||
unhide: [], |
|||
hide: [], |
|||
}; |
|||
/** |
|||
* list of unique IDs of hook functions, to avoid duplicates |
|||
* |
|||
* @private |
|||
*/ |
|||
this.hookIds = {}; |
|||
/** List of downloads associated with the popup. |
|||
* @private |
|||
* @type {Array} |
|||
*/ |
|||
this.downloads = []; |
|||
/** |
|||
* Number of uncompleted downloads. |
|||
* |
|||
* @type {number} |
|||
*/ |
|||
this.pending = null; |
|||
/** |
|||
* Tolerance in pixels when detecting whether the mouse has left the popup. |
|||
* |
|||
* @type {number} |
|||
*/ |
|||
this.fuzz = 5; |
|||
/** |
|||
* Flag to toggle running {@link #limitHorizontalPosition} to regulate the popup's position. |
|||
* |
|||
* @type {boolean} |
|||
*/ |
|||
this.constrained = true; |
|||
/** |
|||
* The popup width in pixels. |
|||
* |
|||
* @private |
|||
* @type {number} |
|||
*/ |
|||
this.width = 0; |
|||
/** |
|||
* The popup width in pixels. |
|||
* |
|||
* @private |
|||
* @type {number} |
|||
*/ |
|||
this.height = 0; |
|||
/** |
|||
* The main content DIV element. |
|||
* |
|||
* @type {HTMLDivElement} |
|||
*/ |
|||
this.mainDiv = null; |
|||
this.createMainDiv(); |
|||
// if (!init || typeof init.popups_draggable=='undefined' || init.popups_draggable) { |
|||
// this.makeDraggable(true); |
|||
// } |
|||
} |
|||
/** |
|||
* A UID for each Navpopup. This constructor property is just a counter. |
|||
* |
|||
* @type {number} |
|||
* @private |
|||
*/ |
|||
Navpopup.uid = 0; |
|||
/** |
|||
* Retrieves the {@link #visible} attribute, indicating whether the popup is currently visible. |
|||
* |
|||
* @type {boolean} |
|||
*/ |
|||
Navpopup.prototype.isVisible = function () { |
|||
return this.visible; |
|||
}; |
|||
/** |
|||
* Repositions popup using CSS style. |
|||
* |
|||
* @private |
|||
* @param {number} x x-coordinate (px) |
|||
* @param {number} y y-coordinate (px) |
|||
* @param {boolean} noLimitHor Don't call {@link #limitHorizontalPosition} |
|||
*/ |
|||
Navpopup.prototype.reposition = function (x, y, noLimitHor) { |
|||
log('reposition(' + x + ',' + y + ',' + noLimitHor + ')'); |
|||
if (typeof x != 'undefined' && x !== null) { |
|||
this.left = x; |
|||
} |
|||
if (typeof y != 'undefined' && y !== null) { |
|||
this.top = y; |
|||
} |
|||
if (typeof this.left != 'undefined' && typeof this.top != 'undefined') { |
|||
this.mainDiv.style.left = this.left + 'px'; |
|||
this.mainDiv.style.top = this.top + 'px'; |
|||
} |
|||
if (!noLimitHor) { |
|||
this.limitHorizontalPosition(); |
|||
} |
|||
//console.log('navpop'+this.uid+' - (left,top)=(' + this.left + ',' + this.top + '), css=(' |
|||
//+ this.mainDiv.style.left + ',' + this.mainDiv.style.top + ')'); |
|||
}; |
|||
/** |
|||
* Prevents popups from being in silly locations. Hopefully. |
|||
* Should not be run if {@link #constrained} is true. |
|||
* |
|||
* @private |
|||
*/ |
|||
Navpopup.prototype.limitHorizontalPosition = function () { |
|||
if (!this.constrained || this.tooWide) { |
|||
return; |
|||
} |
|||
this.updateDimensions(); |
|||
const x = this.left; |
|||
const w = this.width; |
|||
const cWidth = document.body.clientWidth; |
|||
// log('limitHorizontalPosition: x='+x+ |
|||
// ', this.left=' + this.left + |
|||
// ', this.width=' + this.width + |
|||
// ', cWidth=' + cWidth); |
|||
if ( |
|||
x + w >= cWidth || |
|||
(x > 0 && |
|||
this.maxWidth && |
|||
this.width < this.maxWidth && |
|||
this.height > this.width && |
|||
x > cWidth - this.maxWidth) |
|||
) { |
|||
// This is a very nasty hack. There has to be a better way! |
|||
// We find the "natural" width of the div by positioning it at the far left |
|||
// then reset it so that it should be flush right (well, nearly) |
|||
this.mainDiv.style.left = '-10000px'; |
|||
this.mainDiv.style.width = this.maxWidth + 'px'; |
|||
const naturalWidth = parseInt(this.mainDiv.offsetWidth, 10); |
|||
let newLeft = cWidth - naturalWidth - 1; |
|||
if (newLeft < 0) { |
|||
newLeft = 0; |
|||
this.tooWide = true; |
|||
} // still unstable for really wide popups? |
|||
log( |
|||
'limitHorizontalPosition: moving to (' + |
|||
newLeft + |
|||
',' + |
|||
this.top + |
|||
');' + |
|||
' naturalWidth=' + |
|||
naturalWidth + |
|||
', clientWidth=' + |
|||
cWidth |
|||
); |
|||
this.reposition(newLeft, null, true); |
|||
} |
|||
}; |
|||
/** |
|||
* Counter indicating the z-order of the "highest" popup. |
|||
* We start the z-index at 1000 so that popups are above everything |
|||
* else on the screen. |
|||
* |
|||
* @private |
|||
* @type {number} |
|||
*/ |
|||
Navpopup.highest = 1000; |
|||
/** |
|||
* Brings popup to the top of the z-order. |
|||
* We increment the {@link #highest} property of the contructor here. |
|||
* |
|||
* @private |
|||
*/ |
|||
Navpopup.prototype.raise = function () { |
|||
this.mainDiv.style.zIndex = Navpopup.highest + 1; |
|||
++Navpopup.highest; |
|||
}; |
|||
/** |
|||
* Shows the popup provided {@link #noshow} is not true. |
|||
* Updates the position, brings the popup to the top of the z-order and unhides it. |
|||
*/ |
|||
Navpopup.prototype.show = function () { |
|||
//document.title+='s'; |
|||
if (this.noshow) { |
|||
return; |
|||
} |
|||
//document.title+='t'; |
|||
this.reposition(); |
|||
this.raise(); |
|||
this.unhide(); |
|||
}; |
|||
/** |
|||
* Checks to see if the mouse pointer has |
|||
* stabilised (checking every <code>time</code>/2 milliseconds) and runs the |
|||
* {@link #show} method if it has. |
|||
* |
|||
* @param {number} time The minimum time (ms) before the popup may be shown. |
|||
*/ |
|||
Navpopup.prototype.showSoonIfStable = function (time) { |
|||
log('showSoonIfStable, time=' + time); |
|||
if (this.visible) { |
|||
return; |
|||
} |
|||
this.noshow = false; |
|||
//~ initialize these variables so that we never run @tt{show} after |
|||
//~ just half the time |
|||
this.stable_x = -10000; |
|||
this.stable_y = -10000; |
|||
const stableShow = function () { |
|||
log('stableShow called'); |
|||
let new_x = Navpopup.tracker.x, |
|||
new_y = Navpopup.tracker.y; |
|||
let dx = savedThis.stable_x - new_x, |
|||
dy = savedThis.stable_y - new_y; |
|||
let fuzz2 = 0; // savedThis.fuzz * savedThis.fuzz; |
|||
//document.title += '[' + [savedThis.stable_x,new_x, savedThis.stable_y,new_y, dx, dy, fuzz2].join(',') + '] '; |
|||
if (dx * dx <= fuzz2 && dy * dy <= fuzz2) { |
|||
log('mouse is stable'); |
|||
clearInterval(savedThis.showSoonStableTimer); |
|||
savedThis.reposition.apply(savedThis, [new_x + 2, new_y + 2]); |
|||
savedThis.show.apply(savedThis, []); |
|||
savedThis.limitHorizontalPosition.apply(savedThis, []); |
|||
return; |
|||
} |
|||
savedThis.stable_x = new_x; |
|||
savedThis.stable_y = new_y; |
|||
}; |
|||
var savedThis = this; |
|||
this.showSoonStableTimer = setInterval(stableShow, time / 2); |
|||
}; |
|||
/** |
|||
* Sets the {@link #noshow} flag and hides the popup. This should be called |
|||
* when the mouse leaves the link before |
|||
* (or after) it's actually been displayed. |
|||
*/ |
|||
Navpopup.prototype.banish = function () { |
|||
log('banish called'); |
|||
// hide and prevent showing with showSoon in the future |
|||
this.noshow = true; |
|||
if (this.showSoonStableTimer) { |
|||
log('clearing showSoonStableTimer'); |
|||
clearInterval(this.showSoonStableTimer); |
|||
} |
|||
this.hide(); |
|||
}; |
|||
/** |
|||
* Runs hooks added with {@link #addHook}. |
|||
* |
|||
* @private |
|||
* @param {string} key Key name of the {@link #hooks} array - one of 'create', 'unhide', 'hide' |
|||
* @param {string} when Controls exactly when the hook is run: either 'before' or 'after' |
|||
*/ |
|||
Navpopup.prototype.runHooks = function (key, when) { |
|||
if (!this.hooks[key]) { |
|||
return; |
|||
} |
|||
const keyHooks = this.hooks[key]; |
|||
const len = keyHooks.length; |
|||
for (let i = 0; i < len; ++i) { |
|||
if (keyHooks[i] && keyHooks[i].when == when) { |
|||
if (keyHooks[i].hook.apply(this, [])) { |
|||
// remove the hook |
|||
if (keyHooks[i].hookId) { |
|||
delete this.hookIds[keyHooks[i].hookId]; |
|||
} |
|||
keyHooks[i] = null; |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
/** |
|||
* Adds a hook to the popup. Hook functions are run with <code>this</code> set to refer to the |
|||
* Navpopup instance, and no arguments. |
|||
* |
|||
* @param {Function} hook The hook function. Functions that return true are deleted. |
|||
* @param {string} key Key name of the {@link #hooks} array - one of 'create', 'unhide', 'hide' |
|||
* @param {String} when Controls exactly when the hook is run: either 'before' or 'after' |
|||
* @param {String} uid A truthy string identifying the hook function; if it matches another hook |
|||
* in this position, it won't be added again. |
|||
*/ |
|||
Navpopup.prototype.addHook = function (hook, key, when, uid) { |
|||
when = when || 'after'; |
|||
if (!this.hooks[key]) { |
|||
return; |
|||
} |
|||
// if uid is specified, don't add duplicates |
|||
let hookId = null; |
|||
if (uid) { |
|||
hookId = [key, when, uid].join('|'); |
|||
if (this.hookIds[hookId]) { |
|||
return; |
|||
} |
|||
this.hookIds[hookId] = true; |
|||
} |
|||
this.hooks[key].push({ hook: hook, when: when, hookId: hookId }); |
|||
}; |
|||
/** |
|||
* Creates the main DIV element, which contains all the actual popup content. |
|||
* Runs hooks with key 'create'. |
|||
* |
|||
* @private |
|||
*/ |
|||
Navpopup.prototype.createMainDiv = function () { |
|||
if (this.mainDiv) { |
|||
return; |
|||
} |
|||
this.runHooks('create', 'before'); |
|||
const mainDiv = document.createElement('div'); |
|||
const savedThis = this; |
|||
mainDiv.onclick = function (e) { |
|||
savedThis.onclickHandler(e); |
|||
}; |
|||
mainDiv.className = this.className ? this.className : 'navpopup_maindiv'; |
|||
mainDiv.id = mainDiv.className + this.uid; |
|||
mainDiv.style.position = 'absolute'; |
|||
mainDiv.style.minWidth = '350px'; |
|||
mainDiv.style.display = 'none'; |
|||
mainDiv.className = 'navpopup'; |
|||
// easy access to javascript object through DOM functions |
|||
mainDiv.navpopup = this; |
|||
this.mainDiv = mainDiv; |
|||
document.body.appendChild(mainDiv); |
|||
this.runHooks('create', 'after'); |
|||
}; |
|||
/** |
|||
* Calls the {@link #raise} method. |
|||
* |
|||
* @private |
|||
*/ |
|||
Navpopup.prototype.onclickHandler = function (/*e*/) { |
|||
this.raise(); |
|||
}; |
|||
/** |
|||
* Makes the popup draggable, using a {@link Drag} object. |
|||
* |
|||
* @private |
|||
*/ |
|||
Navpopup.prototype.makeDraggable = function (handleName) { |
|||
if (!this.mainDiv) { |
|||
this.createMainDiv(); |
|||
} |
|||
const drag = new Drag(); |
|||
if (!handleName) { |
|||
drag.startCondition = function (e) { |
|||
try { |
|||
if (!e.shiftKey) { |
|||
return false; |
|||
} |
|||
} catch (err) { |
|||
return false; |
|||
} |
|||
return true; |
|||
}; |
|||
} |
|||
let dragHandle; |
|||
if (handleName) { |
|||
dragHandle = document.getElementById(handleName); |
|||
} |
|||
if (!dragHandle) { |
|||
dragHandle = this.mainDiv; |
|||
} |
|||
const np = this; |
|||
drag.endHook = function (x, y) { |
|||
Navpopup.tracker.dirty = true; |
|||
np.reposition(x, y); |
|||
}; |
|||
drag.init(dragHandle, this.mainDiv); |
|||
}; |
|||
/** |
|||
* Hides the popup using CSS. Runs hooks with key 'hide'. |
|||
* Sets {@link #visible} appropriately. |
|||
* {@link #banish} should be called externally instead of this method. |
|||
* |
|||
* @private |
|||
*/ |
|||
Navpopup.prototype.hide = function () { |
|||
this.runHooks('hide', 'before'); |
|||
this.abortDownloads(); |
|||
if (typeof this.visible != 'undefined' && this.visible) { |
|||
this.mainDiv.style.display = 'none'; |
|||
this.visible = false; |
|||
} |
|||
this.runHooks('hide', 'after'); |
|||
}; |
|||
/** |
|||
* Shows the popup using CSS. Runs hooks with key 'unhide'. |
|||
* Sets {@link #visible} appropriately. {@link #show} should be called externally instead of this method. |
|||
* |
|||
* @private |
|||
*/ |
|||
Navpopup.prototype.unhide = function () { |
|||
this.runHooks('unhide', 'before'); |
|||
if (typeof this.visible != 'undefined' && !this.visible) { |
|||
this.mainDiv.style.display = 'inline'; |
|||
this.visible = true; |
|||
} |
|||
this.runHooks('unhide', 'after'); |
|||
}; |
|||
/** |
|||
* Sets the <code>innerHTML</code> attribute of the main div containing the popup content. |
|||
* |
|||
* @param {string} html The HTML to set. |
|||
*/ |
|||
Navpopup.prototype.setInnerHTML = function (html) { |
|||
this.mainDiv.innerHTML = html; |
|||
}; |
|||
/** |
|||
* Updates the {@link #width} and {@link #height} attributes with the CSS properties. |
|||
* |
|||
* @private |
|||
*/ |
|||
Navpopup.prototype.updateDimensions = function () { |
|||
this.width = parseInt(this.mainDiv.offsetWidth, 10); |
|||
this.height = parseInt(this.mainDiv.offsetHeight, 10); |
|||
}; |
|||
/** |
|||
* Checks if the point (x,y) is within {@link #fuzz} of the |
|||
* {@link #mainDiv}. |
|||
* |
|||
* @param {number} x x-coordinate (px) |
|||
* @param {number} y y-coordinate (px) |
|||
* @type {boolean} |
|||
*/ |
|||
Navpopup.prototype.isWithin = function (x, y) { |
|||
//~ If we're not even visible, no point should be considered as |
|||
//~ being within the popup. |
|||
if (!this.visible) { |
|||
return false; |
|||
} |
|||
this.updateDimensions(); |
|||
const fuzz = this.fuzz || 0; |
|||
//~ Use a simple box metric here. |
|||
return ( |
|||
x + fuzz >= this.left && |
|||
x - fuzz <= this.left + this.width && |
|||
y + fuzz >= this.top && |
|||
y - fuzz <= this.top + this.height |
|||
); |
|||
}; |
|||
/** |
|||
* Adds a download to {@link #downloads}. |
|||
* |
|||
* @param {Downloader} download |
|||
*/ |
|||
Navpopup.prototype.addDownload = function (download) { |
|||
if (!download) { |
|||
return; |
|||
} |
|||
this.downloads.push(download); |
|||
}; |
|||
/** |
|||
* Aborts the downloads listed in {@link #downloads}. |
|||
* |
|||
* @see Downloader#abort |
|||
*/ |
|||
Navpopup.prototype.abortDownloads = function () { |
|||
for (let i = 0; i < this.downloads.length; ++i) { |
|||
const d = this.downloads[i]; |
|||
if (d && d.abort) { |
|||
d.abort(); |
|||
} |
|||
} |
|||
this.downloads = []; |
|||
}; |
|||
/** |
|||
* A {@link Mousetracker} instance which is a property of the constructor (pseudo-global). |
|||
*/ |
|||
Navpopup.tracker = new Mousetracker(); |
|||
// ENDFILE: navpopup.js |
|||
// STARTFILE: diff.js |
|||
/* |
|||
* Javascript Diff Algorithm |
|||
* By John Resig (http://ejohn.org/) and [[:en:User:Lupin]] |
|||
* |
|||
* More Info: |
|||
* http://ejohn.org/projects/javascript-diff-algorithm/ |
|||
*/ |
|||
function delFmt(x) { |
|||
if (!x.length) { |
|||
return ''; |
|||
} |
|||
return "<del class='popupDiff'>" + x.join('') + '</del>'; |
|||
} |
|||
function insFmt(x) { |
|||
if (!x.length) { |
|||
return ''; |
|||
} |
|||
return "<ins class='popupDiff'>" + x.join('') + '</ins>'; |
|||
} |
|||
function countCrossings(a, b, i, eject) { |
|||
// count the crossings on the edge starting at b[i] |
|||
if (!b[i].row && b[i].row !== 0) { |
|||
return -1; |
|||
} |
|||
let count = 0; |
|||
for (let j = 0; j < a.length; ++j) { |
|||
if (!a[j].row && a[j].row !== 0) { |
|||
continue; |
|||
} |
|||
if ((j - b[i].row) * (i - a[j].row) > 0) { |
|||
if (eject) { |
|||
return true; |
|||
} |
|||
count++; |
|||
} |
|||
} |
|||
return count; |
|||
} |
|||
function shortenDiffString(str, context) { |
|||
const re = /(<del[\s\S]*?<\/del>|<ins[\s\S]*?<\/ins>)/; |
|||
const splitted = str.parenSplit(re); |
|||
let ret = ['']; |
|||
for (let i = 0; i < splitted.length; i += 2) { |
|||
if (splitted[i].length < 2 * context) { |
|||
ret[ret.length - 1] += splitted[i]; |
|||
if (i + 1 < splitted.length) { |
|||
ret[ret.length - 1] += splitted[i + 1]; |
|||
} |
|||
continue; |
|||
} else { |
|||
if (i > 0) { |
|||
ret[ret.length - 1] += splitted[i].substring(0, context); |
|||
} |
|||
if (i + 1 < splitted.length) { |
|||
ret.push(splitted[i].substring(splitted[i].length - context) + splitted[i + 1]); |
|||
} |
|||
} |
|||
} |
|||
while (ret.length > 0 && !ret[0]) { |
|||
ret = ret.slice(1); |
|||
} |
|||
return ret; |
|||
} |
|||
function diffString(o, n, simpleSplit) { |
|||
const splitRe = /([[]{2}|[\]]{2}|[{]{2,3}|[}]{2,3}|[|]|=|<|>|[*:]+|\s|\b)/; |
|||
// We need to split the strings o and n first, and entify() the parts |
|||
// individually, so that the HTML entities are never cut apart. (AxelBoldt) |
|||
let out, i, oSplitted, nSplitted; |
|||
if (simpleSplit) { |
|||
oSplitted = o.split(/\b/); |
|||
nSplitted = n.split(/\b/); |
|||
} else { |
|||
oSplitted = o.parenSplit(splitRe); |
|||
nSplitted = n.parenSplit(splitRe); |
|||
} |
|||
for (i = 0; i < oSplitted.length; ++i) { |
|||
oSplitted[i] = oSplitted[i].entify(); |
|||
} |
|||
for (i = 0; i < nSplitted.length; ++i) { |
|||
nSplitted[i] = nSplitted[i].entify(); |
|||
} |
|||
out = diff(oSplitted, nSplitted); |
|||
let str = ''; |
|||
let acc = []; // accumulator for prettier output |
|||
// crossing pairings -- eg 'A B' vs 'B A' -- cause problems, so let's iron them out |
|||
// this doesn't always do things optimally but it should be fast enough |
|||
let maxOutputPair = 0; |
|||
for (i = 0; i < out.n.length; ++i) { |
|||
if (out.n[i].paired) { |
|||
if (maxOutputPair > out.n[i].row) { |
|||
// tangle - delete pairing |
|||
out.o[out.n[i].row] = out.o[out.n[i].row].text; |
|||
out.n[i] = out.n[i].text; |
|||
} |
|||
if (maxOutputPair < out.n[i].row) { |
|||
maxOutputPair = out.n[i].row; |
|||
} |
|||
} |
|||
} |
|||
// output the stuff preceding the first paired old line |
|||
for (i = 0; i < out.o.length && !out.o[i].paired; ++i) { |
|||
acc.push(out.o[i]); |
|||
} |
|||
str += delFmt(acc); |
|||
acc = []; |
|||
// main loop |
|||
for (i = 0; i < out.n.length; ++i) { |
|||
// output unpaired new "lines" |
|||
while (i < out.n.length && !out.n[i].paired) { |
|||
acc.push(out.n[i++]); |
|||
} |
|||
str += insFmt(acc); |
|||
acc = []; |
|||
if (i < out.n.length) { |
|||
// this new "line" is paired with the (out.n[i].row)th old "line" |
|||
str += out.n[i].text; |
|||
// output unpaired old rows starting after this new line's partner |
|||
let m = out.n[i].row + 1; |
|||
while (m < out.o.length && !out.o[m].paired) { |
|||
acc.push(out.o[m++]); |
|||
} |
|||
str += delFmt(acc); |
|||
acc = []; |
|||
} |
|||
} |
|||
return str; |
|||
} |
|||
// see http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Object |
|||
// FIXME: use obj.hasOwnProperty instead of this kludge! |
|||
const jsReservedProperties = RegExp( |
|||
'^(constructor|prototype|__((define|lookup)[GS]etter)__' + |
|||
'|eval|hasOwnProperty|propertyIsEnumerable' + |
|||
'|to(Source|String|LocaleString)|(un)?watch|valueOf)$' |
|||
); |
|||
function diffBugAlert(word) { |
|||
if (!diffBugAlert.list[word]) { |
|||
diffBugAlert.list[word] = 1; |
|||
alert('Bad word: ' + word + '\n\nPlease report this bug.'); |
|||
} |
|||
} |
|||
diffBugAlert.list = {}; |
|||
function makeDiffHashtable(src) { |
|||
const ret = {}; |
|||
for (let i = 0; i < src.length; i++) { |
|||
if (jsReservedProperties.test(src[i])) { |
|||
src[i] += '<!-- -->'; |
|||
} |
|||
if (!ret[src[i]]) { |
|||
ret[src[i]] = []; |
|||
} |
|||
try { |
|||
ret[src[i]].push(i); |
|||
} catch (err) { |
|||
diffBugAlert(src[i]); |
|||
} |
|||
} |
|||
return ret; |
|||
} |
|||
function diff(o, n) { |
|||
// pass 1: make hashtable ns with new rows as keys |
|||
const ns = makeDiffHashtable(n); |
|||
// pass 2: make hashtable os with old rows as keys |
|||
const os = makeDiffHashtable(o); |
|||
// pass 3: pair unique new rows and matching unique old rows |
|||
let i; |
|||
for (i in ns) { |
|||
if (ns[i].length == 1 && os[i] && os[i].length == 1) { |
|||
n[ns[i][0]] = { text: n[ns[i][0]], row: os[i][0], paired: true }; |
|||
o[os[i][0]] = { text: o[os[i][0]], row: ns[i][0], paired: true }; |
|||
} |
|||
} |
|||
// pass 4: pair matching rows immediately following paired rows (not necessarily unique) |
|||
for (i = 0; i < n.length - 1; i++) { |
|||
if ( |
|||
n[i].paired && |
|||
!n[i + 1].paired && |
|||
n[i].row + 1 < o.length && |
|||
!o[n[i].row + 1].paired && |
|||
n[i + 1] == o[n[i].row + 1] |
|||
) { |
|||
n[i + 1] = { text: n[i + 1], row: n[i].row + 1, paired: true }; |
|||
o[n[i].row + 1] = { text: o[n[i].row + 1], row: i + 1, paired: true }; |
|||
} |
|||
} |
|||
// pass 5: pair matching rows immediately preceding paired rows (not necessarily unique) |
|||
for (i = n.length - 1; i > 0; i--) { |
|||
if ( |
|||
n[i].paired && |
|||
!n[i - 1].paired && |
|||
n[i].row > 0 && |
|||
!o[n[i].row - 1].paired && |
|||
n[i - 1] == o[n[i].row - 1] |
|||
) { |
|||
n[i - 1] = { text: n[i - 1], row: n[i].row - 1, paired: true }; |
|||
o[n[i].row - 1] = { text: o[n[i].row - 1], row: i - 1, paired: true }; |
|||
} |
|||
} |
|||
return { o: o, n: n }; |
|||
} |
|||
// ENDFILE: diff.js |
|||
// STARTFILE: init.js |
|||
function setSiteInfo() { |
|||
if (window.popupLocalDebug) { |
|||
pg.wiki.hostname = 'en.wikipedia.org'; |
|||
} else { |
|||
pg.wiki.hostname = location.hostname; // use in preference to location.hostname for flexibility (?) |
|||
} |
|||
pg.wiki.wikimedia = /(wiki([pm]edia|source|books|news|quote|versity|species|voyage|data)|metawiki|wiktionary|mediawiki)[.]org/.test(pg.wiki.hostname); |
|||
pg.wiki.wikia = /[.]wikia[.]com$/i.test(pg.wiki.hostname); |
|||
pg.wiki.isLocal = /^localhost/.test(pg.wiki.hostname); |
|||
pg.wiki.commons = |
|||
pg.wiki.wikimedia && pg.wiki.hostname != 'commons.wikimedia.org' ? |
|||
'commons.wikimedia.org' : |
|||
null; |
|||
pg.wiki.lang = mw.config.get('wgContentLanguage'); |
|||
const port = location.port ? ':' + location.port : ''; |
|||
pg.wiki.sitebase = pg.wiki.hostname + port; |
|||
} |
|||
function setUserInfo() { |
|||
const params = { |
|||
action: 'query', |
|||
list: 'users', |
|||
ususers: mw.config.get('wgUserName'), |
|||
usprop: 'rights', |
|||
}; |
|||
pg.user.canReview = false; |
|||
if (getValueOf('popupReview')) { |
|||
getMwApi() |
|||
.get(params) |
|||
.done((data) => { |
|||
const rights = data.query.users[0].rights; |
|||
pg.user.canReview = rights.indexOf('review') !== -1; // TODO: Should it be a getValueOf('ReviewRight') ? |
|||
}); |
|||
} |
|||
} |
|||
function fetchSpecialPageNames() { |
|||
const params = { |
|||
action: 'query', |
|||
meta: 'siteinfo', |
|||
siprop: 'specialpagealiases', |
|||
formatversion: 2, |
|||
// cache for an hour |
|||
uselang: 'content', |
|||
maxage: 3600, |
|||
}; |
|||
return getMwApi() |
|||
.get(params) |
|||
.then((data) => { |
|||
pg.wiki.specialpagealiases = data.query.specialpagealiases; |
|||
}); |
|||
} |
|||
function setTitleBase() { |
|||
const protocol = window.popupLocalDebug ? 'http:' : location.protocol; |
|||
pg.wiki.articlePath = mw.config.get('wgArticlePath').replace(/\/\$1/, ''); // as in http://some.thing.com/wiki/Article |
|||
pg.wiki.botInterfacePath = mw.config.get('wgScript'); |
|||
pg.wiki.APIPath = mw.config.get('wgScriptPath') + '/api.php'; |
|||
// default mediawiki setting is paths like http://some.thing.com/articlePath/index.php?title=foo |
|||
const titletail = pg.wiki.botInterfacePath + '?title='; |
|||
//var titletail2 = joinPath([pg.wiki.botInterfacePath, 'wiki.phtml?title=']); |
|||
// other sites may need to add code here to set titletail depending on how their urls work |
|||
pg.wiki.titlebase = protocol + '//' + pg.wiki.sitebase + titletail; |
|||
//pg.wiki.titlebase2 = protocol + '//' + joinPath([pg.wiki.sitebase, titletail2]); |
|||
pg.wiki.wikibase = protocol + '//' + pg.wiki.sitebase + pg.wiki.botInterfacePath; |
|||
pg.wiki.apiwikibase = protocol + '//' + pg.wiki.sitebase + pg.wiki.APIPath; |
|||
pg.wiki.articlebase = protocol + '//' + pg.wiki.sitebase + pg.wiki.articlePath; |
|||
pg.wiki.commonsbase = protocol + '//' + pg.wiki.commons + pg.wiki.botInterfacePath; |
|||
pg.wiki.apicommonsbase = protocol + '//' + pg.wiki.commons + pg.wiki.APIPath; |
|||
pg.re.basenames = RegExp( |
|||
'^(' + |
|||
map(literalizeRegex, [ |
|||
pg.wiki.titlebase, //pg.wiki.titlebase2, |
|||
pg.wiki.articlebase, |
|||
]).join('|') + |
|||
')' |
|||
); |
|||
} |
|||
////////////////////////////////////////////////// |
|||
// Global regexps |
|||
function setMainRegex() { |
|||
const reStart = '[^:]*://'; |
|||
let preTitles = |
|||
// Take customizable wgScript into account (it isn't guaranteed to be index.php) |
|||
'(?:' + literalizeRegex(mw.config.get('wgScript')) + '|' + |
|||
// handle index.php (likely to work even if different from wgScript) and legacy wiki.phtml |
|||
literalizeRegex(mw.config.get('wgScriptPath')) + '/(?:index[.]php|wiki[.]phtml))'; |
|||
preTitles += '[?]title=|' + literalizeRegex(pg.wiki.articlePath + '/'); |
|||
const reEnd = '(' + preTitles + ')([^&?#]*)[^#]*(?:#(.+))?'; |
|||
pg.re.main = RegExp(reStart + literalizeRegex(pg.wiki.sitebase) + reEnd); |
|||
} |
|||
function buildSpecialPageGroup(specialPageObj) { |
|||
const variants = []; |
|||
variants.push(mw.util.escapeRegExp(specialPageObj.realname)); |
|||
variants.push(mw.util.escapeRegExp(encodeURI(specialPageObj.realname))); |
|||
specialPageObj.aliases.forEach((alias) => { |
|||
variants.push(mw.util.escapeRegExp(alias)); |
|||
variants.push(mw.util.escapeRegExp(encodeURI(alias))); |
|||
}); |
|||
return variants.join('|'); |
|||
} |
|||
function setRegexps() { |
|||
setMainRegex(); |
|||
const sp = nsRe(pg.nsSpecialId); |
|||
pg.re.urlNoPopup = RegExp('((title=|/)' + sp + '(?:%3A|:)|section=[0-9]|^#$)'); |
|||
pg.wiki.specialpagealiases.forEach((specialpage) => { |
|||
if (specialpage.realname === 'Contributions') { |
|||
pg.re.contribs = RegExp( |
|||
'(title=|/)' + |
|||
sp + |
|||
'(?:%3A|:)(?:' + |
|||
buildSpecialPageGroup(specialpage) + |
|||
')' + |
|||
'(&target=|/|/' + |
|||
nsRe(pg.nsUserId) + |
|||
':)(.*)', |
|||
'i' |
|||
); |
|||
} else if (specialpage.realname === 'Diff') { |
|||
pg.re.specialdiff = RegExp( |
|||
'/' + sp + '(?:%3A|:)(?:' + buildSpecialPageGroup(specialpage) + ')/([^?#]*)', |
|||
'i' |
|||
); |
|||
} else if (specialpage.realname === 'Emailuser') { |
|||
pg.re.email = RegExp( |
|||
'(title=|/)' + |
|||
sp + |
|||
'(?:%3A|:)(?:' + |
|||
buildSpecialPageGroup(specialpage) + |
|||
')' + |
|||
'(&target=|/|/(?:' + |
|||
nsRe(pg.nsUserId) + |
|||
':)?)(.*)', |
|||
'i' |
|||
); |
|||
} else if (specialpage.realname === 'Whatlinkshere') { |
|||
pg.re.backlinks = RegExp( |
|||
'(title=|/)' + |
|||
sp + |
|||
'(?:%3A|:)(?:' + |
|||
buildSpecialPageGroup(specialpage) + |
|||
')' + |
|||
'(&target=|/)([^&]*)', |
|||
'i' |
|||
); |
|||
} |
|||
}); |
|||
const im = nsReImage(); |
|||
// note: tries to get images in infobox templates too, e.g. movie pages, album pages etc |
|||
// (^|\[\[)image: *([^|\]]*[^|\] ]) * |
|||
// (^|\[\[)image: *([^|\]]*[^|\] ])([^0-9\]]*([0-9]+) *px)? |
|||
// $4 = 120 as in 120px |
|||
pg.re.image = RegExp( |
|||
'(^|\\[\\[)' + |
|||
im + |
|||
': *([^|\\]]*[^|\\] ])' + |
|||
'([^0-9\\]]*([0-9]+) *px)?|(?:\\n *[|]?|[|]) *' + |
|||
'(' + |
|||
getValueOf('popupImageVarsRegexp') + |
|||
')' + |
|||
' *= *(?:\\[\\[ *)?(?:' + |
|||
im + |
|||
':)?' + |
|||
'([^|]*?)(?:\\]\\])? *[|]? *\\n', |
|||
'img' |
|||
); |
|||
pg.re.imageBracketCount = 6; |
|||
pg.re.category = RegExp('\\[\\[' + nsRe(pg.nsCategoryId) + ': *([^|\\]]*[^|\\] ]) *', 'i'); |
|||
pg.re.categoryBracketCount = 1; |
|||
pg.re.ipUser = RegExp( |
|||
'^' + |
|||
// IPv6 |
|||
'(?::(?::|(?::[0-9A-Fa-f]{1,4}){1,7})|[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4}){0,6}::|[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4}){7})' + |
|||
// IPv4 |
|||
'|(((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}' + |
|||
'(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9]))$' |
|||
); |
|||
pg.re.stub = RegExp(getValueOf('popupStubRegexp'), 'im'); |
|||
pg.re.disambig = RegExp(getValueOf('popupDabRegexp'), 'im'); |
|||
// FIXME replace with general parameter parsing function, this is daft |
|||
pg.re.oldid = /[?&]oldid=([^&]*)/; |
|||
pg.re.diff = /[?&]diff=([^&]*)/; |
|||
} |
|||
////////////////////////////////////////////////// |
|||
// miscellany |
|||
function setupCache() { |
|||
// page caching |
|||
pg.cache.pages = []; |
|||
} |
|||
function setMisc() { |
|||
pg.current.link = null; |
|||
pg.current.links = []; |
|||
pg.current.linksHash = {}; |
|||
setupCache(); |
|||
pg.timer.checkPopupPosition = null; |
|||
pg.counter.loop = 0; |
|||
// ids change with each popup: popupImage0, popupImage1 etc |
|||
pg.idNumber = 0; |
|||
// for myDecodeURI |
|||
pg.misc.decodeExtras = [ |
|||
{ from: '%2C', to: ',' }, |
|||
{ from: '_', to: ' ' }, |
|||
{ from: '%24', to: '$' }, |
|||
{ from: '%26', to: '&' }, // no , |
|||
]; |
|||
} |
|||
function getMwApi() { |
|||
if (!pg.api.client) { |
|||
pg.api.userAgent = 'Navigation popups/1.0 (' + mw.config.get('wgServerName') + ')'; |
|||
pg.api.client = new mw.Api({ |
|||
ajax: { |
|||
headers: { |
|||
'Api-User-Agent': pg.api.userAgent, |
|||
}, |
|||
}, |
|||
}); |
|||
} |
|||
return pg.api.client; |
|||
} |
|||
// We need a callback since this might end up asynchronous because of |
|||
// the mw.loader.using() call. |
|||
function setupPopups(callback) { |
|||
if (setupPopups.completed) { |
|||
if (typeof callback === 'function') { |
|||
callback(); |
|||
} |
|||
return; |
|||
} |
|||
// These dependencies should alse be enforced from the gadget, |
|||
// but not everyone loads this as a gadget, so double check |
|||
mw.loader |
|||
.using([ |
|||
'mediawiki.util', |
|||
'mediawiki.api', |
|||
'mediawiki.user', |
|||
'user.options', |
|||
'mediawiki.jqueryMsg', |
|||
]) |
|||
.then(fetchSpecialPageNames) |
|||
.then(() => { |
|||
// NB translatable strings should be set up first (strings.js) |
|||
// basics |
|||
setupDebugging(); |
|||
setSiteInfo(); |
|||
setTitleBase(); |
|||
setOptions(); // see options.js |
|||
setUserInfo(); |
|||
// namespaces etc |
|||
setNamespaces(); |
|||
setInterwiki(); |
|||
// regexps |
|||
setRegexps(); |
|||
setRedirs(); |
|||
// other stuff |
|||
setMisc(); |
|||
setupLivePreview(); |
|||
// main deal here |
|||
setupTooltips(); |
|||
log('In setupPopups(), just called setupTooltips()'); |
|||
Navpopup.tracker.enable(); |
|||
setupPopups.completed = true; |
|||
if (typeof callback === 'function') { |
|||
callback(); |
|||
} |
|||
}); |
|||
} |
|||
// ENDFILE: init.js |
|||
// STARTFILE: navlinks.js |
|||
////////////////////////////////////////////////// |
|||
// navlinks... let the fun begin |
|||
// |
|||
function defaultNavlinkSpec() { |
|||
let str = ''; |
|||
str += '<b><<mainlink|shortcut= >></b>'; |
|||
if (getValueOf('popupLastEditLink')) { |
|||
str += |
|||
'*<<lastEdit|shortcut=/>>|<<lastContrib>>|<<sinceMe>>if(oldid){|<<oldEdit>>|<<diffCur>>}'; |
|||
} |
|||
// user links |
|||
// contribs - log - count - email - block |
|||
// count only if applicable; block only if popupAdminLinks |
|||
str += 'if(user){<br><<contribs|shortcut=c>>*<<userlog|shortcut=L|log>>'; |
|||
str += 'if(ipuser){*<<arin>>}if(wikimedia){*<<count|shortcut=#>>}'; |
|||
str += |
|||
'if(ipuser){}else{*<<email|shortcut=E>>}if(admin){*<<block|shortcut=b>>|<<blocklog|log>>}}'; |
|||
// editing links |
|||
// talkpage -> edit|new - history - un|watch - article|edit |
|||
// other page -> edit - history - un|watch - talk|edit|new |
|||
const editstr = '<<edit|shortcut=e>>'; |
|||
const editOldidStr = |
|||
'if(oldid){<<editOld|shortcut=e>>|<<revert|shortcut=v|rv>>|<<edit|cur>>}else{' + |
|||
editstr + |
|||
'}'; |
|||
const historystr = '<<history|shortcut=h>>|<<editors|shortcut=E|>>'; |
|||
const watchstr = '<<unwatch|unwatchShort>>|<<watch|shortcut=w|watchThingy>>'; |
|||
str += |
|||
'<br>if(talk){' + |
|||
editOldidStr + |
|||
'|<<new|shortcut=+>>' + |
|||
'*' + |
|||
historystr + |
|||
'*' + |
|||
watchstr + |
|||
'*' + |
|||
'<b><<article|shortcut=a>></b>|<<editArticle|edit>>' + |
|||
'}else{' + // not a talk page |
|||
editOldidStr + |
|||
'*' + |
|||
historystr + |
|||
'*' + |
|||
watchstr + |
|||
'*' + |
|||
'<b><<talk|shortcut=t>></b>|<<editTalk|edit>>|<<newTalk|shortcut=+|new>>}'; |
|||
// misc links |
|||
str += '<br><<whatLinksHere|shortcut=l>>*<<relatedChanges|shortcut=r>>*<<move|shortcut=m>>'; |
|||
// admin links |
|||
str += |
|||
'if(admin){<br><<unprotect|unprotectShort>>|<<protect|shortcut=p>>|<<protectlog|log>>*' + |
|||
'<<undelete|undeleteShort>>|<<delete|shortcut=d>>|<<deletelog|log>>}'; |
|||
return str; |
|||
} |
|||
function navLinksHTML(article, hint, params) { |
|||
//oldid, rcid) { |
|||
const str = '<span class="popupNavLinks">' + defaultNavlinkSpec() + '</span>'; |
|||
// BAM |
|||
return navlinkStringToHTML(str, article, params); |
|||
} |
|||
function expandConditionalNavlinkString(s, article, z, recursionCount) { |
|||
const oldid = z.oldid, |
|||
rcid = z.rcid, |
|||
diff = z.diff; |
|||
// nested conditionals (up to 10 deep) are ok, hopefully! (work from the inside out) |
|||
if (typeof recursionCount != typeof 0) { |
|||
recursionCount = 0; |
|||
} |
|||
const conditionalSplitRegex = RegExp( |
|||
//(1 if \\( (2 2) \\) {(3 3)} (4 else {(5 5)} 4)1) |
|||
'(;?\\s*if\\s*\\(\\s*([\\w]*)\\s*\\)\\s*\\{([^{}]*)\\}(\\s*else\\s*\\{([^{}]*?)\\}|))', |
|||
'i' |
|||
); |
|||
const splitted = s.parenSplit(conditionalSplitRegex); |
|||
// $1: whole conditional |
|||
// $2: test condition |
|||
// $3: true expansion |
|||
// $4: else clause (possibly empty) |
|||
// $5: false expansion (possibly null) |
|||
const numParens = 5; |
|||
let ret = splitted[0]; |
|||
for (let i = 1; i < splitted.length; i = i + numParens + 1) { |
|||
const testString = splitted[i + 2 - 1]; |
|||
const trueString = splitted[i + 3 - 1]; |
|||
let falseString = splitted[i + 5 - 1]; |
|||
if (typeof falseString == 'undefined' || !falseString) { |
|||
falseString = ''; |
|||
} |
|||
let testResult = null; |
|||
switch (testString) { |
|||
case 'user': |
|||
testResult = !!article.userName(); |
|||
break; |
|||
case 'talk': |
|||
testResult = !article.talkPage(); // talkPage converts _articles_ to talkPages |
|||
break; |
|||
case 'admin': |
|||
testResult = !!getValueOf('popupAdminLinks'); |
|||
break; |
|||
case 'oldid': |
|||
testResult = !!(typeof oldid != 'undefined' && oldid); |
|||
break; |
|||
case 'rcid': |
|||
testResult = !!(typeof rcid != 'undefined' && rcid); |
|||
break; |
|||
case 'ipuser': |
|||
testResult = !!article.isIpUser(); |
|||
break; |
|||
case 'mainspace_en': |
|||
testResult = isInMainNamespace(article) && pg.wiki.hostname == 'en.wikipedia.org'; |
|||
break; |
|||
case 'wikimedia': |
|||
testResult = !!pg.wiki.wikimedia; |
|||
break; |
|||
case 'diff': |
|||
testResult = !!(typeof diff != 'undefined' && diff); |
|||
break; |
|||
} |
|||
switch (testResult) { |
|||
case null: |
|||
ret += splitted[i]; |
|||
break; |
|||
case true: |
|||
ret += trueString; |
|||
break; |
|||
case false: |
|||
ret += falseString; |
|||
break; |
|||
} |
|||
// append non-conditional string |
|||
ret += splitted[i + numParens]; |
|||
} |
|||
if (conditionalSplitRegex.test(ret) && recursionCount < 10) { |
|||
return expandConditionalNavlinkString(ret, article, z, recursionCount + 1); |
|||
} |
|||
return ret; |
|||
} |
|||
function navlinkStringToArray(s, article, params) { |
|||
s = expandConditionalNavlinkString(s, article, params); |
|||
const splitted = s.parenSplit(/<<(.*?)>>/); |
|||
const ret = []; |
|||
for (let i = 0; i < splitted.length; ++i) { |
|||
if (i % 2) { |
|||
// i odd, so s is a tag |
|||
const t = new navlinkTag(); |
|||
const ss = splitted[i].split('|'); |
|||
t.id = ss[0]; |
|||
for (let j = 1; j < ss.length; ++j) { |
|||
const sss = ss[j].split('='); |
|||
if (sss.length > 1) { |
|||
t[sss[0]] = sss[1]; |
|||
} else { |
|||
// no assignment (no "="), so treat this as a title (overwriting the last one) |
|||
t.text = popupString(sss[0]); |
|||
} |
|||
} |
|||
t.article = article; |
|||
const oldid = params.oldid, |
|||
rcid = params.rcid, |
|||
diff = params.diff; |
|||
if (typeof oldid !== 'undefined' && oldid !== null) { |
|||
t.oldid = oldid; |
|||
} |
|||
if (typeof rcid !== 'undefined' && rcid !== null) { |
|||
t.rcid = rcid; |
|||
} |
|||
if (typeof diff !== 'undefined' && diff !== null) { |
|||
t.diff = diff; |
|||
} |
|||
if (!t.text && t.id !== 'mainlink') { |
|||
t.text = popupString(t.id); |
|||
} |
|||
ret.push(t); |
|||
} else { |
|||
// plain HTML |
|||
ret.push(splitted[i]); |
|||
} |
|||
} |
|||
return ret; |
|||
} |
|||
function navlinkSubstituteHTML(s) { |
|||
return s |
|||
.split('*') |
|||
.join(getValueOf('popupNavLinkSeparator')) |
|||
.split('<menurow>') |
|||
.join('<li class="popup_menu_row">') |
|||
.split('</menurow>') |
|||
.join('</li>') |
|||
.split('<menu>') |
|||
.join('<ul class="popup_menu">') |
|||
.split('</menu>') |
|||
.join('</ul>'); |
|||
} |
|||
function navlinkDepth(magic, s) { |
|||
return s.split('<' + magic + '>').length - s.split('</' + magic + '>').length; |
|||
} |
|||
// navlinkString: * becomes the separator |
|||
// <<foo|bar=baz|fubar>> becomes a foo-link with attribute bar='baz' |
|||
// and visible text 'fubar' |
|||
// if(test){...} and if(test){...}else{...} work too (nested ok) |
|||
function navlinkStringToHTML(s, article, params) { |
|||
//limitAlert(navlinkStringToHTML, 5, 'navlinkStringToHTML\n' + article + '\n' + (typeof article)); |
|||
const p = navlinkStringToArray(s, article, params); |
|||
let html = ''; |
|||
let menudepth = 0; // nested menus not currently allowed, but doesn't do any harm to code for it |
|||
let menurowdepth = 0; |
|||
for (let i = 0; i < p.length; ++i) { |
|||
if (typeof p[i] == typeof '') { |
|||
html += navlinkSubstituteHTML(p[i]); |
|||
menudepth += navlinkDepth('menu', p[i]); |
|||
menurowdepth += navlinkDepth('menurow', p[i]); |
|||
// if (menudepth === 0) { |
|||
// tagType='span'; |
|||
// } else if (menurowdepth === 0) { |
|||
// tagType='li'; |
|||
// } else { |
|||
// tagType = null; |
|||
// } |
|||
} else if (typeof p[i].type != 'undefined' && p[i].type == 'navlinkTag') { |
|||
if (menudepth > 0 && menurowdepth === 0) { |
|||
html += '<li class="popup_menu_item">' + p[i].html() + '</li>'; |
|||
} else { |
|||
html += p[i].html(); |
|||
} |
|||
} |
|||
} |
|||
return html; |
|||
} |
|||
function navlinkTag() { |
|||
this.type = 'navlinkTag'; |
|||
} |
|||
navlinkTag.prototype.html = function () { |
|||
this.getNewWin(); |
|||
this.getPrintFunction(); |
|||
let html = ''; |
|||
let opening, closing; |
|||
const tagType = 'span'; |
|||
if (!tagType) { |
|||
opening = ''; |
|||
closing = ''; |
|||
} else { |
|||
opening = '<' + tagType + ' class="popup_' + this.id + '">'; |
|||
closing = '</' + tagType + '>'; |
|||
} |
|||
if (typeof this.print != 'function') { |
|||
errlog('Oh dear - invalid print function for a navlinkTag, id=' + this.id); |
|||
} else { |
|||
html = this.print(this); |
|||
if (typeof html != typeof '') { |
|||
html = ''; |
|||
} else if (typeof this.shortcut != 'undefined') { |
|||
html = addPopupShortcut(html, this.shortcut); |
|||
} |
|||
} |
|||
return opening + html + closing; |
|||
}; |
|||
navlinkTag.prototype.getNewWin = function () { |
|||
getValueOf('popupLinksNewWindow'); |
|||
if (typeof pg.option.popupLinksNewWindow[this.id] === 'undefined') { |
|||
this.newWin = null; |
|||
} |
|||
this.newWin = pg.option.popupLinksNewWindow[this.id]; |
|||
}; |
|||
navlinkTag.prototype.getPrintFunction = function () { |
|||
//think about this some more |
|||
// this.id and this.article should already be defined |
|||
if (typeof this.id != typeof '' || typeof this.article != typeof {}) { |
|||
return; |
|||
} |
|||
this.noPopup = 1; |
|||
switch (this.id) { |
|||
case 'contribs': |
|||
case 'history': |
|||
case 'whatLinksHere': |
|||
case 'userPage': |
|||
case 'monobook': |
|||
case 'userTalk': |
|||
case 'talk': |
|||
case 'article': |
|||
case 'lastEdit': |
|||
this.noPopup = null; |
|||
} |
|||
switch (this.id) { |
|||
case 'email': |
|||
case 'contribs': |
|||
case 'block': |
|||
case 'unblock': |
|||
case 'userlog': |
|||
case 'userSpace': |
|||
case 'deletedContribs': |
|||
this.article = this.article.userName(); |
|||
} |
|||
switch (this.id) { |
|||
case 'userTalk': |
|||
case 'newUserTalk': |
|||
case 'editUserTalk': |
|||
case 'userPage': |
|||
case 'monobook': |
|||
case 'editMonobook': |
|||
case 'blocklog': |
|||
this.article = this.article.userName(true); |
|||
/* fall through */ |
|||
case 'pagelog': |
|||
case 'deletelog': |
|||
case 'protectlog': |
|||
delete this.oldid; |
|||
} |
|||
if (this.id == 'editMonobook' || this.id == 'monobook') { |
|||
this.article.append('/monobook.js'); |
|||
} |
|||
if (this.id != 'mainlink') { |
|||
// FIXME anchor handling should be done differently with Title object |
|||
this.article = this.article.removeAnchor(); |
|||
// if (typeof this.text=='undefined') this.text=popupString(this.id); |
|||
} |
|||
switch (this.id) { |
|||
case 'undelete': |
|||
this.print = specialLink; |
|||
this.specialpage = 'Undelete'; |
|||
this.sep = '/'; |
|||
break; |
|||
case 'whatLinksHere': |
|||
this.print = specialLink; |
|||
this.specialpage = 'Whatlinkshere'; |
|||
break; |
|||
case 'relatedChanges': |
|||
this.print = specialLink; |
|||
this.specialpage = 'Recentchangeslinked'; |
|||
break; |
|||
case 'move': |
|||
this.print = specialLink; |
|||
this.specialpage = 'Movepage'; |
|||
break; |
|||
case 'contribs': |
|||
this.print = specialLink; |
|||
this.specialpage = 'Contributions'; |
|||
break; |
|||
case 'deletedContribs': |
|||
this.print = specialLink; |
|||
this.specialpage = 'Deletedcontributions'; |
|||
break; |
|||
case 'email': |
|||
this.print = specialLink; |
|||
this.specialpage = 'EmailUser'; |
|||
this.sep = '/'; |
|||
break; |
|||
case 'block': |
|||
this.print = specialLink; |
|||
this.specialpage = 'Blockip'; |
|||
this.sep = '&ip='; |
|||
break; |
|||
case 'unblock': |
|||
this.print = specialLink; |
|||
this.specialpage = 'Ipblocklist'; |
|||
this.sep = '&action=unblock&ip='; |
|||
break; |
|||
case 'userlog': |
|||
this.print = specialLink; |
|||
this.specialpage = 'Log'; |
|||
this.sep = '&user='; |
|||
break; |
|||
case 'blocklog': |
|||
this.print = specialLink; |
|||
this.specialpage = 'Log'; |
|||
this.sep = '&type=block&page='; |
|||
break; |
|||
case 'pagelog': |
|||
this.print = specialLink; |
|||
this.specialpage = 'Log'; |
|||
this.sep = '&page='; |
|||
break; |
|||
case 'protectlog': |
|||
this.print = specialLink; |
|||
this.specialpage = 'Log'; |
|||
this.sep = '&type=protect&page='; |
|||
break; |
|||
case 'deletelog': |
|||
this.print = specialLink; |
|||
this.specialpage = 'Log'; |
|||
this.sep = '&type=delete&page='; |
|||
break; |
|||
case 'userSpace': |
|||
this.print = specialLink; |
|||
this.specialpage = 'PrefixIndex'; |
|||
this.sep = '&namespace=2&prefix='; |
|||
break; |
|||
case 'search': |
|||
this.print = specialLink; |
|||
this.specialpage = 'Search'; |
|||
this.sep = '&fulltext=Search&search='; |
|||
break; |
|||
case 'thank': |
|||
this.print = specialLink; |
|||
this.specialpage = 'Thanks'; |
|||
this.sep = '/'; |
|||
this.article.value = this.diff !== 'prev' ? this.diff : this.oldid; |
|||
break; |
|||
case 'unwatch': |
|||
case 'watch': |
|||
this.print = magicWatchLink; |
|||
this.action = |
|||
this.id + |
|||
'&autowatchlist=1&autoimpl=' + |
|||
popupString('autoedit_version') + |
|||
'&actoken=' + |
|||
autoClickToken(); |
|||
break; |
|||
case 'history': |
|||
case 'historyfeed': |
|||
case 'unprotect': |
|||
case 'protect': |
|||
this.print = wikiLink; |
|||
this.action = this.id; |
|||
break; |
|||
case 'delete': |
|||
this.print = wikiLink; |
|||
this.action = 'delete'; |
|||
if (this.article.namespaceId() == pg.nsImageId) { |
|||
const img = this.article.stripNamespace(); |
|||
this.action += '&image=' + img; |
|||
} |
|||
break; |
|||
case 'markpatrolled': |
|||
case 'edit': // editOld should keep the oldid, but edit should not. |
|||
delete this.oldid; |
|||
/* fall through */ |
|||
case 'view': |
|||
case 'purge': |
|||
case 'render': |
|||
this.print = wikiLink; |
|||
this.action = this.id; |
|||
break; |
|||
case 'raw': |
|||
this.print = wikiLink; |
|||
this.action = 'raw'; |
|||
break; |
|||
case 'new': |
|||
this.print = wikiLink; |
|||
this.action = 'edit§ion=new'; |
|||
break; |
|||
case 'mainlink': |
|||
if (typeof this.text == 'undefined') { |
|||
this.text = this.article.toString().entify(); |
|||
} |
|||
if (getValueOf('popupSimplifyMainLink') && isInStrippableNamespace(this.article)) { |
|||
// only show the /subpage part of the title text |
|||
const s = this.text.split('/'); |
|||
this.text = s[s.length - 1]; |
|||
if (this.text === '' && s.length > 1) { |
|||
this.text = s[s.length - 2]; |
|||
} |
|||
} |
|||
this.print = titledWikiLink; |
|||
if ( |
|||
typeof this.title === 'undefined' && |
|||
pg.current.link && |
|||
typeof pg.current.link.href !== 'undefined' |
|||
) { |
|||
this.title = safeDecodeURI( |
|||
pg.current.link.originalTitle ? pg.current.link.originalTitle : this.article |
|||
); |
|||
if (typeof this.oldid !== 'undefined' && this.oldid) { |
|||
this.title = tprintf('Revision %s of %s', [this.oldid, this.title]); |
|||
} |
|||
} |
|||
this.action = 'view'; |
|||
break; |
|||
case 'userPage': |
|||
case 'article': |
|||
case 'monobook': |
|||
case 'editMonobook': |
|||
case 'editArticle': |
|||
delete this.oldid; |
|||
//alert(this.id+'\n'+this.article + '\n'+ typeof this.article); |
|||
this.article = this.article.articleFromTalkOrArticle(); |
|||
//alert(this.id+'\n'+this.article + '\n'+ typeof this.article); |
|||
this.print = wikiLink; |
|||
if (this.id.indexOf('edit') === 0) { |
|||
this.action = 'edit'; |
|||
} else { |
|||
this.action = 'view'; |
|||
} |
|||
break; |
|||
case 'userTalk': |
|||
case 'talk': |
|||
this.article = this.article.talkPage(); |
|||
delete this.oldid; |
|||
this.print = wikiLink; |
|||
this.action = 'view'; |
|||
break; |
|||
case 'arin': |
|||
this.print = arinLink; |
|||
break; |
|||
case 'count': |
|||
this.print = editCounterLink; |
|||
break; |
|||
case 'google': |
|||
this.print = googleLink; |
|||
break; |
|||
case 'editors': |
|||
this.print = editorListLink; |
|||
break; |
|||
case 'globalsearch': |
|||
this.print = globalSearchLink; |
|||
break; |
|||
case 'lastEdit': |
|||
this.print = titledDiffLink; |
|||
this.title = popupString('Show the last edit'); |
|||
this.from = 'prev'; |
|||
this.to = 'cur'; |
|||
break; |
|||
case 'oldEdit': |
|||
this.print = titledDiffLink; |
|||
this.title = popupString('Show the edit made to get revision') + ' ' + this.oldid; |
|||
this.from = 'prev'; |
|||
this.to = this.oldid; |
|||
break; |
|||
case 'editOld': |
|||
this.print = wikiLink; |
|||
this.action = 'edit'; |
|||
break; |
|||
case 'undo': |
|||
this.print = wikiLink; |
|||
this.action = 'edit&undo='; |
|||
break; |
|||
case 'revert': |
|||
this.print = wikiLink; |
|||
this.action = 'revert'; |
|||
break; |
|||
case 'nullEdit': |
|||
this.print = wikiLink; |
|||
this.action = 'nullEdit'; |
|||
break; |
|||
case 'diffCur': |
|||
this.print = titledDiffLink; |
|||
this.title = tprintf('Show changes since revision %s', [this.oldid]); |
|||
this.from = this.oldid; |
|||
this.to = 'cur'; |
|||
break; |
|||
case 'editUserTalk': |
|||
case 'editTalk': |
|||
delete this.oldid; |
|||
this.article = this.article.talkPage(); |
|||
this.action = 'edit'; |
|||
this.print = wikiLink; |
|||
break; |
|||
case 'newUserTalk': |
|||
case 'newTalk': |
|||
this.article = this.article.talkPage(); |
|||
this.action = 'edit§ion=new'; |
|||
this.print = wikiLink; |
|||
break; |
|||
case 'lastContrib': |
|||
case 'sinceMe': |
|||
this.print = magicHistoryLink; |
|||
break; |
|||
case 'togglePreviews': |
|||
this.text = popupString(pg.option.simplePopups ? 'enable previews' : 'disable previews'); |
|||
/* fall through */ |
|||
case 'disablePopups': |
|||
case 'purgePopups': |
|||
this.print = popupMenuLink; |
|||
break; |
|||
default: |
|||
this.print = function () { |
|||
return 'Unknown navlink type: ' + String(this.id); |
|||
}; |
|||
} |
|||
}; |
|||
// |
|||
// end navlinks |
|||
////////////////////////////////////////////////// |
|||
// ENDFILE: navlinks.js |
|||
// STARTFILE: shortcutkeys.js |
|||
function popupHandleKeypress(evt) { |
|||
const keyCode = window.event ? window.event.keyCode : evt.keyCode ? evt.keyCode : evt.which; |
|||
if (!keyCode || !pg.current.link || !pg.current.link.navpopup) { |
|||
return; |
|||
} |
|||
if (keyCode == 27) { |
|||
// escape |
|||
killPopup(); |
|||
return false; // swallow keypress |
|||
} |
|||
const letter = String.fromCharCode(keyCode); |
|||
const links = pg.current.link.navpopup.mainDiv.getElementsByTagName('A'); |
|||
let startLink = 0; |
|||
let i, j; |
|||
if (popupHandleKeypress.lastPopupLinkSelected) { |
|||
for (i = 0; i < links.length; ++i) { |
|||
if (links[i] == popupHandleKeypress.lastPopupLinkSelected) { |
|||
startLink = i; |
|||
} |
|||
} |
|||
} |
|||
for (j = 0; j < links.length; ++j) { |
|||
i = (startLink + j + 1) % links.length; |
|||
if (links[i].getAttribute('popupkey') == letter) { |
|||
if (evt && evt.preventDefault) { |
|||
evt.preventDefault(); |
|||
} |
|||
links[i].focus(); |
|||
popupHandleKeypress.lastPopupLinkSelected = links[i]; |
|||
return false; // swallow keypress |
|||
} |
|||
} |
|||
// pass keypress on |
|||
if (document.oldPopupOnkeypress) { |
|||
return document.oldPopupOnkeypress(evt); |
|||
} |
|||
return true; |
|||
} |
|||
function addPopupShortcuts() { |
|||
if (document.onkeypress != popupHandleKeypress) { |
|||
document.oldPopupOnkeypress = document.onkeypress; |
|||
} |
|||
document.onkeypress = popupHandleKeypress; |
|||
} |
|||
function rmPopupShortcuts() { |
|||
popupHandleKeypress.lastPopupLinkSelected = null; |
|||
try { |
|||
if (document.oldPopupOnkeypress && document.oldPopupOnkeypress == popupHandleKeypress) { |
|||
// panic |
|||
document.onkeypress = null; //function () {}; |
|||
return; |
|||
} |
|||
document.onkeypress = document.oldPopupOnkeypress; |
|||
} catch (nasties) { |
|||
/* IE goes here */ |
|||
} |
|||
} |
|||
function addLinkProperty(html, property) { |
|||
// take "<a href=...>...</a> and add a property |
|||
// not sophisticated at all, easily broken |
|||
const i = html.indexOf('>'); |
|||
if (i < 0) { |
|||
return html; |
|||
} |
|||
return html.substring(0, i) + ' ' + property + html.substring(i); |
|||
} |
|||
function addPopupShortcut(html, key) { |
|||
if (!getValueOf('popupShortcutKeys')) { |
|||
return html; |
|||
} |
|||
const ret = addLinkProperty(html, 'popupkey="' + key + '"'); |
|||
if (key == ' ') { |
|||
key = popupString('spacebar'); |
|||
} |
|||
return ret.replace(/^(.*?)(title=")(.*?)(".*)$/i, '$1$2$3 [' + key + ']$4'); |
|||
} |
|||
// ENDFILE: shortcutkeys.js |
|||
// STARTFILE: diffpreview.js |
|||
/** |
|||
* Load diff data. |
|||
* |
|||
* lets jump through hoops to find the rev ids we need to retrieve |
|||
* |
|||
* @param {Title} article |
|||
* @param {string} oldid |
|||
* @param {string} diff |
|||
* @param {Navpopup} navpop |
|||
*/ |
|||
function loadDiff(article, oldid, diff, navpop) { |
|||
navpop.diffData = { oldRev: {}, newRev: {} }; |
|||
mw.loader.using('mediawiki.api').then(() => { |
|||
const api = getMwApi(); |
|||
const params = { |
|||
action: 'compare', |
|||
prop: 'ids|title', |
|||
}; |
|||
params.fromtitle = article.toString(); |
|||
switch (diff) { |
|||
case 'cur': |
|||
switch (oldid) { |
|||
case null: |
|||
case '': |
|||
case 'prev': |
|||
// this can only work if we have the title |
|||
// cur -> prev |
|||
params.torelative = 'prev'; |
|||
break; |
|||
default: |
|||
params.fromrev = oldid; |
|||
params.torelative = 'cur'; |
|||
break; |
|||
} |
|||
break; |
|||
case 'prev': |
|||
if (oldid && oldid !== 'cur') { |
|||
params.fromrev = oldid; |
|||
} |
|||
params.torelative = 'prev'; |
|||
break; |
|||
case 'next': |
|||
params.fromrev = oldid || 0; |
|||
params.torelative = 'next'; |
|||
break; |
|||
default: |
|||
params.fromrev = oldid || 0; |
|||
params.torev = diff || 0; |
|||
break; |
|||
} |
|||
api.get(params).then((data) => { |
|||
navpop.diffData.oldRev.revid = data.compare.fromrevid; |
|||
navpop.diffData.newRev.revid = data.compare.torevid; |
|||
addReviewLink(navpop, 'popupMiscTools'); |
|||
const go = function () { |
|||
pendingNavpopTask(navpop); |
|||
let url = pg.wiki.apiwikibase + '?format=json&formatversion=2&action=query&'; |
|||
url += 'revids=' + navpop.diffData.oldRev.revid + '|' + navpop.diffData.newRev.revid; |
|||
url += '&prop=revisions&rvslots=main&rvprop=ids|timestamp|content'; |
|||
getPageWithCaching(url, doneDiff, navpop); |
|||
return true; // remove hook once run |
|||
}; |
|||
if (navpop.visible || !getValueOf('popupLazyDownloads')) { |
|||
go(); |
|||
} else { |
|||
navpop.addHook(go, 'unhide', 'before', 'DOWNLOAD_DIFFS'); |
|||
} |
|||
}); |
|||
}); |
|||
} |
|||
// Put a "mark patrolled" link to an element target |
|||
// TODO: Allow patrol a revision, as well as a diff |
|||
function addReviewLink(navpop, target) { |
|||
if (!pg.user.canReview) { |
|||
return; |
|||
} |
|||
// If 'newRev' is older than 'oldRev' than it could be confusing, so we do not show the review link. |
|||
if (navpop.diffData.newRev.revid <= navpop.diffData.oldRev.revid) { |
|||
return; |
|||
} |
|||
const params = { |
|||
action: 'query', |
|||
prop: 'info|flagged', |
|||
revids: navpop.diffData.oldRev.revid, |
|||
formatversion: 2, |
|||
}; |
|||
getMwApi() |
|||
.get(params) |
|||
.then((data) => { |
|||
const stable_revid = |
|||
(data.query.pages[0].flagged && data.query.pages[0].flagged.stable_revid) || 0; |
|||
// The diff can be reviewed if the old version is the last reviewed version |
|||
// TODO: Other possible conditions that we may want to implement instead of this one: |
|||
// * old version is patrolled and the new version is not patrolled |
|||
// * old version is patrolled and the new version is more recent than the last reviewed version |
|||
if (stable_revid == navpop.diffData.oldRev.revid) { |
|||
const a = document.createElement('a'); |
|||
a.innerHTML = popupString('mark patrolled'); |
|||
a.title = popupString('markpatrolledHint'); |
|||
a.onclick = function () { |
|||
const params = { |
|||
action: 'review', |
|||
revid: navpop.diffData.newRev.revid, |
|||
comment: tprintf('defaultpopupReviewedSummary', [ |
|||
navpop.diffData.oldRev.revid, |
|||
navpop.diffData.newRev.revid, |
|||
]), |
|||
}; |
|||
getMwApi() |
|||
.postWithToken('csrf', params) |
|||
.done(() => { |
|||
a.style.display = 'none'; |
|||
// TODO: Update current page and other already constructed popups |
|||
}) |
|||
.fail(() => { |
|||
alert(popupString('Could not marked this edit as patrolled')); |
|||
}); |
|||
}; |
|||
setPopupHTML(a, target, navpop.idNumber, null, true); |
|||
} |
|||
}); |
|||
} |
|||
function doneDiff(download) { |
|||
if (!download.owner || !download.owner.diffData) { |
|||
return; |
|||
} |
|||
const navpop = download.owner; |
|||
completedNavpopTask(navpop); |
|||
let pages, |
|||
revisions = []; |
|||
try { |
|||
// Process the downloads |
|||
pages = getJsObj(download.data).query.pages; |
|||
for (var i = 0; i < pages.length; i++) { |
|||
revisions = revisions.concat(pages[i].revisions); |
|||
} |
|||
for (i = 0; i < revisions.length; i++) { |
|||
if (revisions[i].revid == navpop.diffData.oldRev.revid) { |
|||
navpop.diffData.oldRev.revision = revisions[i]; |
|||
} else if (revisions[i].revid == navpop.diffData.newRev.revid) { |
|||
navpop.diffData.newRev.revision = revisions[i]; |
|||
} |
|||
} |
|||
} catch (someError) { |
|||
errlog('Could not get diff'); |
|||
} |
|||
insertDiff(navpop); |
|||
} |
|||
function rmBoringLines(a, b, context) { |
|||
if (typeof context == 'undefined') { |
|||
context = 2; |
|||
} |
|||
// this is fairly slow... i think it's quicker than doing a word-based diff from the off, though |
|||
const aa = [], |
|||
aaa = []; |
|||
const bb = [], |
|||
bbb = []; |
|||
let i, j; |
|||
// first, gather all disconnected nodes in a and all crossing nodes in a and b |
|||
for (i = 0; i < a.length; ++i) { |
|||
if (!a[i].paired) { |
|||
aa[i] = 1; |
|||
} else if (countCrossings(b, a, i, true)) { |
|||
aa[i] = 1; |
|||
bb[a[i].row] = 1; |
|||
} |
|||
} |
|||
// pick up remaining disconnected nodes in b |
|||
for (i = 0; i < b.length; ++i) { |
|||
if (bb[i] == 1) { |
|||
continue; |
|||
} |
|||
if (!b[i].paired) { |
|||
bb[i] = 1; |
|||
} |
|||
} |
|||
// another pass to gather context: we want the neighbours of included nodes which are not |
|||
// yet included we have to add in partners of these nodes, but we don't want to add context |
|||
// for *those* nodes in the next pass |
|||
for (i = 0; i < b.length; ++i) { |
|||
if (bb[i] == 1) { |
|||
for (j = Math.max(0, i - context); j < Math.min(b.length, i + context); ++j) { |
|||
if (!bb[j]) { |
|||
bb[j] = 1; |
|||
aa[b[j].row] = 0.5; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
for (i = 0; i < a.length; ++i) { |
|||
if (aa[i] == 1) { |
|||
for (j = Math.max(0, i - context); j < Math.min(a.length, i + context); ++j) { |
|||
if (!aa[j]) { |
|||
aa[j] = 1; |
|||
bb[a[j].row] = 0.5; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
for (i = 0; i < bb.length; ++i) { |
|||
if (bb[i] > 0) { |
|||
// it's a row we need |
|||
if (b[i].paired) { |
|||
bbb.push(b[i].text); |
|||
} // joined; partner should be in aa |
|||
else { |
|||
bbb.push(b[i]); |
|||
} |
|||
} |
|||
} |
|||
for (i = 0; i < aa.length; ++i) { |
|||
if (aa[i] > 0) { |
|||
// it's a row we need |
|||
if (a[i].paired) { |
|||
aaa.push(a[i].text); |
|||
} // joined; partner should be in aa |
|||
else { |
|||
aaa.push(a[i]); |
|||
} |
|||
} |
|||
} |
|||
return { a: aaa, b: bbb }; |
|||
} |
|||
function stripOuterCommonLines(a, b, context) { |
|||
let i = 0; |
|||
while (i < a.length && i < b.length && a[i] == b[i]) { |
|||
++i; |
|||
} |
|||
let j = a.length - 1; |
|||
let k = b.length - 1; |
|||
while (j >= 0 && k >= 0 && a[j] == b[k]) { |
|||
--j; |
|||
--k; |
|||
} |
|||
return { |
|||
a: a.slice(Math.max(0, i - 1 - context), Math.min(a.length + 1, j + context + 1)), |
|||
b: b.slice(Math.max(0, i - 1 - context), Math.min(b.length + 1, k + context + 1)), |
|||
}; |
|||
} |
|||
function insertDiff(navpop) { |
|||
// for speed reasons, we first do a line-based diff, discard stuff that seems boring, then |
|||
// do a word-based diff |
|||
// FIXME: sometimes this gives misleading diffs as distant chunks are squashed together |
|||
let oldlines = navpop.diffData.oldRev.revision.slots.main.content.split('\n'); |
|||
let newlines = navpop.diffData.newRev.revision.slots.main.content.split('\n'); |
|||
let inner = stripOuterCommonLines(oldlines, newlines, getValueOf('popupDiffContextLines')); |
|||
oldlines = inner.a; |
|||
newlines = inner.b; |
|||
let truncated = false; |
|||
getValueOf('popupDiffMaxLines'); |
|||
if ( |
|||
oldlines.length > pg.option.popupDiffMaxLines || |
|||
newlines.length > pg.option.popupDiffMaxLines |
|||
) { |
|||
// truncate |
|||
truncated = true; |
|||
inner = stripOuterCommonLines( |
|||
oldlines.slice(0, pg.option.popupDiffMaxLines), |
|||
newlines.slice(0, pg.option.popupDiffMaxLines), |
|||
pg.option.popupDiffContextLines |
|||
); |
|||
oldlines = inner.a; |
|||
newlines = inner.b; |
|||
} |
|||
const lineDiff = diff(oldlines, newlines); |
|||
const lines2 = rmBoringLines(lineDiff.o, lineDiff.n); |
|||
const oldlines2 = lines2.a; |
|||
const newlines2 = lines2.b; |
|||
const simpleSplit = !String.prototype.parenSplit.isNative; |
|||
let html = '<hr />'; |
|||
if (getValueOf('popupDiffDates')) { |
|||
html += diffDatesTable(navpop); |
|||
html += '<hr />'; |
|||
} |
|||
html += shortenDiffString( |
|||
diffString(oldlines2.join('\n'), newlines2.join('\n'), simpleSplit), |
|||
getValueOf('popupDiffContextCharacters') |
|||
).join('<hr />'); |
|||
setPopupTipsAndHTML( |
|||
html.split('\n').join('<br>') + |
|||
(truncated ? |
|||
'<hr /><b>' + popupString('Diff truncated for performance reasons') + '</b>' : |
|||
''), |
|||
'popupPreview', |
|||
navpop.idNumber |
|||
); |
|||
} |
|||
function diffDatesTable(navpop) { |
|||
let html = '<table class="popup_diff_dates">'; |
|||
html += diffDatesTableRow(navpop.diffData.newRev.revision, tprintf('New revision')); |
|||
html += diffDatesTableRow(navpop.diffData.oldRev.revision, tprintf('Old revision')); |
|||
html += '</table>'; |
|||
return html; |
|||
} |
|||
function diffDatesTableRow(revision, label) { |
|||
let txt = ''; |
|||
const lastModifiedDate = new Date(revision.timestamp); |
|||
txt = formattedDateTime(lastModifiedDate); |
|||
const revlink = generalLink({ |
|||
url: mw.config.get('wgScript') + '?oldid=' + revision.revid, |
|||
text: label, |
|||
title: label, |
|||
}); |
|||
return simplePrintf('<tr><td>%s</td><td>%s</td></tr>', [revlink, txt]); |
|||
} |
|||
// ENDFILE: diffpreview.js |
|||
// STARTFILE: links.js |
|||
///////////////////// |
|||
// LINK GENERATION // |
|||
///////////////////// |
|||
// titledDiffLink --> titledWikiLink --> generalLink |
|||
// wikiLink --> titledWikiLink --> generalLink |
|||
// editCounterLink --> generalLink |
|||
// TODO Make these functions return Element objects, not just raw HTML strings. |
|||
function titledDiffLink(l) { |
|||
// article, text, title, from, to) { |
|||
return titledWikiLink({ |
|||
article: l.article, |
|||
action: l.to + '&oldid=' + l.from, |
|||
newWin: l.newWin, |
|||
noPopup: l.noPopup, |
|||
text: l.text, |
|||
title: l.title, |
|||
/* hack: no oldid here */ |
|||
actionName: 'diff', |
|||
}); |
|||
} |
|||
function wikiLink(l) { |
|||
//{article:article, action:action, text:text, oldid, newid}) { |
|||
if ( |
|||
!(typeof l.article == typeof {} && typeof l.action == typeof '' && typeof l.text == typeof '') |
|||
) { |
|||
return null; |
|||
} |
|||
if (typeof l.oldid == 'undefined') { |
|||
l.oldid = null; |
|||
} |
|||
const savedOldid = l.oldid; |
|||
if (!/^(edit|view|revert|render)$|^raw/.test(l.action)) { |
|||
l.oldid = null; |
|||
} |
|||
let hint = popupString(l.action + 'Hint'); // revertHint etc etc etc |
|||
const oldidData = [l.oldid, safeDecodeURI(l.article)]; |
|||
let revisionString = tprintf('revision %s of %s', oldidData); |
|||
log('revisionString=' + revisionString); |
|||
switch (l.action) { |
|||
case 'edit§ion=new': |
|||
hint = popupString('newSectionHint'); |
|||
break; |
|||
case 'edit&undo=': |
|||
if (l.diff && l.diff != 'prev' && savedOldid) { |
|||
l.action += l.diff + '&undoafter=' + savedOldid; |
|||
} else if (savedOldid) { |
|||
l.action += savedOldid; |
|||
} |
|||
hint = popupString('undoHint'); |
|||
break; |
|||
case 'raw&ctype=text/css': |
|||
hint = popupString('rawHint'); |
|||
break; |
|||
case 'revert': |
|||
var p = parseParams(pg.current.link.href); |
|||
l.action = |
|||
'edit&autoclick=wpSave&actoken=' + |
|||
autoClickToken() + |
|||
'&autoimpl=' + |
|||
popupString('autoedit_version') + |
|||
'&autosummary=' + |
|||
revertSummary(l.oldid, p.diff); |
|||
if (p.diff == 'prev') { |
|||
l.action += '&direction=prev'; |
|||
revisionString = tprintf('the revision prior to revision %s of %s', oldidData); |
|||
} |
|||
if (getValueOf('popupRevertSummaryPrompt')) { |
|||
l.action += '&autosummaryprompt=true'; |
|||
} |
|||
if (getValueOf('popupMinorReverts')) { |
|||
l.action += '&autominor=true'; |
|||
} |
|||
log('revisionString is now ' + revisionString); |
|||
break; |
|||
case 'nullEdit': |
|||
l.action = |
|||
'edit&autoclick=wpSave&actoken=' + |
|||
autoClickToken() + |
|||
'&autoimpl=' + |
|||
popupString('autoedit_version') + |
|||
'&autosummary=null'; |
|||
break; |
|||
case 'historyfeed': |
|||
l.action = 'history&feed=rss'; |
|||
break; |
|||
case 'markpatrolled': |
|||
l.action = 'markpatrolled&rcid=' + l.rcid; |
|||
} |
|||
if (hint) { |
|||
if (l.oldid) { |
|||
hint = simplePrintf(hint, [revisionString]); |
|||
} else { |
|||
hint = simplePrintf(hint, [safeDecodeURI(l.article)]); |
|||
} |
|||
} else { |
|||
hint = safeDecodeURI(l.article + '&action=' + l.action) + l.oldid ? '&oldid=' + l.oldid : ''; |
|||
} |
|||
return titledWikiLink({ |
|||
article: l.article, |
|||
action: l.action, |
|||
text: l.text, |
|||
newWin: l.newWin, |
|||
title: hint, |
|||
oldid: l.oldid, |
|||
noPopup: l.noPopup, |
|||
onclick: l.onclick, |
|||
}); |
|||
} |
|||
function revertSummary(oldid, diff) { |
|||
let ret = ''; |
|||
if (diff == 'prev') { |
|||
ret = getValueOf('popupQueriedRevertToPreviousSummary'); |
|||
} else { |
|||
ret = getValueOf('popupQueriedRevertSummary'); |
|||
} |
|||
return ret + '&autorv=' + oldid; |
|||
} |
|||
function titledWikiLink(l) { |
|||
// possible properties of argument: |
|||
// article, action, text, title, oldid, actionName, className, noPopup |
|||
// oldid = null is fine here |
|||
// article and action are mandatory args |
|||
if (typeof l.article == 'undefined' || typeof l.action == 'undefined') { |
|||
errlog('got undefined article or action in titledWikiLink'); |
|||
return null; |
|||
} |
|||
const base = pg.wiki.titlebase + l.article.urlString(); |
|||
let url = base; |
|||
if (typeof l.actionName == 'undefined' || !l.actionName) { |
|||
l.actionName = 'action'; |
|||
} |
|||
// no need to add &action=view, and this confuses anchors |
|||
if (l.action != 'view') { |
|||
url = base + '&' + l.actionName + '=' + l.action; |
|||
} |
|||
if (typeof l.oldid != 'undefined' && l.oldid) { |
|||
url += '&oldid=' + l.oldid; |
|||
} |
|||
let cssClass = pg.misc.defaultNavlinkClassname; |
|||
if (typeof l.className != 'undefined' && l.className) { |
|||
cssClass = l.className; |
|||
} |
|||
return generalNavLink({ |
|||
url: url, |
|||
newWin: l.newWin, |
|||
title: typeof l.title != 'undefined' ? l.title : null, |
|||
text: typeof l.text != 'undefined' ? l.text : null, |
|||
className: cssClass, |
|||
noPopup: l.noPopup, |
|||
onclick: l.onclick, |
|||
}); |
|||
} |
|||
pg.fn.getLastContrib = function getLastContrib(wikipage, newWin) { |
|||
getHistoryInfo(wikipage, (x) => { |
|||
processLastContribInfo(x, { page: wikipage, newWin: newWin }); |
|||
}); |
|||
}; |
|||
function processLastContribInfo(info, stuff) { |
|||
if (!info.edits || !info.edits.length) { |
|||
alert('Popups: an odd thing happened. Please retry.'); |
|||
return; |
|||
} |
|||
if (!info.firstNewEditor) { |
|||
alert( |
|||
tprintf('Only found one editor: %s made %s edits', [ |
|||
info.edits[0].editor, |
|||
info.edits.length, |
|||
]) |
|||
); |
|||
return; |
|||
} |
|||
const newUrl = |
|||
pg.wiki.titlebase + |
|||
new Title(stuff.page).urlString() + |
|||
'&diff=cur&oldid=' + |
|||
info.firstNewEditor.oldid; |
|||
displayUrl(newUrl, stuff.newWin); |
|||
} |
|||
pg.fn.getDiffSinceMyEdit = function getDiffSinceMyEdit(wikipage, newWin) { |
|||
getHistoryInfo(wikipage, (x) => { |
|||
processDiffSinceMyEdit(x, { page: wikipage, newWin: newWin }); |
|||
}); |
|||
}; |
|||
function processDiffSinceMyEdit(info, stuff) { |
|||
if (!info.edits || !info.edits.length) { |
|||
alert('Popups: something fishy happened. Please try again.'); |
|||
return; |
|||
} |
|||
const friendlyName = stuff.page.split('_').join(' '); |
|||
if (!info.myLastEdit) { |
|||
alert( |
|||
tprintf("Couldn't find an edit by %s\nin the last %s edits to\n%s", [ |
|||
info.userName, |
|||
getValueOf('popupHistoryLimit'), |
|||
friendlyName, |
|||
]) |
|||
); |
|||
return; |
|||
} |
|||
if (info.myLastEdit.index === 0) { |
|||
alert( |
|||
tprintf('%s seems to be the last editor to the page %s', [info.userName, friendlyName]) |
|||
); |
|||
return; |
|||
} |
|||
const newUrl = |
|||
pg.wiki.titlebase + |
|||
new Title(stuff.page).urlString() + |
|||
'&diff=cur&oldid=' + |
|||
info.myLastEdit.oldid; |
|||
displayUrl(newUrl, stuff.newWin); |
|||
} |
|||
function displayUrl(url, newWin) { |
|||
if (newWin) { |
|||
window.open(url); |
|||
} else { |
|||
document.location = url; |
|||
} |
|||
} |
|||
pg.fn.purgePopups = function purgePopups() { |
|||
processAllPopups(true); |
|||
setupCache(); // deletes all cached items (not browser cached, though...) |
|||
pg.option = {}; |
|||
abortAllDownloads(); |
|||
}; |
|||
function processAllPopups(nullify, banish) { |
|||
for (let i = 0; pg.current.links && i < pg.current.links.length; ++i) { |
|||
if (!pg.current.links[i].navpopup) { |
|||
continue; |
|||
} |
|||
if (nullify || banish) { |
|||
pg.current.links[i].navpopup.banish(); |
|||
} |
|||
pg.current.links[i].simpleNoMore = false; |
|||
if (nullify) { |
|||
pg.current.links[i].navpopup = null; |
|||
} |
|||
} |
|||
} |
|||
pg.fn.disablePopups = function disablePopups() { |
|||
processAllPopups(false, true); |
|||
setupTooltips(null, true); |
|||
}; |
|||
pg.fn.togglePreviews = function togglePreviews() { |
|||
processAllPopups(true, true); |
|||
pg.option.simplePopups = !pg.option.simplePopups; |
|||
abortAllDownloads(); |
|||
}; |
|||
function magicWatchLink(l) { |
|||
//Yuck!! Would require a thorough redesign to add this as a click event though ... |
|||
l.onclick = simplePrintf("pg.fn.modifyWatchlist('%s','%s');return false;", [ |
|||
l.article.toString(true).split('\\').join('\\\\').split("'").join("\\'"), |
|||
this.id, |
|||
]); |
|||
return wikiLink(l); |
|||
} |
|||
pg.fn.modifyWatchlist = function modifyWatchlist(title, action) { |
|||
const reqData = { |
|||
action: 'watch', |
|||
formatversion: 2, |
|||
titles: title, |
|||
uselang: mw.config.get('wgUserLanguage'), |
|||
}; |
|||
if (action === 'unwatch') { |
|||
reqData.unwatch = true; |
|||
} |
|||
// Load the Addedwatchtext or Removedwatchtext message and show it |
|||
const mwTitle = mw.Title.newFromText(title); |
|||
let messageName; |
|||
if (mwTitle && mwTitle.getNamespaceId() > 0 && mwTitle.getNamespaceId() % 2 === 1) { |
|||
messageName = action === 'watch' ? 'addedwatchtext-talk' : 'removedwatchtext-talk'; |
|||
} else { |
|||
messageName = action === 'watch' ? 'addedwatchtext' : 'removedwatchtext'; |
|||
} |
|||
$.when( |
|||
getMwApi().postWithToken('watch', reqData), |
|||
getMwApi().loadMessagesIfMissing([messageName]) |
|||
).done(() => { |
|||
mw.notify(mw.message(messageName, title).parseDom()); |
|||
}); |
|||
}; |
|||
function magicHistoryLink(l) { |
|||
// FIXME use onclick change href trick to sort this out instead of window.open |
|||
let jsUrl = '', |
|||
title = '', |
|||
onClick = ''; |
|||
switch (l.id) { |
|||
case 'lastContrib': |
|||
onClick = simplePrintf("pg.fn.getLastContrib('%s',%s)", [ |
|||
l.article.toString(true).split('\\').join('\\\\').split("'").join("\\'"), |
|||
l.newWin, |
|||
]); |
|||
title = popupString('lastContribHint'); |
|||
break; |
|||
case 'sinceMe': |
|||
onClick = simplePrintf("pg.fn.getDiffSinceMyEdit('%s',%s)", [ |
|||
l.article.toString(true).split('\\').join('\\\\').split("'").join("\\'"), |
|||
l.newWin, |
|||
]); |
|||
title = popupString('sinceMeHint'); |
|||
break; |
|||
} |
|||
jsUrl = 'javascript:' + onClick; // jshint ignore:line |
|||
onClick += ';return false;'; |
|||
return generalNavLink({ |
|||
url: jsUrl, |
|||
newWin: false, // can't have new windows with JS links, I think |
|||
title: title, |
|||
text: l.text, |
|||
noPopup: l.noPopup, |
|||
onclick: onClick, |
|||
}); |
|||
} |
|||
function popupMenuLink(l) { |
|||
const jsUrl = simplePrintf('javascript:pg.fn.%s()', [l.id]); // jshint ignore:line |
|||
const title = popupString(simplePrintf('%sHint', [l.id])); |
|||
const onClick = simplePrintf('pg.fn.%s();return false;', [l.id]); |
|||
return generalNavLink({ |
|||
url: jsUrl, |
|||
newWin: false, |
|||
title: title, |
|||
text: l.text, |
|||
noPopup: l.noPopup, |
|||
onclick: onClick, |
|||
}); |
|||
} |
|||
function specialLink(l) { |
|||
// properties: article, specialpage, text, sep |
|||
if (typeof l.specialpage == 'undefined' || !l.specialpage) { |
|||
return null; |
|||
} |
|||
const base = |
|||
pg.wiki.titlebase + |
|||
mw.config.get('wgFormattedNamespaces')[pg.nsSpecialId] + |
|||
':' + |
|||
l.specialpage; |
|||
if (typeof l.sep == 'undefined' || l.sep === null) { |
|||
l.sep = '&target='; |
|||
} |
|||
let article = l.article.urlString({ |
|||
keepSpaces: l.specialpage == 'Search', |
|||
}); |
|||
let hint = popupString(l.specialpage + 'Hint'); |
|||
switch (l.specialpage) { |
|||
case 'Log': |
|||
switch (l.sep) { |
|||
case '&user=': |
|||
hint = popupString('userLogHint'); |
|||
break; |
|||
case '&type=block&page=': |
|||
hint = popupString('blockLogHint'); |
|||
break; |
|||
case '&page=': |
|||
hint = popupString('pageLogHint'); |
|||
break; |
|||
case '&type=protect&page=': |
|||
hint = popupString('protectLogHint'); |
|||
break; |
|||
case '&type=delete&page=': |
|||
hint = popupString('deleteLogHint'); |
|||
break; |
|||
default: |
|||
log('Unknown log type, sep=' + l.sep); |
|||
hint = 'Missing hint (FIXME)'; |
|||
} |
|||
break; |
|||
case 'PrefixIndex': |
|||
article += '/'; |
|||
break; |
|||
} |
|||
if (hint) { |
|||
hint = simplePrintf(hint, [safeDecodeURI(l.article)]); |
|||
} else { |
|||
hint = safeDecodeURI(l.specialpage + ':' + l.article); |
|||
} |
|||
const url = base + l.sep + article; |
|||
return generalNavLink({ |
|||
url: url, |
|||
title: hint, |
|||
text: l.text, |
|||
newWin: l.newWin, |
|||
noPopup: l.noPopup, |
|||
}); |
|||
} |
|||
/** |
|||
* Builds a link from a object representing a link |
|||
* |
|||
* @param {Object} link |
|||
* @param {string} link.url URL |
|||
* @param {string} link.text The text to show for a link |
|||
* @param {string} link.title Title of the link, this shows up |
|||
* when you hover over the link |
|||
* @param {boolean} link.newWin Should open in a new Window |
|||
* @param {number} link.noPopup Should nest new popups from link (0 or 1) |
|||
* @param {string} link.onclick |
|||
* @return {string|null} null if no url is given |
|||
*/ |
|||
function generalLink(link) { |
|||
if (typeof link.url == 'undefined') { |
|||
return null; |
|||
} |
|||
const elem = document.createElement( 'a' ); |
|||
elem.href = link.url; |
|||
elem.title = link.title; |
|||
// The onclick event adds raw JS in textual form to the HTML. |
|||
// TODO: We should look into removing this, and/or auditing what gets sent. |
|||
elem.setAttribute( 'onclick', link.onclick ); |
|||
if ( link.noPopup ) { |
|||
elem.setAttribute('noPopup', '1' ); |
|||
} |
|||
let newWin; |
|||
if (typeof link.newWin == 'undefined' || link.newWin === null) { |
|||
newWin = getValueOf('popupNewWindows'); |
|||
} else { |
|||
newWin = link.newWin; |
|||
} |
|||
if (newWin) { |
|||
elem.target = '_blank'; |
|||
} |
|||
if (link.className) { |
|||
elem.className = link.className; |
|||
} |
|||
elem.innerText = pg.unescapeQuotesHTML(link.text); |
|||
return elem.outerHTML; |
|||
} |
|||
function appendParamsToLink(linkstr, params) { |
|||
const sp = linkstr.parenSplit(/(href="[^"]+?)"/i); |
|||
if (sp.length < 2) { |
|||
return null; |
|||
} |
|||
let ret = sp.shift() + sp.shift(); |
|||
ret += '&' + params + '"'; |
|||
ret += sp.join(''); |
|||
return ret; |
|||
} |
|||
function changeLinkTargetLink(x) { |
|||
// newTarget, text, hint, summary, clickButton, minor, title (optional), alsoChangeLabel { |
|||
if (x.newTarget) { |
|||
log('changeLinkTargetLink: newTarget=' + x.newTarget); |
|||
} |
|||
if (x.oldTarget !== decodeURIComponent(x.oldTarget)) { |
|||
log('This might be an input problem: ' + x.oldTarget); |
|||
} |
|||
// FIXME: first character of page title as well as namespace should be case insensitive |
|||
// eg [[:category:X1]] and [[:Category:X1]] are equivalent |
|||
// this'll break if charAt(0) is nasty |
|||
const cA = mw.util.escapeRegExp(x.oldTarget); |
|||
let chs = cA.charAt(0).toUpperCase(); |
|||
chs = '[' + chs + chs.toLowerCase() + ']'; |
|||
let currentArticleRegexBit = chs + cA.substring(1); |
|||
currentArticleRegexBit = currentArticleRegexBit |
|||
.split(/(?:[_ ]+|%20)/g) |
|||
.join('(?:[_ ]+|%20)') |
|||
.split('\\(') |
|||
.join('(?:%28|\\()') |
|||
.split('\\)') |
|||
.join('(?:%29|\\))'); // why does this need to match encoded strings ? links in the document ? |
|||
// leading and trailing space should be ignored, and anchor bits optional: |
|||
currentArticleRegexBit = '\\s*(' + currentArticleRegexBit + '(?:#[^\\[\\|]*)?)\\s*'; |
|||
// e.g. Computer (archaic) -> \s*([Cc]omputer[_ ](?:%2528|\()archaic(?:%2528|\)))\s* |
|||
// autoedit=s~\[\[([Cc]ad)\]\]~[[Computer-aided%20design|$1]]~g;s~\[\[([Cc]AD)[|]~[[Computer-aided%20design|~g |
|||
const title = x.title || mw.config.get('wgPageName').split('_').join(' '); |
|||
const lk = titledWikiLink({ |
|||
article: new Title(title), |
|||
newWin: x.newWin, |
|||
action: 'edit', |
|||
text: x.text, |
|||
title: x.hint, |
|||
className: 'popup_change_title_link', |
|||
}); |
|||
let cmd = ''; |
|||
if (x.newTarget) { |
|||
// escape '&' and other nasties |
|||
const t = x.newTarget; |
|||
const s = mw.util.escapeRegExp(x.newTarget); |
|||
if (x.alsoChangeLabel) { |
|||
cmd += 's~\\[\\[' + currentArticleRegexBit + '\\]\\]~[[' + t + ']]~g;'; |
|||
cmd += 's~\\[\\[' + currentArticleRegexBit + '[|]~[[' + t + '|~g;'; |
|||
cmd += 's~\\[\\[' + s + '\\|' + s + '\\]\\]~[[' + t + ']]~g'; |
|||
} else { |
|||
cmd += 's~\\[\\[' + currentArticleRegexBit + '\\]\\]~[[' + t + '|$1]]~g;'; |
|||
cmd += 's~\\[\\[' + currentArticleRegexBit + '[|]~[[' + t + '|~g;'; |
|||
cmd += 's~\\[\\[' + s + '\\|' + s + '\\]\\]~[[' + t + ']]~g'; |
|||
} |
|||
} else { |
|||
cmd += 's~\\[\\[' + currentArticleRegexBit + '\\]\\]~$1~g;'; |
|||
cmd += 's~\\[\\[' + currentArticleRegexBit + '[|](.*?)\\]\\]~$2~g'; |
|||
} |
|||
// Build query |
|||
cmd = 'autoedit=' + encodeURIComponent(cmd); |
|||
cmd += |
|||
'&autoclick=' + |
|||
encodeURIComponent(x.clickButton) + |
|||
'&actoken=' + |
|||
encodeURIComponent(autoClickToken()); |
|||
cmd += x.minor === null ? '' : '&autominor=' + encodeURIComponent(x.minor); |
|||
cmd += x.watch === null ? '' : '&autowatch=' + encodeURIComponent(x.watch); |
|||
cmd += '&autosummary=' + encodeURIComponent(x.summary); |
|||
cmd += '&autoimpl=' + encodeURIComponent(popupString('autoedit_version')); |
|||
return appendParamsToLink(lk, cmd); |
|||
} |
|||
function redirLink(redirMatch, article) { |
|||
// NB redirMatch is in wikiText |
|||
let ret = ''; |
|||
if (getValueOf('popupAppendRedirNavLinks') && getValueOf('popupNavLinks')) { |
|||
ret += '<hr />'; |
|||
if (getValueOf('popupFixRedirs') && typeof autoEdit != 'undefined' && autoEdit) { |
|||
ret += popupString('Redirects to: (Fix '); |
|||
log('redirLink: newTarget=' + redirMatch); |
|||
ret += addPopupShortcut( |
|||
changeLinkTargetLink({ |
|||
newTarget: redirMatch, |
|||
text: popupString('target'), |
|||
hint: popupString('Fix this redirect, changing just the link target'), |
|||
summary: simplePrintf(getValueOf('popupFixRedirsSummary'), [ |
|||
article.toString(), |
|||
redirMatch, |
|||
]), |
|||
oldTarget: article.toString(), |
|||
clickButton: getValueOf('popupRedirAutoClick'), |
|||
minor: true, |
|||
watch: getValueOf('popupWatchRedirredPages'), |
|||
}), |
|||
'R' |
|||
); |
|||
ret += popupString(' or '); |
|||
ret += addPopupShortcut( |
|||
changeLinkTargetLink({ |
|||
newTarget: redirMatch, |
|||
text: popupString('target & label'), |
|||
hint: popupString('Fix this redirect, changing the link target and label'), |
|||
summary: simplePrintf(getValueOf('popupFixRedirsSummary'), [ |
|||
article.toString(), |
|||
redirMatch, |
|||
]), |
|||
oldTarget: article.toString(), |
|||
clickButton: getValueOf('popupRedirAutoClick'), |
|||
minor: true, |
|||
watch: getValueOf('popupWatchRedirredPages'), |
|||
alsoChangeLabel: true, |
|||
}), |
|||
'R' |
|||
); |
|||
ret += popupString(')'); |
|||
} else { |
|||
ret += popupString('Redirects') + popupString(' to '); |
|||
} |
|||
return ret; |
|||
} else { |
|||
return ( |
|||
'<br> ' + |
|||
popupString('Redirects') + |
|||
popupString(' to ') + |
|||
titledWikiLink({ |
|||
article: new Title().fromWikiText(redirMatch), |
|||
action: 'view' /* FIXME: newWin */, |
|||
text: safeDecodeURI(redirMatch), |
|||
title: popupString('Bypass redirect'), |
|||
}) |
|||
); |
|||
} |
|||
} |
|||
function arinLink(l) { |
|||
if (!saneLinkCheck(l)) { |
|||
return null; |
|||
} |
|||
if (!l.article.isIpUser() || !pg.wiki.wikimedia) { |
|||
return null; |
|||
} |
|||
const uN = l.article.userName(); |
|||
return generalNavLink({ |
|||
url: 'http://ws.arin.net/cgi-bin/whois.pl?queryinput=' + encodeURIComponent(uN), |
|||
newWin: l.newWin, |
|||
title: tprintf('Look up %s in ARIN whois database', [uN]), |
|||
text: l.text, |
|||
noPopup: 1, |
|||
}); |
|||
} |
|||
function toolDbName(cookieStyle) { |
|||
let ret = mw.config.get('wgDBname'); |
|||
if (!cookieStyle) { |
|||
ret += '_p'; |
|||
} |
|||
return ret; |
|||
} |
|||
function saneLinkCheck(l) { |
|||
if (typeof l.article != typeof {} || typeof l.text != typeof '') { |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
function editCounterLink(l) { |
|||
if (!saneLinkCheck(l)) { |
|||
return null; |
|||
} |
|||
if (!pg.wiki.wikimedia) { |
|||
return null; |
|||
} |
|||
const uN = l.article.userName(); |
|||
const tool = getValueOf('popupEditCounterTool'); |
|||
let url; |
|||
const defaultToolUrl = 'https://xtools.wmflabs.org/ec?user=$1&project=$2.$3&uselang=' + mw.config.get('wgUserLanguage'); |
|||
switch (tool) { |
|||
case 'custom': |
|||
url = simplePrintf(getValueOf('popupEditCounterUrl'), [ |
|||
encodeURIComponent(uN), |
|||
toolDbName(), |
|||
]); |
|||
break; |
|||
case 'soxred': // no longer available |
|||
case 'kate': // no longer available |
|||
case 'interiot': // no longer available |
|||
/* fall through */ |
|||
case 'supercount': |
|||
default: |
|||
var theWiki = pg.wiki.hostname.split('.'); |
|||
url = simplePrintf(defaultToolUrl, [encodeURIComponent(uN), theWiki[0], theWiki[1]]); |
|||
} |
|||
return generalNavLink({ |
|||
url: url, |
|||
title: tprintf('editCounterLinkHint', [uN]), |
|||
newWin: l.newWin, |
|||
text: l.text, |
|||
noPopup: 1, |
|||
}); |
|||
} |
|||
function globalSearchLink(l) { |
|||
if (!saneLinkCheck(l)) { |
|||
return null; |
|||
} |
|||
const base = 'https://global-search.toolforge.org/?uselang=' + mw.config.get('wgUserLanguage') + '&q='; |
|||
const article = l.article.urlString({ keepSpaces: true }); |
|||
return generalNavLink({ |
|||
url: base + article, |
|||
newWin: l.newWin, |
|||
title: tprintf('globalSearchHint', [safeDecodeURI(l.article)]), |
|||
text: l.text, |
|||
noPopup: 1, |
|||
}); |
|||
} |
|||
function googleLink(l) { |
|||
if (!saneLinkCheck(l)) { |
|||
return null; |
|||
} |
|||
const base = 'https://www.google.com/search?q='; |
|||
const article = l.article.urlString({ keepSpaces: true }); |
|||
return generalNavLink({ |
|||
url: base + '%22' + article + '%22', |
|||
newWin: l.newWin, |
|||
title: tprintf('googleSearchHint', [safeDecodeURI(l.article)]), |
|||
text: l.text, |
|||
noPopup: 1, |
|||
}); |
|||
} |
|||
function editorListLink(l) { |
|||
if (!saneLinkCheck(l)) { |
|||
return null; |
|||
} |
|||
const article = l.article.articleFromTalkPage() || l.article; |
|||
const url = |
|||
'https://xtools.wmflabs.org/articleinfo/' + |
|||
encodeURI(pg.wiki.hostname) + |
|||
'/' + |
|||
article.urlString() + |
|||
'?uselang=' + |
|||
mw.config.get('wgUserLanguage'); |
|||
return generalNavLink({ |
|||
url: url, |
|||
title: tprintf('editorListHint', [article]), |
|||
newWin: l.newWin, |
|||
text: l.text, |
|||
noPopup: 1, |
|||
}); |
|||
} |
|||
function generalNavLink(l) { |
|||
l.className = l.className === null ? 'popupNavLink' : l.className; |
|||
return generalLink(l); |
|||
} |
|||
////////////////////////////////////////////////// |
|||
// magic history links |
|||
// |
|||
function getHistoryInfo(wikipage, whatNext) { |
|||
log('getHistoryInfo'); |
|||
getHistory( |
|||
wikipage, |
|||
whatNext ? |
|||
(d) => { |
|||
whatNext(processHistory(d)); |
|||
} : |
|||
processHistory |
|||
); |
|||
} |
|||
// FIXME eliminate pg.idNumber ... how? :-( |
|||
function getHistory(wikipage, onComplete) { |
|||
log('getHistory'); |
|||
const url = |
|||
pg.wiki.apiwikibase + |
|||
'?format=json&formatversion=2&action=query&prop=revisions&titles=' + |
|||
new Title(wikipage).urlString() + |
|||
'&rvlimit=' + |
|||
getValueOf('popupHistoryLimit'); |
|||
log('getHistory: url=' + url); |
|||
return startDownload(url, pg.idNumber + 'history', onComplete); |
|||
} |
|||
function processHistory(download) { |
|||
const jsobj = getJsObj(download.data); |
|||
try { |
|||
const revisions = anyChild(jsobj.query.pages).revisions; |
|||
const edits = []; |
|||
for (let i = 0; i < revisions.length; ++i) { |
|||
edits.push({ oldid: revisions[i].revid, editor: revisions[i].user }); |
|||
} |
|||
log('processed ' + edits.length + ' edits'); |
|||
return finishProcessHistory(edits, mw.config.get('wgUserName')); |
|||
} catch (someError) { |
|||
log('Something went wrong with JSON business'); |
|||
return finishProcessHistory([]); |
|||
} |
|||
} |
|||
function finishProcessHistory(edits, userName) { |
|||
const histInfo = {}; |
|||
histInfo.edits = edits; |
|||
histInfo.userName = userName; |
|||
for (let i = 0; i < edits.length; ++i) { |
|||
if (typeof histInfo.myLastEdit === 'undefined' && userName && edits[i].editor == userName) { |
|||
histInfo.myLastEdit = { |
|||
index: i, |
|||
oldid: edits[i].oldid, |
|||
previd: i === 0 ? null : edits[i - 1].oldid, |
|||
}; |
|||
} |
|||
if (typeof histInfo.firstNewEditor === 'undefined' && edits[i].editor != edits[0].editor) { |
|||
histInfo.firstNewEditor = { |
|||
index: i, |
|||
oldid: edits[i].oldid, |
|||
previd: i === 0 ? null : edits[i - 1].oldid, |
|||
}; |
|||
} |
|||
} |
|||
//pg.misc.historyInfo=histInfo; |
|||
return histInfo; |
|||
} |
|||
// ENDFILE: links.js |
|||
// STARTFILE: options.js |
|||
////////////////////////////////////////////////// |
|||
// options |
|||
// check for existing value, else use default |
|||
function defaultize(x) { |
|||
if (pg.option[x] === null || typeof pg.option[x] == 'undefined') { |
|||
if (typeof window[x] != 'undefined') { |
|||
pg.option[x] = window[x]; |
|||
} else { |
|||
pg.option[x] = pg.optionDefault[x]; |
|||
} |
|||
} |
|||
} |
|||
function newOption(x, def) { |
|||
pg.optionDefault[x] = def; |
|||
} |
|||
function setDefault(x, def) { |
|||
return newOption(x, def); |
|||
} |
|||
function getValueOf(varName) { |
|||
defaultize(varName); |
|||
return pg.option[varName]; |
|||
} |
|||
/*eslint-disable */ |
|||
function useDefaultOptions() { |
|||
// for testing |
|||
for (var p in pg.optionDefault) { |
|||
pg.option[p] = pg.optionDefault[p]; |
|||
if (typeof window[p] != 'undefined') { |
|||
delete window[p]; |
|||
} |
|||
} |
|||
} |
|||
/*eslint-enable */ |
|||
function setOptions() { |
|||
// user-settable parameters and defaults |
|||
let userIsSysop = false; |
|||
if (mw.config.get('wgUserGroups')) { |
|||
for (let g = 0; g < mw.config.get('wgUserGroups').length; ++g) { |
|||
if (mw.config.get('wgUserGroups')[g] == 'sysop') { |
|||
userIsSysop = true; |
|||
} |
|||
} |
|||
} |
|||
// Basic options |
|||
newOption('popupDelay', 0.5); |
|||
newOption('popupHideDelay', 0.5); |
|||
newOption('simplePopups', false); |
|||
newOption('popupStructure', 'shortmenus'); // see later - default for popupStructure is 'original' if simplePopups is true |
|||
newOption('popupActionsMenu', true); |
|||
newOption('popupSetupMenu', true); |
|||
newOption('popupAdminLinks', userIsSysop); |
|||
newOption('popupShortcutKeys', false); |
|||
newOption('popupHistoricalLinks', true); |
|||
newOption('popupOnlyArticleLinks', true); |
|||
newOption('removeTitles', true); |
|||
newOption('popupMaxWidth', 350); |
|||
newOption('popupSimplifyMainLink', true); |
|||
newOption('popupAppendRedirNavLinks', true); |
|||
newOption('popupTocLinks', false); |
|||
newOption('popupSubpopups', true); |
|||
newOption('popupDragHandle', false /* 'popupTopLinks'*/); |
|||
newOption('popupLazyPreviews', true); |
|||
newOption('popupLazyDownloads', true); |
|||
newOption('popupAllDabsStubs', false); |
|||
newOption('popupDebugging', false); |
|||
newOption('popupActiveNavlinks', true); |
|||
newOption('popupModifier', false); // ctrl, shift, alt or meta |
|||
newOption('popupModifierAction', 'enable'); // or 'disable' |
|||
newOption('popupDraggable', true); |
|||
newOption('popupReview', false); |
|||
newOption('popupLocale', false); |
|||
newOption('popupDateTimeFormatterOptions', { |
|||
year: 'numeric', |
|||
month: 'long', |
|||
day: 'numeric', |
|||
hour12: false, |
|||
hour: '2-digit', |
|||
minute: '2-digit', |
|||
second: '2-digit', |
|||
}); |
|||
newOption('popupDateFormatterOptions', { |
|||
year: 'numeric', |
|||
month: 'long', |
|||
day: 'numeric', |
|||
}); |
|||
newOption('popupTimeFormatterOptions', { |
|||
hour12: false, |
|||
hour: '2-digit', |
|||
minute: '2-digit', |
|||
second: '2-digit', |
|||
}); |
|||
// images |
|||
newOption('popupImages', true); |
|||
newOption('imagePopupsForImages', true); |
|||
newOption('popupNeverGetThumbs', false); |
|||
//newOption('popupImagesToggleSize', true); |
|||
newOption('popupThumbAction', 'imagepage'); //'sizetoggle'); |
|||
newOption('popupImageSize', 60); |
|||
newOption('popupImageSizeLarge', 200); |
|||
// redirs, dabs, reversion |
|||
newOption('popupFixRedirs', false); |
|||
newOption('popupRedirAutoClick', 'wpDiff'); |
|||
newOption('popupFixDabs', false); |
|||
newOption('popupDabsAutoClick', 'wpDiff'); |
|||
newOption('popupRevertSummaryPrompt', false); |
|||
newOption('popupMinorReverts', false); |
|||
newOption('popupRedlinkRemoval', false); |
|||
newOption('popupRedlinkAutoClick', 'wpDiff'); |
|||
newOption('popupWatchDisambiggedPages', null); |
|||
newOption('popupWatchRedirredPages', null); |
|||
newOption('popupDabWiktionary', 'last'); |
|||
// navlinks |
|||
newOption('popupNavLinks', true); |
|||
newOption('popupNavLinkSeparator', ' ⋅ '); |
|||
newOption('popupLastEditLink', true); |
|||
newOption('popupEditCounterTool', 'supercount'); |
|||
newOption('popupEditCounterUrl', ''); |
|||
// previews etc |
|||
newOption('popupPreviews', true); |
|||
newOption('popupSummaryData', true); |
|||
newOption('popupMaxPreviewSentences', 5); |
|||
newOption('popupMaxPreviewCharacters', 600); |
|||
newOption('popupLastModified', true); |
|||
newOption('popupPreviewKillTemplates', true); |
|||
newOption('popupPreviewRawTemplates', true); |
|||
newOption('popupPreviewFirstParOnly', true); |
|||
newOption('popupPreviewCutHeadings', true); |
|||
newOption('popupPreviewButton', false); |
|||
newOption('popupPreviewButtonEvent', 'click'); |
|||
// diffs |
|||
newOption('popupPreviewDiffs', true); |
|||
newOption('popupDiffMaxLines', 100); |
|||
newOption('popupDiffContextLines', 2); |
|||
newOption('popupDiffContextCharacters', 40); |
|||
newOption('popupDiffDates', true); |
|||
newOption('popupDiffDatePrinter', 'toLocaleString'); // no longer in use |
|||
// edit summaries. God, these are ugly. |
|||
newOption('popupReviewedSummary', popupString('defaultpopupReviewedSummary')); |
|||
newOption('popupFixDabsSummary', popupString('defaultpopupFixDabsSummary')); |
|||
newOption('popupExtendedRevertSummary', popupString('defaultpopupExtendedRevertSummary')); |
|||
newOption('popupRevertSummary', popupString('defaultpopupRevertSummary')); |
|||
newOption('popupRevertToPreviousSummary', popupString('defaultpopupRevertToPreviousSummary')); |
|||
newOption('popupQueriedRevertSummary', popupString('defaultpopupQueriedRevertSummary')); |
|||
newOption( |
|||
'popupQueriedRevertToPreviousSummary', |
|||
popupString('defaultpopupQueriedRevertToPreviousSummary') |
|||
); |
|||
newOption('popupFixRedirsSummary', popupString('defaultpopupFixRedirsSummary')); |
|||
newOption('popupRedlinkSummary', popupString('defaultpopupRedlinkSummary')); |
|||
newOption('popupRmDabLinkSummary', popupString('defaultpopupRmDabLinkSummary')); |
|||
// misc |
|||
newOption('popupHistoryLimit', 50); |
|||
newOption('popupFilters', [ |
|||
popupFilterStubDetect, |
|||
popupFilterDisambigDetect, |
|||
popupFilterPageSize, |
|||
popupFilterCountLinks, |
|||
popupFilterCountImages, |
|||
popupFilterCountCategories, |
|||
popupFilterLastModified, |
|||
popupFilterWikibaseItem, |
|||
]); |
|||
newOption('extraPopupFilters', []); |
|||
newOption('popupOnEditSelection', 'cursor'); |
|||
newOption('popupPreviewHistory', true); |
|||
newOption('popupImageLinks', true); |
|||
newOption('popupCategoryMembers', true); |
|||
newOption('popupUserInfo', true); |
|||
newOption('popupHistoryPreviewLimit', 25); |
|||
newOption('popupContribsPreviewLimit', 25); |
|||
newOption('popupRevDelUrl', '//en.wikipedia.org/wiki/Wikipedia:Revision_deletion'); |
|||
newOption('popupShowGender', true); |
|||
// new windows |
|||
newOption('popupNewWindows', false); |
|||
newOption('popupLinksNewWindow', { lastContrib: true, sinceMe: true }); |
|||
// regexps |
|||
newOption( |
|||
'popupDabRegexp', |
|||
'disambiguation\\}\\}|\\{\\{\\s*(d(ab|isamb(ig(uation)?)?)|(((geo|hn|road?|school|number)dis)|[234][lc][acw]|(road|ship)index))\\s*(\\|[^}]*)?\\}\\}|is a .*disambiguation.*page' |
|||
); |
|||
newOption('popupAnchorRegexp', 'anchors?'); //how to identify an anchors template |
|||
newOption('popupStubRegexp', '(sect)?stub[}][}]|This .*-related article is a .*stub'); |
|||
newOption( |
|||
'popupImageVarsRegexp', |
|||
'image|image_(?:file|skyline|name|flag|seal)|cover|badge|logo' |
|||
); |
|||
} |
|||
// ENDFILE: options.js |
|||
// STARTFILE: strings.js |
|||
////////////////////////////////////////////////// |
|||
// Translatable strings |
|||
////////////////////////////////////////////////// |
|||
// |
|||
// See instructions at |
|||
// https://en.wikipedia.org/wiki/Wikipedia:Tools/Navigation_popups/Translation |
|||
pg.string = { |
|||
///////////////////////////////////// |
|||
// summary data, searching etc. |
|||
///////////////////////////////////// |
|||
article: 'article', |
|||
category: 'category', |
|||
categories: 'categories', |
|||
image: 'image', |
|||
images: 'images', |
|||
stub: 'stub', |
|||
'section stub': 'section stub', |
|||
'Empty page': 'Empty page', |
|||
kB: 'kB', |
|||
bytes: 'bytes', |
|||
day: 'day', |
|||
days: 'days', |
|||
hour: 'hour', |
|||
hours: 'hours', |
|||
minute: 'minute', |
|||
minutes: 'minutes', |
|||
second: 'second', |
|||
seconds: 'seconds', |
|||
week: 'week', |
|||
weeks: 'weeks', |
|||
search: 'search', |
|||
SearchHint: 'Find English Wikipedia articles containing %s', |
|||
web: 'web', |
|||
global: 'global', |
|||
globalSearchHint: 'Search across Wikipedias in different languages for %s', |
|||
googleSearchHint: 'Google for %s', |
|||
///////////////////////////////////// |
|||
// article-related actions and info |
|||
// (some actions also apply to user pages) |
|||
///////////////////////////////////// |
|||
actions: 'actions', ///// view articles and view talk |
|||
popupsMenu: 'popups', |
|||
togglePreviewsHint: 'Toggle preview generation in popups on this page', |
|||
'enable previews': 'enable previews', |
|||
'disable previews': 'disable previews', |
|||
'toggle previews': 'toggle previews', |
|||
'show preview': 'show preview', |
|||
reset: 'reset', |
|||
'more...': 'more...', |
|||
disable: 'disable popups', |
|||
disablePopupsHint: 'Disable popups on this page. Reload page to re-enable.', |
|||
historyfeedHint: 'RSS feed of recent changes to this page', |
|||
purgePopupsHint: 'Reset popups, clearing all cached popup data.', |
|||
PopupsHint: 'Reset popups, clearing all cached popup data.', |
|||
spacebar: 'space', |
|||
view: 'view', |
|||
'view article': 'view article', |
|||
viewHint: 'Go to %s', |
|||
talk: 'talk', |
|||
'talk page': 'talk page', |
|||
'this revision': 'this revision', |
|||
'revision %s of %s': 'revision %s of %s', |
|||
'Revision %s of %s': 'Revision %s of %s', |
|||
'the revision prior to revision %s of %s': 'the revision prior to revision %s of %s', |
|||
'Toggle image size': 'Click to toggle image size', |
|||
del: 'del', ///// delete, protect, move |
|||
delete: 'delete', |
|||
deleteHint: 'Delete %s', |
|||
undeleteShort: 'un', |
|||
UndeleteHint: 'Show the deletion history for %s', |
|||
protect: 'protect', |
|||
protectHint: 'Restrict editing rights to %s', |
|||
unprotectShort: 'un', |
|||
unprotectHint: 'Allow %s to be edited by anyone again', |
|||
'send thanks': 'send thanks', |
|||
ThanksHint: 'Send a thank you notification to this user', |
|||
move: 'move', |
|||
'move page': 'move page', |
|||
MovepageHint: 'Change the title of %s', |
|||
edit: 'edit', ///// edit articles and talk |
|||
'edit article': 'edit article', |
|||
editHint: 'Change the content of %s', |
|||
'edit talk': 'edit talk', |
|||
new: 'new', |
|||
'new topic': 'new topic', |
|||
newSectionHint: 'Start a new section on %s', |
|||
'null edit': 'null edit', |
|||
nullEditHint: 'Submit an edit to %s, making no changes ', |
|||
hist: 'hist', ///// history, diffs, editors, related |
|||
history: 'history', |
|||
historyHint: 'List the changes made to %s', |
|||
'History preview failed': 'History preview failed :-(', |
|||
last: 'prev', // For labelling the previous revision in history pages; the key is "last" for backwards compatibility |
|||
lastEdit: 'lastEdit', |
|||
'mark patrolled': 'mark patrolled', |
|||
markpatrolledHint: 'Mark this edit as patrolled', |
|||
'Could not marked this edit as patrolled': 'Could not marked this edit as patrolled', |
|||
'show last edit': 'most recent edit', |
|||
'Show the last edit': 'Show the effects of the most recent change', |
|||
lastContrib: 'lastContrib', |
|||
'last set of edits': 'latest edits', |
|||
lastContribHint: 'Show the net effect of changes made by the last editor', |
|||
cur: 'cur', |
|||
diffCur: 'diffCur', |
|||
'Show changes since revision %s': 'Show changes since revision %s', |
|||
'%s old': '%s old', // as in 4 weeks old |
|||
oldEdit: 'oldEdit', |
|||
purge: 'purge', |
|||
purgeHint: 'Demand a fresh copy of %s', |
|||
raw: 'source', |
|||
rawHint: 'Download the source of %s', |
|||
render: 'simple', |
|||
renderHint: 'Show a plain HTML version of %s', |
|||
'Show the edit made to get revision': 'Show the edit made to get revision', |
|||
sinceMe: 'sinceMe', |
|||
'changes since mine': 'diff my edit', |
|||
sinceMeHint: 'Show changes since my last edit', |
|||
"Couldn't find an edit by %s\nin the last %s edits to\n%s": |
|||
"Couldn't find an edit by %s\nin the last %s edits to\n%s", |
|||
eds: 'eds', |
|||
editors: 'editors', |
|||
editorListHint: 'List the users who have edited %s', |
|||
related: 'related', |
|||
relatedChanges: 'relatedChanges', |
|||
'related changes': 'related changes', |
|||
RecentchangeslinkedHint: 'Show changes in articles related to %s', |
|||
editOld: 'editOld', ///// edit old version, or revert |
|||
rv: 'rv', |
|||
revert: 'revert', |
|||
revertHint: 'Revert to %s', |
|||
defaultpopupReviewedSummary: |
|||
'Accepted by reviewing the [[Special:diff/%s/%s|difference]] between this version and previously accepted version using [[:en:Wikipedia:Tools/Navigation_popups|popups]]', |
|||
defaultpopupRedlinkSummary: |
|||
'Removing link to empty page [[%s]] using [[:en:Wikipedia:Tools/Navigation_popups|popups]]', |
|||
defaultpopupFixDabsSummary: |
|||
'Disambiguate [[%s]] to [[%s]] using [[:en:Wikipedia:Tools/Navigation_popups|popups]]', |
|||
defaultpopupFixRedirsSummary: |
|||
'Redirect bypass from [[%s]] to [[%s]] using [[:en:Wikipedia:Tools/Navigation_popups|popups]]', |
|||
defaultpopupExtendedRevertSummary: |
|||
'Revert to revision dated %s by %s, oldid %s using [[:en:Wikipedia:Tools/Navigation_popups|popups]]', |
|||
defaultpopupRevertToPreviousSummary: |
|||
'Revert to the revision prior to revision %s using [[:en:Wikipedia:Tools/Navigation_popups|popups]]', |
|||
defaultpopupRevertSummary: |
|||
'Revert to revision %s using [[:en:Wikipedia:Tools/Navigation_popups|popups]]', |
|||
defaultpopupQueriedRevertToPreviousSummary: |
|||
'Revert to the revision prior to revision $1 dated $2 by $3 using [[:en:Wikipedia:Tools/Navigation_popups|popups]]', |
|||
defaultpopupQueriedRevertSummary: |
|||
'Revert to revision $1 dated $2 by $3 using [[:en:Wikipedia:Tools/Navigation_popups|popups]]', |
|||
defaultpopupRmDabLinkSummary: |
|||
'Remove link to dab page [[%s]] using [[:en:Wikipedia:Tools/Navigation_popups|popups]]', |
|||
Redirects: 'Redirects', // as in Redirects to ... |
|||
' to ': ' to ', // as in Redirects to ... |
|||
'Bypass redirect': 'Bypass redirect', |
|||
'Fix this redirect': 'Fix this redirect', |
|||
disambig: 'disambig', ///// add or remove dab etc. |
|||
disambigHint: 'Disambiguate this link to [[%s]]', |
|||
'Click to disambiguate this link to:': 'Click to disambiguate this link to:', |
|||
'remove this link': 'remove this link', |
|||
'remove all links to this page from this article': |
|||
'remove all links to this page from this article', |
|||
'remove all links to this disambig page from this article': |
|||
'remove all links to this disambig page from this article', |
|||
mainlink: 'mainlink', ///// links, watch, unwatch |
|||
wikiLink: 'wikiLink', |
|||
wikiLinks: 'wikiLinks', |
|||
'links here': 'links here', |
|||
whatLinksHere: 'whatLinksHere', |
|||
'what links here': 'what links here', |
|||
WhatlinkshereHint: 'List the pages that are hyperlinked to %s', |
|||
unwatchShort: 'un', |
|||
watchThingy: 'watch', // called watchThingy because {}.watch is a function |
|||
watchHint: 'Add %s to my watchlist', |
|||
unwatchHint: 'Remove %s from my watchlist', |
|||
'Only found one editor: %s made %s edits': 'Only found one editor: %s made %s edits', |
|||
'%s seems to be the last editor to the page %s': |
|||
'%s seems to be the last editor to the page %s', |
|||
rss: 'rss', |
|||
///////////////////////////////////// |
|||
// diff previews |
|||
///////////////////////////////////// |
|||
'Diff truncated for performance reasons': 'Diff truncated for performance reasons', |
|||
'Old revision': 'Old revision', |
|||
'New revision': 'New revision', |
|||
'Something went wrong :-(': 'Something went wrong :-(', |
|||
'Empty revision, maybe non-existent': 'Empty revision, maybe non-existent', |
|||
'Unknown date': 'Unknown date', |
|||
///////////////////////////////////// |
|||
// other special previews |
|||
///////////////////////////////////// |
|||
'Empty category': 'Empty category', |
|||
'Category members (%s shown)': 'Category members (%s shown)', |
|||
'No image links found': 'No image links found', |
|||
'File links': 'File links', |
|||
'No image found': 'No image found', |
|||
'Image from Commons': 'Image from Commons', |
|||
'Description page': 'Description page', |
|||
'Alt text:': 'Alt text:', |
|||
revdel: 'Hidden revision', |
|||
///////////////////////////////////// |
|||
// user-related actions and info |
|||
///////////////////////////////////// |
|||
user: 'user', ///// user page, talk, email, space |
|||
'user page': 'user page', |
|||
'user talk': 'user talk', |
|||
'edit user talk': 'edit user talk', |
|||
'leave comment': 'leave comment', |
|||
email: 'email', |
|||
'email user': 'email user', |
|||
EmailuserHint: 'Send an email to %s', |
|||
space: 'space', // short form for userSpace link |
|||
PrefixIndexHint: 'Show pages in the userspace of %s', |
|||
count: 'count', ///// contributions, log |
|||
'edit counter': 'edit counter', |
|||
editCounterLinkHint: 'Count the contributions made by %s', |
|||
contribs: 'contribs', |
|||
contributions: 'contributions', |
|||
deletedContribs: 'deleted contributions', |
|||
DeletedcontributionsHint: 'List deleted edits made by %s', |
|||
ContributionsHint: 'List the contributions made by %s', |
|||
log: 'log', |
|||
'user log': 'user log', |
|||
userLogHint: "Show %s's user log", |
|||
arin: 'ARIN lookup', ///// ARIN lookup, block user or IP |
|||
'Look up %s in ARIN whois database': 'Look up %s in the ARIN whois database', |
|||
unblockShort: 'un', |
|||
block: 'block', |
|||
'block user': 'block user', |
|||
IpblocklistHint: 'Unblock %s', |
|||
BlockipHint: 'Prevent %s from editing', |
|||
'block log': 'block log', |
|||
blockLogHint: 'Show the block log for %s', |
|||
protectLogHint: 'Show the protection log for %s', |
|||
pageLogHint: 'Show the page log for %s', |
|||
deleteLogHint: 'Show the deletion log for %s', |
|||
'Invalid %s %s': 'The option %s is invalid: %s', |
|||
'No backlinks found': 'No backlinks found', |
|||
' and more': ' and more', |
|||
undo: 'undo', |
|||
undoHint: 'undo this edit', |
|||
'Download preview data': 'Download preview data', |
|||
'Invalid or IP user': 'Invalid or IP user', |
|||
'Not a registered username': 'Not a registered username', |
|||
BLOCKED: 'BLOCKED', |
|||
'Has blocks': 'Has blocks', |
|||
' edits since: ': ' edits since: ', |
|||
'last edit on ': 'last edit on ', |
|||
'he/him': 'he/him', |
|||
'she/her': 'she/her', |
|||
///////////////////////////////////// |
|||
// Autoediting |
|||
///////////////////////////////////// |
|||
'Enter a non-empty edit summary or press cancel to abort': |
|||
'Enter a non-empty edit summary or press cancel to abort', |
|||
'Failed to get revision information, please edit manually.\n\n': |
|||
'Failed to get revision information, please edit manually.\n\n', |
|||
'The %s button has been automatically clicked. Please wait for the next page to load.': |
|||
'The %s button has been automatically clicked. Please wait for the next page to load.', |
|||
'Could not find button %s. Please check the settings in your javascript file.': |
|||
'Could not find button %s. Please check the settings in your javascript file.', |
|||
///////////////////////////////////// |
|||
// Popups setup |
|||
///////////////////////////////////// |
|||
'Open full-size image': 'Open full-size image', |
|||
zxy: 'zxy', |
|||
autoedit_version: 'np20140416', |
|||
}; |
|||
function popupString(str) { |
|||
if (typeof popupStrings != 'undefined' && popupStrings && popupStrings[str]) { |
|||
return popupStrings[str]; |
|||
} |
|||
if (pg.string[str]) { |
|||
return pg.string[str]; |
|||
} |
|||
return str; |
|||
} |
|||
function tprintf(str, subs) { |
|||
if (typeof subs != typeof []) { |
|||
subs = [subs]; |
|||
} |
|||
return simplePrintf(popupString(str), subs); |
|||
} |
|||
// ENDFILE: strings.js |
|||
// STARTFILE: run.js |
|||
//////////////////////////////////////////////////////////////////// |
|||
// Run things |
|||
//////////////////////////////////////////////////////////////////// |
|||
// For some reason popups requires a fully loaded page jQuery.ready(...) causes problems for some. |
|||
// The old addOnloadHook did something similar to the below |
|||
if (document.readyState == 'complete') { |
|||
autoEdit(); |
|||
} |
|||
//will setup popups |
|||
else { |
|||
$(window).on('load', autoEdit); |
|||
} |
|||
// Support for MediaWiki's live preview, VisualEditor's saves and Echo's flyout. |
|||
(function () { |
|||
let once = true; |
|||
function dynamicContentHandler($content) { |
|||
// Try to detect the hook fired on initial page load and disregard |
|||
// it, we already hook to onload (possibly to different parts of |
|||
// page - it's configurable) and running twice might be bad. Ugly… |
|||
if ($content.attr('id') == 'mw-content-text') { |
|||
if (once) { |
|||
once = false; |
|||
return; |
|||
} |
|||
} |
|||
function registerHooksForVisibleNavpops() { |
|||
for (let i = 0; pg.current.links && i < pg.current.links.length; ++i) { |
|||
const navpop = pg.current.links[i].navpopup; |
|||
if (!navpop || !navpop.isVisible()) { |
|||
continue; |
|||
} |
|||
Navpopup.tracker.addHook(posCheckerHook(navpop)); |
|||
} |
|||
} |
|||
function doIt() { |
|||
registerHooksForVisibleNavpops(); |
|||
$content.each(function () { |
|||
this.ranSetupTooltipsAlready = false; |
|||
setupTooltips(this); |
|||
}); |
|||
} |
|||
setupPopups(doIt); |
|||
} |
|||
// This hook is also fired after page load. |
|||
mw.hook('wikipage.content').add(dynamicContentHandler); |
|||
mw.hook('ext.echo.overlay.beforeShowingOverlay').add(($overlay) => { |
|||
dynamicContentHandler($overlay.find('.mw-echo-state')); |
|||
}); |
|||
}()); |
|||
}); |
|||
// ENDFILE: run.js |
|||
2026年6月14日 (日) 15:57的最新版本
/**
* SPDX-License-Identifier: CC-BY-SA-4.0
* _addText: '{{Gadget Header|license=CC-BY-SA-4.0}}'
*
* @base {@link https://en.wikipedia.org/wiki/MediaWiki:Gadget-popups.js}
* @base {@link https://zh.wikipedia.org/w/index.php?title=User:Lupin/strings-draft&oldid=579996170}
* @base {@link https://zh.wikipedia.org/wiki/MediaWiki:Gadget-navpop.css}
* @source {@link https://git.qiuwen.net.cn/InterfaceAdmin/QiuwenGadgets/src/branch/master/src/Navigation_popups}
* @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";
var __getOwnPropNames = Object.getOwnPropertyNames;
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/global-this.js
var require_global_this = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/global-this.js"(exports, module2) {
"use strict";
var check = function(it) {
return it && it.Math === Math && it;
};
module2.exports = // eslint-disable-next-line es/no-global-this -- safe
check(typeof globalThis == "object" && globalThis) || check(typeof window == "object" && window) || // eslint-disable-next-line no-restricted-globals -- safe
check(typeof self == "object" && self) || check(typeof global == "object" && global) || check(typeof exports == "object" && exports) || // eslint-disable-next-line no-new-func -- fallback
/* @__PURE__ */ (function() {
return this;
})() || Function("return this")();
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/fails.js
var require_fails = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/fails.js"(exports, module2) {
"use strict";
module2.exports = function(exec) {
try {
return !!exec();
} catch (error) {
return true;
}
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/descriptors.js
var require_descriptors = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/descriptors.js"(exports, module2) {
"use strict";
var fails = require_fails();
module2.exports = !fails(function() {
return Object.defineProperty({}, 1, { get: function() {
return 7;
} })[1] !== 7;
});
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/function-bind-native.js
var require_function_bind_native = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/function-bind-native.js"(exports, module2) {
"use strict";
var fails = require_fails();
module2.exports = !fails(function() {
var test = function() {
}.bind();
return typeof test != "function" || test.hasOwnProperty("prototype");
});
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/function-call.js
var require_function_call = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/function-call.js"(exports, module2) {
"use strict";
var NATIVE_BIND = require_function_bind_native();
var call = Function.prototype.call;
module2.exports = NATIVE_BIND ? call.bind(call) : function() {
return call.apply(call, arguments);
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-property-is-enumerable.js
var require_object_property_is_enumerable = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-property-is-enumerable.js"(exports) {
"use strict";
var $propertyIsEnumerable = {}.propertyIsEnumerable;
var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
var NASHORN_BUG = getOwnPropertyDescriptor && !$propertyIsEnumerable.call({ 1: 2 }, 1);
exports.f = NASHORN_BUG ? function propertyIsEnumerable(V) {
var descriptor = getOwnPropertyDescriptor(this, V);
return !!descriptor && descriptor.enumerable;
} : $propertyIsEnumerable;
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/create-property-descriptor.js
var require_create_property_descriptor = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/create-property-descriptor.js"(exports, module2) {
"use strict";
module2.exports = function(bitmap, value) {
return {
enumerable: !(bitmap & 1),
configurable: !(bitmap & 2),
writable: !(bitmap & 4),
value
};
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/function-uncurry-this.js
var require_function_uncurry_this = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/function-uncurry-this.js"(exports, module2) {
"use strict";
var NATIVE_BIND = require_function_bind_native();
var FunctionPrototype = Function.prototype;
var call = FunctionPrototype.call;
var uncurryThisWithBind = NATIVE_BIND && FunctionPrototype.bind.bind(call, call);
module2.exports = NATIVE_BIND ? uncurryThisWithBind : function(fn) {
return function() {
return call.apply(fn, arguments);
};
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/classof-raw.js
var require_classof_raw = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/classof-raw.js"(exports, module2) {
"use strict";
var uncurryThis = require_function_uncurry_this();
var toString = uncurryThis({}.toString);
var stringSlice = uncurryThis("".slice);
module2.exports = function(it) {
return stringSlice(toString(it), 8, -1);
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/indexed-object.js
var require_indexed_object = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/indexed-object.js"(exports, module2) {
"use strict";
var uncurryThis = require_function_uncurry_this();
var fails = require_fails();
var classof = require_classof_raw();
var $Object = Object;
var split = uncurryThis("".split);
module2.exports = fails(function() {
return !$Object("z").propertyIsEnumerable(0);
}) ? function(it) {
return classof(it) === "String" ? split(it, "") : $Object(it);
} : $Object;
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-null-or-undefined.js
var require_is_null_or_undefined = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-null-or-undefined.js"(exports, module2) {
"use strict";
module2.exports = function(it) {
return it === null || it === void 0;
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/require-object-coercible.js
var require_require_object_coercible = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/require-object-coercible.js"(exports, module2) {
"use strict";
var isNullOrUndefined = require_is_null_or_undefined();
var $TypeError = TypeError;
module2.exports = function(it) {
if (isNullOrUndefined(it)) throw new $TypeError("Can't call method on " + it);
return it;
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-indexed-object.js
var require_to_indexed_object = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-indexed-object.js"(exports, module2) {
"use strict";
var IndexedObject = require_indexed_object();
var requireObjectCoercible = require_require_object_coercible();
module2.exports = function(it) {
return IndexedObject(requireObjectCoercible(it));
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-callable.js
var require_is_callable = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-callable.js"(exports, module2) {
"use strict";
var documentAll = typeof document == "object" && document.all;
module2.exports = typeof documentAll == "undefined" && documentAll !== void 0 ? function(argument) {
return typeof argument == "function" || argument === documentAll;
} : function(argument) {
return typeof argument == "function";
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-object.js
var require_is_object = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-object.js"(exports, module2) {
"use strict";
var isCallable = require_is_callable();
module2.exports = function(it) {
return typeof it == "object" ? it !== null : isCallable(it);
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/get-built-in.js
var require_get_built_in = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/get-built-in.js"(exports, module2) {
"use strict";
var globalThis2 = require_global_this();
var isCallable = require_is_callable();
var aFunction = function(argument) {
return isCallable(argument) ? argument : void 0;
};
module2.exports = function(namespace, method) {
return arguments.length < 2 ? aFunction(globalThis2[namespace]) : globalThis2[namespace] && globalThis2[namespace][method];
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-is-prototype-of.js
var require_object_is_prototype_of = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-is-prototype-of.js"(exports, module2) {
"use strict";
var uncurryThis = require_function_uncurry_this();
module2.exports = uncurryThis({}.isPrototypeOf);
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/environment-user-agent.js
var require_environment_user_agent = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/environment-user-agent.js"(exports, module2) {
"use strict";
var globalThis2 = require_global_this();
var navigator2 = globalThis2.navigator;
var userAgent = navigator2 && navigator2.userAgent;
module2.exports = userAgent ? String(userAgent) : "";
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/environment-v8-version.js
var require_environment_v8_version = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/environment-v8-version.js"(exports, module2) {
"use strict";
var globalThis2 = require_global_this();
var userAgent = require_environment_user_agent();
var process = globalThis2.process;
var Deno = globalThis2.Deno;
var versions = process && process.versions || Deno && Deno.version;
var v8 = versions && versions.v8;
var match;
var version;
if (v8) {
match = v8.split(".");
version = match[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1]);
}
if (!version && userAgent) {
match = userAgent.match(/Edge\/(\d+)/);
if (!match || match[1] >= 74) {
match = userAgent.match(/Chrome\/(\d+)/);
if (match) version = +match[1];
}
}
module2.exports = version;
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/symbol-constructor-detection.js
var require_symbol_constructor_detection = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/symbol-constructor-detection.js"(exports, module2) {
"use strict";
var V8_VERSION = require_environment_v8_version();
var fails = require_fails();
var globalThis2 = require_global_this();
var $String = globalThis2.String;
module2.exports = !!Object.getOwnPropertySymbols && !fails(function() {
var symbol = /* @__PURE__ */ Symbol("symbol detection");
return !$String(symbol) || !(Object(symbol) instanceof Symbol) || // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
!Symbol.sham && V8_VERSION && V8_VERSION < 41;
});
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/use-symbol-as-uid.js
var require_use_symbol_as_uid = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/use-symbol-as-uid.js"(exports, module2) {
"use strict";
var NATIVE_SYMBOL = require_symbol_constructor_detection();
module2.exports = NATIVE_SYMBOL && !Symbol.sham && typeof Symbol.iterator == "symbol";
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-symbol.js
var require_is_symbol = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-symbol.js"(exports, module2) {
"use strict";
var getBuiltIn = require_get_built_in();
var isCallable = require_is_callable();
var isPrototypeOf = require_object_is_prototype_of();
var USE_SYMBOL_AS_UID = require_use_symbol_as_uid();
var $Object = Object;
module2.exports = USE_SYMBOL_AS_UID ? function(it) {
return typeof it == "symbol";
} : function(it) {
var $Symbol = getBuiltIn("Symbol");
return isCallable($Symbol) && isPrototypeOf($Symbol.prototype, $Object(it));
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/try-to-string.js
var require_try_to_string = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/try-to-string.js"(exports, module2) {
"use strict";
var $String = String;
module2.exports = function(argument) {
try {
return $String(argument);
} catch (error) {
return "Object";
}
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/a-callable.js
var require_a_callable = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/a-callable.js"(exports, module2) {
"use strict";
var isCallable = require_is_callable();
var tryToString = require_try_to_string();
var $TypeError = TypeError;
module2.exports = function(argument) {
if (isCallable(argument)) return argument;
throw new $TypeError(tryToString(argument) + " is not a function");
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/get-method.js
var require_get_method = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/get-method.js"(exports, module2) {
"use strict";
var aCallable = require_a_callable();
var isNullOrUndefined = require_is_null_or_undefined();
module2.exports = function(V, P) {
var func = V[P];
return isNullOrUndefined(func) ? void 0 : aCallable(func);
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/ordinary-to-primitive.js
var require_ordinary_to_primitive = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/ordinary-to-primitive.js"(exports, module2) {
"use strict";
var call = require_function_call();
var isCallable = require_is_callable();
var isObject = require_is_object();
var $TypeError = TypeError;
module2.exports = function(input, pref) {
var fn, val;
if (pref === "string" && isCallable(fn = input.toString) && !isObject(val = call(fn, input))) return val;
if (isCallable(fn = input.valueOf) && !isObject(val = call(fn, input))) return val;
if (pref !== "string" && isCallable(fn = input.toString) && !isObject(val = call(fn, input))) return val;
throw new $TypeError("Can't convert object to primitive value");
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-pure.js
var require_is_pure = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-pure.js"(exports, module2) {
"use strict";
module2.exports = false;
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/define-global-property.js
var require_define_global_property = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/define-global-property.js"(exports, module2) {
"use strict";
var globalThis2 = require_global_this();
var defineProperty = Object.defineProperty;
module2.exports = function(key, value) {
try {
defineProperty(globalThis2, key, { value, configurable: true, writable: true });
} catch (error) {
globalThis2[key] = value;
}
return value;
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/shared-store.js
var require_shared_store = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/shared-store.js"(exports, module2) {
"use strict";
var IS_PURE = require_is_pure();
var globalThis2 = require_global_this();
var defineGlobalProperty = require_define_global_property();
var SHARED = "__core-js_shared__";
var store = module2.exports = globalThis2[SHARED] || defineGlobalProperty(SHARED, {});
(store.versions || (store.versions = [])).push({
version: "3.49.0",
mode: IS_PURE ? "pure" : "global",
copyright: "© 2013–2025 Denis Pushkarev (zloirock.ru), 2025–2026 CoreJS Company (core-js.io). All rights reserved.",
license: "https://github.com/zloirock/core-js/blob/v3.49.0/LICENSE",
source: "https://github.com/zloirock/core-js"
});
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/shared.js
var require_shared = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/shared.js"(exports, module2) {
"use strict";
var store = require_shared_store();
module2.exports = function(key, value) {
return store[key] || (store[key] = value || {});
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-object.js
var require_to_object = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-object.js"(exports, module2) {
"use strict";
var requireObjectCoercible = require_require_object_coercible();
var $Object = Object;
module2.exports = function(argument) {
return $Object(requireObjectCoercible(argument));
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/has-own-property.js
var require_has_own_property = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/has-own-property.js"(exports, module2) {
"use strict";
var uncurryThis = require_function_uncurry_this();
var toObject = require_to_object();
var hasOwnProperty = uncurryThis({}.hasOwnProperty);
module2.exports = Object.hasOwn || function hasOwn(it, key) {
return hasOwnProperty(toObject(it), key);
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/uid.js
var require_uid = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/uid.js"(exports, module2) {
"use strict";
var uncurryThis = require_function_uncurry_this();
var id = 0;
var postfix = Math.random();
var toString = uncurryThis(1.1.toString);
module2.exports = function(key) {
return "Symbol(" + (key === void 0 ? "" : key) + ")_" + toString(++id + postfix, 36);
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/well-known-symbol.js
var require_well_known_symbol = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/well-known-symbol.js"(exports, module2) {
"use strict";
var globalThis2 = require_global_this();
var shared = require_shared();
var hasOwn = require_has_own_property();
var uid = require_uid();
var NATIVE_SYMBOL = require_symbol_constructor_detection();
var USE_SYMBOL_AS_UID = require_use_symbol_as_uid();
var Symbol2 = globalThis2.Symbol;
var WellKnownSymbolsStore = shared("wks");
var createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol2["for"] || Symbol2 : Symbol2 && Symbol2.withoutSetter || uid;
module2.exports = function(name) {
if (!hasOwn(WellKnownSymbolsStore, name)) {
WellKnownSymbolsStore[name] = NATIVE_SYMBOL && hasOwn(Symbol2, name) ? Symbol2[name] : createWellKnownSymbol("Symbol." + name);
}
return WellKnownSymbolsStore[name];
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-primitive.js
var require_to_primitive = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-primitive.js"(exports, module2) {
"use strict";
var call = require_function_call();
var isObject = require_is_object();
var isSymbol = require_is_symbol();
var getMethod = require_get_method();
var ordinaryToPrimitive = require_ordinary_to_primitive();
var wellKnownSymbol = require_well_known_symbol();
var $TypeError = TypeError;
var TO_PRIMITIVE = wellKnownSymbol("toPrimitive");
module2.exports = function(input, pref) {
if (!isObject(input) || isSymbol(input)) return input;
var exoticToPrim = getMethod(input, TO_PRIMITIVE);
var result;
if (exoticToPrim) {
if (pref === void 0) pref = "default";
result = call(exoticToPrim, input, pref);
if (!isObject(result) || isSymbol(result)) return result;
throw new $TypeError("Can't convert object to primitive value");
}
if (pref === void 0) pref = "number";
return ordinaryToPrimitive(input, pref);
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-property-key.js
var require_to_property_key = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-property-key.js"(exports, module2) {
"use strict";
var toPrimitive = require_to_primitive();
var isSymbol = require_is_symbol();
module2.exports = function(argument) {
var key = toPrimitive(argument, "string");
return isSymbol(key) ? key : key + "";
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/document-create-element.js
var require_document_create_element = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/document-create-element.js"(exports, module2) {
"use strict";
var globalThis2 = require_global_this();
var isObject = require_is_object();
var document2 = globalThis2.document;
var EXISTS = isObject(document2) && isObject(document2.createElement);
module2.exports = function(it) {
return EXISTS ? document2.createElement(it) : {};
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/ie8-dom-define.js
var require_ie8_dom_define = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/ie8-dom-define.js"(exports, module2) {
"use strict";
var DESCRIPTORS = require_descriptors();
var fails = require_fails();
var createElement = require_document_create_element();
module2.exports = !DESCRIPTORS && !fails(function() {
return Object.defineProperty(createElement("div"), "a", {
get: function() {
return 7;
}
}).a !== 7;
});
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-get-own-property-descriptor.js
var require_object_get_own_property_descriptor = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-get-own-property-descriptor.js"(exports) {
"use strict";
var DESCRIPTORS = require_descriptors();
var call = require_function_call();
var propertyIsEnumerableModule = require_object_property_is_enumerable();
var createPropertyDescriptor = require_create_property_descriptor();
var toIndexedObject = require_to_indexed_object();
var toPropertyKey = require_to_property_key();
var hasOwn = require_has_own_property();
var IE8_DOM_DEFINE = require_ie8_dom_define();
var $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
exports.f = DESCRIPTORS ? $getOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P) {
O = toIndexedObject(O);
P = toPropertyKey(P);
if (IE8_DOM_DEFINE) try {
return $getOwnPropertyDescriptor(O, P);
} catch (error) {
}
if (hasOwn(O, P)) return createPropertyDescriptor(!call(propertyIsEnumerableModule.f, O, P), O[P]);
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/v8-prototype-define-bug.js
var require_v8_prototype_define_bug = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/v8-prototype-define-bug.js"(exports, module2) {
"use strict";
var DESCRIPTORS = require_descriptors();
var fails = require_fails();
module2.exports = DESCRIPTORS && fails(function() {
return Object.defineProperty(function() {
}, "prototype", {
value: 42,
writable: false
}).prototype !== 42;
});
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/an-object.js
var require_an_object = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/an-object.js"(exports, module2) {
"use strict";
var isObject = require_is_object();
var $String = String;
var $TypeError = TypeError;
module2.exports = function(argument) {
if (isObject(argument)) return argument;
throw new $TypeError($String(argument) + " is not an object");
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-define-property.js
var require_object_define_property = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-define-property.js"(exports) {
"use strict";
var DESCRIPTORS = require_descriptors();
var IE8_DOM_DEFINE = require_ie8_dom_define();
var V8_PROTOTYPE_DEFINE_BUG = require_v8_prototype_define_bug();
var anObject = require_an_object();
var toPropertyKey = require_to_property_key();
var $TypeError = TypeError;
var $defineProperty = Object.defineProperty;
var $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
var ENUMERABLE = "enumerable";
var CONFIGURABLE = "configurable";
var WRITABLE = "writable";
exports.f = DESCRIPTORS ? V8_PROTOTYPE_DEFINE_BUG ? function defineProperty(O, P, Attributes) {
anObject(O);
P = toPropertyKey(P);
anObject(Attributes);
if (typeof O === "function" && P === "prototype" && "value" in Attributes && WRITABLE in Attributes && !Attributes[WRITABLE]) {
var current = $getOwnPropertyDescriptor(O, P);
if (current && current[WRITABLE]) {
O[P] = Attributes.value;
Attributes = {
configurable: CONFIGURABLE in Attributes ? Attributes[CONFIGURABLE] : current[CONFIGURABLE],
enumerable: ENUMERABLE in Attributes ? Attributes[ENUMERABLE] : current[ENUMERABLE],
writable: false
};
}
}
return $defineProperty(O, P, Attributes);
} : $defineProperty : function defineProperty(O, P, Attributes) {
anObject(O);
P = toPropertyKey(P);
anObject(Attributes);
if (IE8_DOM_DEFINE) try {
return $defineProperty(O, P, Attributes);
} catch (error) {
}
if ("get" in Attributes || "set" in Attributes) throw new $TypeError("Accessors not supported");
if ("value" in Attributes) O[P] = Attributes.value;
return O;
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/create-non-enumerable-property.js
var require_create_non_enumerable_property = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/create-non-enumerable-property.js"(exports, module2) {
"use strict";
var DESCRIPTORS = require_descriptors();
var definePropertyModule = require_object_define_property();
var createPropertyDescriptor = require_create_property_descriptor();
module2.exports = DESCRIPTORS ? function(object, key, value) {
return definePropertyModule.f(object, key, createPropertyDescriptor(1, value));
} : function(object, key, value) {
object[key] = value;
return object;
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/function-name.js
var require_function_name = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/function-name.js"(exports, module2) {
"use strict";
var DESCRIPTORS = require_descriptors();
var hasOwn = require_has_own_property();
var FunctionPrototype = Function.prototype;
var getDescriptor = DESCRIPTORS && Object.getOwnPropertyDescriptor;
var EXISTS = hasOwn(FunctionPrototype, "name");
var PROPER = EXISTS && function something() {
}.name === "something";
var CONFIGURABLE = EXISTS && (!DESCRIPTORS || DESCRIPTORS && getDescriptor(FunctionPrototype, "name").configurable);
module2.exports = {
EXISTS,
PROPER,
CONFIGURABLE
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/inspect-source.js
var require_inspect_source = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/inspect-source.js"(exports, module2) {
"use strict";
var uncurryThis = require_function_uncurry_this();
var isCallable = require_is_callable();
var store = require_shared_store();
var functionToString = uncurryThis(Function.toString);
if (!isCallable(store.inspectSource)) {
store.inspectSource = function(it) {
return functionToString(it);
};
}
module2.exports = store.inspectSource;
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/weak-map-basic-detection.js
var require_weak_map_basic_detection = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/weak-map-basic-detection.js"(exports, module2) {
"use strict";
var globalThis2 = require_global_this();
var isCallable = require_is_callable();
var WeakMap = globalThis2.WeakMap;
module2.exports = isCallable(WeakMap) && /native code/.test(String(WeakMap));
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/shared-key.js
var require_shared_key = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/shared-key.js"(exports, module2) {
"use strict";
var shared = require_shared();
var uid = require_uid();
var keys = shared("keys");
module2.exports = function(key) {
return keys[key] || (keys[key] = uid(key));
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/hidden-keys.js
var require_hidden_keys = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/hidden-keys.js"(exports, module2) {
"use strict";
module2.exports = {};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/internal-state.js
var require_internal_state = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/internal-state.js"(exports, module2) {
"use strict";
var NATIVE_WEAK_MAP = require_weak_map_basic_detection();
var globalThis2 = require_global_this();
var isObject = require_is_object();
var createNonEnumerableProperty = require_create_non_enumerable_property();
var hasOwn = require_has_own_property();
var shared = require_shared_store();
var sharedKey = require_shared_key();
var hiddenKeys = require_hidden_keys();
var OBJECT_ALREADY_INITIALIZED = "Object already initialized";
var TypeError2 = globalThis2.TypeError;
var WeakMap = globalThis2.WeakMap;
var set;
var get;
var has;
var enforce = function(it) {
return has(it) ? get(it) : set(it, {});
};
var getterFor = function(TYPE) {
return function(it) {
var state;
if (!isObject(it) || (state = get(it)).type !== TYPE) {
throw new TypeError2("Incompatible receiver, " + TYPE + " required");
}
return state;
};
};
if (NATIVE_WEAK_MAP || shared.state) {
store = shared.state || (shared.state = new WeakMap());
store.get = store.get;
store.has = store.has;
store.set = store.set;
set = function(it, metadata) {
if (store.has(it)) throw new TypeError2(OBJECT_ALREADY_INITIALIZED);
metadata.facade = it;
store.set(it, metadata);
return metadata;
};
get = function(it) {
return store.get(it) || {};
};
has = function(it) {
return store.has(it);
};
} else {
STATE = sharedKey("state");
hiddenKeys[STATE] = true;
set = function(it, metadata) {
if (hasOwn(it, STATE)) throw new TypeError2(OBJECT_ALREADY_INITIALIZED);
metadata.facade = it;
createNonEnumerableProperty(it, STATE, metadata);
return metadata;
};
get = function(it) {
return hasOwn(it, STATE) ? it[STATE] : {};
};
has = function(it) {
return hasOwn(it, STATE);
};
}
var store;
var STATE;
module2.exports = {
set,
get,
has,
enforce,
getterFor
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/make-built-in.js
var require_make_built_in = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/make-built-in.js"(exports, module2) {
"use strict";
var uncurryThis = require_function_uncurry_this();
var fails = require_fails();
var isCallable = require_is_callable();
var hasOwn = require_has_own_property();
var DESCRIPTORS = require_descriptors();
var CONFIGURABLE_FUNCTION_NAME = require_function_name().CONFIGURABLE;
var inspectSource = require_inspect_source();
var InternalStateModule = require_internal_state();
var enforceInternalState = InternalStateModule.enforce;
var getInternalState = InternalStateModule.get;
var $String = String;
var defineProperty = Object.defineProperty;
var stringSlice = uncurryThis("".slice);
var replace = uncurryThis("".replace);
var join = uncurryThis([].join);
var CONFIGURABLE_LENGTH = DESCRIPTORS && !fails(function() {
return defineProperty(function() {
}, "length", { value: 8 }).length !== 8;
});
var TEMPLATE = String(String).split("String");
var makeBuiltIn = module2.exports = function(value, name, options) {
if (stringSlice($String(name), 0, 7) === "Symbol(") {
name = "[" + replace($String(name), /^Symbol\(([^)]*)\).*$/, "$1") + "]";
}
if (options && options.getter) name = "get " + name;
if (options && options.setter) name = "set " + name;
if (!hasOwn(value, "name") || CONFIGURABLE_FUNCTION_NAME && value.name !== name) {
if (DESCRIPTORS) defineProperty(value, "name", { value: name, configurable: true });
else value.name = name;
}
if (CONFIGURABLE_LENGTH && options && hasOwn(options, "arity") && value.length !== options.arity) {
defineProperty(value, "length", { value: options.arity });
}
try {
if (options && hasOwn(options, "constructor") && options.constructor) {
if (DESCRIPTORS) defineProperty(value, "prototype", { writable: false });
} else if (value.prototype) value.prototype = void 0;
} catch (error) {
}
var state = enforceInternalState(value);
if (!hasOwn(state, "source")) {
state.source = join(TEMPLATE, typeof name == "string" ? name : "");
}
return value;
};
Function.prototype.toString = makeBuiltIn(function toString() {
return isCallable(this) && getInternalState(this).source || inspectSource(this);
}, "toString");
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/define-built-in.js
var require_define_built_in = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/define-built-in.js"(exports, module2) {
"use strict";
var isCallable = require_is_callable();
var definePropertyModule = require_object_define_property();
var makeBuiltIn = require_make_built_in();
var defineGlobalProperty = require_define_global_property();
module2.exports = function(O, key, value, options) {
if (!options) options = {};
var simple = options.enumerable;
var name = options.name !== void 0 ? options.name : key;
if (isCallable(value)) makeBuiltIn(value, name, options);
if (options.global) {
if (simple) O[key] = value;
else defineGlobalProperty(key, value);
} else {
try {
if (!options.unsafe) delete O[key];
else if (O[key]) simple = true;
} catch (error) {
}
if (simple) O[key] = value;
else definePropertyModule.f(O, key, {
value,
enumerable: false,
configurable: !options.nonConfigurable,
writable: !options.nonWritable
});
}
return O;
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/math-trunc.js
var require_math_trunc = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/math-trunc.js"(exports, module2) {
"use strict";
var ceil = Math.ceil;
var floor = Math.floor;
module2.exports = Math.trunc || function trunc(x) {
var n = +x;
return (n > 0 ? floor : ceil)(n);
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-integer-or-infinity.js
var require_to_integer_or_infinity = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-integer-or-infinity.js"(exports, module2) {
"use strict";
var trunc = require_math_trunc();
module2.exports = function(argument) {
var number = +argument;
return number !== number || number === 0 ? 0 : trunc(number);
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-absolute-index.js
var require_to_absolute_index = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-absolute-index.js"(exports, module2) {
"use strict";
var toIntegerOrInfinity = require_to_integer_or_infinity();
var max = Math.max;
var min = Math.min;
module2.exports = function(index, length) {
var integer = toIntegerOrInfinity(index);
return integer < 0 ? max(integer + length, 0) : min(integer, length);
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-length.js
var require_to_length = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-length.js"(exports, module2) {
"use strict";
var toIntegerOrInfinity = require_to_integer_or_infinity();
var min = Math.min;
module2.exports = function(argument) {
var len = toIntegerOrInfinity(argument);
return len > 0 ? min(len, 9007199254740991) : 0;
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/length-of-array-like.js
var require_length_of_array_like = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/length-of-array-like.js"(exports, module2) {
"use strict";
var toLength = require_to_length();
module2.exports = function(obj) {
return toLength(obj.length);
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/array-includes.js
var require_array_includes = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/array-includes.js"(exports, module2) {
"use strict";
var toIndexedObject = require_to_indexed_object();
var toAbsoluteIndex = require_to_absolute_index();
var lengthOfArrayLike = require_length_of_array_like();
var createMethod = function(IS_INCLUDES) {
return function($this, el, fromIndex) {
var O = toIndexedObject($this);
var length = lengthOfArrayLike(O);
if (length === 0) return !IS_INCLUDES && -1;
var index = toAbsoluteIndex(fromIndex, length);
var value;
if (IS_INCLUDES && el !== el) while (length > index) {
value = O[index++];
if (value !== value) return true;
}
else for (; length > index; index++) {
if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
}
return !IS_INCLUDES && -1;
};
};
module2.exports = {
// `Array.prototype.includes` method
// https://tc39.es/ecma262/#sec-array.prototype.includes
includes: createMethod(true),
// `Array.prototype.indexOf` method
// https://tc39.es/ecma262/#sec-array.prototype.indexof
indexOf: createMethod(false)
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-keys-internal.js
var require_object_keys_internal = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-keys-internal.js"(exports, module2) {
"use strict";
var uncurryThis = require_function_uncurry_this();
var hasOwn = require_has_own_property();
var toIndexedObject = require_to_indexed_object();
var indexOf = require_array_includes().indexOf;
var hiddenKeys = require_hidden_keys();
var push = uncurryThis([].push);
module2.exports = function(object, names) {
var O = toIndexedObject(object);
var i = 0;
var result = [];
var key;
for (key in O) !hasOwn(hiddenKeys, key) && hasOwn(O, key) && push(result, key);
while (names.length > i) if (hasOwn(O, key = names[i++])) {
~indexOf(result, key) || push(result, key);
}
return result;
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/enum-bug-keys.js
var require_enum_bug_keys = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/enum-bug-keys.js"(exports, module2) {
"use strict";
module2.exports = [
"constructor",
"hasOwnProperty",
"isPrototypeOf",
"propertyIsEnumerable",
"toLocaleString",
"toString",
"valueOf"
];
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-get-own-property-names.js
var require_object_get_own_property_names = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-get-own-property-names.js"(exports) {
"use strict";
var internalObjectKeys = require_object_keys_internal();
var enumBugKeys = require_enum_bug_keys();
var hiddenKeys = enumBugKeys.concat("length", "prototype");
exports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
return internalObjectKeys(O, hiddenKeys);
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-get-own-property-symbols.js
var require_object_get_own_property_symbols = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/object-get-own-property-symbols.js"(exports) {
"use strict";
exports.f = Object.getOwnPropertySymbols;
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/own-keys.js
var require_own_keys = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/own-keys.js"(exports, module2) {
"use strict";
var getBuiltIn = require_get_built_in();
var uncurryThis = require_function_uncurry_this();
var getOwnPropertyNamesModule = require_object_get_own_property_names();
var getOwnPropertySymbolsModule = require_object_get_own_property_symbols();
var anObject = require_an_object();
var concat = uncurryThis([].concat);
module2.exports = getBuiltIn("Reflect", "ownKeys") || function ownKeys(it) {
var keys = getOwnPropertyNamesModule.f(anObject(it));
var getOwnPropertySymbols = getOwnPropertySymbolsModule.f;
return getOwnPropertySymbols ? concat(keys, getOwnPropertySymbols(it)) : keys;
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/copy-constructor-properties.js
var require_copy_constructor_properties = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/copy-constructor-properties.js"(exports, module2) {
"use strict";
var hasOwn = require_has_own_property();
var ownKeys = require_own_keys();
var getOwnPropertyDescriptorModule = require_object_get_own_property_descriptor();
var definePropertyModule = require_object_define_property();
module2.exports = function(target, source, exceptions) {
var keys = ownKeys(source);
var defineProperty = definePropertyModule.f;
var getOwnPropertyDescriptor = getOwnPropertyDescriptorModule.f;
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (!hasOwn(target, key) && !(exceptions && hasOwn(exceptions, key))) {
defineProperty(target, key, getOwnPropertyDescriptor(source, key));
}
}
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-forced.js
var require_is_forced = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-forced.js"(exports, module2) {
"use strict";
var fails = require_fails();
var isCallable = require_is_callable();
var replacement = /#|\.prototype\./;
var isForced = function(feature, detection) {
var value = data[normalize(feature)];
return value === POLYFILL ? true : value === NATIVE ? false : isCallable(detection) ? fails(detection) : !!detection;
};
var normalize = isForced.normalize = function(string) {
return String(string).replace(replacement, ".").toLowerCase();
};
var data = isForced.data = {};
var NATIVE = isForced.NATIVE = "N";
var POLYFILL = isForced.POLYFILL = "P";
module2.exports = isForced;
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/export.js
var require_export = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/export.js"(exports, module2) {
"use strict";
var globalThis2 = require_global_this();
var getOwnPropertyDescriptor = require_object_get_own_property_descriptor().f;
var createNonEnumerableProperty = require_create_non_enumerable_property();
var defineBuiltIn = require_define_built_in();
var defineGlobalProperty = require_define_global_property();
var copyConstructorProperties = require_copy_constructor_properties();
var isForced = require_is_forced();
module2.exports = function(options, source) {
var TARGET = options.target;
var GLOBAL = options.global;
var STATIC = options.stat;
var FORCED, target, key, targetProperty, sourceProperty, descriptor;
if (GLOBAL) {
target = globalThis2;
} else if (STATIC) {
target = globalThis2[TARGET] || defineGlobalProperty(TARGET, {});
} else {
target = globalThis2[TARGET] && globalThis2[TARGET].prototype;
}
if (target) for (key in source) {
sourceProperty = source[key];
if (options.dontCallGetSet) {
descriptor = getOwnPropertyDescriptor(target, key);
targetProperty = descriptor && descriptor.value;
} else targetProperty = target[key];
FORCED = isForced(GLOBAL ? key : TARGET + (STATIC ? "." : "#") + key, options.forced);
if (!FORCED && targetProperty !== void 0) {
if (typeof sourceProperty == typeof targetProperty) continue;
copyConstructorProperties(sourceProperty, targetProperty);
}
if (options.sham || targetProperty && targetProperty.sham) {
createNonEnumerableProperty(sourceProperty, "sham", true);
}
defineBuiltIn(target, key, sourceProperty, options);
}
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-array.js
var require_is_array = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/is-array.js"(exports, module2) {
"use strict";
var classof = require_classof_raw();
module2.exports = Array.isArray || function isArray(argument) {
return classof(argument) === "Array";
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-string-tag-support.js
var require_to_string_tag_support = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-string-tag-support.js"(exports, module2) {
"use strict";
var wellKnownSymbol = require_well_known_symbol();
var TO_STRING_TAG = wellKnownSymbol("toStringTag");
var test = {};
test[TO_STRING_TAG] = "z";
module2.exports = String(test) === "[object z]";
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/classof.js
var require_classof = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/classof.js"(exports, module2) {
"use strict";
var TO_STRING_TAG_SUPPORT = require_to_string_tag_support();
var isCallable = require_is_callable();
var classofRaw = require_classof_raw();
var wellKnownSymbol = require_well_known_symbol();
var TO_STRING_TAG = wellKnownSymbol("toStringTag");
var $Object = Object;
var CORRECT_ARGUMENTS = classofRaw(/* @__PURE__ */ (function() {
return arguments;
})()) === "Arguments";
var tryGet = function(it, key) {
try {
return it[key];
} catch (error) {
}
};
module2.exports = TO_STRING_TAG_SUPPORT ? classofRaw : function(it) {
var O, tag, result;
return it === void 0 ? "Undefined" : it === null ? "Null" : typeof (tag = tryGet(O = $Object(it), TO_STRING_TAG)) == "string" ? tag : CORRECT_ARGUMENTS ? classofRaw(O) : (result = classofRaw(O)) === "Object" && isCallable(O.callee) ? "Arguments" : result;
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-string.js
var require_to_string = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/to-string.js"(exports, module2) {
"use strict";
var classof = require_classof();
var $String = String;
module2.exports = function(argument) {
if (classof(argument) === "Symbol") throw new TypeError("Cannot convert a Symbol value to a string");
return $String(argument);
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/create-property.js
var require_create_property = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/create-property.js"(exports, module2) {
"use strict";
var DESCRIPTORS = require_descriptors();
var definePropertyModule = require_object_define_property();
var createPropertyDescriptor = require_create_property_descriptor();
module2.exports = function(object, key, value) {
if (DESCRIPTORS) definePropertyModule.f(object, key, createPropertyDescriptor(0, value));
else object[key] = value;
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/parse-json-string.js
var require_parse_json_string = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/internals/parse-json-string.js"(exports, module2) {
"use strict";
var uncurryThis = require_function_uncurry_this();
var hasOwn = require_has_own_property();
var $SyntaxError = SyntaxError;
var $parseInt = parseInt;
var fromCharCode = String.fromCharCode;
var at = uncurryThis("".charAt);
var slice = uncurryThis("".slice);
var exec = uncurryThis(/./.exec);
var codePoints = {
'\\"': '"',
"\\\\": "\\",
"\\/": "/",
"\\b": "\b",
"\\f": "\f",
"\\n": "\n",
"\\r": "\r",
"\\t": " "
};
var IS_4_HEX_DIGITS = /^[\da-f]{4}$/i;
var IS_C0_CONTROL_CODE = /^[\u0000-\u001F]$/;
module2.exports = function(source, i) {
var unterminated = true;
var value = "";
while (i < source.length) {
var chr = at(source, i);
if (chr === "\\") {
var twoChars = slice(source, i, i + 2);
if (hasOwn(codePoints, twoChars)) {
value += codePoints[twoChars];
i += 2;
} else if (twoChars === "\\u") {
i += 2;
var fourHexDigits = slice(source, i, i + 4);
if (!exec(IS_4_HEX_DIGITS, fourHexDigits)) throw new $SyntaxError("Bad Unicode escape at: " + i);
value += fromCharCode($parseInt(fourHexDigits, 16));
i += 4;
} else throw new $SyntaxError('Unknown escape sequence: "' + twoChars + '"');
} else if (chr === '"') {
unterminated = false;
i++;
break;
} else {
if (exec(IS_C0_CONTROL_CODE, chr)) throw new $SyntaxError("Bad control character in string literal at: " + i);
value += chr;
i++;
}
}
if (unterminated) throw new $SyntaxError("Unterminated string at: " + i);
return { value, end: i };
};
}
});
// node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/modules/es.json.parse.js
var require_es_json_parse = __commonJS({
"node_modules/.pnpm/core-js@3.49.0/node_modules/core-js/modules/es.json.parse.js"() {
"use strict";
var $2 = require_export();
var DESCRIPTORS = require_descriptors();
var globalThis2 = require_global_this();
var getBuiltIn = require_get_built_in();
var uncurryThis = require_function_uncurry_this();
var call = require_function_call();
var isCallable = require_is_callable();
var isObject = require_is_object();
var isArray = require_is_array();
var hasOwn = require_has_own_property();
var toString = require_to_string();
var lengthOfArrayLike = require_length_of_array_like();
var createProperty = require_create_property();
var fails = require_fails();
var parseJSONString = require_parse_json_string();
var NATIVE_SYMBOL = require_symbol_constructor_detection();
var JSON2 = globalThis2.JSON;
var Number2 = globalThis2.Number;
var SyntaxError2 = globalThis2.SyntaxError;
var nativeParse = JSON2 && JSON2.parse;
var enumerableOwnProperties = getBuiltIn("Object", "keys");
var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
var at = uncurryThis("".charAt);
var slice = uncurryThis("".slice);
var exec = uncurryThis(/./.exec);
var push = uncurryThis([].push);
var IS_DIGIT = /^\d$/;
var IS_NON_ZERO_DIGIT = /^[1-9]$/;
var IS_NUMBER_START = /^[\d-]$/;
var IS_WHITESPACE = /^[\t\n\r ]$/;
var PRIMITIVE = 0;
var OBJECT = 1;
var $parse = function(source, reviver) {
source = toString(source);
var context = new Context(source, 0, "");
var root = context.parse();
var value = root.value;
var endIndex = context.skip(IS_WHITESPACE, root.end);
if (endIndex < source.length) {
throw new SyntaxError2('Unexpected extra character: "' + at(source, endIndex) + '" after the parsed data at: ' + endIndex);
}
return isCallable(reviver) ? internalize({ "": value }, "", reviver, root) : value;
};
var internalize = function(holder, name, reviver, node) {
var val = holder[name];
var unmodified = node && val === node.value;
var context = unmodified && typeof node.source == "string" ? { source: node.source } : {};
var elementRecordsLen, keys, len, i, P;
if (isObject(val)) {
var nodeIsArray = isArray(val);
var nodes = unmodified ? node.nodes : nodeIsArray ? [] : {};
if (nodeIsArray) {
elementRecordsLen = nodes.length;
len = lengthOfArrayLike(val);
for (i = 0; i < len; i++) {
internalizeProperty(val, i, internalize(val, "" + i, reviver, i < elementRecordsLen ? nodes[i] : void 0));
}
} else {
keys = enumerableOwnProperties(val);
len = lengthOfArrayLike(keys);
for (i = 0; i < len; i++) {
P = keys[i];
internalizeProperty(val, P, internalize(val, P, reviver, hasOwn(nodes, P) ? nodes[P] : void 0));
}
}
}
return call(reviver, holder, name, val, context);
};
var internalizeProperty = function(object, key, value) {
if (DESCRIPTORS) {
var descriptor = getOwnPropertyDescriptor(object, key);
if (descriptor && !descriptor.configurable) return;
}
if (value === void 0) delete object[key];
else createProperty(object, key, value);
};
var Node = function(value, end, source, nodes) {
this.value = value;
this.end = end;
this.source = source;
this.nodes = nodes;
};
var Context = function(source, index) {
this.source = source;
this.index = index;
};
Context.prototype = {
fork: function(nextIndex) {
return new Context(this.source, nextIndex);
},
parse: function() {
var source = this.source;
var i = this.skip(IS_WHITESPACE, this.index);
var fork = this.fork(i);
var chr = at(source, i);
if (exec(IS_NUMBER_START, chr)) return fork.number();
switch (chr) {
case "{":
return fork.object();
case "[":
return fork.array();
case '"':
return fork.string();
case "t":
return fork.keyword(true);
case "f":
return fork.keyword(false);
case "n":
return fork.keyword(null);
}
throw new SyntaxError2('Unexpected character: "' + chr + '" at: ' + i);
},
node: function(type, value, start, end, nodes) {
return new Node(value, end, type ? null : slice(this.source, start, end), nodes);
},
object: function() {
var source = this.source;
var i = this.index + 1;
var expectKeypair = false;
var object = {};
var nodes = {};
var closed = false;
while (i < source.length) {
i = this.until(['"', "}"], i);
if (at(source, i) === "}" && !expectKeypair) {
i++;
closed = true;
break;
}
var result = this.fork(i).string();
var key = result.value;
i = result.end;
i = this.until([":"], i) + 1;
i = this.skip(IS_WHITESPACE, i);
result = this.fork(i).parse();
createProperty(nodes, key, result);
createProperty(object, key, result.value);
i = this.until([",", "}"], result.end);
var chr = at(source, i);
if (chr === ",") {
expectKeypair = true;
i++;
} else if (chr === "}") {
i++;
closed = true;
break;
}
}
if (!closed) throw new SyntaxError2("Unterminated object at: " + i);
return this.node(OBJECT, object, this.index, i, nodes);
},
array: function() {
var source = this.source;
var i = this.index + 1;
var expectElement = false;
var array = [];
var nodes = [];
var closed = false;
while (i < source.length) {
i = this.skip(IS_WHITESPACE, i);
if (at(source, i) === "]" && !expectElement) {
i++;
closed = true;
break;
}
var result = this.fork(i).parse();
push(nodes, result);
push(array, result.value);
i = this.until([",", "]"], result.end);
if (at(source, i) === ",") {
expectElement = true;
i++;
} else if (at(source, i) === "]") {
i++;
closed = true;
break;
}
}
if (!closed) throw new SyntaxError2("Unterminated array at: " + i);
return this.node(OBJECT, array, this.index, i, nodes);
},
string: function() {
var index = this.index;
var parsed = parseJSONString(this.source, this.index + 1);
return this.node(PRIMITIVE, parsed.value, index, parsed.end);
},
number: function() {
var source = this.source;
var startIndex = this.index;
var i = startIndex;
if (at(source, i) === "-") i++;
if (at(source, i) === "0") i++;
else if (exec(IS_NON_ZERO_DIGIT, at(source, i))) i = this.skip(IS_DIGIT, i + 1);
else throw new SyntaxError2("Failed to parse number at: " + i);
if (at(source, i) === ".") {
var fractionStartIndex = i + 1;
i = this.skip(IS_DIGIT, fractionStartIndex);
if (fractionStartIndex === i) throw new SyntaxError2("Failed to parse number's fraction at: " + i);
}
if (at(source, i) === "e" || at(source, i) === "E") {
i++;
if (at(source, i) === "+" || at(source, i) === "-") i++;
var exponentStartIndex = i;
i = this.skip(IS_DIGIT, i);
if (exponentStartIndex === i) throw new SyntaxError2("Failed to parse number's exponent value at: " + i);
}
return this.node(PRIMITIVE, Number2(slice(source, startIndex, i)), startIndex, i);
},
keyword: function(value) {
var keyword = "" + value;
var index = this.index;
var endIndex = index + keyword.length;
if (slice(this.source, index, endIndex) !== keyword) throw new SyntaxError2("Failed to parse value at: " + index);
return this.node(PRIMITIVE, value, index, endIndex);
},
skip: function(regex, i) {
var source = this.source;
for (; i < source.length; i++) if (!exec(regex, at(source, i))) break;
return i;
},
until: function(array, i) {
i = this.skip(IS_WHITESPACE, i);
var chr = at(this.source, i);
for (var j = 0; j < array.length; j++) if (array[j] === chr) return i;
throw new SyntaxError2('Unexpected character: "' + chr + '" at: ' + i);
}
};
var NO_SOURCE_SUPPORT = fails(function() {
var unsafeInt = "9007199254740993";
var source;
nativeParse(unsafeInt, function(key, value, context) {
source = context.source;
});
return source !== unsafeInt;
});
var PROPER_BASE_PARSE = NATIVE_SYMBOL && !fails(function() {
return 1 / nativeParse("-0 ") !== -Infinity;
});
$2({ target: "JSON", stat: true, forced: NO_SOURCE_SUPPORT }, {
parse: function parse(text, reviver) {
return PROPER_BASE_PARSE && !isCallable(reviver) ? nativeParse(text) : $parse(text, reviver);
}
});
}
});
// dist/Navigation_popups/Navigation_popups.js
//! src/Navigation_popups/modules/api.ts
require_es_json_parse();
var _templateObject;
var _templateObject2;
var _templateObject3;
var _templateObject4;
var _templateObject5;
var _templateObject6;
var _templateObject7;
var _templateObject8;
var _templateObject9;
var _templateObject0;
var _templateObject1;
var _templateObject10;
var _templateObject11;
function asyncGeneratorStep(n, t, e, r, o, a, c) {
try {
var i = n[a](c), u = i.value;
} catch (n2) {
return void e(n2);
}
i.done ? t(u) : Promise.resolve(u).then(r, o);
}
function _asyncToGenerator(n) {
return function() {
var t = this, e = arguments;
return new Promise(function(r, o) {
var a = n.apply(t, e);
function _next(n2) {
asyncGeneratorStep(a, r, o, _next, _throw, "next", n2);
}
function _throw(n2) {
asyncGeneratorStep(a, r, o, _next, _throw, "throw", n2);
}
_next(void 0);
});
};
}
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;
}
function _taggedTemplateLiteral(e, t) {
return t || (t = e.slice(0)), Object.freeze(Object.defineProperties(e, { raw: { value: Object.freeze(t) } }));
}
var import_ext_gadget = require("ext.gadget.Util");
var api = (0, import_ext_gadget.initMwApi)("Navigation popups/1.0");
//! src/Navigation_popups/modules/string.ts
var message = {
// summary data, searching etc.
article: window.wgULS("条目", "條目"),
category: window.wgULS("个分类", "個分類"),
categories: window.wgULS("个分类", "個分類"),
image: window.wgULS("个文件", "個檔案"),
images: window.wgULS("个文件", "個檔案"),
stub: "小作品",
"section stub": window.wgULS("小章节", "小章節"),
"Empty page": window.wgULS("空页面", "空頁面"),
kB: window.wgULS("千字节<sub>(以1000为一进)</sub>", "千位元組<sub>(以1000為一進)</sub>"),
bytes: window.wgULS("字节", "位元組"),
day: "天",
days: "天",
hour: window.wgULS("小时", "小時"),
hours: window.wgULS("小时", "小時"),
minute: "分",
minutes: "分",
second: "秒",
seconds: "秒",
week: "周",
weeks: "周",
month: "月",
months: "月",
year: "年",
years: "年",
search: window.wgULS("搜索", "搜尋"),
SearchHint: window.wgULS("搜索包含 %s 的页面", "搜尋包含 %s 的頁面"),
web: "Bing",
global: "全域",
"more...": "更多……",
// article-related actions and info
// (some actions also apply to user pages)
actions: window.wgULS("操作", "動作"),
// /// view articles and view talk
popupsMenu: "Popups",
"disable previews": window.wgULS("禁用预览", "禁用預覽"),
togglePreviewsHint: window.wgULS("切换本页 Popups 的预览开关", "切換本頁 Popups 的預覽開關"),
"toggle previews": window.wgULS("切换预览开关", "切換預覽開關"),
reset: window.wgULS("复位", "複位"),
disable: "禁用 Popups",
disablePopupsHint: window.wgULS("在本页禁用 Popups,刷新页面以重新启用。", "在本頁禁用 Popups,重新整理頁面以重新啟用。"),
purgePopupsHint: window.wgULS("复位 Popups,清除所有缓存数据。", "複位 Popups,清除所有快取資料。"),
PopupsHint: window.wgULS("复位 Popups,清除所有缓存数据。", "複位 Popups,清除所有快取資料。"),
spacebar: "空格",
view: window.wgULS("查看", "檢視"),
"view article": window.wgULS("查看条目", "檢視條目"),
viewHint: window.wgULS("前往 %s", "前往 %s"),
talk: window.wgULS("讨论", "討論"),
"talk page": window.wgULS("讨论页", "討論頁"),
"this revision": window.wgULS("此修订版本", "此修訂版本"),
"revision %s of %s": window.wgULS("页面 $2 的修订版本 $1", "頁面 $2 的修訂版本 $1"),
"Revision %s of %s": window.wgULS("页面 $2 的修订版本 $1", "頁面 $2 的修訂版本 $1"),
"the revision prior to revision %s of %s": window.wgULS("页面 $2 的修订版本 $1 之前的修订版本", "頁面 $2 的修訂版本 $1 之前的修訂版本"),
"Toggle image size": window.wgULS("点击切换图片大小", "點擊切換圖片大小"),
del: window.wgULS("删除", "删除"),
// /// delete, protect, move
delete: window.wgULS("删除", "删除"),
deleteHint: window.wgULS("删除 %s", "删除 %s"),
undeleteShort: window.wgULS("恢复", "恢復"),
UndeleteHint: window.wgULS("恢复 %s", "恢復 %s"),
protect: window.wgULS("保护", "保護"),
protectHint: window.wgULS("保护 %s", "保護 %s"),
unprotectShort: window.wgULS("解除", "解除"),
unprotectHint: window.wgULS("解除对 %s 的保护", "解除對 %s 的保護"),
move: window.wgULS("移动", "移動"),
"move page": window.wgULS("移动页面", "移動頁面"),
MovepageHint: window.wgULS("修改 %s 的标题", "修改 %s 的標題"),
edit: window.wgULS("编辑", "編輯"),
// /// edit articles and talk
"edit article": window.wgULS("编辑条目", "編輯條目"),
editHint: window.wgULS("修改 %s 的内容", "修改 %s 的內容"),
"edit talk": window.wgULS("编辑讨论页", "編輯對話頁"),
new: window.wgULS("新", "新"),
"new topic": window.wgULS("新话题", "新話題"),
newSectionHint: window.wgULS("在 %s 增加新的讨论话题", "在 %s 增加新的討論話題"),
"null edit": window.wgULS("空编辑", "空編輯"),
nullEditHint: window.wgULS("进行一次对 %s 的空编辑", "製造一次對 %s 的空編輯"),
hist: window.wgULS("历史", "歷史"),
// /// history, diffs, editors, related
history: window.wgULS("历史", "歷史"),
historyHint: window.wgULS("%s 的修订历史", "%s 的修訂歷史"),
last: window.wgULS("之前", "之前"),
// [[MediaWiki:Last]]
lastEdit: window.wgULS("最近更改", "最近更改"),
"show last edit": window.wgULS("最近一次更改", "最新一次修訂"),
"Show the last edit": window.wgULS("显示最近一次更改的差异", "顯示最新一次修訂的差異"),
lastContrib: window.wgULS("最近编辑", "最近編輯"),
"last set of edits": window.wgULS("最近编辑", "最近編輯"),
lastContribHint: window.wgULS("显示由最后一位编辑者造成的差异", "顯示由最後一位編輯者製造的差異"),
cur: window.wgULS("当前", "當前"),
diffCur: window.wgULS("与当前版本的差异", "與目前版本的差異"),
"Show changes since revision %s": window.wgULS("显示自修订版本 %s 的差异", "顯示自修訂版本 %s 的差異"),
"%s old": window.wgULS("%s 前的最后版本", "%s 前的最后版本"),
// as in 4 weeks old
oldEdit: window.wgULS("旧编辑", "舊編輯"),
purge: window.wgULS("清除缓存", "清除快取"),
purgeHint: window.wgULS("清除服务器中 %s 的缓存", "清除伺服器中 %s 的快取"),
raw: window.wgULS("源代码", "原始碼"),
rawHint: window.wgULS("查看 %s 的源代码", "檢視 %s 的原始碼"),
render: window.wgULS("仅正文", "僅正文"),
renderHint: window.wgULS("显示 %s 的纯HTML解析(仅正文内容)", "顯示 %s 的純HTML解析(僅正文內容)"),
"Show the edit made to get revision": window.wgULS("显示编辑以得到修订版本", "顯示編輯以得到修訂版本"),
sinceMe: window.wgULS("自我", "自我"),
"changes since mine": window.wgULS("自我修订的差异", "自我修訂的差異"),
sinceMeHint: window.wgULS("显示自我上次修改以来的差异", "顯示自我上次修改以來的差異"),
"Couldn't find an edit by %s\nin the last %s edits to\n%s": window.wgULS("在 $3 最近 $2 次编辑中找不到 $1 做出的修改", "在 $3 最近 $2 次編輯中找不到 $1 做出的修改"),
eds: window.wgULS("编辑", "編輯"),
editors: window.wgULS("编辑者", "編輯者"),
editorListHint: window.wgULS("列出编辑过 %s 的用户", "列出編輯過 %s 的使用者"),
related: window.wgULS("相关", "相關"),
relatedChanges: window.wgULS("相关更改", "相關更改"),
"related changes": window.wgULS("相关更改", "相關更改"),
RecentchangeslinkedHint: window.wgULS("显示相关 %s 的修改", "顯示相關 %s 的修改"),
editOld: window.wgULS("编辑旧版", "編輯舊版"),
// /// edit old version, or revert
rv: window.wgULS("回退", "恢復"),
revert: window.wgULS("回退", "恢復"),
revertHint: window.wgULS("回退到 %s", "恢復到 %s"),
undo: window.wgULS("撤销", "撤銷"),
undoHint: window.wgULS("撤销这次编辑", "撤銷這次編輯"),
defaultpopupRedlinkSummary: window.wgULS("移除到空页面[[%s]]的链接(Popups)", "移除到空頁面[[%s]]的連結(Popups)"),
defaultpopupFixDabsSummary: window.wgULS("消歧义[[%s]]到[[%s]](Popups)", "消歧義[[%s]]到[[%s]](Popups)"),
defaultpopupFixRedirsSummary: window.wgULS("忽略从[[%s]]到[[%s]]的重定向(Popups)", "忽略從[[%s]]到[[%s]]的重新導向(Popups)"),
defaultpopupExtendedRevertSummary: window.wgULS("回退到$2在$1时编辑的修订版本$3(Popups)", "還原到$2在$1時製作的修訂版本$3(Popups)"),
defaultpopupRevertToPreviousSummary: window.wgULS("回退到修订版本%s的上一个版本(Popups)", "還原到修訂版本%s的上一個版本(Popups)"),
defaultpopupRevertSummary: window.wgULS("回退到修订版本%s(Popups)", "還原到修訂版本%s(Popups)"),
defaultpopupQueriedRevertToPreviousSummary: window.wgULS("回退到修订版本$1的上一个版本,由$3在$2时编辑(Popups)", "還原到修訂版本$1的上一個版本,由$3在$2時製作(Popups)"),
defaultpopupQueriedRevertSummary: window.wgULS("回退到$3在$2时编辑的修订版本$1(Popups)", "還原到$3在$2時製作的修訂版本$1(Popups)"),
defaultpopupRmDabLinkSummary: window.wgULS("移除到消歧义页[[%s]]的链接(Popups)", "移除到消歧義頁[[%s]]的連結(Popups)"),
Redirects: window.wgULS("重定向", "重定向"),
// as in Redirects to ...
// " to ": window.wgULS( "到","到" ),
// as in Redirects to ...
"Bypass redirect": window.wgULS("忽略重定向", "忽略重新導向"),
"Fix this redirect": window.wgULS("修复重定向", "修復重新導向"),
disambig: window.wgULS("消歧义", "消歧義"),
// /// add or remove dab etc.
disambigHint: window.wgULS("消歧义这个链接到 [[%s]]", "消歧義這個連結到 [[%s]]"),
"Click to disambiguate this link to:": window.wgULS("点击以消歧义这个链接到:", "點擊以消歧義這個連結到:"),
"remove this link": window.wgULS("移除链接", "移除連結"),
"remove all links to this page from this article": window.wgULS("移除此条目到这页的所有链接", "移除此條目到這頁的所有連結"),
"remove all links to this disambig page from this article": window.wgULS("移除此条目到这消歧义的所有链接", "移除此條目到這消歧義的所有連結"),
mainlink: window.wgULS("主链接", "主連結"),
// /// links, watch, unwatch
wikiLink: window.wgULS("个内部链接", "个內部連結"),
wikiLinks: window.wgULS("个内部链接", "个內部連結"),
"links here": window.wgULS("链入", "鏈入"),
whatLinksHere: window.wgULS("链入页面", "鏈入頁面"),
"what links here": window.wgULS("链入页面", "鏈入頁面"),
WhatlinkshereHint: window.wgULS("显示链接到 %s 的页面", "顯示連結到 %s 的頁面"),
unwatchShort: window.wgULS("取消", "取消"),
watchThingy: window.wgULS("监视", "監視"),
// called watchThingy because {}.watch is a function
watchHint: window.wgULS("加入 %s 到我的监视列表", "加入 %s 到我的監視列表"),
unwatchHint: window.wgULS("从我的监视列表移除 %s", "從我的監視列表移除 %s"),
"Only found one editor: %s made %s edits": window.wgULS("仅找到一位编者:%s 制造了 %s 次编辑", "僅找到一位編者:%s 製造了 %s 次編輯"),
"%s seems to be the last editor to the page %s": window.wgULS("%s 看上去是 %s 这页的最后一位编者", "%s 看上去是 %s 這頁的最後一位編者"),
rss: window.wgULS("RSS", "RSS"),
// diff previews
"Diff truncated for performance reasons": window.wgULS("出于性能考虑,差异已被截断", "出於效能考慮,差異已被截斷"),
"Old revision": window.wgULS("旧版本", "舊版本"),
"New revision": window.wgULS("新版本", "新版本"),
"Something went wrong :-(": window.wgULS("出问题了 :-(", "出問題了 :-("),
"Empty revision, maybe non-existent": window.wgULS("空的修订,可能并不存在", "空的修訂,可能並不存在"),
"Unknown date": window.wgULS("未知日期", "未知日期"),
// other special previews
"Empty category": window.wgULS("空的分类", "空的分類"),
"Category members (%s shown)": window.wgULS("分类成员(%s 显示)", "分類成員(%s 顯示)"),
"No image links found": window.wgULS("未找到文件链接", "未找到檔案連結"),
"File links": window.wgULS("文件链接", "檔案連結"),
"not commons": window.wgULS("维基共享中无此名称的文件。", "維基共享中無此名稱的檔案。"),
"commons only": window.wgULS("此文件来自维基共享。", "此檔案來自維基共享。"),
"No image found": window.wgULS("找不到文件", "找不到檔案"),
"commons dupe": window.wgULS("维基共享中存在此文件的副本。", "維基共享中存在此檔案的副本。"),
"commons conflict": window.wgULS("维基共享中存在此文件名称不同的副本。", "維基共享中存在此檔名稱不同的副本。"),
// user-related actions and info
user: window.wgULS("用户", "使用者"),
// /// user page, talk, email, space
"user page": window.wgULS("用户页", "使用者頁"),
"user talk": window.wgULS("用户讨论", "使用者對話"),
"edit user talk": window.wgULS("编辑用户讨论", "編輯使用者對話"),
"leave comment": window.wgULS("留言", "留言"),
email: window.wgULS("电邮", "電郵"),
"email user": window.wgULS("电邮用户", "電郵使用者"),
EmailuserHint: window.wgULS("给 %s 发送电子邮件", "給 %s 發送電子郵件"),
space: window.wgULS("子页面", "子頁面"),
// short form for userSpace link
PrefixindexHint: window.wgULS("显示 %s 的用户页子页面", "顯示 %s 的使用者頁子頁面"),
count: window.wgULS("统计", "統計"),
// /// contributions, tree, log
"edit counter": window.wgULS("编辑次数", "編輯次數"),
katelinkHint: window.wgULS("%s 的编辑次数", "%s 的編輯次數"),
contribs: window.wgULS("贡献", "貢獻"),
contributions: window.wgULS("贡献", "貢獻"),
deletedContribs: window.wgULS("已删除的贡献", "已刪除的貢獻"),
ContributionsHint: window.wgULS("%s 的用户贡献", "%s 的使用者貢獻"),
tree: window.wgULS("树", "樹"),
contribsTreeHint: window.wgULS("根据名字空间查看 %s 的贡献", "根據命名空間檢視 %s 的貢獻"),
log: window.wgULS("日志", "日誌"),
"user log": window.wgULS("用户日志", "使用者日誌"),
userLogHint: window.wgULS("显示 %s 的用户日志", "顯示 %s 的使用者日誌"),
unblockShort: window.wgULS("解除", "解除"),
block: window.wgULS("封禁", "封鎖"),
"block user": window.wgULS("封禁用户", "封鎖使用者"),
IpblocklistHint: window.wgULS("解封 %s", "解封 %s"),
BlockipHint: window.wgULS("封禁 %s", "封鎖 %s"),
"block log": window.wgULS("封禁日志", "封鎖日誌"),
blockLogHint: window.wgULS("显示 %s 的封禁日志", "顯示 %s 的封鎖日誌"),
protectLogHint: window.wgULS("显示 %s 的保护日志", "顯示 %s 的保護日誌"),
pageLogHint: window.wgULS("显示 %s 的日志", "顯示 %s 的日誌"),
deleteLogHint: window.wgULS("显示 %s 的删除日志", "顯示 %s 的刪除日誌"),
"Invalid %s %s": window.wgULS("选项 %s 不可用:%s", "選項 %s 不可用:%s"),
m: "小",
// Autoediting
"Enter a non-empty edit summary or press cancel to abort": window.wgULS("输入编辑摘要,或按取消中止操作", "輸入編輯摘要,或按取消中止操作"),
"Failed to get revision information, please edit manually.\n\n": window.wgULS("获取修订版本信息失败,请手动修改。\n\n", "獲取修訂版本資訊失敗,請手動修改。\n\n"),
"The %s button has been automatically clicked. Please wait for the next page to load.": window.wgULS("按钮 %s 已被自动点击,请等待下一个页面加载。", "按鈕 %s 已被自動點擊,請等待下一個頁面載入。"),
"Could not find button %s. Please check the settings in your javascript file.": window.wgULS("找不到按钮 %s,请检查您 JavaScript 文件中的设置。", "找不到按鈕 %s,請檢查您 JavaScript 檔案中的設定。"),
// Popups setup
"Open full-size image": window.wgULS("查看全尺寸图像", "檢視全尺寸影像"),
// 以下内容由 AnnAngela 补正
bingSearchHint: window.wgULS("在 Bing 上搜索“%s”", "在 bing 上搜尋「%s」"),
"enable previews": window.wgULS("启用预览", "啟用預覽"),
"show preview": window.wgULS("禁用预览", "禁用預覽"),
historyfeedHint: window.wgULS("该页面的近期更改 RSS feed", "該頁面的近期更改 RSS feed"),
"send thanks": window.wgULS("发送感谢", "傳送感謝"),
ThanksHint: window.wgULS("向该用户发送一封感谢消息", "向該使用者傳送一封感謝訊息"),
"mark patrolled": window.wgULS("标记为已巡查", "標記為已巡查"),
markpatrolledHint: window.wgULS("标记该编辑为已巡查", "標記該編輯為已巡查"),
"Could not marked this edit as patrolled": window.wgULS("无法标记该编辑为已巡查", "無法標記該編輯為已巡查"),
defaultpopupReviewedSummary: window.wgULS("标记从版本%s到%s间的编辑为已巡查", "標記從版本%s到%s間的編輯為已巡查"),
"Image from Commons": window.wgULS("来自维基共享的图片", "來自維基共用的圖片"),
"Description page": window.wgULS("图片描述页", "圖片描述頁"),
"Alt text:": window.wgULS("替换文本(Alt):", "替換文字(Alt):"),
revdel: window.wgULS("历史版本被隐藏", "歷史版本被隱藏"),
DeletedcontributionsHint: window.wgULS("用户%s的被删除编辑次数", "使用者%s的被刪除編輯次數"),
"No backlinks found": window.wgULS("找不到链入页面", "找不到鏈入頁面"),
" and more": window.wgULS("以及其他页面", "以及其他頁面"),
"Download preview data": window.wgULS("下载预览数据", "下載預覽資料"),
"Not a registered username": window.wgULS("非已注册的用户", "非已註冊的使用者"),
BLOCKED: window.wgULS("被封禁", "被封鎖"),
"Has blocks": window.wgULS("被部分封禁", "被部分封鎖"),
" edits since: ": window.wgULS("次编辑,注册日期为", "次編輯,註冊日期為"),
"last edit on ": window.wgULS("最后一次编辑于", "最後一次編輯於"),
EmailUserHint: window.wgULS("给 %s 发送电子邮件", "給 %s 發送電子郵件"),
RANGEBLOCKED: window.wgULS("IP段被封禁", "IP段被封鎖"),
"IP user": window.wgULS("IP用户", "IP使用者"),
"♀": "♀",
"♂": "♂",
HIDDEN: window.wgULS("全域隐藏", "全域隱藏"),
LOCKED: window.wgULS("全域锁定", "全域鎖定"),
"Invalid user": window.wgULS("非法用户名", "非法使用者名稱"),
diff: window.wgULS("差异", "差異"),
" to ": "至",
autoedit_version: "np20140416",
PrefixIndexHint: window.wgULS("显示用户%s的子页面", "顯示使用者%s的子頁面"),
nullEditSummary: window.wgULS("进行一次零编辑", "進行一次零編輯"),
// 用户组名称从系统消息获取
"group-no-autoconfirmed": window.wgULS("非自动确认用户", "非自動確認使用者"),
separator: "、",
comma: ","
};
//! src/Navigation_popups/modules/core.js
var popups = () => {
const pg = {
api: {},
re: {},
ns: {},
string: {},
wiki: {},
user: {},
misc: {},
option: {},
optionDefault: {},
flag: {},
cache: {},
structures: {},
timer: {},
counter: {},
current: {},
fn: {},
endoflist: null
};
if (window.pg && !(window.pg instanceof HTMLElement)) {
return;
}
window.pg = pg;
const setupTooltips = (container, remove, force, popData) => {
log("setupTooltips, container=".concat(container, ", remove=").concat(remove));
if (!container) {
if (getValueOf("popupOnEditSelection") && document && document.editform && document.editform.wpTextbox1) {
document.editform.wpTextbox1.onmouseup = doSelectionPopup;
}
container = defaultPopupsContainer();
}
if (!remove && !force && container.ranSetupTooltipsAlready) {
return;
}
container.ranSetupTooltipsAlready = !remove;
const anchors = container.querySelectorAll("a");
setupTooltipsLoop(anchors, 0, 250, 100, remove, popData);
};
const defaultPopupsContainer = () => {
if (getValueOf("popupOnlyArticleLinks")) {
return document.querySelector(".skin-vector-2022 .vector-body") || document.querySelector("#mw_content") || document.querySelector("#content") || document.querySelector("#article") || document;
}
return document;
};
const setupTooltipsLoop = function setupTooltipsLoop2(anchors, begin, howmany, sleep, remove, popData, ...args) {
log(simplePrintf("setupTooltipsLoop(%s,%s,%s,%s,%s)", [anchors, begin, howmany, sleep, remove, popData, ...args]));
const finish = begin + howmany;
const loopend = Math.min(finish, anchors.length);
let j = loopend - begin;
log("setupTooltips: anchors.length=".concat(anchors.length, ", begin=").concat(begin, ", howmany=").concat(howmany, ", loopend=").concat(loopend, ", remove=").concat(remove));
const doTooltip = remove ? removeTooltip : addTooltip;
if (j > 0) {
do {
const a = anchors[loopend - j];
if (a === void 0 || !a || !a.href) {
log("got null anchor at index ".concat(loopend) - j);
continue;
}
doTooltip(a, popData);
} while (--j);
}
if (finish < anchors.length) {
setTimeout(() => {
setupTooltipsLoop2(anchors, finish, howmany, sleep, remove, popData);
}, sleep);
} else {
if (!remove && !getValueOf("popupTocLinks")) {
rmTocTooltips();
}
pg.flag.finishedLoading = true;
}
};
const rmTocTooltips = () => {
const toc = document.querySelector("#toc");
if (toc) {
const tocLinks = toc.querySelectorAll("a");
const tocLen = tocLinks.length;
for (let j = 0; j < tocLen; ++j) {
removeTooltip(tocLinks[j], true);
}
}
};
const addTooltip = (a, popData) => {
if (!isPopupLink(a)) {
return;
}
a.onmouseover = mouseOverWikiLink;
a.onmouseout = mouseOutWikiLink;
a.onmousedown = killPopup;
a.hasPopup = true;
a.popData = popData;
};
const removeTooltip = (a) => {
if (!a.hasPopup) {
return;
}
a.onmouseover = null;
a.onmouseout = null;
if (a.originalTitle) {
a.title = a.originalTitle;
}
a.hasPopup = false;
};
const removeTitle = (a) => {
a.originalTitle || (a.originalTitle = a.title);
a.title = "";
};
const restoreTitle = (a) => {
if (a.title || !a.originalTitle) {
return;
}
a.title = a.originalTitle;
};
const registerHooks = (np) => {
const popupMaxWidth = getValueOf("popupMaxWidth");
if (typeof popupMaxWidth === "number") {
const setMaxWidth = () => {
np.mainDiv.style.maxWidth = "".concat(popupMaxWidth, "px");
np.maxWidth = popupMaxWidth;
};
np.addHook(setMaxWidth, "unhide", "before");
}
np.addHook(addPopupShortcuts, "unhide", "after");
np.addHook(rmPopupShortcuts, "hide", "before");
};
const removeModifierKeyListener = (a) => {
document.removeEventListener("keydown", a.modifierKeyListener, false);
document.removeEventListener("keyup", a.modifierKeyListener, false);
};
const mouseOverWikiLink = function mouseOverWikiLink3(evt) {
if (!evt && window.event) {
evt = window.event;
}
if (getValueOf("popupModifier")) {
const action = getValueOf("popupModifierAction");
const key = action === "disable" ? "keyup" : "keydown";
const self2 = this;
self2.modifierKeyListener = (evt2) => {
mouseOverWikiLink2(self2, evt2);
};
document.addEventListener(key, self2.modifierKeyListener, false);
}
return mouseOverWikiLink2(this, evt);
};
const footnoteTarget = (a) => {
const aTitle = Title.fromAnchor(a);
const anch = aTitle.anchor;
if (!/^(cite_note-|_note-|endnote)/.test(anch)) {
return false;
}
const lTitle = Title.fromURL(location.href);
if (lTitle.toString(true) !== aTitle.toString(true)) {
return false;
}
let el = document.getElementById("".concat(anch));
while (el && typeof el.nodeName === "string") {
const nt = el.nodeName.toLowerCase();
if (nt === "li") {
return el;
} else if (nt === "body") {
return false;
} else if (el.parentNode) {
el = el.parentNode;
} else {
return false;
}
}
return false;
};
const footnotePreview = (x, navpop) => {
setPopupHTML("<hr>".concat(x.innerHTML), "popupPreview", navpop.idNumber);
};
const modifierPressed = (evt) => {
const mod = getValueOf("popupModifier");
if (!mod) {
return false;
}
if (!evt && window.event) {
evt = window.event;
}
return evt && mod && evt["".concat(mod.toLowerCase(), "Key")];
};
const isCorrectModifier = (_a, evt) => {
if (!getValueOf("popupModifier")) {
return true;
}
const action = getValueOf("popupModifierAction");
return action === "enable" && modifierPressed(evt) || action === "disable" && !modifierPressed(evt);
};
const mouseOverWikiLink2 = (a, evt) => {
if (!isCorrectModifier(a, evt)) {
return;
}
if (getValueOf("removeTitles")) {
removeTitle(a);
}
if (a === pg.current.link && a.navpopup && a.navpopup.isVisible()) {
return;
}
pg.current.link = a;
if (getValueOf("simplePopups") && !pg.option.popupStructure) {
setDefault("popupStructure", "original");
}
const article = new Title().fromAnchor(a);
pg.current.article = article;
if (!a.navpopup) {
a.navpopup = newNavpopup(a, article);
pg.current.linksHash[a.href] = a.navpopup;
pg.current.links.push(a);
}
if (a.navpopup.pending === null || a.navpopup.pending !== 0) {
simplePopupContent(a, article);
}
a.navpopup.showSoonIfStable(a.navpopup.delay);
clearInterval(pg.timer.checkPopupPosition);
pg.timer.checkPopupPosition = setInterval(checkPopupPosition, 600);
if (getValueOf("simplePopups") && getValueOf("popupPreviewButton") && !a.simpleNoMore) {
const d = document.createElement("div");
d.className = "popupPreviewButtonDiv";
const s = document.createElement("span");
d.append(s);
s.className = "popupPreviewButton";
s["on".concat(getValueOf("popupPreviewButtonEvent"))] = () => {
a.simpleNoMore = true;
d.style.display = "none";
nonsimplePopupContent(a, article);
};
s.innerHTML = popupString("show preview");
setPopupHTML(d, "popupPreview", a.navpopup.idNumber);
}
if (a.navpopup.pending !== 0) {
nonsimplePopupContent(a, article);
}
};
const simplePopupContent = (a, article) => {
a.navpopup.hasPopupMenu = false;
a.navpopup.setInnerHTML(popupHTML(a));
fillEmptySpans({
navpopup: a.navpopup
});
if (getValueOf("popupDraggable")) {
let dragHandle = getValueOf("popupDragHandle") || null;
if (dragHandle && dragHandle !== "all") {
dragHandle += a.navpopup.idNumber;
}
setTimeout(() => {
a.navpopup.makeDraggable(dragHandle);
}, 150);
}
if (getValueOf("popupRedlinkRemoval") && a.className === "new") {
setPopupHTML("<br>".concat(popupRedlinkHTML(article)), "popupRedlink", a.navpopup.idNumber);
}
};
const debugData = (navpopup) => {
if (getValueOf("popupDebugging") && navpopup.idNumber) {
setPopupHTML("idNumber=".concat(navpopup.idNumber, ", pending=").concat(navpopup.pending), "popupError", navpopup.idNumber);
}
};
const newNavpopup = (a, article) => {
const navpopup = new Navpopup();
navpopup.fuzz = 5;
navpopup.delay = getValueOf("popupDelay") * 1e3;
navpopup.idNumber = ++pg.idNumber;
navpopup.parentAnchor = a;
navpopup.parentPopup = a.popData && a.popData.owner;
navpopup.article = article;
registerHooks(navpopup);
return navpopup;
};
const shouldShowNonSimple = (a) => {
return !getValueOf("simplePopups") || a.simpleNoMore;
};
const shouldShow = (a, option) => {
if (shouldShowNonSimple(a)) {
return getValueOf(option);
}
return window[option] !== void 0 && window[option];
};
const nonsimplePopupContent = (a, article) => {
let diff2;
let history;
const params = parseParams(a.href);
const oldid = params.oldid === void 0 ? null : params.oldid;
if (shouldShow(a, "popupPreviewDiffs")) {
({
diff: diff2
} = params);
}
if (shouldShow(a, "popupPreviewHistory")) {
history = params.action === "history";
}
a.navpopup.pending = 0;
const referenceElement = footnoteTarget(a);
if (referenceElement) {
footnotePreview(referenceElement, a.navpopup);
} else if (diff2 || diff2 === 0) {
loadDiff(article, oldid, diff2, a.navpopup);
} else if (history) {
loadAPIPreview("history", article, a.navpopup);
} else if (shouldShowNonSimple(a) && pg.re.contribs.test(a.href)) {
loadAPIPreview("contribs", article, a.navpopup);
} else if (shouldShowNonSimple(a) && pg.re.backlinks.test(a.href)) {
loadAPIPreview("backlinks", article, a.navpopup);
} else if (
// FIXME should be able to get all preview combinations with options
article.namespaceId() === pg.nsImageId && (shouldShow(a, "imagePopupsForImages") || !anchorContainsImage(a))
) {
loadAPIPreview("imagepagepreview", article, a.navpopup);
loadImage(article, a.navpopup);
} else {
if (article.namespaceId() === pg.nsCategoryId && shouldShow(a, "popupCategoryMembers")) {
loadAPIPreview("category", article, a.navpopup);
} else if ((article.namespaceId() === pg.nsUserId || article.namespaceId() === pg.nsUsertalkId) && shouldShow(a, "popupUserInfo")) {
loadAPIPreview("userinfo", article, a.navpopup);
}
if (shouldShowNonSimple(a)) {
startArticlePreview(article, oldid, a.navpopup);
}
}
};
const pendingNavpopTask = (navpop) => {
if (navpop && navpop.pending === null) {
navpop.pending = 0;
}
++navpop.pending;
debugData(navpop);
};
const completedNavpopTask = (navpop) => {
if (navpop && navpop.pending) {
--navpop.pending;
}
debugData(navpop);
};
const startArticlePreview = (article, oldid, navpop) => {
navpop.redir = 0;
loadPreview(article, oldid, navpop);
};
const loadPreview = (article, oldid, navpop) => {
if (!navpop.redir) {
navpop.originalArticle = article;
}
article.oldid = oldid;
loadAPIPreview("revision", article, navpop);
};
const loadPreviewFromRedir = (redirMatch, navpop) => {
const target = new Title().fromWikiText(redirMatch[2]);
if (navpop.article.anchor) {
target.anchor = navpop.article.anchor;
}
navpop.redir++;
navpop.redirTarget = target;
const warnRedir = redirLink(target, navpop.article);
setPopupHTML(warnRedir, "popupWarnRedir", navpop.idNumber);
navpop.article = target;
fillEmptySpans({
redir: true,
redirTarget: target,
navpopup: navpop
});
return loadPreview(target, null, navpop);
};
const insertPreview = (download) => {
if (!download.owner) {
return;
}
const redirMatch = pg.re.redirect.exec(download.data);
if (download.owner.redir === 0 && redirMatch) {
loadPreviewFromRedir(redirMatch, download.owner);
return;
}
if (download.owner.visible || !getValueOf("popupLazyPreviews")) {
insertPreviewNow(download);
} else {
const id = download.owner.redir ? "PREVIEW_REDIR_HOOK" : "PREVIEW_HOOK";
download.owner.addHook(() => {
insertPreviewNow(download);
return true;
}, "unhide", "after", id);
}
};
const insertPreviewNow = (download) => {
if (!download.owner) {
return;
}
const wikiText = download.data;
const navpop = download.owner;
const art = navpop.redirTarget || navpop.originalArticle;
makeFixDabs(wikiText, navpop);
if (getValueOf("popupSummaryData")) {
getPageInfo(wikiText, download);
setPopupTrailer(getPageInfo(wikiText, download), navpop.idNumber);
}
let imagePage = "";
imagePage = art.namespaceId() === pg.nsImageId ? art.toString() : getValidImageFromWikiText(wikiText);
if (imagePage) {
loadImage(Title.fromWikiText(imagePage), navpop);
}
if (getValueOf("popupPreviews")) {
insertArticlePreview(download, art, navpop);
}
};
const insertArticlePreview = (download, art, navpop) => {
if (download && typeof download.data === "string") {
if (art.namespaceId() === pg.nsTemplateId && getValueOf("popupPreviewRawTemplates")) {
const h = '<hr><span style="font-family: monospace;">'.concat(download.data.entify().split(String.raw(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n"], ["\\n"])))).join(String.raw(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["<br>\n"], ["<br>\\n"])))), "</span>");
setPopupHTML(h, "popupPreview", navpop.idNumber);
} else {
const p = prepPreviewmaker(download.data, art, navpop);
p.showPreview();
}
}
};
const prepPreviewmaker = (data, article, navpop) => {
const d = anchorize(data, article.anchorString());
const urlBase = joinPath([pg.wiki.articlebase, article.urlString()]);
const p = new Previewmaker(d, urlBase, navpop);
return p;
};
const anchorize = (d, anch) => {
if (!anch) {
return d;
}
const anchRe = new RegExp("(?:=+\\s*".concat(literalizeRegex(anch).replace(/[ _]/g, "[_ ]"), "\\s*=+|\\{\\{\\s*").concat(getValueOf("popupAnchorRegexp"), "\\s*(?:\\|[^|}]*)*?\\s*").concat(literalizeRegex(anch), "\\s*(?:\\|[^}]*)?}})"));
const match = d.match(anchRe);
if (match && match.length > 0 && match[0]) {
return d.slice(Math.max(0, d.indexOf(match[0])));
}
const lines = d.split("\n");
for (let i = 0; i < lines.length; ++i) {
lines[i] = lines[i].replace(/\[{2}([^\]|]*?\|)?(.*?)]{2}/g, "$2").replace(/'''([^'])/g, "$1").replace(/''([^'])/g, "$1");
if (anchRe.test(lines[i])) {
return d.split("\n").slice(i).join("\n").replace(/^[^=]*/, "");
}
}
return d;
};
const killPopup = function killPopup2() {
removeModifierKeyListener(this);
if (getValueOf("popupShortcutKeys")) {
rmPopupShortcuts();
}
if (!pg) {
return;
}
if (pg.current.link && pg.current.link.navpopup) {
pg.current.link.navpopup.banish();
}
pg.current.link = null;
abortAllDownloads();
if (pg.timer.checkPopupPosition) {
clearInterval(pg.timer.checkPopupPosition);
pg.timer.checkPopupPosition = null;
}
return true;
};
class Drag {
constructor() {
this.startCondition = null;
this.endHook = null;
}
/**
* Gets an event in a cross-browser manner.
*
* @param {Event} e
* @private
*/
static fixE(e) {
if (e === void 0) {
e = window.event;
}
if (e.layerX === void 0) {
e.layerX = e.offsetX;
}
if (e.layerY === void 0) {
e.layerY = e.offsetY;
}
return e;
}
/**
* Initialises the Drag instance by telling it which object you want to be draggable, and what
* you want to drag it by.
*
* @param {DOMElement} o The "handle" by which <code>oRoot</code> is dragged.
* @param {DOMElement} oRoot The object which moves when <code>o</code> is dragged, or <code>o</code> if omitted.
*/
init(o, oRoot) {
const self2 = this;
this.obj = o;
o.onmousedown = (e) => {
self2.start(e);
};
o.dragging = false;
o.popups_draggable = true;
o.hmode = true;
o.vmode = true;
o.root = oRoot || o;
if (Number.isNaN(Number.parseInt(o.root.style.left, 10))) {
o.root.style.left = "0px";
}
if (Number.isNaN(Number.parseInt(o.root.style.top, 10))) {
o.root.style.top = "0px";
}
o.root.onthisStart = () => {
};
o.root.onthisEnd = () => {
};
o.root.onthis = () => {
};
}
/**
* Starts the drag.
*
* @private
* @param {Event} e
*/
start(e) {
const o = this.obj;
e = Drag.fixE(e);
if (this.startCondition && !this.startCondition(e)) {
return;
}
const y = Number.parseInt(o.vmode ? o.root.style.top : o.root.style.bottom, 10);
const x = Number.parseInt(o.hmode ? o.root.style.left : o.root.style.right, 10);
o.root.onthisStart(x, y);
o.lastMouseX = e.clientX;
o.lastMouseY = e.clientY;
const self2 = this;
o.onmousemoveDefault = document.onmousemove;
o.dragging = true;
document.onmousemove = (e2) => {
self2.drag(e2);
};
document.onmouseup = (e2) => {
self2.end(e2);
};
return false;
}
/**
* Does the drag.
*
* @param {Event} e
* @private
*/
drag(e) {
e = Drag.fixE(e);
const o = this.obj;
const ey = e.clientY;
const ex = e.clientX;
const y = Number.parseInt(o.vmode ? o.root.style.top : o.root.style.bottom, 10);
const x = Number.parseInt(o.hmode ? o.root.style.left : o.root.style.right, 10);
const nx = x + (ex - o.lastMouseX) * (o.hmode ? 1 : -1);
const ny = y + (ey - o.lastMouseY) * (o.vmode ? 1 : -1);
this.obj.root.style[o.hmode ? "left" : "right"] = "".concat(nx, "px");
this.obj.root.style[o.vmode ? "top" : "bottom"] = "".concat(ny, "px");
this.obj.lastMouseX = ex;
this.obj.lastMouseY = ey;
this.obj.root.onthis(nx, ny);
return false;
}
/**
* Ends the drag.
*
* @private
*/
end() {
document.onmousemove = this.obj.onmousemoveDefault;
document.onmouseup = null;
this.obj.dragging = false;
if (this.endHook) {
this.endHook(Number.parseInt(this.obj.root.style[this.obj.hmode ? "left" : "right"], 10), Number.parseInt(this.obj.root.style[this.obj.vmode ? "top" : "bottom"], 10));
}
}
}
pg.structures.original = {};
pg.structures.original.popupLayout = () => {
return ["popupError", "popupImage", "popupTopLinks", "popupTitle", "popupUserData", "popupData", "popupOtherLinks", "popupRedir", ["popupWarnRedir", "popupRedirTopLinks", "popupRedirTitle", "popupRedirData", "popupRedirOtherLinks"], "popupMiscTools", ["popupRedlink"], "popupPrePreviewSep", "popupPreview", "popupSecondPreview", "popupPreviewMore", "popupPostPreview", "popupFixDab"];
};
pg.structures.original.popupRedirSpans = () => {
return ["popupRedir", "popupWarnRedir", "popupRedirTopLinks", "popupRedirTitle", "popupRedirData", "popupRedirOtherLinks"];
};
pg.structures.original.popupTitle = (x) => {
log("defaultstructure.popupTitle");
if (!getValueOf("popupNavLinks")) {
return navlinkStringToHTML("<b><<mainlink>></b>", x.article, x.params);
}
return "";
};
pg.structures.original.popupTopLinks = (x) => {
log("defaultstructure.popupTopLinks");
if (getValueOf("popupNavLinks")) {
return navLinksHTML(x.article, x.hint, x.params);
}
return "";
};
pg.structures.original.popupImage = (x) => {
log("original.popupImage, x.article=".concat(x.article, ", x.navpop.idNumber=").concat(x.navpop.idNumber));
return imageHTML(x.article, x.navpop.idNumber);
};
pg.structures.original.popupRedirTitle = pg.structures.original.popupTitle;
pg.structures.original.popupRedirTopLinks = pg.structures.original.popupTopLinks;
const copyStructure = (oldStructure, newStructure) => {
pg.structures[newStructure] = {};
for (const prop in pg.structures[oldStructure]) {
if (!Object.hasOwn(pg.structures[oldStructure], prop)) {
continue;
}
pg.structures[newStructure][prop] = pg.structures[oldStructure][prop];
}
};
copyStructure("original", "nostalgia");
pg.structures.nostalgia.popupTopLinks = (x) => {
let str = "";
str += "<b><<mainlink|shortcut= >></b>";
str += "if(user){<br><<contribs|shortcut=c>>";
str += "if(wikimedia){*<<count|shortcut=#>>}";
str += "if(ipuser){}else{*<<email|shortcut=E>>}if(admin){*<<block|shortcut=b>>}}";
const editstr = "<<edit|shortcut=e>>";
const editOldidStr = "if(oldid){<<editOld|shortcut=e>>|<<revert|shortcut=v|rv>>|<<edit|cur>>}else{".concat(editstr, "}");
const historystr = "<<history|shortcut=h>>";
const watchstr = "<<unwatch|unwatchShort>>|<<watch|shortcut=w|watchThingy>>";
str += "<br>if(talk){".concat(editOldidStr, "|<<new|shortcut=+>>*").concat(historystr, "*").concat(watchstr, "*<b><<article|shortcut=a>></b>|<<editArticle|edit>>}else{").concat(
// not a talk page
editOldidStr,
"*"
).concat(historystr, "*").concat(watchstr, "*<b><<talk|shortcut=t>></b>|<<editTalk|edit>>|<<newTalk|shortcut=+|new>>}");
str += "<br><<whatLinksHere|shortcut=l>>*<<relatedChanges|shortcut=r>>";
str += "if(admin){<br>}else{*}<<move|shortcut=m>>";
str += "if(admin){*<<unprotect|unprotectShort>>|<<protect|shortcut=p>>*<<undelete|undeleteShort>>|<<delete|shortcut=d>>}";
return navlinkStringToHTML(str, x.article, x.params);
};
pg.structures.nostalgia.popupRedirTopLinks = pg.structures.nostalgia.popupTopLinks;
copyStructure("original", "fancy");
pg.structures.fancy.popupTitle = (x) => {
return navlinkStringToHTML("<font size=+0><<mainlink>></font>", x.article, x.params);
};
pg.structures.fancy.popupTopLinks = (x) => {
const hist = "<<history|shortcut=h|hist>>|<<lastEdit|shortcut=/|last>>|<<editors|shortcut=E|eds>>";
const watch = "<<unwatch|unwatchShort>>|<<watch|shortcut=w|watchThingy>>";
const move = "<<move|shortcut=m|move>>";
return navlinkStringToHTML("if(talk){<<edit|shortcut=e>>|<<new|shortcut=+|+>>*".concat(hist, "*<<article|shortcut=a>>|<<editArticle|edit>>*").concat(watch, "*").concat(move, "}else{<<edit|shortcut=e>>*").concat(hist, "*<<talk|shortcut=t|>>|<<editTalk|edit>>|<<newTalk|shortcut=+|new>>*").concat(watch, "*").concat(move, "}<br>"), x.article, x.params);
};
pg.structures.fancy.popupOtherLinks = (x) => {
const admin = "<<unprotect|unprotectShort>>|<<protect|shortcut=p>>*<<undelete|undeleteShort>>|<<delete|shortcut=d|del>>";
let user = "<<contribs|shortcut=c>>if(wikimedia){|<<count|shortcut=#|#>>}";
user += "if(ipuser){|<<arin>>}else{*<<email|shortcut=E|".concat(popupString("email"), ">>}if(admin){*<<block|shortcut=b>>}");
const normal = "<<whatLinksHere|shortcut=l|links here>>*<<relatedChanges|shortcut=r|related>>";
return navlinkStringToHTML("<br>if(user){".concat(user, "*}if(admin){").concat(admin, "if(user){<br>}else{*}}").concat(normal), x.article, x.params);
};
pg.structures.fancy.popupRedirTitle = pg.structures.fancy.popupTitle;
pg.structures.fancy.popupRedirTopLinks = pg.structures.fancy.popupTopLinks;
pg.structures.fancy.popupRedirOtherLinks = pg.structures.fancy.popupOtherLinks;
copyStructure("fancy", "fancy2");
pg.structures.fancy2.popupTopLinks = // hack out the <br> at the end and put one at the beginning
(x) => {
return "<br>".concat(pg.structures.fancy.popupTopLinks(x).replace(/<br>$/i, ""));
};
pg.structures.fancy2.popupLayout = () => {
return ["popupError", "popupImage", "popupTitle", "popupUserData", "popupData", "popupTopLinks", "popupOtherLinks", "popupRedir", ["popupWarnRedir", "popupRedirTopLinks", "popupRedirTitle", "popupRedirData", "popupRedirOtherLinks"], "popupMiscTools", ["popupRedlink"], "popupPrePreviewSep", "popupPreview", "popupSecondPreview", "popupPreviewMore", "popupPostPreview", "popupFixDab"];
};
copyStructure("original", "menus");
pg.structures.menus.popupLayout = () => {
return ["popupError", "popupImage", "popupTopLinks", "popupTitle", "popupOtherLinks", "popupRedir", ["popupWarnRedir", "popupRedirTopLinks", "popupRedirTitle", "popupRedirData", "popupRedirOtherLinks"], "popupUserData", "popupData", "popupMiscTools", ["popupRedlink"], "popupPrePreviewSep", "popupPreview", "popupSecondPreview", "popupPreviewMore", "popupPostPreview", "popupFixDab"];
};
pg.structures.menus.popupTopLinks = (x, shorter) => {
const s = [];
const dropdiv = '<div class="popup_drop">';
const enddiv = "</div>";
let hist = "<<history|shortcut=h>>";
if (!shorter) {
hist = "<menurow>".concat(hist, "|<<historyfeed|rss>>|<<editors|shortcut=E>></menurow>");
}
const lastedit = "<<lastEdit|shortcut=/|show last edit>>";
const thank = "if(diff){<<thank|send thanks>>}";
const jsHistory = "<<lastContrib|last set of edits>><<sinceMe|changes since mine>>";
const linkshere = "<<whatLinksHere|shortcut=l|what links here>>";
const related = "<<relatedChanges|shortcut=r|related changes>>";
const search = "<menurow><<search|shortcut=s>></menurow>";
const watch = "<menurow><<unwatch|unwatchShort>>|<<watch|shortcut=w|watchThingy>></menurow>";
const protect = "<menurow><<unprotect|unprotectShort>>|<<protect|shortcut=p>>|<<protectlog|log>></menurow>";
const del = "<menurow><<undelete|undeleteShort>>|<<delete|shortcut=d>>|<<deletelog|log>></menurow>";
const move = "<<move|shortcut=m|move page>>";
const nullPurge = "<menurow><<nullEdit|shortcut=n|null edit>>|<<purge|shortcut=P>></menurow>";
const viewOptions = "<menurow><<view|shortcut=v>>|<<render|shortcut=S>>|<<raw>></menurow>";
const editRow = "if(oldid){<menurow><<edit|shortcut=e>>|<<editOld|shortcut=e|this revision>></menurow><menurow><<revert|shortcut=v>>|<<undo>></menurow>}else{<<edit|shortcut=e>>}";
const markPatrolled = "if(rcid){<<markpatrolled|mark patrolled>>}";
const newTopic = "if(talk){<<new|shortcut=+|new topic>>}";
const protectDelete = "if(admin){".concat(protect).concat(del, "}");
if (getValueOf("popupActionsMenu")) {
s.push("<<mainlink>>*".concat(dropdiv).concat(menuTitle("actions")));
} else {
s.push("".concat(dropdiv, "<<mainlink>>"));
}
s.push("<menu>", editRow + markPatrolled + newTopic + hist + lastedit + thank);
if (!shorter) {
s.push(jsHistory);
}
s.push(move + linkshere + related);
if (!shorter) {
s.push(nullPurge + search);
}
if (!shorter) {
s.push(viewOptions);
}
s.push("<hr>".concat(watch).concat(protectDelete), "<hr>if(talk){<<article|shortcut=a|view article>><<editArticle|edit article>>}else{<<talk|shortcut=t|talk page>><<editTalk|edit talk>><<newTalk|shortcut=+|new topic>>}</menu>".concat(enddiv));
const email = "<<email|shortcut=E|email user>>";
const contribs = "if(wikimedia){<menurow>}<<contribs|shortcut=c|contributions>>if(wikimedia){</menurow>}if(admin){<menurow><<deletedContribs>></menurow>}";
s.push("if(user){*".concat(dropdiv).concat(menuTitle("user")), "<menu>", "<menurow><<userPage|shortcut=u|user page>>|<<userSpace|space>></menurow>", "<<userTalk|shortcut=t|user talk>><<editUserTalk|edit user talk>><<newUserTalk|shortcut=+|leave comment>>");
if (shorter) {
s.push("if(ipuser){}else{".concat(email, "}"));
} else {
s.push("if(ipuser){<<arin>>}else{".concat(email, "}"));
}
s.push("<hr>".concat(contribs, "<<userlog|shortcut=L|user log>>"), "if(wikimedia){<<count|shortcut=#|edit counter>>}", "if(admin){<menurow><<unblock|unblockShort>>|<<block|shortcut=b|block user>></menurow>}", "<<blocklog|shortcut=B|block log>>", "</menu>".concat(enddiv, "}"));
if (getValueOf("popupSetupMenu") && !x.navpop.hasPopupMenu) {
x.navpop.hasPopupMenu = true;
s.push("*".concat(dropdiv).concat(menuTitle("popupsMenu"), "<menu>"), "<<togglePreviews|toggle previews>>", "<<purgePopups|reset>>", "<<disablePopups|disable>>", "</menu>".concat(enddiv));
}
return navlinkStringToHTML(s.join(""), x.article, x.params);
};
const menuTitle = (s) => {
return '<a href="#" noPopup=1>'.concat(popupString(s), "</a>");
};
pg.structures.menus.popupRedirTitle = pg.structures.menus.popupTitle;
pg.structures.menus.popupRedirTopLinks = pg.structures.menus.popupTopLinks;
copyStructure("menus", "shortmenus");
pg.structures.shortmenus.popupTopLinks = (x) => {
return pg.structures.menus.popupTopLinks(x, true);
};
pg.structures.shortmenus.popupRedirTopLinks = pg.structures.shortmenus.popupTopLinks;
pg.structures.lite = {};
pg.structures.lite.popupLayout = () => {
return ["popupTitle", "popupPreview"];
};
pg.structures.lite.popupTitle = (x) => {
log("".concat(x.article, ": structures.lite.popupTitle"));
return '<div><span class="popup_mainlink"><b>'.concat(x.article.toString(), "</b></span></div>");
};
const substitute = (data, cmdBody) => {
const fromRe = new RegExp(cmdBody.from, cmdBody.flags);
return data.replace(fromRe, cmdBody.to);
};
const execCmds = (data, cmdList) => {
var _iterator = _createForOfIteratorHelper(cmdList), _step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done; ) {
const element = _step.value;
data = element.action(data, element);
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
return data;
};
const parseCmd = function parseCmd2(str) {
if (str.length === 0) {
return [];
}
let p = false;
switch (str.charAt(0)) {
case "s":
p = parseSubstitute(str);
break;
default:
return false;
}
if (p) {
return [p, parseCmd2(p.remainder)];
}
return false;
};
const unEscape = (str, sep) => {
return str.split("\\\\").join("\\").split("\\".concat(sep)).join(sep).split(String.raw(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n"], ["\\n"])))).join("\n");
};
const parseSubstitute = (str) => {
let from;
let to;
let flags;
let tmp;
if (str.length < 4) {
return false;
}
const sep = str.charAt(1);
str = str.slice(2);
tmp = skipOver(str, sep);
if (tmp) {
from = tmp.segment;
str = tmp.remainder;
} else {
return false;
}
tmp = skipOver(str, sep);
if (tmp) {
to = tmp.segment;
str = tmp.remainder;
} else {
return false;
}
flags = "";
if (str.length > 0) {
tmp = skipOver(str, ";") || skipToEnd(str, ";");
if (tmp) {
flags = tmp.segment;
str = tmp.remainder;
}
}
return {
action: substitute,
from,
to,
flags,
remainder: str
};
};
const skipOver = (str, sep) => {
const endSegment = findNext(str, sep);
if (endSegment < 0) {
return false;
}
const segment = unEscape(str.slice(0, Math.max(0, endSegment)), sep);
return {
segment,
remainder: str.slice(Math.max(0, endSegment + 1))
};
};
const skipToEnd = (str, _sep) => {
return {
segment: str,
remainder: ""
};
};
const findNext = (str, ch) => {
for (let i = 0; i < str.length; ++i) {
if (str.charAt(i) === "\\") {
i += 2;
}
if (str.charAt(i) === ch) {
return i;
}
}
return -1;
};
const setCheckbox = (param, box) => {
const val = mw.util.getParamValue(param);
if (val) {
switch (val) {
case "1":
case "yes":
case "true":
box.checked = true;
break;
case "0":
case "no":
case "false":
box.checked = false;
}
}
};
const autoEdit = function autoEdit4() {
setupPopups(() => {
if (mw.util.getParamValue("autoimpl") !== popupString("autoedit_version")) {
return false;
}
if (mw.util.getParamValue("autowatchlist") && mw.util.getParamValue("actoken") === autoClickToken()) {
pg.fn.modifyWatchlist(mw.util.getParamValue("title"), mw.util.getParamValue("action"));
}
if (!document.editform) {
return false;
}
if (autoEdit4.alreadyRan) {
return false;
}
autoEdit4.alreadyRan = true;
const cmdString = mw.util.getParamValue("autoedit");
if (cmdString) {
try {
const editbox = document.editform.wpTextbox1;
const cmdList = parseCmd(cmdString);
const input = editbox.value;
const output = execCmds(input, cmdList);
editbox.value = output;
} catch {
return;
}
}
setCheckbox("autominor", document.editform.wpMinoredit);
setCheckbox("autowatch", document.editform.wpWatchthis);
const rvid = mw.util.getParamValue("autorv");
if (rvid) {
const url = "".concat(pg.wiki.apiwikibase, "?action=query&format=json&formatversion=2&prop=revisions&revids=").concat(rvid);
startDownload(url, null, autoEdit2);
} else {
autoEdit2();
}
});
};
const autoEdit2 = (d) => {
let summary = mw.util.getParamValue("autosummary");
let summaryprompt = mw.util.getParamValue("autosummaryprompt");
let summarynotice = "";
if (d && d.data && mw.util.getParamValue("autorv")) {
const s = getRvSummary(summary, d.data);
if (s === false) {
summaryprompt = true;
summarynotice = popupString("Failed to get revision information, please edit manually.\n\n");
summary = simplePrintf(summary, [mw.util.getParamValue("autorv"), "(unknown)", "(unknown)"]);
} else {
summary = s;
}
}
if (summaryprompt) {
const txt = summarynotice + popupString("Enter a non-empty edit summary or press cancel to abort");
const response = prompt(txt, summary);
if (response) {
summary = response;
} else {
return;
}
}
if (summary) {
document.editform.wpSummary.value = summary;
}
setTimeout(autoEdit3, 100);
};
const autoClickToken = () => {
return mw.user.sessionId();
};
const autoEdit3 = () => {
if (mw.util.getParamValue("actoken") !== autoClickToken()) {
return;
}
const btn = mw.util.getParamValue("autoclick");
if (btn) {
if (document.editform && document.editform[btn]) {
const button = document.editform[btn];
const msg = tprintf("The %s button has been automatically clicked. Please wait for the next page to load.", [button.value]);
bannerMessage(msg);
document.title = "(".concat(document.title, ")");
button.click();
} else {
void mw.notify(tprintf("Could not find button %s. Please check the settings in your javascript file.", [btn]), {
tag: "popups",
type: "error"
});
}
}
};
const bannerMessage = (s) => {
const headings = document.querySelectorAll("h1");
if (headings) {
const div = document.createElement("div");
div.innerHTML = "<font size=+1><b>".concat(pg.escapeQuotesHTML(s), "</b></font>");
headings[0].parentNode.insertBefore(div, headings[0]);
}
};
const getRvSummary = (template, json) => {
try {
const o = getJsObj(json);
const [edit] = anyChild(o.query.pages).revisions;
const timestamp = edit.timestamp.split(/[A-Z]/g).join(" ").replace(/^ *| *$/g, "");
return simplePrintf(template, [edit.revid, timestamp, edit.userhidden ? "(hidden)" : edit.user]);
} catch {
return false;
}
};
class Downloader {
constructor(url) {
if (typeof XMLHttpRequest !== "undefined") {
this.http = new XMLHttpRequest();
}
this.url = url;
this.id = null;
this.lastModified = null;
this.callbackFunction = null;
this.onFailure = null;
this.aborted = false;
this.method = "GET";
this.async = true;
}
/**
* Submits the http request.
*
* @param {*} x
*/
send(x) {
if (!this.http) {
return null;
}
return this.http.send(x);
}
/* Aborts the download, setting the <code>aborted</code> field to true. */
abort() {
if (!this.http) {
return null;
}
this.aborted = true;
return this.http.abort();
}
/** Returns the downloaded data. */
getData() {
if (!this.http) {
return null;
}
return this.http.responseText;
}
/** Prepares the download. */
setTarget() {
if (!this.http) {
return null;
}
this.http.open(this.method, this.url, this.async);
this.http.setRequestHeader("Api-User-Agent", pg.api.userAgent);
}
/** Gets the state of the download. */
getReadyState() {
if (!this.http) {
return null;
}
return this.http.readyState;
}
/**
* Starts the download.
* Note that setTarget {@source Downloader#setTarget} must be run first
*/
start() {
if (!this.http) {
return;
}
const self2 = this;
pg.misc.downloadsInProgress[this.id] = self2;
this.http.send(null);
}
/**
* Gets the 'Last-Modified' date from the download headers.
* Should be run after the download completes.
* Returns <code>null</code> on failure.
*
* @return {Date}
*/
getLastModifiedDate() {
if (!this.http) {
return null;
}
let lastmod;
try {
lastmod = this.http.getResponseHeader("Last-Modified");
} catch {
}
if (lastmod) {
return new Date(lastmod);
}
return null;
}
/**
* Sets the callback function.
*
* @param {Function} f callback function, called as <code>f(this)</code> on success
*/
setCallback(f) {
if (!this.http) {
return;
}
this.http.onreadystatechange = f;
}
getStatus() {
if (!this.http) {
return null;
}
return this.http.status;
}
}
new Downloader();
pg.misc.downloadsInProgress = {};
const newDownload = function newDownload2(url, id, callback, onfailure) {
const d = new Downloader(url);
if (!d.http) {
return "ohdear";
}
d.id = id;
d.setTarget();
onfailure || (onfailure = 2);
const f = function() {
if (d.getReadyState() === 4) {
delete pg.misc.downloadsInProgress[this.id];
try {
if (d.getStatus() === 200) {
d.data = d.getData();
d.lastModified = d.getLastModifiedDate();
callback(d);
} else if (typeof onfailure === "number") {
if (onfailure > 0) {
newDownload2(url, id, callback, onfailure - 1);
}
} else if (typeof onfailure === "function") {
onfailure(d, url, id, callback);
}
} catch {
}
}
};
d.setCallback(f);
return d;
};
const fakeDownload = (url, id, callback, data, lastModified, owner) => {
const d = newDownload(url, callback);
d.owner = owner;
d.id = id;
d.data = data;
d.lastModified = lastModified;
return callback(d);
};
const startDownload = (url, id, callback) => {
const d = newDownload(url, id, callback);
if (typeof d === "string") {
return d;
}
d.start();
return d;
};
const abortAllDownloads = () => {
for (const x in pg.misc.downloadsInProgress) {
if (!Object.hasOwn(pg.misc.downloadsInProgress, x)) {
continue;
}
try {
pg.misc.downloadsInProgress[x].aborted = true;
pg.misc.downloadsInProgress[x].abort();
delete pg.misc.downloadsInProgress[x];
} catch {
}
}
};
const Insta = {};
const setupLivePreview = () => {
var _Insta$conf$user;
let _b;
Insta.conf = {
baseUrl: "",
user: {},
wiki: {
lang: pg.wiki.lang,
interwiki: pg.wiki.interwiki,
default_thumb_width: 180
},
paths: {
articles: "".concat(pg.wiki.articlePath, "/"),
// Only used for Insta previews with images. (not in popups)
math: "/math/",
images: "https://tu.zhongwen.wiki/images/qiuwenbaike/zh/",
images_fallback: "//wm.zhongwen.wiki/commons/"
},
locale: {
user: mw.config.get("wgFormattedNamespaces")[pg.nsUserId],
image: mw.config.get("wgFormattedNamespaces")[pg.nsImageId],
category: mw.config.get("wgFormattedNamespaces")[pg.nsCategoryId],
// shouldn't be used in popup previews, i think
months: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
}
};
(_Insta$conf$user = Insta.conf.user).name || (_Insta$conf$user.name = "Qiuwen Baike contributors");
Insta.conf.user.signature = "[[".concat(Insta.conf.locale.user, ":").concat(Insta.conf.user.name, "|").concat(Insta.conf.user.name, "]]");
Insta.BLOCK_IMAGE = new RegExp("^\\[\\[(?:File|Image|".concat(Insta.conf.locale.image, "):.*?\\|.*?(?:frame|thumbnail|thumb|none|right|left|center)"), "i");
};
Insta.dump = function(from, to) {
if (typeof from === "string") {
from = document.getElementById("".concat(from));
}
if (typeof to === "string") {
to = document.getElementById("".concat(to));
}
to.innerHTML = this.convert(from.value);
};
Insta.convert = (wiki) => {
const ll = typeof wiki === "string" ? wiki.replace(/\r/g, "").split(/\n/) : wiki;
let o = "";
let p = 0;
let r;
const remain = () => {
return ll.length;
};
const sh = () => {
return ll.shift();
};
const ps = (s) => {
o += s;
};
const f = function f2(...args) {
let i = 1;
const a = args;
let [f3] = a;
let o2 = "";
let c;
let p2;
for (; i < a.length; i++) {
if ((p2 = f3.indexOf("?")) + 1) {
c = f3.charAt(p2 + 1) === "?" ? 1 : 0;
i -= c;
o2 += f3.slice(0, Math.max(0, p2)) + (c ? "?" : a[i]);
f3 = f3.slice(p2 + 1 + c);
} else {
break;
}
}
return o2 + f3;
};
const html_entities = (s) => {
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
};
const htmlescape_text = (s) => {
return s.replace(/</g, "<").replace(/>/g, ">").replace(/:/g, ":").replace(/\[/g, "[").replace(/]/g, "]");
};
const htmlescape_attr = (s) => {
return htmlescape_text(s).replace(/'/g, "'").replace(/"/g, """);
};
const str_imatch = (a, b) => {
let i;
let l;
for (i = 0, l = Math.min(a.length, b.length); i < l; i++) {
if (a.charAt(i) !== b.charAt(i)) {
break;
}
}
return i;
};
const compareLineStringOrReg = (c) => {
return typeof c === "string" ? ll[0] && ll[0].slice(0, c.length) === c : r = ll[0] && ll[0].match(c);
};
const compareLineString = (c) => {
return ll[0] === c;
};
const charAtPoint = (p2) => {
return ll[0].charAt(p2);
};
const endl = (s) => {
ps(s);
sh();
};
const parse_list = () => {
let prev = "";
while (remain() && compareLineStringOrReg(/^([#*:;]+)(.*)$/)) {
const l_match = r;
sh();
const ipos = str_imatch(prev, l_match[1]);
for (let prevPos = prev.length - 1; prevPos >= ipos; prevPos--) {
const pi = prev.charAt(prevPos);
if (pi === "*") {
ps("</ul>");
} else if (pi === "#") {
ps("</ol>");
} else if (["", "*", "#"].indexOf(l_match[1].charAt(prevPos))) {
ps("</dl>");
}
}
for (let matchPos = ipos; matchPos < l_match[1].length; matchPos++) {
const li = l_match[1].charAt(matchPos);
if (li === "*") {
ps("<ul>");
} else if (li === "#") {
ps("<ol>");
} else if (["", "*", "#"].indexOf(prev.charAt(matchPos))) {
ps("<dl>");
}
}
switch (l_match[1].at(-1)) {
case "*":
case "#":
ps("<li>".concat(parse_inline_nowiki(l_match[2])));
break;
case ";": {
ps("<dt>");
const dt_match = l_match[2].match(/(.*?)(:.*?)$/);
if (dt_match) {
ps(parse_inline_nowiki(dt_match[1]));
ll.unshift(dt_match[2]);
} else {
ps(parse_inline_nowiki(l_match[2]));
}
break;
}
case ":":
ps("<dd>".concat(parse_inline_nowiki(l_match[2])));
}
[, prev] = l_match;
}
for (let i = prev.length - 1; i >= 0; i--) {
ps(f("</?>", prev.charAt(i) === "*" ? "ul" : prev.charAt(i) === "#" ? "ol" : "dl"));
}
};
const parse_table = () => {
endl(f("<table>", compareLineStringOrReg(/^{\|( .*)$/) ? r[1] : ""));
for (; remain(); ) {
if (compareLineStringOrReg("|")) {
switch (charAtPoint(1)) {
case "}":
endl("</table>");
return;
case "-":
endl(f("<tr>", compareLineStringOrReg(/\|-*(.*)/)[1]));
break;
default:
parse_table_data();
}
} else if (compareLineStringOrReg("!")) {
parse_table_data();
} else {
sh();
}
}
};
const parse_table_data = () => {
let td_line;
let match_i;
const td_match = sh().match(/^(\|\+|\||!)((?:([^[|]*?)\|(?!\|))?(.*))$/);
if (td_match[1] === "|+") {
ps("<caption");
} else {
ps("<t".concat(td_match[1] === "|" ? "d" : "h"));
}
if (td_match[3]) {
match_i = 4;
} else {
match_i = 2;
}
ps(">");
if (td_match[1] === "|+") {
ps(parse_inline_nowiki(td_match[match_i]));
} else {
td_line = td_match[match_i].split(td_match[1] === "|" ? "||" : /\|\||!!/);
ps(parse_inline_nowiki(td_line.shift()));
while (td_line.length > 0) {
ll.unshift(td_match[1] + td_line.pop());
}
}
let tc = 0;
const td = [];
while (remain()) {
td.push(sh());
if (compareLineStringOrReg("|")) {
if (!tc) {
break;
} else if (charAtPoint(1) === "}") {
tc--;
}
} else if (!tc && compareLineStringOrReg("!")) {
break;
} else if (compareLineStringOrReg("{|")) {
tc++;
}
}
if (td.length > 0) {
ps(Insta.convert(td));
}
};
const parse_pre = () => {
ps("<pre>");
do {
endl("".concat(parse_inline_nowiki(ll[0].slice(1)), "\n"));
} while (remain() && compareLineStringOrReg(" "));
ps("</pre>");
};
const parse_block_image = () => {
ps(parse_image(sh()));
};
const parse_image = (str) => {
let tag = str.substring(str.indexOf(":") + 1, str.length - 2);
let width;
let attr = [];
let filename;
let caption = "";
let thumb = 0;
let frame = 0;
let center = 0;
let align = "";
if (/\|/.test(tag)) {
let nesting = 0;
let last_attr;
for (let i = tag.length - 1; i > 0; i--) {
if (tag.charAt(i) === "|" && !nesting) {
last_attr = tag.slice(i + 1);
tag = tag.slice(0, Math.max(0, i));
break;
} else {
switch (tag.slice(i - 1, i - 1 + 2)) {
case "]]":
nesting++;
i--;
break;
case "[[":
nesting--;
i--;
}
}
}
attr = tag.split(/\s*\|\s*/);
attr.push(last_attr);
filename = attr.shift();
let w_match;
for (; attr.length > 0; attr.shift()) {
w_match = attr[0].match(/^(\d*)(?:[px]*\d*)?px$/);
if (w_match) {
[, width] = w_match;
} else {
switch (attr[0]) {
case "thumb":
case "thumbnail":
thumb = true;
frame = true;
break;
case "frame":
frame = true;
break;
case "none":
case "right":
case "left":
center = false;
[align] = attr;
break;
case "center":
center = true;
align = "none";
break;
default:
if (attr.length === 1) {
[caption] = attr;
}
}
}
}
} else {
filename = tag;
}
return "";
};
const parse_inline_nowiki = (str) => {
let start;
let lastend = 0;
let substart = 0;
let nestlev = 0;
let open;
let close;
let subloop;
let html = "";
while ((start = str.indexOf("<no".concat("wiki", ">"), substart)) !== -1) {
html += parse_inline_wiki(str.substring(lastend, start));
start += 8;
substart = start;
subloop = true;
do {
open = str.indexOf("<no".concat("wiki", ">"), substart);
close = str.indexOf("</no".concat("wiki", ">"), substart);
if (close <= open || open === -1) {
if (close === -1) {
return html + html_entities(str.slice(start));
}
substart = close + 9;
if (nestlev) {
nestlev--;
} else {
lastend = substart;
html += html_entities(str.substring(start, lastend - 9));
subloop = false;
}
} else {
substart = open + 8;
nestlev++;
}
} while (subloop);
}
return html + parse_inline_wiki(str.slice(lastend));
};
const parse_inline_images = (str) => {
let start;
let substart = 0;
let nestlev = 0;
let loop;
let close;
let open;
let wiki2;
let html;
while ((start = str.indexOf("[[", substart)) !== -1) {
if (new RegExp("^(Image|File|".concat(Insta.conf.locale.image, "):"), "i").test(str.slice(start + 2))) {
loop = true;
substart = start;
do {
substart += 2;
close = str.indexOf("]]", substart);
open = str.indexOf("[[", substart);
if (close <= open || open === -1) {
if (close === -1) {
return str;
}
substart = close;
if (nestlev) {
nestlev--;
} else {
wiki2 = str.substring(start, close + 2);
html = parse_image(wiki2);
str = str.replace(wiki2, html);
substart = start + html.length;
loop = false;
}
} else {
substart = open;
nestlev++;
}
} while (loop);
} else {
break;
}
}
return str;
};
const parse_inline_formatting = (str) => {
let em;
let st;
let i;
let li;
let o2 = "";
while ((i = str.indexOf("''", li)) + 1) {
o2 += str.substring(li, i);
li = i + 2;
if (str.charAt(i + 2) === "'") {
li++;
st = !st;
o2 += st ? "<strong>" : "</strong>";
} else {
em = !em;
o2 += em ? "<em>" : "</em>";
}
}
return o2 + str.slice(li);
};
const parse_inline_wiki = (str) => {
str = parse_inline_images(str);
str = parse_inline_formatting(str);
str = str.replace(/<math>(.*?)<\/math>/gi, "");
let date = /* @__PURE__ */ new Date();
let minutes = date.getUTCMinutes();
if (minutes < 10) {
minutes = "0".concat(minutes);
}
date = f("?:?, ? ? ? (UTC)", date.getUTCHours(), minutes, date.getUTCDate(), Insta.conf.locale.months[date.getUTCMonth()], date.getUTCFullYear());
return str.replace(/~{5}(?!~)/g, date).replace(/~{4}(?!~)/g, "".concat(Insta.conf.user.name, " ").concat(date)).replace(/~{3}(?!~)/g, Insta.conf.user.name).replace(new RegExp("\\[\\[:((?:".concat(Insta.conf.locale.category, "|Image|File|").concat(Insta.conf.locale.image, "|").concat(Insta.conf.wiki.interwiki, "):[^|]*?)\\]\\](\\w*)"), "gi"), (_$0, $1, $2) => {
return f("<a href='?'>?</a>", Insta.conf.paths.articles + htmlescape_attr($1), htmlescape_text($1) + htmlescape_text($2));
}).replace(new RegExp("\\[\\[(?:".concat(Insta.conf.locale.category, "|").concat(Insta.conf.wiki.interwiki, "):.*?\\]\\]"), "gi"), "").replace(new RegExp("\\[\\[:((?:".concat(Insta.conf.locale.category, "|Image|File|").concat(Insta.conf.locale.image, "|").concat(Insta.conf.wiki.interwiki, "):.*?)\\|([^\\]]+?)\\]\\](\\w*)"), "gi"), (_$0, $1, $2, $3) => {
return f("<a href='?'>?</a>", Insta.conf.paths.articles + htmlescape_attr($1), htmlescape_text($2) + htmlescape_text($3));
}).replace(/\[\[(\/[^|]*?)]]/g, (_$0, $1) => {
return f("<a href='?'>?</a>", Insta.conf.baseUrl + htmlescape_attr($1), htmlescape_text($1));
}).replace(/\[\[(\/.*?)\|(.+?)]]/g, (_$0, $1, $2) => {
return f("<a href='?'>?</a>", Insta.conf.baseUrl + htmlescape_attr($1), htmlescape_text($2));
}).replace(/\[\[([^[|]*?)]](\w*)/g, (_$0, $1, $2) => {
return f("<a href='?'>?</a>", Insta.conf.paths.articles + htmlescape_attr($1), htmlescape_text($1) + htmlescape_text($2));
}).replace(/\[\[([^[]*?)\|([^\]]+?)]](\w*)/g, (_$0, $1, $2, $3) => {
return f("<a href='?'>?</a>", Insta.conf.paths.articles + htmlescape_attr($1), htmlescape_text($2) + htmlescape_text($3));
}).replace(/\[\[([^\]]*?:)?(.*?)( *\(.*?\))?\|]]/g, (_$0, $1, $2, $3) => {
return f("<a href='?'>?</a>", Insta.conf.paths.articles + htmlescape_attr($1) + htmlescape_attr($2) + htmlescape_attr($3), htmlescape_text($2));
}).replace(/\[(https?|news|ftp|mailto|gopher|irc):(\/*)([^\]]*?) (.*?)]/g, (_$0, $1, $2, $3, $4) => {
return f("<a class='external' href='?:?'>?</a>", htmlescape_attr($1), htmlescape_attr($2) + htmlescape_attr($3), htmlescape_text($4));
}).replace(/\[http:\/\/(.*?)]/g, (_$0, $1) => {
return f("<a class='external' href='http://?'>[#]</a>", htmlescape_attr($1));
}).replace(/\[(news|ftp|mailto|gopher|irc):(\/*)(.*?)]/g, (_$0, $1, $2, $3) => {
return f("<a class='external' href='?:?'>?:?</a>", htmlescape_attr($1), htmlescape_attr($2) + htmlescape_attr($3), htmlescape_text($1), htmlescape_text($2) + htmlescape_text($3));
}).replace(/(^| )(https?|news|ftp|mailto|gopher|irc):(\/*)([^ $]*[^ !$,.:;?])/g, (_$0, $1, $2, $3, $4) => {
return f("?<a class='external' href='?:?'>?:?</a>", htmlescape_text($1), htmlescape_attr($2), htmlescape_attr($3) + htmlescape_attr($4), htmlescape_text($2), htmlescape_text($3) + htmlescape_text($4));
}).replace("__NOTOC__", "").replace("__NOINDEX__", "").replace("__INDEX__", "").replace("__NOEDITSECTION__", "");
};
for (; remain(); ) {
if (compareLineStringOrReg(/^(={1,6})(.*)\1(.*)$/)) {
p = 0;
endl(f("<h?>?</h?>?", r[1].length, parse_inline_nowiki(r[2]), r[1].length, r[3]));
} else if (compareLineStringOrReg(/^[#*:;]/)) {
p = 0;
parse_list();
} else if (compareLineStringOrReg(" ")) {
p = 0;
parse_pre();
} else if (compareLineStringOrReg("{|")) {
p = 0;
parse_table();
} else if (compareLineStringOrReg(/^----+$/)) {
p = 0;
endl("<hr>");
} else if (compareLineStringOrReg(Insta.BLOCK_IMAGE)) {
p = 0;
parse_block_image();
} else {
if (compareLineString("")) {
p = remain() > 1 && ll[1] === "";
if (p) {
endl("<p><br>");
}
} else {
if (!p) {
ps("<p>");
p = 1;
}
ps("".concat(parse_inline_nowiki(ll[0]), " "));
}
sh();
}
}
return o;
};
const wiki2html = (txt, baseurl) => {
Insta.conf.baseUrl = baseurl;
return Insta.convert(txt);
};
const popupFilterPageSize = (data) => {
return formatBytes(data.length);
};
const popupFilterCountLinks = (data) => {
const num = countLinks(data);
return "".concat(String(num), " ").concat(num === 1 ? popupString("wikiLink") : popupString("wikiLinks"));
};
const popupFilterCountImages = (data) => {
const num = countImages(data);
return "".concat(String(num), " ").concat(num === 1 ? popupString("image") : popupString("images"));
};
const popupFilterCountCategories = (data) => {
const num = countCategories(data);
return "".concat(String(num), " ").concat(num === 1 ? popupString("category") : popupString("categories"));
};
const popupFilterLastModified = (_data, download) => {
const lastmod = download.lastModified;
const now = /* @__PURE__ */ new Date();
const age = now - lastmod;
if (lastmod && getValueOf("popupLastModified")) {
return tprintf("%s old", [formatAge(age)]).replace(/ /g, " ");
}
return "";
};
const formatAge = (age) => {
let a = 0 + age;
const aa = a;
const seclen = 1e3;
const minlen = 60 * seclen;
const hourlen = 60 * minlen;
const daylen = 24 * hourlen;
const weeklen = 7 * daylen;
const numweeks = (a - a % weeklen) / weeklen;
a -= numweeks * weeklen;
const sweeks = addunit(numweeks, "week");
const numdays = (a - a % daylen) / daylen;
a -= numdays * daylen;
const sdays = addunit(numdays, "day");
const numhours = (a - a % hourlen) / hourlen;
a -= numhours * hourlen;
const shours = addunit(numhours, "hour");
const nummins = (a - a % minlen) / minlen;
a -= nummins * minlen;
const smins = addunit(nummins, "minute");
const numsecs = (a - a % seclen) / seclen;
a -= numsecs * seclen;
const ssecs = addunit(numsecs, "second");
if (aa > 4 * weeklen) {
return sweeks;
}
if (aa > weeklen) {
return "".concat(sweeks, " ").concat(sdays);
}
if (aa > daylen) {
return "".concat(sdays, " ").concat(shours);
}
if (aa > 6 * hourlen) {
return shours;
}
if (aa > hourlen) {
return "".concat(shours, " ").concat(smins);
}
if (aa > 10 * minlen) {
return smins;
}
if (aa > minlen) {
return "".concat(smins, " ").concat(ssecs);
}
return ssecs;
};
const addunit = (num, str) => {
return "".concat(num, " ").concat(num === 1 ? popupString(str) : popupString("".concat(str, "s")));
};
const runPopupFilters = (list, data, download) => {
const ret = [];
var _iterator2 = _createForOfIteratorHelper(list), _step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done; ) {
const element = _step2.value;
if (element && typeof element === "function") {
const s = element(data, download, download.owner.article);
if (s) {
ret.push(s);
}
}
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
return ret;
};
const getPageInfo = (data, download) => {
if (!data || data.length === 0) {
return popupString("Empty page");
}
const popupFilters = getValueOf("popupFilters") || [];
const extraPopupFilters = getValueOf("extraPopupFilters") || [];
const pageInfoArray = runPopupFilters([...popupFilters, ...extraPopupFilters], data, download);
let pageInfo = pageInfoArray.join(", ");
if (pageInfo !== "") {
pageInfo = upcaseFirst(pageInfo);
}
return pageInfo;
};
const countLinks = (wikiText) => {
return wikiText.split("[[").length - 1;
};
const countImages = (wikiText) => {
return (wikiText.split(pg.re.image).length - 1) / (pg.re.imageBracketCount + 1);
};
const countCategories = (wikiText) => {
return (wikiText.split(pg.re.category).length - 1) / (pg.re.categoryBracketCount + 1);
};
const popupFilterStubDetect = (data, _download, article) => {
const counts = stubCount(data, article);
if (counts.real) {
return popupString("stub");
}
if (counts.sect) {
return popupString("section stub");
}
return "";
};
const popupFilterDisambigDetect = (data, _download, article) => {
if (!getValueOf("popupAllDabsStubs") && article.namespace()) {
return "";
}
return isDisambig(data, article) ? popupString("disambig") : "";
};
const formatBytes = (num) => {
return num > 949 ? Math.round(num / 100) / 10 + popupString("kB") : "".concat(num, " ").concat(popupString("bytes"));
};
const Stringwrapper = function Stringwrapper2() {
this.indexOf = function(x) {
return this.toString().indexOf(x);
};
this.toString = function() {
return this.value;
};
this.split = function(x) {
return this.toString().split(x);
};
this.substring = function(x, y) {
if (y === void 0) {
return this.toString().slice(Math.max(0, x));
}
return this.toString().substring(x, y);
};
this.split = function(x) {
return this.toString().split(x);
};
this.replace = function(x, y) {
return this.toString().replace(x, y);
};
};
class Title extends Stringwrapper {
constructor(val) {
super();
this.value = null;
this.anchor = "";
this.setUtf(val);
}
/**
* Returns the canonical representation of the article title, optionally without anchor.
*
* @param {boolean} omitAnchor
* @fixme Decide specs for anchor
* @return String The article title and the anchor.
*/
toString(omitAnchor) {
return this.value + (!omitAnchor && this.anchor ? "#".concat(this.anchorString()) : "");
}
anchorString() {
if (!this.anchor) {
return "";
}
const split = this.anchor.split(/((?:\.[\dA-F]{2})+)/);
const len = split.length;
let value;
for (let j = 1; j < len; j += 2) {
value = split[j].split(".").join("%");
try {
value = decodeURIComponent(value);
} catch {
}
split[j] = value.split("_").join(" ");
}
return split.join("");
}
urlAnchor() {
const split = this.anchor.split("/((?:[%][0-9A-F]{2})+)/");
const len = split.length;
for (let j = 1; j < len; j += 2) {
split[j] = split[j].split("%").join(".");
}
return split.join("");
}
anchorFromUtf(str) {
this.anchor = encodeURIComponent(str.split(" ").join("_")).split("%3A").join(":").split("'").join("%27").split("%").join(".");
}
fromURL(h) {
if (typeof h !== "string") {
this.value = null;
return this;
}
const splitted = h.split("?");
splitted[0] = splitted[0].split("&").join("%26");
h = splitted.join("?");
const contribs = pg.re.contribs.exec(h);
if (contribs) {
if (contribs[1] === "title=") {
contribs[3] = contribs[3].split("+").join(" ");
}
const u = new Title(contribs[3]);
this.setUtf(Title.decodeNasties("".concat(mw.config.get("wgFormattedNamespaces")[pg.nsUserId], ":").concat(u.stripNamespace())));
return this;
}
const email = pg.re.email.exec(h);
if (email) {
this.setUtf(Title.decodeNasties("".concat(mw.config.get("wgFormattedNamespaces")[pg.nsUserId], ":").concat(new Title(email[3]).stripNamespace())));
return this;
}
const backlinks = pg.re.backlinks.exec(h);
if (backlinks) {
this.setUtf(Title.decodeNasties(new Title(backlinks[3])));
return this;
}
const specialdiff = pg.re.specialdiff.exec(h);
if (specialdiff) {
this.setUtf(Title.decodeNasties(new Title("".concat(mw.config.get("wgFormattedNamespaces")[pg.nsSpecialId], ":Diff"))));
return this;
}
const m = pg.re.main.exec(h);
if (m === null) {
this.value = null;
} else {
const fromBotInterface = /\?(.+&)?title=/.test(h);
if (fromBotInterface) {
m[2] = m[2].split("+").join("_");
}
const extracted = m[2] + (m[3] ? "#".concat(m[3]) : "");
if (pg.flag.isSafari && /%25[\dA-Fa-f]{2}/.test(extracted)) {
this.setUtf(decodeURIComponent(unescape(extracted)));
} else {
this.setUtf(Title.decodeNasties(extracted));
}
}
return this;
}
static decodeNasties(txt) {
try {
let ret = decodeURI(Title.decodeEscapes(txt));
ret = ret.replace(/[ _]*$/, "");
return ret;
} catch {
return txt;
}
}
// Decode valid %-encodings, otherwise escape them
static decodeEscapes(txt) {
const split = txt.split(/((?:%[\dA-Fa-f]{2})+)/);
const len = split.length;
if (len === 1) {
return split[0].replace(/%(?![\dA-Fa-f]{2})/g, "%25");
}
for (let i = 1; i < len; i += 2) {
split[i] = decodeURIComponent(split[i]);
}
return split.join("");
}
fromAnchor(a) {
if (!a) {
this.value = null;
return this;
}
return this.fromURL(a.href);
}
fromWikiText(txt) {
txt = myDecodeURI(txt);
this.setUtf(txt);
return this;
}
hintValue() {
if (!this.value) {
return "";
}
return safeDecodeURI(this.value);
}
toUserName(withNs) {
if (this.namespaceId() !== pg.nsUserId && this.namespaceId() !== pg.nsUsertalkId) {
this.value = null;
return;
}
this.value = (withNs ? "".concat(mw.config.get("wgFormattedNamespaces")[pg.nsUserId], ":") : "") + this.stripNamespace().split("/")[0];
}
userName(withNs) {
const t = new Title(this.value);
t.toUserName(withNs);
if (t.value) {
return t;
}
return null;
}
toTalkPage() {
if (this.value === null) {
return null;
}
const namespaceId = this.namespaceId();
if (namespaceId >= 0 && namespaceId % 2 === 0) {
const localizedNamespace = mw.config.get("wgFormattedNamespaces")[namespaceId + 1];
if (localizedNamespace !== void 0) {
this.value = localizedNamespace === "" ? this.stripNamespace() : "".concat(localizedNamespace.split(" ").join("_"), ":").concat(this.stripNamespace());
return this.value;
}
}
this.value = null;
return null;
}
// Return canonical, localized namespace
namespace() {
return mw.config.get("wgFormattedNamespaces")[this.namespaceId()];
}
namespaceId() {
const n = this.value.indexOf(":");
if (n === -1) {
return 0;
}
const namespaceId = mw.config.get("wgNamespaceIds")[this.value.slice(0, Math.max(0, n)).split(" ").join("_").toLowerCase()];
if (namespaceId === void 0) {
return 0;
}
return namespaceId;
}
talkPage() {
const t = new Title(this.value);
t.toTalkPage();
if (t.value) {
return t;
}
return null;
}
isTalkPage() {
if (this.talkPage() === null) {
return true;
}
return false;
}
toArticleFromTalkPage() {
if (this.value === null) {
return null;
}
const namespaceId = this.namespaceId();
if (namespaceId >= 0 && namespaceId % 2 === 1) {
const localizedNamespace = mw.config.get("wgFormattedNamespaces")[namespaceId - 1];
if (localizedNamespace !== void 0) {
this.value = localizedNamespace === "" ? this.stripNamespace() : "".concat(localizedNamespace.split(" ").join("_"), ":").concat(this.stripNamespace());
return this.value;
}
}
this.value = null;
return null;
}
articleFromTalkPage() {
const t = new Title(this.value);
t.toArticleFromTalkPage();
if (t.value) {
return t;
}
return null;
}
articleFromTalkOrArticle() {
const t = new Title(this.value);
if (t.toArticleFromTalkPage()) {
return t;
}
return this;
}
isIpUser() {
return pg.re.ipUser.test(this.userName());
}
stripNamespace() {
const n = this.value.indexOf(":");
if (n === -1) {
return this.value;
}
const namespaceId = this.namespaceId();
if (namespaceId === pg.nsMainspaceId) {
return this.value;
}
return this.value.slice(Math.max(0, n + 1));
}
setUtf(value) {
if (!value) {
this.value = "";
return;
}
const anch = value.indexOf("#");
if (anch === -1) {
this.value = value.split("_").join(" ");
this.anchor = "";
return;
}
this.value = value.slice(0, Math.max(0, anch)).split("_").join(" ");
this.anchor = value.slice(Math.max(0, anch + 1));
this.ns = null;
}
setUrl(urlfrag) {
const anch = urlfrag.indexOf("#");
this.value = safeDecodeURI(urlfrag.slice(0, Math.max(0, anch)));
this.anchor = this.value.slice(Math.max(0, anch + 1));
}
append(x) {
this.setUtf(this.value + x);
}
urlString(x) {
x || (x = {});
let v = this.toString(true);
if (!x.omitAnchor && this.anchor) {
v += "#".concat(this.urlAnchor());
}
if (!x.keepSpaces) {
v = v.split(" ").join("_");
}
return encodeURI(v).split("&").join("%26").split("?").join("%3F").split("+").join("%2B");
}
removeAnchor() {
return new Title(this.toString(true));
}
toUrl() {
return pg.wiki.titlebase + this.urlString();
}
}
Title.fromURL = (h) => {
return new Title().fromURL(h);
};
Title.fromAnchor = (a) => {
return new Title().fromAnchor(a);
};
Title.fromWikiText = (txt) => {
return new Title().fromWikiText(txt);
};
const parseParams = (url) => {
const specialDiff = pg.re.specialdiff.exec(url);
if (specialDiff) {
const split = specialDiff[1].split("/");
if (split.length === 1) {
return {
oldid: split[0],
diff: "prev"
};
} else if (split.length === 2) {
return {
oldid: split[0],
diff: split[1]
};
}
}
const ret = {};
if (!url.includes("?")) {
return ret;
}
[url] = url.split("#");
const s = url.split("?").slice(1).join(",");
const t = s.split("&");
var _iterator3 = _createForOfIteratorHelper(t), _step3;
try {
for (_iterator3.s(); !(_step3 = _iterator3.n()).done; ) {
const element = _step3.value;
const z = element.split("=");
z.push(null);
[, ret[z[0]]] = z;
}
} catch (err) {
_iterator3.e(err);
} finally {
_iterator3.f();
}
if (ret.diff && ret.oldid === void 0) {
ret.oldid = "prev";
}
if (ret.oldid && (ret.oldid === "prev" || ret.oldid === "next" || ret.oldid === "cur")) {
const helper = ret.diff;
ret.diff = ret.oldid;
ret.oldid = helper;
}
return ret;
};
const myDecodeURI = (str) => {
let ret;
try {
ret = decodeURI(str.toString());
} catch {
return str;
}
for (let i = 0; i < pg.misc.decodeExtras.length; ++i) {
const {
from
} = pg.misc.decodeExtras[i];
const {
to
} = pg.misc.decodeExtras[i];
ret = ret.split(from).join(to);
}
return ret;
};
const safeDecodeURI = (str) => {
const ret = myDecodeURI(str);
return ret || str;
};
const isDisambig = (data, article) => {
if (!getValueOf("popupAllDabsStubs") && article.namespace()) {
return false;
}
return !article.isTalkPage() && pg.re.disambig.test(data);
};
const stubCount = (data, article) => {
if (!getValueOf("popupAllDabsStubs") && article.namespace()) {
return false;
}
let sectStub = 0;
let realStub = 0;
if (pg.re.stub.test(data)) {
const s = data.split(pg.re.stub);
for (let i = 1; i < s.length; i += 2) {
if (s[i]) {
++sectStub;
} else {
++realStub;
}
}
}
return {
real: realStub,
sect: sectStub
};
};
const isValidImageName = (str) => {
return !str.includes("{");
};
const isInStrippableNamespace = (article) => {
return article.namespaceId() !== 0;
};
const isInMainNamespace = (article) => {
return article.namespaceId() === 0;
};
const anchorContainsImage = (a) => {
if (a === null) {
return false;
}
const kids = a.childNodes;
var _iterator4 = _createForOfIteratorHelper(kids), _step4;
try {
for (_iterator4.s(); !(_step4 = _iterator4.n()).done; ) {
const kid = _step4.value;
if (kid.nodeName === "IMG") {
return true;
}
}
} catch (err) {
_iterator4.e(err);
} finally {
_iterator4.f();
}
return false;
};
const isPopupLink = (a) => {
if (!markNopopupSpanLinks.done) {
markNopopupSpanLinks();
}
if (a.inNopopupSpan) {
return false;
}
if (a.onmousedown || a.getAttribute("nopopup")) {
return false;
}
const h = a.href;
if (h === "".concat(document.location.href, "#")) {
return false;
}
if (!pg.re.basenames.test(h)) {
return false;
}
if (!pg.re.urlNoPopup.test(h)) {
return true;
}
return (pg.re.email.test(h) || pg.re.contribs.test(h) || pg.re.backlinks.test(h) || pg.re.specialdiff.test(h)) && !h.includes("&limit=");
};
const markNopopupSpanLinks = function markNopopupSpanLinks2() {
if (!getValueOf("popupOnlyArticleLinks")) {
fixVectorMenuPopups();
}
const $body = $("body");
const s = $body.find(".nopopups").toArray();
var _iterator5 = _createForOfIteratorHelper(s), _step5;
try {
for (_iterator5.s(); !(_step5 = _iterator5.n()).done; ) {
const element = _step5.value;
const as = element.querySelectorAll("a");
var _iterator6 = _createForOfIteratorHelper(as), _step6;
try {
for (_iterator6.s(); !(_step6 = _iterator6.n()).done; ) {
const a = _step6.value;
a.inNopopupSpan = true;
}
} catch (err) {
_iterator6.e(err);
} finally {
_iterator6.f();
}
}
} catch (err) {
_iterator5.e(err);
} finally {
_iterator5.f();
}
markNopopupSpanLinks2.done = true;
};
const fixVectorMenuPopups = () => {
const $body = $("body");
$body.find("nav.vector-menu h3:first a:first").prop("inNopopupSpan", true);
};
const getPageWithCaching = (url, onComplete, owner) => {
log("getPageWithCaching, url=".concat(url));
const i = findInPageCache(url);
let d;
if (i > -1) {
d = fakeDownload(url, owner.idNumber, onComplete, pg.cache.pages[i].data, pg.cache.pages[i].lastModified, owner);
} else {
d = getPage(url, onComplete, owner);
if (d && owner && owner.addDownload) {
owner.addDownload(d);
d.owner = owner;
}
}
};
const getPage = (url, onComplete, owner) => {
log("getPage");
const callback = (d) => {
if (!d.aborted) {
addPageToCache(d);
onComplete(d);
}
};
return startDownload(url, owner.idNumber, callback);
};
const findInPageCache = (url) => {
for (let i = 0; i < pg.cache.pages.length; ++i) {
if (url === pg.cache.pages[i].url) {
return i;
}
}
return -1;
};
const addPageToCache = (download) => {
log("addPageToCache ".concat(download.url));
const page = {
url: download.url,
data: download.data,
lastModified: download.lastModified
};
return pg.cache.pages.push(page);
};
const getJsObj = (json) => {
try {
const json_ret = JSON.parse(json);
if (json_ret.warnings) {
for (let w = 0; w < json_ret.warnings.length; w++) {
if (json_ret.warnings[w]["*"]) {
log(json_ret.warnings[w]["*"]);
} else {
log(json_ret.warnings[w].warnings);
}
}
} else if (json_ret.error) {
errlog("".concat(json_ret.error.code, ": ").concat(json_ret.error.info));
}
return json_ret;
} catch {
errlog("Something went wrong with getJsObj, json=".concat(json));
return 1;
}
};
const anyChild = (obj) => {
for (const p in obj) {
if (!Object.hasOwn(obj, p)) {
continue;
}
return obj[p];
}
return null;
};
const upcaseFirst = (str) => {
if (typeof str !== "string" || str === "") {
return;
}
return str.charAt(0).toUpperCase() + str.slice(1);
};
const findInArray = (arr, foo) => {
if (!arr || arr.length === 0) {
return -1;
}
const len = arr.length;
for (let i = 0; i < len; ++i) {
if (arr[i] === foo) {
return i;
}
}
return -1;
};
const nextOne = (array, value) => {
const i = findInArray(array, value);
if (i < 0) {
return null;
}
return array[i + 1];
};
const literalizeRegex = (str) => {
return mw.util.escapeRegExp(str);
};
String.prototype.entify = function() {
return this.split("&").join("&").split("<").join("<").split(">").join(
">"
/* +shy */
).split('"').join(""");
};
const removeNulls = (val) => {
return val !== null;
};
const joinPath = (list) => {
return list.filter(removeNulls).join("/");
};
const simplePrintf = (str, subs) => {
if (!str || !subs) {
return str;
}
const ret = [];
const s = str.split(/(%s|\$\d+)/);
let i = 0;
do {
ret.push(s.shift());
if (s.length === 0) {
break;
}
const cmd = s.shift();
if (cmd === "%s") {
if (i < subs.length) {
ret.push(subs[i]);
} else {
ret.push(cmd);
}
++i;
} else {
const j = Number.parseInt(cmd.replace("$", ""), 10) - 1;
if (j > -1 && j < subs.length) {
ret.push(subs[j]);
} else {
ret.push(cmd);
}
}
} while (s.length > 0);
return ret.join("");
};
const isString = (x) => {
return typeof x === "string" || x instanceof String;
};
const isNumber = (x) => {
return typeof x === "number" || x instanceof Number;
};
const isRegExp = (x) => {
return x instanceof RegExp;
};
const isArray = (x) => {
return Array.isArray(x);
};
const isObject = (x) => {
return x instanceof Object;
};
const isFunction = (x) => {
return !isRegExp(x) && (typeof x === "function" || x instanceof Function);
};
const repeatString = (s, mult) => {
let ret = "";
for (let i = 0; i < mult; ++i) {
ret += s;
}
return ret;
};
const zeroFill = (s, min) => {
min || (min = 2);
const t = s.toString();
return repeatString("0", min - t.length) + t;
};
const map = (f, o) => {
if (isArray(o)) {
return map_array(f, o);
}
return map_object(f, o);
};
const map_array = (f, o) => {
const ret = [];
var _iterator7 = _createForOfIteratorHelper(o), _step7;
try {
for (_iterator7.s(); !(_step7 = _iterator7.n()).done; ) {
const element = _step7.value;
ret.push(f(element));
}
} catch (err) {
_iterator7.e(err);
} finally {
_iterator7.f();
}
return ret;
};
const map_object = (f, o) => {
const ret = {};
for (const i in o) {
if (!Object.hasOwn(o, i)) {
continue;
}
ret[o] = f(o[i]);
}
return ret;
};
pg.escapeQuotesHTML = (text) => {
return text.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
};
pg.unescapeQuotesHTML = (html) => {
const txt = document.createElement("textarea");
txt.innerHTML = html;
return txt.value;
};
const retargetDab = (newTarget, oldTarget, friendlyCurrentArticleName, titleToEdit) => {
log("retargetDab: newTarget=".concat(newTarget, " oldTarget=").concat(oldTarget));
return changeLinkTargetLink({
newTarget,
text: newTarget.split(" ").join(" "),
hint: tprintf("disambigHint", [newTarget]),
summary: simplePrintf(getValueOf("popupFixDabsSummary"), [friendlyCurrentArticleName, newTarget]),
clickButton: getValueOf("popupDabsAutoClick"),
minor: true,
oldTarget,
watch: getValueOf("popupWatchDisambiggedPages"),
title: titleToEdit
});
};
const listLinks = (wikitext, oldTarget, titleToEdit) => {
const reg = /\[\[([^|]*?) *(\||]])/gi;
let ret = [];
const splitted = wikitext.split(reg);
const omitRegex = /^[a-z]*:|^[Ss]pecial:|^[Ii]mage|^[Cc]ategory/;
const friendlyCurrentArticleName = oldTarget.toString();
const wikPos = getValueOf("popupDabWiktionary");
for (let i = 1; i < splitted.length; i += 3) {
if (typeof splitted[i] === "string" && splitted[i].length > 0 && !omitRegex.test(splitted[i])) {
ret.push(retargetDab(splitted[i], oldTarget, friendlyCurrentArticleName, titleToEdit));
}
}
ret = rmDupesFromSortedList(ret.sort());
if (wikPos) {
const wikTarget = "wiktionary:".concat(friendlyCurrentArticleName.replace(/^(.+)\s+\([^)]+\)\s*$/, "$1"));
const meth = wikPos.toLowerCase() === "first" ? "unshift" : "push";
ret[meth](retargetDab(wikTarget, oldTarget, friendlyCurrentArticleName, titleToEdit));
}
ret.push(changeLinkTargetLink({
newTarget: null,
text: popupString("remove this link").split(" ").join(" "),
hint: popupString("remove all links to this disambig page from this article"),
clickButton: getValueOf("popupDabsAutoClick"),
oldTarget,
summary: simplePrintf(getValueOf("popupRmDabLinkSummary"), [friendlyCurrentArticleName]),
watch: getValueOf("popupWatchDisambiggedPages"),
title: titleToEdit
}));
return ret;
};
const rmDupesFromSortedList = (list) => {
const ret = [];
var _iterator8 = _createForOfIteratorHelper(list), _step8;
try {
for (_iterator8.s(); !(_step8 = _iterator8.n()).done; ) {
const element = _step8.value;
if (ret.length === 0 || element !== ret.at(-1)) {
ret.push(element);
}
}
} catch (err) {
_iterator8.e(err);
} finally {
_iterator8.f();
}
return ret;
};
const makeFixDab = (data, navpop) => {
const titleToEdit = navpop.parentPopup && navpop.parentPopup.article.toString();
const list = listLinks(data, navpop.originalArticle, titleToEdit);
if (list.length === 0) {
log("listLinks returned empty list");
return null;
}
let html = "<hr>".concat(popupString("Click to disambiguate this link to:"), "<br>");
html += list.join(", ");
return html;
};
const makeFixDabs = (wikiText, navpop) => {
if (getValueOf("popupFixDabs") && isDisambig(wikiText, navpop.article) && Title.fromURL(location.href).namespaceId() !== pg.nsSpecialId && navpop.article.talkPage()) {
setPopupHTML(makeFixDab(wikiText, navpop), "popupFixDab", navpop.idNumber);
}
};
const popupRedlinkHTML = (article) => {
return changeLinkTargetLink({
newTarget: null,
text: popupString("remove this link").split(" ").join(" "),
hint: popupString("remove all links to this page from this article"),
clickButton: getValueOf("popupRedlinkAutoClick"),
oldTarget: article.toString(),
summary: simplePrintf(getValueOf("popupRedlinkSummary"), [article.toString()])
});
};
const setPopupHTML = function setPopupHTML2(str, elementId, popupId, onSuccess, append) {
if (popupId === void 0) {
popupId = pg.idNumber;
}
const popupElement = document.getElementById("".concat(elementId).concat(popupId));
if (popupElement) {
if (!append) {
popupElement.innerHTML = "";
}
if (isString(str)) {
popupElement.innerHTML += str;
} else {
popupElement.append(str);
}
if (onSuccess) {
onSuccess();
}
setTimeout(checkPopupPosition, 100);
return true;
}
setTimeout(() => {
setPopupHTML2(str, elementId, popupId, onSuccess);
}, 600);
return null;
};
const setPopupTrailer = (str, id) => {
return setPopupHTML(str, "popupData", id);
};
const fillEmptySpans = (args) => {
let redir = true;
let rcid;
if (typeof args !== "object" || args.redir === void 0 || !args.redir) {
redir = false;
}
const a = args.navpopup.parentAnchor;
let article;
let hint;
let oldid;
let params = {};
if (redir && typeof args.redirTarget === typeof {}) {
article = args.redirTarget;
} else {
article = new Title().fromAnchor(a);
hint = a.originalTitle || article.hintValue();
params = parseParams(a.href);
oldid = getValueOf("popupHistoricalLinks") ? params.oldid : null;
({
rcid
} = params);
}
const x = {
article,
hint,
oldid,
rcid,
navpop: args.navpopup,
params
};
const structure = pg.structures[getValueOf("popupStructure")];
if (typeof structure !== "object") {
setPopupHTML("popupError", "Unknown structure (this should never happen): ".concat(pg.option.popupStructure), args.navpopup.idNumber);
return;
}
const spans = flatten(pg.misc.layout);
const numspans = spans.length;
const redirs = pg.misc.redirSpans;
for (let i = 0; i < numspans; ++i) {
const found = redirs && redirs.includes(spans[i]);
if (found && !redir || !found && redir) {
continue;
}
const structurefn = structure[spans[i]];
if (structurefn === void 0) {
continue;
}
let setfn = setPopupHTML;
if (getValueOf("popupActiveNavlinks") && (spans[i].indexOf("popupTopLinks") === 0 || spans[i].indexOf("popupRedirTopLinks") === 0)) {
setfn = setPopupTipsAndHTML;
}
switch (typeof structurefn) {
case "function":
log("running ".concat(spans[i], "({\n article:").concat(x.article, ", hint:").concat(x.hint, ", oldid: ").concat(x.oldid, "})"));
setfn(structurefn(x), spans[i], args.navpopup.idNumber);
break;
case "string":
setfn(structurefn, spans[i], args.navpopup.idNumber);
break;
default:
errlog("unknown thing with label ".concat(spans[i], " (span index was ").concat(i, ")"));
break;
}
}
};
const flatten = function flatten2(list, start) {
const ret = [];
if (start === void 0) {
start = 0;
}
for (let i = start; i < list.length; ++i) {
if (typeof list[i] === typeof []) {
return [...ret, ...flatten2(list[i]), ...flatten2(list, i + 1)];
}
ret.push(list[i]);
}
return ret;
};
const popupHTML = function popupHTML2(a) {
getValueOf("popupStructure");
const structure = pg.structures[pg.option.popupStructure];
if (typeof structure !== "object") {
pg.option.popupStructure = pg.optionDefault.popupStructure;
return popupHTML2(a);
}
if (typeof structure.popupLayout !== "function") {
return "Bad layout";
}
pg.misc.layout = structure.popupLayout();
pg.misc.redirSpans = typeof structure.popupRedirSpans === "function" ? structure.popupRedirSpans() : [];
return makeEmptySpans(pg.misc.layout, a.navpopup);
};
const makeEmptySpans = function makeEmptySpans2(list, navpop) {
let ret = "";
var _iterator9 = _createForOfIteratorHelper(list), _step9;
try {
for (_iterator9.s(); !(_step9 = _iterator9.n()).done; ) {
const element = _step9.value;
if (typeof element === "string") {
ret += emptySpanHTML(element, navpop.idNumber, "div");
} else if (typeof element === typeof [] && element.length > 0) {
ret = ret.split(/(<\/[^>]*?>$)/).join(makeEmptySpans2(element, navpop));
} else if (typeof element === typeof {} && element.nodeType) {
ret += emptySpanHTML(element.name, navpop.idNumber, element.nodeType);
}
}
} catch (err) {
_iterator9.e(err);
} finally {
_iterator9.f();
}
return ret;
};
const emptySpanHTML = function emptySpanHTML2(name, id, tag, classname) {
tag || (tag = "span");
classname || (classname = emptySpanHTML2.classAliases[name]);
classname || (classname = name);
if (name === getValueOf("popupDragHandle")) {
classname += " popupDragHandle";
}
return simplePrintf('<%s id="%s" class="%s"></%s>', [tag, name + id, classname, tag]);
};
emptySpanHTML.classAliases = {
popupSecondPreview: "popupPreview"
};
const imageHTML = (_article, idNumber) => {
return simplePrintf('<a id="popupImageLink$1"><img align="right" valign="top" id="popupImg$1" style="display:none"></img></a>', [idNumber]);
};
const popTipsSoonFn = (id, when, popData) => {
when || (when = 250);
const popTips = () => {
setupTooltips(document.getElementById("".concat(id)), false, true, popData);
};
return () => {
setTimeout(popTips, when, popData);
};
};
const setPopupTipsAndHTML = (html, divname, idnumber, popData) => {
setPopupHTML(html, divname, idnumber, getValueOf("popupSubpopups") ? popTipsSoonFn(divname + idnumber, null, popData) : null);
};
const fuzzyCursorOffMenus = (_x, _y, _fuzz, parent) => {
if (!parent) {
return null;
}
const uls = parent.querySelectorAll("ul");
var _iterator0 = _createForOfIteratorHelper(uls), _step0;
try {
for (_iterator0.s(); !(_step0 = _iterator0.n()).done; ) {
const ul = _step0.value;
if (ul.className === "popup_menu" && ul.offsetWidth > 0) {
return false;
}
}
} catch (err) {
_iterator0.e(err);
} finally {
_iterator0.f();
}
return true;
};
const checkPopupPosition = () => {
if (pg.current.link && pg.current.link.navpopup) {
pg.current.link.navpopup.limitHorizontalPosition();
}
};
const mouseOutWikiLink = function mouseOutWikiLink2() {
const self2 = this;
removeModifierKeyListener(self2);
if (self2.navpopup === null || self2.navpopup === void 0) {
return;
}
if (!self2.navpopup.isVisible()) {
self2.navpopup.banish();
return;
}
restoreTitle(self2);
Navpopup.tracker.addHook(posCheckerHook(self2.navpopup));
};
const posCheckerHook = (navpop) => {
return () => {
if (!navpop.isVisible()) {
return true;
}
if (Navpopup.tracker.dirty) {
return false;
}
const {
x
} = Navpopup.tracker;
const {
y
} = Navpopup.tracker;
const mouseOverNavpop = navpop.isWithin(x, y, navpop.fuzz, navpop.mainDiv) || !fuzzyCursorOffMenus(x, y, navpop.fuzz, navpop.mainDiv);
let t = getValueOf("popupHideDelay");
if (t) {
t *= 1e3;
}
if (!t) {
if (!mouseOverNavpop) {
if (navpop.parentAnchor) {
restoreTitle(navpop.parentAnchor);
}
navpop.banish();
return true;
}
return false;
}
const d = Date.now();
if (!navpop.mouseLeavingTime) {
navpop.mouseLeavingTime = d;
return false;
}
if (mouseOverNavpop) {
navpop.mouseLeavingTime = null;
return false;
}
if (d - navpop.mouseLeavingTime > t) {
navpop.mouseLeavingTime = null;
navpop.banish();
return true;
}
return false;
};
};
const runStopPopupTimer = (navpop) => {
if (!navpop.stopPopupTimer) {
navpop.stopPopupTimer = setInterval(posCheckerHook(navpop), 500);
navpop.addHook(() => {
clearInterval(navpop.stopPopupTimer);
}, "hide", "before");
}
};
class Previewmaker {
constructor(wikiText, baseUrl, owner) {
this.originalData = wikiText;
this.baseUrl = baseUrl;
this.owner = owner;
this.maxCharacters = getValueOf("popupMaxPreviewCharacters");
this.maxSentences = getValueOf("popupMaxPreviewSentences");
this.setData();
}
setData() {
const maxSize = Math.max(1e4, 2 * this.maxCharacters);
this.data = this.originalData.slice(0, Math.max(0, maxSize));
}
/**
* Remove HTML comments
*
* @private
*/
killComments() {
this.data = this.data.replace(/^<!--[^$]*?-->\n|\n<!--[^$]*?-->(?=\n)|<!--[^$]*?-->/g, "");
}
/**
* @private
*/
killDivs() {
this.data = this.data.replace(/< *div[^>]* *>[\S\s]*?< *\/ *div *>/gi, "");
}
/**
* @private
*/
killGalleries() {
this.data = this.data.replace(/< *gallery[^>]* *>[\S\s]*?< *\/ *gallery *>/gi, "");
}
/**
* @param {Object} opening
* @param {Object} closing
* @param {Object} subopening
* @param {Object} subclosing
* @param {Object} repl
* @private
*/
kill(opening, closing, subopening, subclosing, repl) {
let oldk = this.data;
let k = Previewmaker.killStuff(this.data, opening, closing, subopening, subclosing, repl);
while (k.length < oldk.length) {
oldk = k;
k = Previewmaker.killStuff(k, opening, closing, subopening, subclosing, repl);
}
this.data = k;
}
/**
* @param {Object} txt
* @param {Object} opening
* @param {Object} closing
* @param {Object} subopening
* @param {Object} subclosing
* @param {Object} repl
* @private
*/
static killStuff(txt, opening, closing, subopening, subclosing, repl) {
const op = Previewmaker.makeRegexp(opening);
const cl = Previewmaker.makeRegexp(closing, "^");
const sb = subopening ? Previewmaker.makeRegexp(subopening, "^") : null;
const sc = subclosing ? Previewmaker.makeRegexp(subclosing, "^") : cl;
if (!op || !cl) {
void mw.notify("Navigation Popups error: op or cl is null! something is wrong.", {
tag: "popups",
type: "error"
});
return;
}
if (!op.test(txt)) {
return txt;
}
let ret = "";
const opResult = op.exec(txt);
ret = txt.slice(0, Math.max(0, opResult.index));
txt = txt.slice(Math.max(0, opResult.index + opResult[0].length));
let depth = 1;
while (txt.length > 0) {
let removal = 0;
if (depth === 1 && cl.test(txt)) {
depth--;
removal = cl.exec(txt)[0].length;
} else if (depth > 1 && sc.test(txt)) {
depth--;
removal = sc.exec(txt)[0].length;
} else if (sb && sb.test(txt)) {
depth++;
removal = sb.exec(txt)[0].length;
}
removal || (removal = 1);
txt = txt.slice(Math.max(0, removal));
if (depth === 0) {
break;
}
}
return ret + (repl || "") + txt;
}
/**
* @param {string|RegExp} x
* @param {string|RegExp} prefix
* @param {string|RegExp} suffix
* @private
*/
static makeRegexp(x, prefix, suffix) {
prefix || (prefix = "");
suffix || (suffix = "");
let reStr = "";
let flags = "";
if (isString(x)) {
reStr = prefix + literalizeRegex(x) + suffix;
} else if (isRegExp(x)) {
let s = x.toString().slice(1);
const sp = s.split("/");
flags = sp.at(-1);
sp[sp.length - 1] = "";
s = sp.join("/");
s = s.slice(0, Math.max(0, s.length - 1));
reStr = prefix + s + suffix;
} else {
log("makeRegexp failed");
}
log("makeRegexp: got reStr=".concat(reStr, ", flags=").concat(flags));
return new RegExp(reStr, flags);
}
/**
* @private
*/
killBoxTemplates() {
this.kill(/{{[^\s{|}]*?(float|box)[ _](begin|start)/i, /}}\s*/, "{{");
this.kill(/{{[^\s{|}]*?(infobox|elementbox|frame)[ _]/i, /}}\s*/, "{{");
}
/**
* @private
*/
killTemplates() {
this.kill("{{", "}}", "{", "}", " ");
}
/**
* @private
*/
killTables() {
this.kill("{|", /\|}\s*/, "{|");
this.kill(/<table.*?>/i, /<\/table.*?>/i, /<table.*?>/i);
this.data = this.data.replace(/^\|.*$/gm, "");
}
/**
* @private
*/
killImages() {
const forbiddenNamespaceAliases = [];
for (var _i = 0, _Object$entries = Object.entries(mw.config.get("wgNamespaceIds")); _i < _Object$entries.length; _i++) {
const [localizedNamespaceLc, namespaceId] = _Object$entries[_i];
if (namespaceId !== pg.nsImageId && namespaceId !== pg.nsCategoryId) {
return;
}
forbiddenNamespaceAliases.push(localizedNamespaceLc.split(" ").join("[ _]"));
}
this.kill(new RegExp("[[][[]\\s*(".concat(forbiddenNamespaceAliases.join("|"), ")\\s*:"), "i"), /]]\s*/, "[", "]");
}
/**
* @private
*/
killHTML() {
this.kill(/<ref\b[^/>]*?>/i, /<\/ref>/i);
this.data = this.data.replace(/(^|\n) *<.*/g, "\n");
const splitted = this.data.split(/(<[\W\w]*?(?:>|$|(?=<)))/);
const len = splitted.length;
for (let i = 1; i < len; i += 2) {
switch (splitted[i]) {
case "<no".concat("wiki", ">"):
case "</no".concat("wiki", ">"):
case "<block".concat("quote", ">"):
case "</block".concat("quote", ">"):
break;
default:
splitted[i] = "";
}
}
this.data = splitted.join("");
}
/**
* @private
*/
killChunks() {
const italicChunkRegex = /((^|\n)\s*:*\s*''[^']([^']|'''|'[^']){20}(.|\n[^\n])*''[\s!.?]*\n)+/g;
this.data = this.data.replace(italicChunkRegex, "\n");
}
/**
* @private
*/
mopup() {
this.data = this.data.replace(/^-{4,}/gm, "");
this.data = this.data.replace(/(^|\n) *:[^\n]*/g, "");
this.data = this.data.replace(/^__[_a-z]*__ *$/gim, "");
}
/**
* @private
*/
firstBit() {
let d = this.data;
if (getValueOf("popupPreviewCutHeadings")) {
this.data = this.data.replace(/\s*(==+[^=]*==+)\s*/g, "\n\n$1 ");
this.data = this.data.replace(/([:;]) *\n{2,}/g, "$1\n");
this.data = this.data.replace(/^\s*/, "");
const stuff = /^([^\n]|\n\S)*/.exec(this.data);
if (stuff) {
[d] = stuff;
}
if (!getValueOf("popupPreviewFirstParOnly")) {
d = this.data;
}
d = d.replace(/(==+[^=]*==+)\s*/g, "$1\n\n");
}
d = d.split(/([!.?]+["']*\s)/g);
d[0] = d[0].replace(/^\s*/, "");
const notSentenceEnds = /([^.][a-z]\. *[a-z]|etc|sic|dr|mr|mrs|ms|st|no|op|cit|\[[^\]]*|\s[a-z])$/i;
d = this.fixSentenceEnds(d, notSentenceEnds);
this.fullLength = d.join("").length;
let n = this.maxSentences;
let dd = Previewmaker.firstSentences(d, n);
do {
dd = Previewmaker.firstSentences(d, n);
--n;
} while (dd.length > this.maxCharacters && n !== 0);
this.data = dd;
}
/**
* @param {string} strs
* @param {RegExp} reg
* @private
*/
fixSentenceEnds(strs, reg) {
for (let i = 0; i < strs.length - 2; ++i) {
if (reg.test(strs[i])) {
const a = [];
for (let j = 0; j < strs.length; ++j) {
if (j < i) {
a[j] = strs[j];
}
if (j === i) {
a[i] = strs[i] + strs[i + 1] + strs[i + 2];
}
if (j > i + 2) {
a[j - 2] = strs[j];
}
}
return this.fixSentenceEnds(a, reg);
}
}
return strs;
}
/**
* @param {string[]} strs
* @param {number} howmany
* @private
*/
static firstSentences(strs, howmany) {
const t = strs.slice(0, 2 * howmany);
return t.join("");
}
/**
* @private
*/
killBadWhitespace() {
this.data = this.data.replace(/^ *'+ *$/gm, "");
}
/**
* Runs the various methods to generate the preview.
* The preview is stored in the <code>html</html> field.
*
* @private
*/
makePreview() {
if (this.owner.article.namespaceId() !== pg.nsTemplateId && this.owner.article.namespaceId() !== pg.nsImageId) {
this.killComments();
this.killDivs();
this.killGalleries();
this.killBoxTemplates();
if (getValueOf("popupPreviewKillTemplates")) {
this.killTemplates();
} else {
this.killMultilineTemplates();
}
this.killTables();
this.killImages();
this.killHTML();
this.killChunks();
this.mopup();
this.firstBit();
this.killBadWhitespace();
} else {
this.killHTML();
}
this.html = wiki2html(this.data, this.baseUrl);
this.fixHTML();
this.stripLongTemplates();
}
/**
* @param {string} data
* @private
*/
static esWiki2HtmlPart(data) {
const reLinks = /(?:\[\[([^\]|]*)(?:\|([^\]|]*))*]]([a-z]*))/gi;
reLinks.lastIndex = 0;
let match;
let result = "";
let postfixIndex = 0;
while ((match = reLinks.exec(data)) !== null) {
var _match$;
result += "".concat(pg.escapeQuotesHTML(data.substring(postfixIndex, match.index)), '<a href="').concat(Insta.conf.paths.articles).concat(pg.escapeQuotesHTML(match[1]), '">').concat(pg.escapeQuotesHTML(((_match$ = match[2]) !== null && _match$ !== void 0 ? _match$ : match[1]) + match[3]), "</a>");
postfixIndex = reLinks.lastIndex;
}
result += pg.escapeQuotesHTML(data.slice(Math.max(0, postfixIndex)));
return result;
}
editSummaryPreview() {
const reAes = /\/\* *(.*?) *\*\//g;
reAes.lastIndex = 0;
const match = reAes.exec(this.data);
if (match) {
const prefix = this.data.slice(0, Math.max(0, match.index - 1));
const [, section] = match;
const postfix = this.data.slice(Math.max(0, reAes.lastIndex));
let start = "<span class='autocomment'>";
let end = "</span>";
if (prefix.length > 0) {
start = "".concat(Previewmaker.esWiki2HtmlPart(prefix), " ").concat(start, "- ");
}
if (postfix.length > 0) {
end = ": ".concat(end).concat(Previewmaker.esWiki2HtmlPart(postfix));
}
const t = new Title().fromURL(this.baseUrl);
t.anchorFromUtf(section);
const sectionLink = "".concat(Insta.conf.paths.articles + pg.escapeQuotesHTML(t.toString(true)), "#").concat(pg.escapeQuotesHTML(t.anchor));
return "".concat(start, '<a href="').concat(sectionLink, '">→</a> ').concat(pg.escapeQuotesHTML(section)).concat(end);
}
return Previewmaker.esWiki2HtmlPart(this.data);
}
/**
* Works around livepreview bugs.
*
* @private
*/
fixHTML() {
if (!this.html) {
return;
}
let ret = this.html;
ret = ret.replace(new RegExp('(<a href="'.concat(pg.wiki.articlePath, '/[^"]*)[?](.*?")'), "g"), "$1%3F$2");
ret = ret.replace(new RegExp("(<a href='".concat(pg.wiki.articlePath, "/[^']*)[?](.*?')"), "g"), "$1%3F$2");
this.html = ret;
}
/**
* Generates the preview and displays it in the current popup.
* Does nothing if the generated preview is invalid or consists of whitespace only.
* Also activates wikilinks in the preview for subpopups if the popupSubpopups option is true.
*/
showPreview() {
this.makePreview();
if (typeof this.html !== "string") {
return;
}
if (/^\s*$/.test(this.html)) {
return;
}
setPopupHTML("<hr>", "popupPrePreviewSep", this.owner.idNumber);
setPopupTipsAndHTML(this.html, "popupPreview", this.owner.idNumber, {
owner: this.owner
});
const more = this.fullLength > this.data.length ? this.moreLink() : "";
setPopupHTML(more, "popupPreviewMore", this.owner.idNumber);
}
/**
* @private
*/
moreLink() {
const a = document.createElement("a");
a.className = "popupMoreLink";
a.innerHTML = popupString("more...");
const self2 = this;
a.onclick = () => {
self2.maxCharacters += 2e3;
self2.maxSentences += 20;
self2.setData();
self2.showPreview();
};
return a;
}
/**
* @private
*/
stripLongTemplates() {
this.html = this.html.replace(/^.{0,1000}{{[^}]*?(<(p|br)( \/)?>\s*){2,}([^{}]*?}})?/gi, "");
this.html = this.html.split("\n").join(" ");
this.html = this.html.replace(/{{[^}]*<pre>[^}]*}}/gi, "");
}
/**
* @private
*/
killMultilineTemplates() {
this.kill("{{{", "}}}");
this.kill(/\s*{{[^{}]*\n/, "}}", "{{");
}
}
const loadAPIPreview = (queryType, article, navpop) => {
const art = new Title(article).urlString();
let url = "".concat(pg.wiki.apiwikibase, "?format=json&formatversion=2&action=query&");
let htmlGenerator = () => {
void mw.notify("invalid html generator", {
tag: "popups",
type: "error"
});
};
let usernameart = "";
switch (queryType) {
case "history":
url += "titles=".concat(art, "&prop=revisions&rvlimit=").concat(getValueOf("popupHistoryPreviewLimit"));
htmlGenerator = APIhistoryPreviewHTML;
break;
case "category":
url += "list=categorymembers&cmtitle=".concat(art);
htmlGenerator = APIcategoryPreviewHTML;
break;
case "userinfo": {
const username = new Title(article).userName();
usernameart = encodeURIComponent(username);
url += pg.re.ipUser.test(username) ? "list=blocks&bkprop=range|restrictions&bkip=".concat(usernameart) : "list=users|usercontribs&usprop=blockinfo|groups|editcount|registration|gender&ususers=".concat(usernameart, "&meta=globaluserinfo&guiprop=groups|unattached&guiuser=").concat(usernameart, "&uclimit=1&ucprop=timestamp&ucuser=").concat(usernameart);
htmlGenerator = APIuserInfoPreviewHTML;
break;
}
case "contribs":
usernameart = encodeURIComponent(new Title(article).userName());
url += "list=usercontribs&ucuser=".concat(usernameart, "&uclimit=").concat(getValueOf("popupContribsPreviewLimit"));
htmlGenerator = APIcontribsPreviewHTML;
break;
case "imagepagepreview": {
let trail = "";
if (getValueOf("popupImageLinks")) {
trail = "&list=imageusage&iutitle=".concat(art);
}
url += "titles=".concat(art, "&prop=revisions|imageinfo&rvprop=content").concat(trail);
htmlGenerator = APIimagepagePreviewHTML;
break;
}
case "backlinks":
url += "list=backlinks&bltitle=".concat(art);
htmlGenerator = APIbacklinksPreviewHTML;
break;
case "revision":
url += article.oldid ? "revids=".concat(article.oldid) : "titles=".concat(article.removeAnchor().urlString());
url += "&prop=revisions|pageprops|info|images|categories&rvprop=ids|timestamp|flags|comment|user|content&cllimit=max&imlimit=max";
htmlGenerator = APIrevisionPreviewHTML;
break;
}
pendingNavpopTask(navpop);
const callback = (d) => {
log("callback of API functions was hit");
if (queryType === "userinfo") {
fetchUserGroupNames(d.data).then(() => {
showAPIPreview(queryType, htmlGenerator(article, d, navpop), navpop.idNumber, navpop, d);
});
return;
}
showAPIPreview(queryType, htmlGenerator(article, d, navpop), navpop.idNumber, navpop, d);
};
const go = () => {
getPageWithCaching(url, callback, navpop);
return true;
};
if (navpop.visible || !getValueOf("popupLazyDownloads")) {
go();
} else {
navpop.addHook(go, "unhide", "before", "DOWNLOAD_".concat(queryType, "_QUERY_DATA"));
}
};
const linkList = (list) => {
list.sort((x, y) => {
return x === y ? 0 : x < y ? -1 : 1;
});
const buf = [];
var _iterator1 = _createForOfIteratorHelper(list), _step1;
try {
for (_iterator1.s(); !(_step1 = _iterator1.n()).done; ) {
const element = _step1.value;
buf.push(wikiLink({
article: new Title(element),
text: element.split(" ").join(" "),
action: "view"
}));
}
} catch (err) {
_iterator1.e(err);
} finally {
_iterator1.f();
}
return buf.join(", ");
};
const getTimeOffset = () => {
const tz = mw.user.options.get("timecorrection");
if (tz && tz.includes("|")) {
return Number.parseInt(tz.split("|")[1], 10);
}
return 0;
};
const getTimeZone = () => {
if (!pg.user.timeZone) {
const tz = mw.user.options.get("timecorrection");
pg.user.timeZone = "UTC";
if (tz) {
const tzComponents = tz.split("|");
if (tzComponents.length === 3 && tzComponents[0] === "ZoneInfo") {
[, , pg.user.timeZone] = tzComponents;
} else {
errlog("Unexpected timezone information: ".concat(tz));
}
}
}
return pg.user.timeZone;
};
const useTimeOffset = () => {
if (Intl.DateTimeFormat.prototype.formatToParts === void 0) {
return true;
}
const tz = mw.user.options.get("timecorrection");
if (tz && !tz.includes("ZoneInfo|")) {
return true;
}
return false;
};
const getLocales = () => {
if (!pg.user.locales) {
let userLanguage = document.querySelector("html").getAttribute("lang");
if (getValueOf("popupLocale")) {
userLanguage = getValueOf("popupLocale");
} else if (userLanguage === "en") {
userLanguage = getMWDateFormat() === "mdy" ? "en-US" : "en-GB";
}
pg.user.locales = Intl.DateTimeFormat.supportedLocalesOf([userLanguage, navigator.language]);
}
return pg.user.locales;
};
const getMWDateFormat = () => {
return mw.user.options.get("date");
};
const editPreviewTable = (article, h, reallyContribs) => {
let html = ["<table>"];
let day;
let curart = article;
let page;
let makeFirstColumnLinks;
if (reallyContribs) {
makeFirstColumnLinks = (currentRevision) => {
let result = "(";
result += '<a href="'.concat(pg.wiki.titlebase).concat(new Title(currentRevision.title).urlString(), "&diff=prev&oldid=").concat(currentRevision.revid, '">').concat(popupString("diff"), "</a>");
result += " | ";
result += '<a href="'.concat(pg.wiki.titlebase).concat(new Title(currentRevision.title).urlString(), '&action=history">').concat(popupString("hist"), "</a>");
result += ")";
return result;
};
} else {
const firstRevid = h[0].revid;
makeFirstColumnLinks = (currentRevision) => {
let result = "(";
result += '<a href="'.concat(pg.wiki.titlebase).concat(new Title(curart).urlString(), "&diff=").concat(firstRevid, "&oldid=").concat(currentRevision.revid, '">').concat(popupString("cur"), "</a>");
result += " | ";
result += '<a href="'.concat(pg.wiki.titlebase).concat(new Title(curart).urlString(), "&diff=prev&oldid=").concat(currentRevision.revid, '">').concat(popupString("last"), "</a>");
result += ")";
return result;
};
}
var _iterator10 = _createForOfIteratorHelper(h.entries()), _step10;
try {
for (_iterator10.s(); !(_step10 = _iterator10.n()).done; ) {
const [i, element] = _step10.value;
if (reallyContribs) {
page = element.title;
curart = new Title(page);
}
const minor = element.minor ? "<b>m </b>" : "";
const editDate = new Date(element.timestamp);
let thisDay = formattedDate(editDate);
const thisTime = formattedTime(editDate);
if (thisDay === day) {
thisDay = "";
} else {
day = thisDay;
}
if (thisDay) {
html.push('<tr><td colspan=3><span class="popup_history_date">'.concat(thisDay, "</span></td></tr>"));
}
html.push('<tr class="popup_history_row_'.concat(i % 2 ? "odd" : "even", '">'), "<td>".concat(makeFirstColumnLinks(element), "</td>"), '<td><a href="'.concat(pg.wiki.titlebase).concat(new Title(curart).urlString(), "&oldid=").concat(element.revid, '">').concat(thisTime, "</a></td>"));
let col3url = "";
let col3txt = "";
if (reallyContribs) {
col3url = pg.wiki.titlebase + curart.urlString();
col3txt = pg.escapeQuotesHTML(page);
} else {
const {
user
} = element;
if (element.userhidden) {
col3url = getValueOf("popupRevDelUrl");
col3txt = pg.escapeQuotesHTML(popupString("revdel"));
} else {
col3url = pg.re.ipUser.test(user) ? "".concat(pg.wiki.titlebase + mw.config.get("wgFormattedNamespaces")[pg.nsSpecialId], ":Contributions&target=").concat(new Title(user).urlString()) : "".concat(pg.wiki.titlebase + mw.config.get("wgFormattedNamespaces")[pg.nsUserId], ":").concat(new Title(user).urlString());
col3txt = pg.escapeQuotesHTML(user);
}
}
html.push("<td>".concat(reallyContribs ? minor : "", '<a href="').concat(col3url, '">').concat(col3txt, "</a></td>"));
let comment = "";
const c = element.comment || element.content;
if (c) {
comment = new Previewmaker(c, new Title(curart).toUrl()).editSummaryPreview();
} else if (element.commenthidden) {
comment = popupString("revdel");
}
html.push("<td>".concat(reallyContribs ? "" : minor).concat(comment, "</td>"), "</tr>");
html = [html.join("")];
}
} catch (err) {
_iterator10.e(err);
} finally {
_iterator10.f();
}
html.push("</table>");
return html.join("");
};
const adjustDate = (d, offset) => {
const o = offset * 60 * 1e3;
return new Date(+d + o);
};
const convertTimeZone = (date, timeZone) => {
return new Date(date.toLocaleString("en-US", {
timeZone
}));
};
const formattedDateTime = (date) => {
if (useTimeOffset()) {
return "".concat(formattedDate(date), " ").concat(formattedTime(date));
}
if (getMWDateFormat() === "ISO 8601") {
const d2 = convertTimeZone(date, getTimeZone());
return "".concat(map(zeroFill, [d2.getFullYear(), d2.getMonth() + 1, d2.getDate()]).join("-"), "T").concat(map(zeroFill, [d2.getHours(), d2.getMinutes(), d2.getSeconds()]).join(":"));
}
const options = getValueOf("popupDateTimeFormatterOptions");
options.timeZone = getTimeZone();
return date.toLocaleString(getLocales(), options);
};
const formattedDate = (date) => {
let d2;
if (useTimeOffset()) {
d2 = adjustDate(date, getTimeOffset());
return map(zeroFill, [d2.getUTCFullYear(), d2.getUTCMonth() + 1, d2.getUTCDate()]).join("-");
}
if (getMWDateFormat() === "ISO 8601") {
d2 = convertTimeZone(date, getTimeZone());
return map(zeroFill, [d2.getFullYear(), d2.getMonth() + 1, d2.getDate()]).join("-");
}
const options = getValueOf("popupDateFormatterOptions");
options.timeZone = getTimeZone();
return date.toLocaleDateString(getLocales(), options);
};
const formattedTime = (date) => {
let d2;
if (useTimeOffset()) {
d2 = adjustDate(date, getTimeOffset());
return map(zeroFill, [d2.getUTCHours(), d2.getUTCMinutes(), d2.getUTCSeconds()]).join(":");
}
if (getMWDateFormat() === "ISO 8601") {
d2 = convertTimeZone(date, getTimeZone());
return map(zeroFill, [d2.getHours(), d2.getMinutes(), d2.getSeconds()]).join(":");
}
const options = getValueOf("popupTimeFormatterOptions");
options.timeZone = getTimeZone();
return date.toLocaleTimeString(getLocales(), options);
};
const fetchUserGroupNames = (userinfoResponse) => {
const queryObj = getJsObj(userinfoResponse).query;
const user = anyChild(queryObj.users);
const messages = [];
if (user.groups) {
var _iterator11 = _createForOfIteratorHelper(user.groups), _step11;
try {
for (_iterator11.s(); !(_step11 = _iterator11.n()).done; ) {
const groupName = _step11.value;
if (!["*", "user", "autoconfirmed"].includes(groupName)) {
messages.push("group-".concat(groupName, "-member"));
}
}
} catch (err) {
_iterator11.e(err);
} finally {
_iterator11.f();
}
}
if (queryObj.globaluserinfo && queryObj.globaluserinfo.groups) {
var _iterator12 = _createForOfIteratorHelper(queryObj.globaluserinfo.groups), _step12;
try {
for (_iterator12.s(); !(_step12 = _iterator12.n()).done; ) {
const groupName = _step12.value;
messages.push("group-".concat(groupName, "-member"));
}
} catch (err) {
_iterator12.e(err);
} finally {
_iterator12.f();
}
}
return getMwApi().loadMessagesIfMissing(messages);
};
const showAPIPreview = (queryType, html, id, navpop, download) => {
let target = "popupPreview";
completedNavpopTask(navpop);
switch (queryType) {
case "imagelinks":
case "category":
target = "popupPostPreview";
break;
case "userinfo":
target = "popupUserData";
break;
case "revision":
insertPreview(download);
return;
}
setPopupTipsAndHTML(html, target, id);
};
const APIrevisionPreviewHTML = (_article, download) => {
try {
const jsObj = getJsObj(download.data);
const page = anyChild(jsObj.query.pages);
if (page.missing) {
download.owner = null;
return;
}
const content = page && page.revisions && page.revisions[0] && page.revisions[0].content ? page.revisions[0].content : null;
if (typeof content === "string") {
download.data = content;
download.lastModified = new Date(page.revisions[0].timestamp);
}
} catch {
return "Revision preview failed :(";
}
};
const APIbacklinksPreviewHTML = (_article, download) => {
try {
const jsObj = getJsObj(download.data);
const list = jsObj.query.backlinks;
let html = [];
if (!list) {
return popupString("No backlinks found");
}
var _iterator13 = _createForOfIteratorHelper(list), _step13;
try {
for (_iterator13.s(); !(_step13 = _iterator13.n()).done; ) {
const element = _step13.value;
const t = new Title(element.title);
html.push('<a href="'.concat(pg.wiki.titlebase).concat(t.urlString(), '">').concat(t.toString().entify(), "</a>"));
}
} catch (err) {
_iterator13.e(err);
} finally {
_iterator13.f();
}
html = html.join(", ");
if (jsObj.continue && jsObj.continue.blcontinue) {
html += popupString(" and more");
}
return html;
} catch {
return "backlinksPreviewHTML went wonky";
}
};
pg.fn.APIsharedImagePagePreviewHTML = (obj) => {
log("APIsharedImagePagePreviewHTML");
const popupid = obj.requestid;
if (obj.query && obj.query.pages) {
const page = anyChild(obj.query.pages);
const content = page && page.revisions && page.revisions[0].contentmodel === "wikitext" ? page.revisions[0].content : null;
if (typeof content === "string" && pg && pg.current && pg.current.link && pg.current.link.navpopup) {
const p = new Previewmaker(content, pg.current.link.navpopup.article, pg.current.link.navpopup);
p.makePreview();
setPopupHTML(p.html, "popupSecondPreview", popupid);
}
}
};
const APIimagepagePreviewHTML = (article, download, navpop) => {
try {
const jsObj = getJsObj(download.data);
const page = anyChild(jsObj.query.pages);
const content = page && page.revisions && page.revisions[0].contentmodel === "wikitext" ? page.revisions[0].content : null;
let ret = "";
let alt = "";
try {
[{
alt
}] = navpop.parentAnchor.childNodes;
} catch {
}
if (alt) {
ret = "".concat(ret, "<hr><b>").concat(popupString("Alt text:"), "</b> ").concat(pg.escapeQuotesHTML(alt));
}
if (typeof content === "string") {
const p = prepPreviewmaker(content, article, navpop);
p.makePreview();
if (p.html) {
ret += "<hr>".concat(p.html);
}
if (getValueOf("popupSummaryData")) {
const info = getPageInfo(content, download);
log(info);
setPopupTrailer(info, navpop.idNumber);
}
}
if (page && page.imagerepository === "shared") {
const art = new Title(article);
const encart = encodeURIComponent("File:".concat(art.stripNamespace()));
const shared_url = "".concat(pg.wiki.apicommonsbase, "?format=json&formatversion=2&callback=pg.fn.APIsharedImagePagePreviewHTML&requestid=").concat(navpop.idNumber, "&action=query&prop=revisions&rvprop=content&titles=").concat(encart);
ret = "".concat(ret, "<hr>").concat(popupString("Image from Commons"), ': <a href="').concat(pg.wiki.commonsbase, "?title=").concat(encart, '">').concat(popupString("Description page"), "</a>");
mw.loader.load(shared_url);
}
showAPIPreview("imagelinks", APIimagelinksPreviewHTML(article, download), navpop.idNumber, download);
return ret;
} catch {
return "API imagepage preview failed :(";
}
};
const APIimagelinksPreviewHTML = (_article, download) => {
try {
const jsobj = getJsObj(download.data);
const list = jsobj.query.imageusage;
if (list) {
const ret = [];
var _iterator14 = _createForOfIteratorHelper(list), _step14;
try {
for (_iterator14.s(); !(_step14 = _iterator14.n()).done; ) {
const element = _step14.value;
ret.push(element.title);
}
} catch (err) {
_iterator14.e(err);
} finally {
_iterator14.f();
}
if (ret.length === 0) {
return popupString("No image links found");
}
return "<h2>".concat(popupString("File links"), "</h2>").concat(linkList(ret));
}
return popupString("No image links found");
} catch {
return "Image links preview generation failed :(";
}
};
const APIcategoryPreviewHTML = (_article, download) => {
try {
const jsobj = getJsObj(download.data);
const list = jsobj.query.categorymembers;
let ret = [];
var _iterator15 = _createForOfIteratorHelper(list), _step15;
try {
for (_iterator15.s(); !(_step15 = _iterator15.n()).done; ) {
const element = _step15.value;
ret.push(element.title);
}
} catch (err) {
_iterator15.e(err);
} finally {
_iterator15.f();
}
if (ret.length === 0) {
return popupString("Empty category");
}
ret = "<h2>".concat(tprintf("Category members (%s shown)", [ret.length]), "</h2>").concat(linkList(ret));
if (jsobj.continue && jsobj.continue.cmcontinue) {
ret += popupString(" and more");
}
return ret;
} catch {
return "Category preview failed :(";
}
};
const APIuserInfoPreviewHTML = (_article, download) => {
let ret = [];
let queryobj = {};
try {
queryobj = getJsObj(download.data).query;
} catch {
return "Userinfo preview failed :(";
}
const user = anyChild(queryobj.users);
if (user) {
const {
globaluserinfo
} = queryobj;
if (user.invalid === "") {
ret.push(popupString("Invalid user"));
} else if (user.missing === "") {
ret.push(popupString("Not a registered username"));
}
if (user.blockedby) {
if (user.blockpartial) {
ret.push("<b>".concat(popupString("Has blocks"), "</b>"));
} else {
ret.push("<b>".concat(popupString("BLOCKED"), "</b>"));
}
}
if (globaluserinfo && ("locked" in globaluserinfo || "hidden" in globaluserinfo)) {
let lockedSulAccountIsAttachedToThis = true;
for (let i = 0; globaluserinfo.unattached && i < globaluserinfo.unattached.length; i++) {
if (globaluserinfo.unattached[i].wiki === mw.config.get("wgDBname")) {
lockedSulAccountIsAttachedToThis = false;
break;
}
}
if (lockedSulAccountIsAttachedToThis) {
if ("locked" in globaluserinfo) {
ret.push("<b><i>".concat(popupString("LOCKED"), "</i></b>"));
}
if ("hidden" in globaluserinfo) {
ret.push("<b><i>".concat(popupString("HIDDEN"), "</i></b>"));
}
}
}
if (getValueOf("popupShowGender") && user.gender) {
switch (user.gender) {
case "male":
ret.push("".concat(popupString("he/him"), " · "));
break;
case "female":
ret.push("".concat(popupString("she/her"), " · "));
break;
}
}
if (user.groups) {
var _iterator16 = _createForOfIteratorHelper(user.groups), _step16;
try {
for (_iterator16.s(); !(_step16 = _iterator16.n()).done; ) {
const groupName = _step16.value;
if (!["*", "user", "autoconfirmed"].includes(groupName)) {
ret.push(pg.escapeQuotesHTML(mw.message("group-".concat(groupName, "-member"), user.gender).text()));
}
}
} catch (err) {
_iterator16.e(err);
} finally {
_iterator16.f();
}
}
if (globaluserinfo && globaluserinfo.groups) {
var _iterator17 = _createForOfIteratorHelper(globaluserinfo.groups), _step17;
try {
for (_iterator17.s(); !(_step17 = _iterator17.n()).done; ) {
const groupName = _step17.value;
ret.push(
// Messages that can be used here:
// * see [[Special:PrefixIndex/MediaWiki:Group-]]
// * for more information
"<i>".concat(pg.escapeQuotesHTML(mw.message("group-".concat(groupName, "-member"), user.gender).text()), "</i>")
);
}
} catch (err) {
_iterator17.e(err);
} finally {
_iterator17.f();
}
}
if (user.registration) {
var _user$editcount;
ret.push(pg.escapeQuotesHTML(((_user$editcount = user.editcount) !== null && _user$editcount !== void 0 ? _user$editcount : "0") + popupString(" edits since: ") + (user.registration ? formattedDate(new Date(user.registration)) : "")));
}
}
if (queryobj.usercontribs && queryobj.usercontribs.length > 0) {
ret.push(popupString("last edit on ") + formattedDate(new Date(queryobj.usercontribs[0].timestamp)));
}
if (queryobj.blocks) {
ret.push(popupString("IP user"));
for (let l = 0; l < queryobj.blocks.length; l++) {
let rbstr = queryobj.blocks[l].rangestart === queryobj.blocks[l].rangeend ? "BLOCK" : "RANGEBLOCK";
rbstr = Array.isArray(queryobj.blocks[l].restrictions) ? "".concat(rbstr, "ED") : "Has ".concat(rbstr.toLowerCase(), "s");
ret.push("<b>".concat(popupString(rbstr), "</b>"));
}
}
for (let m = 0; m < ret.length - 1; m++) {
if (ret[m].length > 3 && ret[m].slice(Math.max(0, ret[m].length - 3)) === " · ") {
ret[m] += ret[m + 1];
ret.splice(m + 1, 1);
m--;
}
}
ret = "<hr>".concat(ret.join(", "));
return ret;
};
const APIcontribsPreviewHTML = (article, download, navpop) => {
return APIhistoryPreviewHTML(article, download, navpop, true);
};
const APIhistoryPreviewHTML = (article, download, _navpop, reallyContribs) => {
try {
const jsobj = getJsObj(download.data);
let edits = [];
edits = reallyContribs ? jsobj.query.usercontribs : anyChild(jsobj.query.pages).revisions;
const ret = editPreviewTable(article, edits, reallyContribs);
return ret;
} catch {
return "History preview failed :-(";
}
};
const setupDebugging = () => {
if (window.popupDebug) {
window.log = (x) => {
console.log(x);
};
window.errlog = (x) => {
console.error("[Popups] ".concat(x));
};
log("Initializing logger");
} else {
window.log = () => {
};
window.errlog = () => {
};
}
};
const loadImage = (image, navpop) => {
if (typeof image.stripNamespace !== "function") {
void mw.notify("loadImages bad", {
tag: "popups",
type: "error"
});
}
if (!getValueOf("popupImages")) {
return;
}
if (!isValidImageName(image.toString())) {
return false;
}
const art = image.urlString();
let url = "".concat(pg.wiki.apiwikibase, "?format=json&formatversion=2&action=query");
url += "&prop=imageinfo&iiprop=url|mime&iiurlwidth=".concat(getValueOf("popupImageSizeLarge"));
url += "&titles=".concat(art);
pendingNavpopTask(navpop);
const callback = (d) => {
popupsInsertImage(navpop.idNumber, navpop, d);
};
const go = () => {
getPageWithCaching(url, callback, navpop);
return true;
};
if (navpop.visible || !getValueOf("popupLazyDownloads")) {
go();
} else {
navpop.addHook(go, "unhide", "after", "DOWNLOAD_IMAGE_QUERY_DATA");
}
};
const popupsInsertImage = (id, _navpop, download) => {
log("popupsInsertImage");
let imageinfo;
try {
const jsObj = getJsObj(download.data);
const imagepage = anyChild(jsObj.query.pages);
if (imagepage.imageinfo === void 0) {
return;
}
[imageinfo] = imagepage.imageinfo;
} catch {
log("popupsInsertImage failed :(");
return;
}
const popupImage = document.querySelector("#popupImg".concat(id));
if (!popupImage) {
log("could not find insertion point for image");
return;
}
popupImage.width = getValueOf("popupImageSize");
popupImage.style.display = "inline";
if (imageinfo.thumburl) {
popupImage.src = imageinfo.thumburl;
} else if (imageinfo.mime.indexOf("image") === 0) {
popupImage.src = imageinfo.url;
log("a thumb could not be found, using original image");
} else {
log("fullsize imagethumb, but not sure if it's an image");
}
const a = document.querySelector("#popupImageLink".concat(id));
if (a === null) {
return null;
}
switch (getValueOf("popupThumbAction")) {
case "imagepage":
if (pg.current.article.namespaceId() !== pg.nsImageId) {
a.href = imageinfo.descriptionurl;
popTipsSoonFn("popupImage".concat(id))();
break;
}
/* falls through */
case "sizetoggle":
a.onclick = toggleSize;
a.title = popupString("Toggle image size");
return;
case "linkfull":
a.href = imageinfo.url;
a.title = popupString("Open full-size image");
}
};
const toggleSize = function toggleSize2() {
const self2 = this;
if (!self2) {
void mw.notify("self is null :/", {
tag: "popups",
type: "error"
});
return;
}
const img = self2.firstChild;
if (!img) {
void mw.notify("img is null :/", {
tag: "popups",
type: "error"
});
return;
}
img.style.width = !img.style.width || img.style.width === "" ? "100%" : "";
};
const getValidImageFromWikiText = (wikiText) => {
let matched;
let match;
const t = removeMatchesUnless(wikiText, /(<!--[\S\s]*?-->)/, 1, /^<!--[^[]*popup/i);
while ((match = pg.re.image.exec(t)) !== null) {
const m = match[2] || match[6];
if (isValidImageName(m)) {
matched = m;
break;
}
}
pg.re.image.lastIndex = 0;
if (!matched) {
return null;
}
return "".concat(mw.config.get("wgFormattedNamespaces")[pg.nsImageId], ":").concat(upcaseFirst(matched));
};
const removeMatchesUnless = (str, re1, parencount, re2) => {
const split = str.split(re1);
const c = parencount + 1;
for (let i = 0; i < split.length; ++i) {
if (i % c === 0 || re2.test(split[i])) {
continue;
}
split[i] = "";
}
return split.join("");
};
const setNamespaces = () => {
pg.nsSpecialId = -1;
pg.nsMainspaceId = 0;
pg.nsImageId = 6;
pg.nsUserId = 2;
pg.nsUsertalkId = 3;
pg.nsCategoryId = 14;
pg.nsTemplateId = 10;
};
const setRedirs = () => {
const r = "redirect";
const R = "REDIRECT";
const redirLists = {
ar: [R, "تحويل"],
be: [r, "перанакіраваньне"],
bg: [r, "пренасочване", "виж"],
bs: [r, "Preusmjeri", "preusmjeri", "PREUSMJERI"],
bn: [R, "পুনর্নির্দেশ"],
cs: [R, "PŘESMĚRUJ"],
cy: [r, "ail-cyfeirio"],
de: [R, "WEITERLEITUNG"],
el: [R, "ΑΝΑΚΑΤΕΥΘΥΝΣΗ"],
eo: [R, "ALIDIREKTU", "ALIDIREKTI"],
es: [R, "REDIRECCIÓN"],
et: [r, "suuna"],
ga: [r, "athsheoladh"],
gl: [r, "REDIRECCIÓN", "REDIRECIONAMENTO"],
he: [R, "הפניה"],
hu: [R, "ÁTIRÁNYÍTÁS"],
is: [r, "tilvísun", "TILVÍSUN"],
it: [R, "RINVIA", "Rinvia"],
ja: [R, "転送"],
mk: [r, "пренасочување", "види"],
nds: [r, "wiederleiden"],
"nds-nl": [R, "DEURVERWIEZING", "DUURVERWIEZING"],
nl: [R, "DOORVERWIJZING"],
nn: [r, "omdiriger"],
pl: [R, "PATRZ", "PRZEKIERUJ", "TAM"],
pt: [R, "redir"],
ru: [R, "ПЕРЕНАПРАВЛЕНИЕ", "ПЕРЕНАПР"],
sk: [r, "presmeruj"],
sr: [r, "Преусмери", "преусмери", "ПРЕУСМЕРИ", "Preusmeri", "preusmeri", "PREUSMERI"],
tt: [R, "yünältü", "перенаправление", "перенапр"],
uk: [R, "ПЕРЕНАПРАВЛЕННЯ", "ПЕРЕНАПР"],
vi: [r, "đổi"],
yi: [R, "ווייטערפירן"],
zh: [R, "重定向"]
// no comma
};
const redirList = redirLists[pg.wiki.lang] || [r, R];
pg.re.redirect = new RegExp("^\\s*[#](".concat(redirList.join("|"), ").*?\\[{2}([^\\|\\]]*)(|[^\\]]*)?\\]{2}\\s*(.*)"), "i");
};
const setInterwiki = () => {
if (pg.wiki.wikimedia) {
pg.wiki.interwiki = "aa|ab|ace|af|ak|als|am|an|ang|ar|arc|arz|as|ast|av|ay|az|ba|bar|bat-smg|bcl|be|be-x-old|bg|bh|bi|bjn|bm|bn|bo|bpy|br|bs|bug|bxr|ca|cbk-zam|cdo|ce|ceb|ch|cho|chr|chy|ckb|co|cr|crh|cs|csb|cu|cv|cy|da|de|diq|dsb|dv|dz|ee|el|eml|en|eo|es|et|eu|ext|fa|ff|fi|fiu-vro|fj|fo|fr|frp|frr|fur|fy|ga|gag|gan|gd|gl|glk|gn|got|gu|gv|ha|hak|haw|he|hi|hif|ho|hr|hsb|ht|hu|hy|hz|ia|id|ie|ig|ii|ik|ilo|io|is|it|iu|ja|jbo|jv|ka|kaa|kab|kbd|kg|ki|kj|kk|kl|km|kn|ko|koi|kr|krc|ks|ksh|ku|kv|kw|ky|la|lad|lb|lbe|lg|li|lij|lmo|ln|lo|lt|ltg|lv|map-bms|mdf|mg|mh|mhr|mi|mk|ml|mn|mo|mr|mrj|ms|mt|mus|mwl|my|myv|mzn|na|nah|nap|nds|nds-nl|ne|new|ng|nl|nn|no|nov|nrm|nv|ny|oc|om|or|os|pa|pag|pam|pap|pcd|pdc|pfl|pi|pih|pl|pms|pnb|pnt|ps|pt|qu|rm|rmy|rn|ro|roa-rup|roa-tara|ru|rue|rw|sa|sah|sc|scn|sco|sd|se|sg|sh|si|simple|sk|sl|sm|sn|so|sq|sr|srn|ss|st|stq|su|sv|sw|szl|ta|te|tet|tg|th|ti|tk|tl|tn|to|tpi|tr|ts|tt|tum|tw|ty|udm|ug|uk|ur|uz|ve|vec|vi|vls|vo|wa|war|wo|wuu|xal|xh|yi|yo|za|zea|zh|zh-classical|zh-min-nan|zh-yue|zu";
pg.re.interwiki = new RegExp("^".concat(pg.wiki.interwiki, ":"));
} else {
pg.wiki.interwiki = null;
pg.re.interwiki = /^$/;
}
};
const nsRe = (namespaceId) => {
const imageNamespaceVariants = [];
for (var _i2 = 0, _Object$entries2 = Object.entries(mw.config.get("wgNamespaceIds")); _i2 < _Object$entries2.length; _i2++) {
const [_localizedNamespaceLc, _namespaceId] = _Object$entries2[_i2];
if (_namespaceId !== namespaceId) {
continue;
}
const localizedNamespaceLc = upcaseFirst(_localizedNamespaceLc);
imageNamespaceVariants.push(mw.util.escapeRegExp(localizedNamespaceLc).split(" ").join("[ _]"), mw.util.escapeRegExp(encodeURI(localizedNamespaceLc)));
}
return "(?:".concat(imageNamespaceVariants.join("|"), ")");
};
const nsReImage = () => {
return nsRe(pg.nsImageId);
};
const getEditboxSelection = () => {
let editbox;
try {
editbox = document.editform.wpTextbox1;
} catch {
return;
}
if (document.selection) {
return document.selection.createRange().text;
}
const selStart = editbox.selectionStart;
const selEnd = editbox.selectionEnd;
return editbox.value.substring(selStart, selEnd);
};
const doSelectionPopup = () => {
const sel = getEditboxSelection();
const open = sel.indexOf("[[");
const pipe = sel.indexOf("|");
const close = sel.indexOf("]]");
if (open === -1 || pipe === -1 && close === -1) {
return;
}
if (pipe !== -1 && open > pipe || close !== -1 && open > close) {
return;
}
const article = new Title(sel.substring(open + 2, pipe < 0 ? close : pipe));
if (getValueOf("popupOnEditSelection") === "boxpreview") {
return doSeparateSelectionPopup(sel, article);
}
if (close > 0 && sel.slice(Math.max(0, close + 2)).includes("[[")) {
return;
}
const a = document.createElement("a");
a.href = pg.wiki.titlebase + article.urlString();
mouseOverWikiLink2(a);
if (a.navpopup) {
a.navpopup.addHook(() => {
runStopPopupTimer(a.navpopup);
}, "unhide", "after");
}
};
const doSeparateSelectionPopup = (str, article) => {
let div = document.querySelector("#selectionPreview");
if (!div) {
div = document.createElement("div");
div.id = "selectionPreview";
try {
const box = document.editform.wpTextbox1;
box.parentNode.insertBefore(div, box);
} catch {
return;
}
}
const p = prepPreviewmaker(str, article, newNavpopup(document.createElement("a"), article));
p.makePreview();
if (p.html) {
div.innerHTML = p.html;
}
div.ranSetupTooltipsAlready = false;
popTipsSoonFn("selectionPreview")();
};
class Mousetracker {
constructor() {
this.loopDelay = 400;
this.timer = null;
this.active = false;
this.dirty = true;
this.hooks = [];
}
/**
* Adds a hook, to be called when we get events.
*
* @param {Function} f A function which is called as
* <code>f(x,y)</code>. It should return <code>true</code> when it
* wants to be removed, and <code>false</code> otherwise.
*/
addHook(f) {
this.hooks.push(f);
}
/**
* Runs hooks, passing them the x
* and y coords of the mouse. Hook functions that return true are
* passed to {@source Mousetracker#removeHooks} for removal.
*
* @private
*/
runHooks() {
if (!this.hooks || this.hooks.length === 0) {
return;
}
let remove = false;
const removeObj = {};
const {
x
} = this;
const {
y
} = this;
const len = this.hooks.length;
for (let i = 0; i < len; ++i) {
if (this.hooks[i](x, y) === true) {
remove = true;
removeObj[i] = true;
}
}
if (remove) {
this.removeHooks(removeObj);
}
}
/**
* Removes hooks.
*
* @private
* @param {Object} removeObj An object whose keys are the index
* numbers of functions for removal, with values that evaluate to true
*/
removeHooks(removeObj) {
const newHooks = [];
const len = this.hooks.length;
for (let i = 0; i < len; ++i) {
if (!removeObj[i]) {
newHooks.push(this.hooks[i]);
}
}
this.hooks = newHooks;
}
/**
* Event listener for mouse wiggles.
* We simply grab the event, set x and y and run the hooks.
* This makes the cpu all hot and bothered :-(
*
* @private
* @param {Event} e Mousemove event
*/
track(e) {
e || (e = window.event);
let x;
let y;
if (e) {
if (e.pageX) {
x = e.pageX;
y = e.pageY;
} else if (e.clientX === void 0) {
return;
} else {
let left;
let top;
const docElt = document.documentElement;
if (docElt) {
left = docElt.scrollLeft;
}
left || (left = document.querySelector("body").scrollLeft || document.scrollLeft || 0);
if (docElt) {
top = docElt.scrollTop;
}
top || (top = document.querySelector("body").scrollTop || document.scrollTop || 0);
x = e.clientX + left;
y = e.clientY + top;
}
this.setPosition(x, y);
}
}
/**
* Sets the x and y coordinates stored and takes appropriate action,
* running hooks as appropriate.
*
* @param {Integer} x, y Screen coordinates to set
* @param {number} x
* @param {number} y
*/
setPosition(x, y) {
this.x = x;
this.y = y;
if (this.dirty || this.hooks.length === 0) {
this.dirty = false;
return;
}
if (typeof this.lastHook_x !== "number") {
this.lastHook_x = -100;
this.lastHook_y = -100;
}
let diff2 = (this.lastHook_x - x) * (this.lastHook_y - y);
diff2 = diff2 >= 0 ? diff2 : -diff2;
if (diff2 > 1) {
this.lastHook_x = x;
this.lastHook_y = y;
if (this.dirty) {
this.dirty = false;
} else {
this.runHooks();
}
}
}
/**
* Sets things in motion, unless they are already that is, registering an event listener on
* <code>document.onmousemove</code>. A half-hearted attempt is made to preserve the old event
* listener if there is one.
*/
enable() {
if (this.active) {
return;
}
this.active = true;
this.savedListener = document.onmousemove;
const self2 = this;
document.onmousemove = (e) => {
self2.track(e);
};
if (this.loopDelay) {
this.timer = setInterval(() => {
self2.runHooks();
}, this.loopDelay);
}
}
/**
* Disables the tracker, removing the event listener.
*/
disable() {
if (!this.active) {
return;
}
if (typeof this.savedListener === "function") {
document.onmousemove = this.savedListener;
} else {
delete document.onmousemove;
}
if (this.timer) {
clearInterval(this.timer);
}
this.active = false;
}
}
class Navpopup {
constructor() {
this.uid = Navpopup.uid++;
this.visible = false;
this.noshow = false;
this.hooks = {
create: [],
unhide: [],
hide: []
};
this.hookIds = {};
this.downloads = [];
this.pending = null;
this.fuzz = 5;
this.constrained = true;
this.width = 0;
this.height = 0;
this.mainDiv = null;
this.createMainDiv();
}
/**
* Retrieves the {@source #visible} attribute, indicating whether the popup is currently visible.
*
* @type boolean
*/
isVisible() {
return this.visible;
}
/**
* Repositions popup using CSS style.
*
* @private
* @param {integer} x x-coordinate (px)
* @param {integer} y y-coordinate (px)
* @param {boolean} noLimitHor Don't call {@source #limitHorizontalPosition}
*/
reposition(x, y, noLimitHor) {
log("reposition(".concat(x, ",").concat(y, ",").concat(noLimitHor, ")"));
if (x !== void 0 && x !== null) {
this.left = x;
}
if (y !== void 0 && y !== null) {
this.top = y;
}
if (this.left !== void 0 && this.top !== void 0) {
this.mainDiv.style.left = "".concat(this.left, "px");
this.mainDiv.style.top = "".concat(this.top, "px");
}
if (!noLimitHor) {
this.limitHorizontalPosition();
}
}
/**
* Prevents popups from being in silly locations. Hopefully.
* Should not be run if {@source #constrained} is true.
*
* @private
*/
limitHorizontalPosition() {
if (!this.constrained || this.tooWide) {
return;
}
this.updateDimensions();
const x = this.left;
const w = this.width;
const cWidth = document.querySelector("body").clientWidth;
if (x + w >= cWidth || x > 0 && this.maxWidth && this.width < this.maxWidth && this.height > this.width && x > cWidth - this.maxWidth) {
this.mainDiv.style.left = "-10000px";
this.mainDiv.style.width = "".concat(this.maxWidth, "px");
const naturalWidth = Number.parseInt(this.mainDiv.offsetWidth, 10);
let newLeft = cWidth - naturalWidth - 1;
if (newLeft < 0) {
newLeft = 0;
this.tooWide = true;
}
log("limitHorizontalPosition: moving to (".concat(newLeft, ",").concat(this.top, "); naturalWidth=").concat(naturalWidth, ", clientWidth=").concat(cWidth));
this.reposition(newLeft, null, true);
}
}
/**
* Brings popup to the top of the z-order.
* We increment the {@source #highest} property of the contructor here.
*
* @private
*/
raise() {
this.mainDiv.style.zIndex = Navpopup.highest + 1;
++Navpopup.highest;
}
/**
* Shows the popup provided {@source #noshow} is not true.
* Updates the position, brings the popup to the top of the z-order and unhides it.
*/
show() {
if (this.noshow) {
return;
}
this.reposition();
this.raise();
this.unhide();
}
/**
* Checks to see if the mouse pointer has
* stabilised (checking every <code>time</code>/2 milliseconds) and runs the
* {@source #show} method if it has.
*
* @param {integer} time The minimum time (ms) before the popup may be shown.
*/
showSoonIfStable(time) {
log("showSoonIfStable, time=".concat(time));
if (this.visible) {
return;
}
this.noshow = false;
this.stable_x = -1e4;
this.stable_y = -1e4;
const stableShow = () => {
log("stableShow called");
const new_x = Navpopup.tracker.x;
const new_y = Navpopup.tracker.y;
const dx = self2.stable_x - new_x;
const dy = self2.stable_y - new_y;
const fuzz2 = 0;
if (dx * dx <= fuzz2 && dy * dy <= fuzz2) {
log("mouse is stable");
clearInterval(self2.showSoonStableTimer);
self2.reposition(new_x + 2, new_y + 2);
self2.show();
self2.limitHorizontalPosition();
return;
}
self2.stable_x = new_x;
self2.stable_y = new_y;
};
const self2 = this;
this.showSoonStableTimer = setInterval(stableShow, time / 2);
}
/**
* Sets the {@source #noshow} flag and hides the popup. This should be called
* when the mouse leaves the link before
* (or after) it's actually been displayed.
*/
banish() {
log("banish called");
this.noshow = true;
if (this.showSoonStableTimer) {
log("clearing showSoonStableTimer");
clearInterval(this.showSoonStableTimer);
}
this.hide();
}
/**
* Runs hooks added with {@source #addHook}.
*
* @private
* @param {string} key Key name of the {@source #hooks} array - one of 'create', 'unhide', 'hide'
* @param {string} when Controls exactly when the hook is run: either 'before' or 'after'
*/
runHooks(key, when) {
if (!this.hooks[key]) {
return;
}
const keyHooks = this.hooks[key];
const len = keyHooks.length;
for (let i = 0; i < len; ++i) {
if (keyHooks[i] && keyHooks[i].when === when && Reflect.apply(keyHooks[i].hook, this, [])) {
if (keyHooks[i].hookId) {
delete this.hookIds[keyHooks[i].hookId];
}
keyHooks[i] = null;
}
}
}
/**
* Adds a hook to the popup. Hook functions are run with <code>this</code> set to refer to the
* Navpopup instance, and no arguments.
*
* @param {Function} hook The hook function. Functions that return true are deleted.
* @param {string} key Key name of the {@source #hooks} array - one of 'create', 'unhide', 'hide'
* @param {string} when Controls exactly when the hook is run: either 'before' or 'after'
* @param {string} uid A truthy string identifying the hook function; if it matches another hook
* in this position, it won't be added again.
*/
addHook(hook, key, when, uid) {
when || (when = "after");
if (!this.hooks[key]) {
return;
}
let hookId;
if (uid) {
hookId = [key, when, uid].join("|");
if (this.hookIds[hookId]) {
return;
}
this.hookIds[hookId] = true;
}
this.hooks[key].push({
hook,
when,
hookId
});
}
/**
* Creates the main DIV element, which contains all the actual popup content.
* Runs hooks with key 'create'.
*
* @private
*/
createMainDiv() {
var _this$className;
if (this.mainDiv) {
return;
}
this.runHooks("create", "before");
const mainDiv = document.createElement("div");
const self2 = this;
mainDiv.onclick = (e) => {
self2.onclickListener(e);
};
mainDiv.className = (_this$className = this.className) !== null && _this$className !== void 0 ? _this$className : "navpopup_maindiv";
mainDiv.id = mainDiv.className + this.uid;
mainDiv.style.position = "absolute";
mainDiv.style.minWidth = "350px";
mainDiv.style.display = "none";
mainDiv.className = "navpopup";
mainDiv.navpopup = this;
this.mainDiv = mainDiv;
document.querySelector("body").append(mainDiv);
this.runHooks("create", "after");
}
/**
* Calls the {@source #raise} method.
*
* @private
*/
onclickListener() {
this.raise();
}
/**
* Makes the popup draggable, using a {@source Drag} object.
*
* @param {string} handleName
* @private
*/
makeDraggable(handleName) {
if (!this.mainDiv) {
this.createMainDiv();
}
const drag = new Drag();
if (!handleName) {
drag.startCondition = (e) => {
try {
if (!e.shiftKey) {
return false;
}
} catch {
return false;
}
return true;
};
}
let dragHandle;
if (handleName) {
dragHandle = document.getElementById("".concat(handleName));
}
dragHandle || (dragHandle = this.mainDiv);
const self2 = this;
drag.endHook = (x, y) => {
Navpopup.tracker.dirty = true;
self2.reposition(x, y);
};
drag.init(dragHandle, this.mainDiv);
}
/**
* Hides the popup using CSS. Runs hooks with key 'hide'.
* Sets {@source #visible} appropriately.
* {@source #banish} should be called externally instead of this method.
*
* @private
*/
hide() {
this.runHooks("hide", "before");
this.abortDownloads();
if (this.visible !== void 0 && this.visible) {
this.mainDiv.style.display = "none";
this.visible = false;
}
this.runHooks("hide", "after");
}
/**
* Shows the popup using CSS. Runs hooks with key 'unhide'.
* Sets {@source #visible} appropriately. {@source #show} should be called externally instead of this method.
*
* @private
*/
unhide() {
this.runHooks("unhide", "before");
if (this.visible !== void 0 && !this.visible) {
this.mainDiv.style.display = "inline";
this.visible = true;
}
this.runHooks("unhide", "after");
}
/**
* Sets the <code>innerHTML</code> attribute of the main div containing the popup content.
*
* @param {string} html The HTML to set.
*/
setInnerHTML(html) {
this.mainDiv.innerHTML = html;
}
/**
* Updates the {@source #width} and {@source #height} attributes with the CSS properties.
*
* @private
*/
updateDimensions() {
this.width = Number.parseInt(this.mainDiv.offsetWidth, 10);
this.height = Number.parseInt(this.mainDiv.offsetHeight, 10);
}
/**
* Checks if the point (x,y) is within {@source #fuzz} of the
* {@source #mainDiv}.
*
* @param {integer} x x-coordinate (px)
* @param {integer} y y-coordinate (px)
* @type boolean
*/
isWithin(x, y) {
if (!this.visible) {
return false;
}
this.updateDimensions();
const fuzz = this.fuzz || 0;
return x + fuzz >= this.left && x - fuzz <= this.left + this.width && y + fuzz >= this.top && y - fuzz <= this.top + this.height;
}
/**
* Adds a download to {@source #downloads}.
*
* @param {Downloader} download
*/
addDownload(download) {
if (!download) {
return;
}
this.downloads.push(download);
}
/**
* Aborts the downloads listed in {@source #downloads}.
*
* @see Downloader#abort
*/
abortDownloads() {
var _iterator18 = _createForOfIteratorHelper(this.downloads), _step18;
try {
for (_iterator18.s(); !(_step18 = _iterator18.n()).done; ) {
const d = _step18.value;
if (d && d.abort) {
d.abort();
}
}
} catch (err) {
_iterator18.e(err);
} finally {
_iterator18.f();
}
this.downloads = [];
}
}
Navpopup.uid = 0;
Navpopup.highest = 1e3;
Navpopup.tracker = new Mousetracker();
const delFmt = (x) => {
if (x.length === 0) {
return "";
}
return "<del class='popupDiff'>".concat(x.join(""), "</del>");
};
const insFmt = (x) => {
if (x.length === 0) {
return "";
}
return "<ins class='popupDiff'>".concat(x.join(""), "</ins>");
};
const countCrossings = (a, b, i, eject) => {
if (!b[i].row && b[i].row !== 0) {
return -1;
}
let count = 0;
var _iterator19 = _createForOfIteratorHelper(a.entries()), _step19;
try {
for (_iterator19.s(); !(_step19 = _iterator19.n()).done; ) {
const [j, element] = _step19.value;
if (!element.row && element.row !== 0) {
continue;
}
if ((j - b[i].row) * (i - element.row) > 0) {
if (eject) {
return true;
}
count++;
}
}
} catch (err) {
_iterator19.e(err);
} finally {
_iterator19.f();
}
return count;
};
const shortenDiffString = function shortenDiffString2(str, context) {
const re = /(<del[\S\s]*?<\/del>|<ins[\S\s]*?<\/ins>)/;
const splitted = str.split(re);
let ret = [""];
for (let i = 0; i < splitted.length; i += 2) {
if (splitted[i].length < 2 * context) {
ret[ret.length - 1] += splitted[i];
if (i + 1 < splitted.length) {
ret[ret.length - 1] += splitted[i + 1];
}
continue;
} else {
if (i > 0) {
ret[ret.length - 1] += splitted[i].slice(0, Math.max(0, context));
}
if (i + 1 < splitted.length) {
ret.push(splitted[i].slice(Math.max(0, splitted[i].length - context)) + splitted[i + 1]);
}
}
}
while (ret.length > 0 && !ret[0]) {
ret = ret.slice(1);
}
return ret;
};
const diffString = (o, n) => {
let i;
const oSplitted = o.split(/\b/);
const nSplitted = n.split(/\b/);
for (i = 0; i < oSplitted.length; ++i) {
oSplitted[i] = oSplitted[i].entify();
}
for (i = 0; i < nSplitted.length; ++i) {
nSplitted[i] = nSplitted[i].entify();
}
const out = diff(oSplitted, nSplitted);
let str = "";
let acc = [];
let maxOutputPair = 0;
for (i = 0; i < out.n.length; ++i) {
if (out.n[i].paired) {
if (maxOutputPair > out.n[i].row) {
out.o[out.n[i].row] = out.o[out.n[i].row].text;
out.n[i] = out.n[i].text;
}
if (maxOutputPair < out.n[i].row) {
maxOutputPair = out.n[i].row;
}
}
}
for (i = 0; i < out.o.length && !out.o[i].paired; ++i) {
acc.push(out.o[i]);
}
str += delFmt(acc);
acc = [];
for (i = 0; i < out.n.length; ++i) {
while (i < out.n.length && !out.n[i].paired) {
acc.push(out.n[i++]);
}
str += insFmt(acc);
acc = [];
if (i < out.n.length) {
str += out.n[i].text;
let m = out.n[i].row + 1;
while (m < out.o.length && !out.o[m].paired) {
acc.push(out.o[m++]);
}
str += delFmt(acc);
acc = [];
}
}
return str;
};
const jsReservedProperties = new RegExp("^(constructor|prototype|__((define|lookup)[GS]etter)__|eval|hasOwnProperty|propertyIsEnumerable|to(Source|String|LocaleString)|(un)?watch|valueOf)$");
const diffBugAlert = function diffBugAlert2(word) {
if (!diffBugAlert2.list[word]) {
diffBugAlert2.list[word] = 1;
void mw.notify("Bad word: ".concat(word, "\n\nPlease report this bug."), {
tag: "popups",
type: "error"
});
}
};
diffBugAlert.list = {};
const makeDiffHashtable = (src) => {
const ret = {};
for (let i = 0; i < src.length; i++) {
var _src$i, _ret$_src$i;
if (jsReservedProperties.test(src[i])) {
src[i] += "<!-- -->";
}
(_ret$_src$i = ret[_src$i = src[i]]) !== null && _ret$_src$i !== void 0 ? _ret$_src$i : ret[_src$i] = [];
try {
ret[src[i]].push(i);
} catch {
diffBugAlert(src[i]);
}
}
return ret;
};
const diff = (o, n) => {
const ns = makeDiffHashtable(n);
const os = makeDiffHashtable(o);
let i;
for (i in ns) {
if (ns[i].length === 1 && os[i] && os[i].length === 1) {
n[ns[i][0]] = {
text: n[ns[i][0]],
row: os[i][0],
paired: true
};
o[os[i][0]] = {
text: o[os[i][0]],
row: ns[i][0],
paired: true
};
}
}
for (i = 0; i < n.length - 1; i++) {
if (n[i].paired && !n[i + 1].paired && n[i].row + 1 < o.length && !o[n[i].row + 1].paired && n[i + 1] === o[n[i].row + 1]) {
n[i + 1] = {
text: n[i + 1],
row: n[i].row + 1,
paired: true
};
o[n[i].row + 1] = {
text: o[n[i].row + 1],
row: i + 1,
paired: true
};
}
}
for (i = n.length - 1; i > 0; i--) {
if (n[i].paired && !n[i - 1].paired && n[i].row > 0 && !o[n[i].row - 1].paired && n[i - 1] === o[n[i].row - 1]) {
n[i - 1] = {
text: n[i - 1],
row: n[i].row - 1,
paired: true
};
o[n[i].row - 1] = {
text: o[n[i].row - 1],
row: i - 1,
paired: true
};
}
}
return {
o,
n
};
};
const setSiteInfo = () => {
if (window.popupLocalDebug) {
pg.wiki.hostname = "en.wikipedia.org";
} else {
pg.wiki.hostname = location.hostname;
}
pg.wiki.wikimedia = /(wiki([mp]edia|source|books|news|quote|versity|species|voyage|data)|metawiki|wiktionary|mediawiki)\.org/.test(pg.wiki.hostname);
pg.wiki.wikia = /\.wikia\.com$/i.test(pg.wiki.hostname);
pg.wiki.isLocal = pg.wiki.hostname.startsWith("localhost");
pg.wiki.commons = pg.wiki.wikimedia && pg.wiki.hostname !== "commons.wikimedia.org" ? "commons.wikimedia.org" : null;
pg.wiki.lang = mw.config.get("wgContentLanguage");
const port = location.port ? ":".concat(location.port) : "";
pg.wiki.sitebase = pg.wiki.hostname + port;
};
const setUserInfo = () => {
const params = {
action: "query",
list: "users",
ususers: mw.config.get("wgUserName"),
usprop: "rights"
};
pg.user.canReview = false;
if (getValueOf("popupReview")) {
getMwApi().get(params).done((data) => {
const [{
rights
}] = data.query.users;
pg.user.canReview = rights.includes("review");
});
}
};
const fetchSpecialPageNames = () => {
const params = {
action: "query",
format: "json",
formatversion: "2",
meta: "siteinfo",
siprop: "specialpagealiases",
uselang: "content",
// cache for an hour
smaxage: 3600,
maxage: 3600
};
return getMwApi().get(params).then((data) => {
pg.wiki.specialpagealiases = data.query.specialpagealiases;
});
};
const setTitleBase = () => {
const protocol = window.popupLocalDebug ? "http:" : location.protocol;
pg.wiki.articlePath = mw.config.get("wgArticlePath").replace(/\/\$1/, "");
pg.wiki.botInterfacePath = mw.config.get("wgScript");
pg.wiki.APIPath = "".concat(mw.config.get("wgScriptPath"), "/api.php");
const titletail = "".concat(pg.wiki.botInterfacePath, "?title=");
pg.wiki.titlebase = "".concat(protocol, "//").concat(pg.wiki.sitebase).concat(titletail);
pg.wiki.wikibase = "".concat(protocol, "//").concat(pg.wiki.sitebase).concat(pg.wiki.botInterfacePath);
pg.wiki.apiwikibase = "".concat(protocol, "//").concat(pg.wiki.sitebase).concat(pg.wiki.APIPath);
pg.wiki.articlebase = "".concat(protocol, "//").concat(pg.wiki.sitebase).concat(pg.wiki.articlePath);
pg.wiki.commonsbase = "".concat(protocol, "//").concat(pg.wiki.commons).concat(pg.wiki.botInterfacePath);
pg.wiki.apicommonsbase = "".concat(protocol, "//").concat(pg.wiki.commons).concat(pg.wiki.APIPath);
pg.re.basenames = new RegExp("^(".concat(map(literalizeRegex, [pg.wiki.titlebase, pg.wiki.articlebase]).join("|"), ")"));
};
const setMainRegex = () => {
const reStart = "[^:]*://";
let preTitles = "".concat(literalizeRegex(mw.config.get("wgScriptPath")), "/(?:index[.]php|wiki[.]phtml)[?]title=");
preTitles += "|".concat(literalizeRegex("".concat(pg.wiki.articlePath, "/")));
const reEnd = "(".concat(preTitles, ")([^&?#]*)[^#]*(?:#(.+))?");
pg.re.main = new RegExp(reStart + literalizeRegex(pg.wiki.sitebase) + reEnd);
};
const buildSpecialPageGroup = (specialPageObj) => {
const variants = [];
variants.push(mw.util.escapeRegExp(specialPageObj.realname), mw.util.escapeRegExp(encodeURI(specialPageObj.realname)));
var _iterator20 = _createForOfIteratorHelper(specialPageObj.aliases), _step20;
try {
for (_iterator20.s(); !(_step20 = _iterator20.n()).done; ) {
const alias = _step20.value;
variants.push(mw.util.escapeRegExp(alias), mw.util.escapeRegExp(encodeURI(alias)));
}
} catch (err) {
_iterator20.e(err);
} finally {
_iterator20.f();
}
return variants.join("|");
};
const setRegexps = () => {
setMainRegex();
const sp = nsRe(pg.nsSpecialId);
pg.re.urlNoPopup = new RegExp("((title=|/)".concat(sp, "(?:%3A|:)|section=[0-9]|^#$)"));
var _iterator21 = _createForOfIteratorHelper(pg.wiki.specialpagealiases), _step21;
try {
for (_iterator21.s(); !(_step21 = _iterator21.n()).done; ) {
const specialpage = _step21.value;
switch (specialpage.realname) {
case "Contributions":
pg.re.contribs = new RegExp("(title=|/)".concat(sp, "(?:%3A|:)(?:").concat(buildSpecialPageGroup(specialpage), ")(&target=|/|/").concat(nsRe(pg.nsUserId), ":)(.*)"), "i");
break;
case "Diff":
pg.re.specialdiff = new RegExp("/".concat(sp, "(?:%3A|:)(?:").concat(buildSpecialPageGroup(specialpage), ")/([^?#]*)"), "i");
break;
case "Emailuser":
pg.re.email = new RegExp("(title=|/)".concat(sp, "(?:%3A|:)(?:").concat(buildSpecialPageGroup(specialpage), ")(&target=|/|/(?:").concat(nsRe(pg.nsUserId), ":)?)(.*)"), "i");
break;
case "Whatlinkshere":
pg.re.backlinks = new RegExp("(title=|/)".concat(sp, "(?:%3A|:)(?:").concat(buildSpecialPageGroup(specialpage), ")(&target=|/)([^&]*)"), "i");
break;
}
}
} catch (err) {
_iterator21.e(err);
} finally {
_iterator21.f();
}
const im = nsReImage();
pg.re.image = new RegExp("(^|\\[\\[)".concat(im, ": *([^|\\]]*[^|\\] ])").concat(String.raw(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral(["([^0-9]]*([0-9]+) *px)?|(?:\n *[|]?|[|]) *"], ["([^0-9\\]]*([0-9]+) *px)?|(?:\\n *[|]?|[|]) *"]))), "(").concat(getValueOf("popupImageVarsRegexp"), ") *= *(?:\\[\\[ *)?(?:").concat(im, ":)?").concat(String.raw(_templateObject5 || (_templateObject5 = _taggedTemplateLiteral(["([^|]*?)(?:]])? *[|]? *\n"], ["([^|]*?)(?:\\]\\])? *[|]? *\\n"])))), "img");
pg.re.imageBracketCount = 6;
pg.re.category = new RegExp("\\[\\[".concat(nsRe(pg.nsCategoryId), ": *([^|\\]]*[^|\\] ]) *"), "i");
pg.re.categoryBracketCount = 1;
pg.re.ipUser = /^(?::(?::|(?::[\dA-Fa-f]{1,4}){1,7})|[\dA-Fa-f]{1,4}(?::[\dA-Fa-f]{1,4}){0,6}::|[\dA-Fa-f]{1,4}(?::[\dA-Fa-f]{1,4}){7})|(((25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)\.){3}(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d))$/;
pg.re.stub = new RegExp(getValueOf("popupStubRegexp"), "im");
pg.re.disambig = new RegExp(getValueOf("popupDabRegexp"), "im");
pg.re.oldid = /[&?]oldid=([^&]*)/;
pg.re.diff = /[&?]diff=([^&]*)/;
};
const setupCache = () => {
pg.cache.pages = [];
};
const setMisc = () => {
pg.current.link = null;
pg.current.links = [];
pg.current.linksHash = {};
setupCache();
pg.timer.checkPopupPosition = null;
pg.counter.loop = 0;
pg.idNumber = 0;
pg.misc.decodeExtras = [
{
from: "%2C",
to: ","
},
{
from: "_",
to: " "
},
{
from: "%24",
to: "$"
},
{
from: "%26",
to: "&"
}
// no ,
];
};
const getMwApi = () => {
if (!pg.api.client) {
pg.api.userAgent = "Navigation popups/1.0";
pg.api.client = api;
}
return pg.api.client;
};
const setupPopups = function setupPopups2(callback) {
if (setupPopups2.completed) {
if (typeof callback === "function") {
callback();
}
return;
}
fetchSpecialPageNames().then(() => {
setupDebugging();
setSiteInfo();
setTitleBase();
setOptions();
setUserInfo();
setNamespaces();
setInterwiki();
setRegexps();
setRedirs();
setMisc();
setupLivePreview();
setupTooltips();
log("In setupPopups(), just called setupTooltips()");
Navpopup.tracker.enable();
setupPopups2.completed = true;
if (typeof callback === "function") {
callback();
}
});
};
const defaultNavlinkSpec = () => {
let str = "";
str += "<b><<mainlink|shortcut= >></b>";
if (getValueOf("popupLastEditLink")) {
str += "*<<lastEdit|shortcut=/>>|<<lastContrib>>|<<sinceMe>>if(oldid){|<<oldEdit>>|<<diffCur>>}";
}
str += "if(user){<br><<contribs|shortcut=c>>*<<userlog|shortcut=L|log>>";
str += "if(ipuser){*<<arin>>}if(wikimedia){*<<count|shortcut=#>>}";
str += "if(ipuser){}else{*<<email|shortcut=E>>}if(admin){*<<block|shortcut=b>>|<<blocklog|log>>}}";
const editstr = "<<edit|shortcut=e>>";
const editOldidStr = "if(oldid){<<editOld|shortcut=e>>|<<revert|shortcut=v|rv>>|<<edit|cur>>}else{".concat(editstr, "}");
const historystr = "<<history|shortcut=h>>|<<editors|shortcut=E|>>";
const watchstr = "<<unwatch|unwatchShort>>|<<watch|shortcut=w|watchThingy>>";
str += "<br>if(talk){".concat(editOldidStr, "|<<new|shortcut=+>>*").concat(historystr, "*").concat(watchstr, "*<b><<article|shortcut=a>></b>|<<editArticle|edit>>}else{").concat(
// not a talk page
editOldidStr,
"*"
).concat(historystr, "*").concat(watchstr, "*<b><<talk|shortcut=t>></b>|<<editTalk|edit>>|<<newTalk|shortcut=+|new>>}");
str += "<br><<whatLinksHere|shortcut=l>>*<<relatedChanges|shortcut=r>>*<<move|shortcut=m>>";
str += "if(admin){<br><<unprotect|unprotectShort>>|<<protect|shortcut=p>>|<<protectlog|log>>*<<undelete|undeleteShort>>|<<delete|shortcut=d>>|<<deletelog|log>>}";
return str;
};
const navLinksHTML = (article, _hint, params) => {
const str = '<span class="popupNavLinks">'.concat(defaultNavlinkSpec(), "</span>");
return navlinkStringToHTML(str, article, params);
};
const expandConditionalNavlinkString = function expandConditionalNavlinkString2(s, article, z, recursionCount) {
const {
oldid
} = z;
const {
rcid
} = z;
const {
diff: diff2
} = z;
if (typeof recursionCount !== "number") {
recursionCount = 0;
}
const conditionalSplitRegex = /(;?\s*if\s*\(\s*(\w*)\s*\)\s*{([^{}]*)}(\s*else\s*{([^{}]*?)}|))/i;
const splitted = s.split(conditionalSplitRegex);
const numParens = 5;
let [ret] = splitted;
for (let i = 1; i < splitted.length; i = i + numParens + 1) {
const testString = splitted[i + 2 - 1];
const trueString = splitted[i + 3 - 1];
let falseString = splitted[i + 5 - 1];
if (falseString === void 0 || !falseString) {
falseString = "";
}
let testResult;
switch (testString) {
case "user":
testResult = !!article.userName();
break;
case "talk":
testResult = !article.talkPage();
break;
case "admin":
testResult = !!getValueOf("popupAdminLinks");
break;
case "oldid":
testResult = !!(oldid !== void 0 && oldid);
break;
case "rcid":
testResult = !!(rcid !== void 0 && rcid);
break;
case "ipuser":
testResult = !!article.isIpUser();
break;
case "mainspace_en":
testResult = isInMainNamespace(article) && pg.wiki.hostname === "en.wikipedia.org";
break;
case "wikimedia":
testResult = !!pg.wiki.wikimedia;
break;
case "diff":
testResult = !!(diff2 !== void 0 && diff2);
break;
}
switch (testResult) {
case null:
ret += splitted[i];
break;
case true:
ret += trueString;
break;
case false:
ret += falseString;
break;
}
ret += splitted[i + numParens];
}
if (conditionalSplitRegex.test(ret) && recursionCount < 10) {
return expandConditionalNavlinkString2(ret, article, z, recursionCount + 1);
}
return ret;
};
const navlinkStringToArray = (s, article, params) => {
s = expandConditionalNavlinkString(s, article, params);
const splitted = s.split(/<<(.*?)>>/);
const ret = [];
var _iterator22 = _createForOfIteratorHelper(splitted.entries()), _step22;
try {
for (_iterator22.s(); !(_step22 = _iterator22.n()).done; ) {
const [i, element] = _step22.value;
if (i % 2) {
const t = new navlinkTag();
const ss = element.split("|");
[t.id] = ss;
for (let j = 1; j < ss.length; ++j) {
const sss = ss[j].split("=");
if (sss.length > 1) {
[, t[sss[0]]] = sss;
} else {
t.text = popupString(sss[0]);
}
}
t.article = article;
const {
oldid
} = params;
const {
rcid
} = params;
const {
diff: diff2
} = params;
if (oldid !== void 0 && oldid !== null) {
t.oldid = oldid;
}
if (rcid !== void 0 && rcid !== null) {
t.rcid = rcid;
}
if (diff2 !== void 0 && diff2 !== null) {
t.diff = diff2;
}
if (!t.text && t.id !== "mainlink") {
t.text = popupString(t.id);
}
ret.push(t);
} else {
ret.push(element);
}
}
} catch (err) {
_iterator22.e(err);
} finally {
_iterator22.f();
}
return ret;
};
const navlinkSubstituteHTML = (s) => {
return s.split("*").join(getValueOf("popupNavLinkSeparator")).split("<menurow>").join('<li class="popup_menu_row">').split("</menurow>").join("</li>").split("<menu>").join('<ul class="popup_menu">').split("</menu>").join("</ul>");
};
const navlinkDepth = (magic, s) => {
return s.split("<".concat(magic, ">")).length - s.split("</".concat(magic, ">")).length;
};
const navlinkStringToHTML = (s, article, params) => {
const p = navlinkStringToArray(s, article, params);
let html = "";
let menudepth = 0;
let menurowdepth = 0;
var _iterator23 = _createForOfIteratorHelper(p), _step23;
try {
for (_iterator23.s(); !(_step23 = _iterator23.n()).done; ) {
const element = _step23.value;
if (typeof element === "string") {
html += navlinkSubstituteHTML(element);
menudepth += navlinkDepth("menu", element);
menurowdepth += navlinkDepth("menurow", element);
} else if (element.type !== void 0 && element.type === "navlinkTag") {
html += menudepth > 0 && menurowdepth === 0 ? '<li class="popup_menu_item">'.concat(element.html(), "</li>") : element.html();
}
}
} catch (err) {
_iterator23.e(err);
} finally {
_iterator23.f();
}
return html;
};
class navlinkTag {
constructor() {
this.type = "navlinkTag";
}
html() {
this.getNewWin();
this.getPrintFunction();
let html = "";
let opening;
let closing;
const tagType = "span";
if (tagType) {
opening = "<".concat(tagType, ' class="popup_').concat(this.id, '">');
closing = "</".concat(tagType, ">");
} else {
opening = "";
closing = "";
}
if (typeof this.print === "function") {
html = this.print(this);
if (typeof html !== "string") {
html = "";
} else if (this.shortcut !== void 0) {
html = addPopupShortcut(html, this.shortcut);
}
} else {
errlog("Oh dear - invalid print function for a navlinkTag, id=".concat(this.id));
}
return opening + html + closing;
}
getNewWin() {
getValueOf("popupLinksNewWindow");
if (pg.option.popupLinksNewWindow[this.id] === void 0) {
this.newWin = null;
}
this.newWin = pg.option.popupLinksNewWindow[this.id];
}
getPrintFunction() {
if (typeof this.id !== "string" || typeof this.article !== typeof {}) {
return;
}
this.noPopup = 1;
switch (this.id) {
case "contribs":
case "history":
case "whatLinksHere":
case "userPage":
case "userTalk":
case "talk":
case "article":
case "lastEdit":
this.noPopup = null;
}
switch (this.id) {
case "email":
case "contribs":
case "block":
case "unblock":
case "userlog":
case "userSpace":
case "deletedContribs":
this.article = this.article.userName();
}
switch (this.id) {
case "userTalk":
case "newUserTalk":
case "editUserTalk":
case "userPage":
case "blocklog":
this.article = this.article.userName(true);
/* falls through */
case "pagelog":
case "deletelog":
case "protectlog":
delete this.oldid;
}
if (this.id !== "mainlink") {
this.article = this.article.removeAnchor();
}
switch (this.id) {
case "undelete":
this.print = specialLink;
this.specialpage = "Undelete";
this.sep = "/";
break;
case "whatLinksHere":
this.print = specialLink;
this.specialpage = "Whatlinkshere";
break;
case "relatedChanges":
this.print = specialLink;
this.specialpage = "Recentchangeslinked";
break;
case "move":
this.print = specialLink;
this.specialpage = "Movepage";
break;
case "contribs":
this.print = specialLink;
this.specialpage = "Contributions";
break;
case "deletedContribs":
this.print = specialLink;
this.specialpage = "Deletedcontributions";
break;
case "email":
this.print = specialLink;
this.specialpage = "EmailUser";
this.sep = "/";
break;
case "block":
this.print = specialLink;
this.specialpage = "Blockip";
this.sep = "&ip=";
break;
case "unblock":
this.print = specialLink;
this.specialpage = "Ipblocklist";
this.sep = "&action=unblock&ip=";
break;
case "userlog":
this.print = specialLink;
this.specialpage = "Log";
this.sep = "&user=";
break;
case "blocklog":
this.print = specialLink;
this.specialpage = "Log";
this.sep = "&type=block&page=";
break;
case "pagelog":
this.print = specialLink;
this.specialpage = "Log";
this.sep = "&page=";
break;
case "protectlog":
this.print = specialLink;
this.specialpage = "Log";
this.sep = "&type=protect&page=";
break;
case "deletelog":
this.print = specialLink;
this.specialpage = "Log";
this.sep = "&type=delete&page=";
break;
case "userSpace":
this.print = specialLink;
this.specialpage = "PrefixIndex";
this.sep = "&namespace=2&prefix=";
break;
case "search":
this.print = specialLink;
this.specialpage = "Search";
this.sep = "&fulltext=Search&search=";
break;
case "thank":
this.print = specialLink;
this.specialpage = "Thanks";
this.sep = "/";
this.article.value = this.diff === "prev" ? this.oldid : this.diff;
break;
case "unwatch":
case "watch":
this.print = magicWatchLink;
this.action = "".concat(this.id, "&autowatchlist=1&autoimpl=").concat(popupString("autoedit_version"), "&actoken=").concat(autoClickToken());
break;
case "history":
case "historyfeed":
case "unprotect":
case "protect":
this.print = wikiLink;
this.action = this.id;
break;
case "delete":
this.print = wikiLink;
this.action = "delete";
if (this.article.namespaceId() === pg.nsImageId) {
const img = this.article.stripNamespace();
this.action += "&image=".concat(img);
}
break;
case "markpatrolled":
case "edit":
delete this.oldid;
/* falls through */
case "view":
case "purge":
case "render":
this.print = wikiLink;
this.action = this.id;
break;
case "raw":
this.print = wikiLink;
this.action = "raw";
break;
case "new":
this.print = wikiLink;
this.action = "edit§ion=new";
break;
case "mainlink":
if (this.text === void 0) {
this.text = this.article.toString().entify();
}
if (getValueOf("popupSimplifyMainLink") && isInStrippableNamespace(this.article)) {
const s = this.text.split("/");
this.text = s.at(-1);
if (this.text === "" && s.length > 1) {
this.text = s.at(-2);
}
}
this.print = titledWikiLink;
if (this.title === void 0 && pg.current.link && pg.current.link.href !== void 0) {
var _pg$current$link$orig;
this.title = safeDecodeURI((_pg$current$link$orig = pg.current.link.originalTitle) !== null && _pg$current$link$orig !== void 0 ? _pg$current$link$orig : this.article);
if (this.oldid !== void 0 && this.oldid) {
this.title = tprintf("Revision %s of %s", [this.oldid, this.title]);
}
}
this.action = "view";
break;
case "userPage":
case "article":
case "editArticle":
delete this.oldid;
this.article = this.article.articleFromTalkOrArticle();
this.print = wikiLink;
this.action = this.id.indexOf("edit") === 0 ? "edit" : "view";
break;
case "userTalk":
case "talk":
this.article = this.article.talkPage();
delete this.oldid;
this.print = wikiLink;
this.action = "view";
break;
case "arin":
this.print = arinLink;
break;
case "count":
this.print = editCounterLink;
break;
case "editors":
this.print = editorListLink;
break;
case "lastEdit":
this.print = titledDiffLink;
this.title = popupString("Show the last edit");
this.from = "prev";
this.to = "cur";
break;
case "oldEdit":
this.print = titledDiffLink;
this.title = "".concat(popupString("Show the edit made to get revision"), " ").concat(this.oldid);
this.from = "prev";
this.to = this.oldid;
break;
case "editOld":
this.print = wikiLink;
this.action = "edit";
break;
case "undo":
this.print = wikiLink;
this.action = "edit&undo=";
break;
case "revert":
this.print = wikiLink;
this.action = "revert";
break;
case "nullEdit":
this.print = wikiLink;
this.action = "nullEdit";
break;
case "diffCur":
this.print = titledDiffLink;
this.title = tprintf("Show changes since revision %s", [this.oldid]);
this.from = this.oldid;
this.to = "cur";
break;
case "editUserTalk":
case "editTalk":
delete this.oldid;
this.article = this.article.talkPage();
this.action = "edit";
this.print = wikiLink;
break;
case "newUserTalk":
case "newTalk":
this.article = this.article.talkPage();
this.action = "edit§ion=new";
this.print = wikiLink;
break;
case "lastContrib":
case "sinceMe":
this.print = magicHistoryLink;
break;
case "togglePreviews":
this.text = popupString(pg.option.simplePopups ? "enable previews" : "disable previews");
/* falls through */
case "disablePopups":
case "purgePopups":
this.print = popupMenuLink;
break;
default:
this.print = function() {
return "Unknown navlink type: ".concat(this.id);
};
}
}
}
const popupHandleKeypress = function popupHandleKeypress2(evt) {
var _evt$keyCode;
const keyCode = window.event ? window.event.keyCode : (_evt$keyCode = evt.keyCode) !== null && _evt$keyCode !== void 0 ? _evt$keyCode : evt.which;
if (!keyCode || !pg.current.link || !pg.current.link.navpopup) {
return;
}
if (keyCode === 27) {
killPopup();
return false;
}
const letter = String.fromCodePoint(keyCode);
const links = pg.current.link.navpopup.mainDiv.querySelectorAll("A");
let startLink = 0;
let i;
let j;
if (popupHandleKeypress2.lastPopupLinkSelected) {
for (i = 0; i < links.length; ++i) {
if (links[i] === popupHandleKeypress2.lastPopupLinkSelected) {
startLink = i;
}
}
}
for (j = 0; j < links.length; ++j) {
i = (startLink + j + 1) % links.length;
if (links[i].getAttribute("popupkey") === letter) {
if (evt && evt.preventDefault) {
evt.preventDefault();
}
links[i].focus();
popupHandleKeypress2.lastPopupLinkSelected = links[i];
return false;
}
}
if (document.oldPopupOnkeypress) {
return document.oldPopupOnkeypress(evt);
}
return true;
};
const addPopupShortcuts = () => {
if (document.onkeypress !== popupHandleKeypress) {
document.oldPopupOnkeypress = document.onkeypress;
}
document.onkeypress = popupHandleKeypress;
};
const rmPopupShortcuts = () => {
popupHandleKeypress.lastPopupLinkSelected = null;
try {
if (document.oldPopupOnkeypress && document.oldPopupOnkeypress === popupHandleKeypress) {
document.onkeypress = null;
return;
}
document.onkeypress = document.oldPopupOnkeypress;
} catch {
}
};
const addLinkProperty = (html, property) => {
const i = html.indexOf(">");
if (i === -1) {
return html;
}
return "".concat(html.slice(0, Math.max(0, i)), " ").concat(property).concat(html.slice(Math.max(0, i)));
};
const addPopupShortcut = (html, key) => {
if (!getValueOf("popupShortcutKeys")) {
return html;
}
const ret = addLinkProperty(html, 'popupkey="'.concat(key, '"'));
if (key === " ") {
key = popupString("spacebar");
}
return ret.replace(/^(.*?)(title=")(.*?)(".*)$/i, "$1$2$3 [".concat(key, "]$4"));
};
const loadDiff = (article, oldid, diff2, navpop) => {
navpop.diffData = {
oldRev: {},
newRev: {}
};
const api2 = getMwApi();
const params = {
action: "compare",
prop: ["ids", "title"],
smaxage: 600,
maxage: 600
};
if (article.title) {
params.fromtitle = article.title;
}
switch (diff2) {
case "cur":
switch (oldid) {
case null:
case "":
case "prev":
params.torelative = "prev";
break;
default:
params.fromrev = oldid;
params.torelative = "cur";
break;
}
break;
case "prev":
if (oldid) {
params.fromrev = oldid;
}
params.torelative = "prev";
break;
case "next":
params.fromrev = oldid || 0;
params.torelative = "next";
break;
default:
params.fromrev = oldid || 0;
params.torev = diff2 || 0;
break;
}
api2.get(params).then((data) => {
navpop.diffData.oldRev.revid = data.compare.fromrevid;
navpop.diffData.newRev.revid = data.compare.torevid;
addReviewLink(navpop, "popupMiscTools");
const go = () => {
pendingNavpopTask(navpop);
let url = "".concat(pg.wiki.apiwikibase, "?format=json&formatversion=2&action=query&");
url += "revids=".concat(navpop.diffData.oldRev.revid, "|").concat(navpop.diffData.newRev.revid);
url += "&prop=revisions&rvprop=ids|timestamp|content";
getPageWithCaching(url, doneDiff, navpop);
return true;
};
if (navpop.visible || !getValueOf("popupLazyDownloads")) {
go();
} else {
navpop.addHook(go, "unhide", "before", "DOWNLOAD_DIFFS");
}
});
};
const addReviewLink = (navpop, target) => {
if (!pg.user.canReview) {
return;
}
if (navpop.diffData.newRev.revid <= navpop.diffData.oldRev.revid) {
return;
}
const params = {
action: "query",
format: "json",
formatversion: "2",
prop: ["info", "flagged"],
revids: navpop.diffData.oldRev.revid
};
getMwApi().get(params).then((data) => {
const stable_revid = data.query.pages[0].flagged && data.query.pages[0].flagged.stable_revid || 0;
if (stable_revid === navpop.diffData.oldRev.revid) {
const a = document.createElement("a");
a.innerHTML = popupString("mark patrolled");
a.title = popupString("markpatrolledHint");
a.onclick = () => {
const params2 = {
action: "review",
comment: tprintf("defaultpopupReviewedSummary", [navpop.diffData.oldRev.revid, navpop.diffData.newRev.revid]),
revid: navpop.diffData.newRev.revid
};
getMwApi().postWithToken("csrf", params2).done(() => {
a.style.display = "none";
}).fail(() => {
void mw.notify(popupString("Could not marked this edit as patrolled"), {
tag: "popups",
type: "error"
});
});
};
setPopupHTML(a, target, navpop.idNumber, null, true);
}
});
};
const doneDiff = (download) => {
if (!download.owner || !download.owner.diffData) {
return;
}
const navpop = download.owner;
completedNavpopTask(navpop);
let pages;
let revisions = [];
try {
({
pages
} = getJsObj(download.data).query);
var _iterator24 = _createForOfIteratorHelper(pages), _step24;
try {
for (_iterator24.s(); !(_step24 = _iterator24.n()).done; ) {
const page = _step24.value;
revisions = [...revisions, ...page.revisions];
}
} catch (err) {
_iterator24.e(err);
} finally {
_iterator24.f();
}
for (var _i3 = 0, _revisions = revisions; _i3 < _revisions.length; _i3++) {
const revision = _revisions[_i3];
if (revision.revid === navpop.diffData.oldRev.revid) {
navpop.diffData.oldRev.revision = revision;
} else if (revision.revid === navpop.diffData.newRev.revid) {
navpop.diffData.newRev.revision = revision;
}
}
} catch {
errlog("Could not get diff");
}
insertDiff(navpop);
};
const rmBoringLines = (a, b, context) => {
if (context === void 0) {
context = 2;
}
const aa = [];
const aaa = [];
const bb = [];
const bbb = [];
let i;
let j;
for (i = 0; i < a.length; ++i) {
if (!a[i].paired) {
aa[i] = 1;
} else if (countCrossings(b, a, i, true)) {
aa[i] = 1;
bb[a[i].row] = 1;
}
}
for (i = 0; i < b.length; ++i) {
if (bb[i] === 1) {
continue;
}
if (!b[i].paired) {
bb[i] = 1;
}
}
for (i = 0; i < b.length; ++i) {
if (bb[i] === 1) {
for (j = Math.max(0, i - context); j < Math.min(b.length, i + context); ++j) {
if (!bb[j]) {
bb[j] = 1;
aa[b[j].row] = 0.5;
}
}
}
}
for (i = 0; i < a.length; ++i) {
if (aa[i] === 1) {
for (j = Math.max(0, i - context); j < Math.min(a.length, i + context); ++j) {
if (!aa[j]) {
aa[j] = 1;
bb[a[j].row] = 0.5;
}
}
}
}
for (i = 0; i < bb.length; ++i) {
if (bb[i] > 0) {
if (b[i].paired) {
bbb.push(b[i].text);
} else {
bbb.push(b[i]);
}
}
}
for (i = 0; i < aa.length; ++i) {
if (aa[i] > 0) {
if (a[i].paired) {
aaa.push(a[i].text);
} else {
aaa.push(a[i]);
}
}
}
return {
a: aaa,
b: bbb
};
};
const stripOuterCommonLines = (a, b, context) => {
let i = 0;
while (i < a.length && i < b.length && a[i] === b[i]) {
++i;
}
let j = a.length - 1;
let k = b.length - 1;
while (j >= 0 && k >= 0 && a[j] === b[k]) {
--j;
--k;
}
return {
a: a.slice(Math.max(0, i - 1 - context), Math.min(a.length + 1, j + context + 1)),
b: b.slice(Math.max(0, i - 1 - context), Math.min(b.length + 1, k + context + 1))
};
};
const insertDiff = (navpop) => {
let oldlines = navpop.diffData.oldRev.revision.content.split("\n");
let newlines = navpop.diffData.newRev.revision.content.split("\n");
let inner = stripOuterCommonLines(oldlines, newlines, getValueOf("popupDiffContextLines"));
oldlines = inner.a;
newlines = inner.b;
let truncated = false;
getValueOf("popupDiffMaxLines");
if (oldlines.length > pg.option.popupDiffMaxLines || newlines.length > pg.option.popupDiffMaxLines) {
truncated = true;
inner = stripOuterCommonLines(oldlines.slice(0, pg.option.popupDiffMaxLines), newlines.slice(0, pg.option.popupDiffMaxLines), pg.option.popupDiffContextLines);
oldlines = inner.a;
newlines = inner.b;
}
const lineDiff = diff(oldlines, newlines);
const lines2 = rmBoringLines(lineDiff.o, lineDiff.n);
const oldlines2 = lines2.a;
const newlines2 = lines2.b;
let html = "<hr>";
if (getValueOf("popupDiffDates")) {
html += diffDatesTable(navpop);
html += "<hr>";
}
html += shortenDiffString(diffString(oldlines2.join("\n"), newlines2.join("\n")), getValueOf("popupDiffContextCharacters")).join("<hr>");
setPopupTipsAndHTML(html.split("\n").join("<br>") + (truncated ? "<hr><b>".concat(popupString("Diff truncated for performance reasons"), "</b>") : ""), "popupPreview", navpop.idNumber);
};
const diffDatesTable = (navpop) => {
let html = '<table class="popup_diff_dates">';
html += diffDatesTableRow(navpop.diffData.newRev.revision, tprintf("New revision"));
html += diffDatesTableRow(navpop.diffData.oldRev.revision, tprintf("Old revision"));
html += "</table>";
return html;
};
const diffDatesTableRow = (revision, label) => {
let txt = "";
const lastModifiedDate = new Date(revision.timestamp);
txt = formattedDateTime(lastModifiedDate);
const revlink = generalLink({
url: "".concat(mw.config.get("wgScript"), "?oldid=").concat(revision.revid),
text: label,
title: label
});
return simplePrintf("<tr><td>%s</td><td>%s</td></tr>", [revlink, txt]);
};
const titledDiffLink = (l) => {
return titledWikiLink({
article: l.article,
action: "".concat(l.to, "&oldid=").concat(l.from),
newWin: l.newWin,
noPopup: l.noPopup,
text: l.text,
title: l.title,
/* hack: no oldid here */
actionName: "diff"
});
};
const wikiLink = (l) => {
if (!(typeof l.article === typeof {} && typeof l.action === "string" && typeof l.text === "string")) {
return null;
}
if (l.oldid === void 0) {
l.oldid = null;
}
const savedOldid = l.oldid;
if (!/^(edit|view|revert|render)$|^raw/.test(l.action)) {
l.oldid = null;
}
let hint = popupString("".concat(l.action, "Hint"));
const oldidData = [l.oldid, safeDecodeURI(l.article)];
let revisionString = tprintf("revision %s of %s", oldidData);
log("revisionString=".concat(revisionString));
switch (l.action) {
case "edit§ion=new":
hint = popupString("newSectionHint");
break;
case "edit&undo=":
if (l.diff && l.diff !== "prev" && savedOldid) {
l.action += "".concat(l.diff, "&undoafter=").concat(savedOldid);
} else if (savedOldid) {
l.action += savedOldid;
}
hint = popupString("undoHint");
break;
case "raw&ctype=text/css":
hint = popupString("rawHint");
break;
case "revert": {
const p = parseParams(pg.current.link.href);
l.action = "edit&autoclick=wpSave&actoken=".concat(autoClickToken(), "&autoimpl=").concat(popupString("autoedit_version"), "&autosummary=").concat(revertSummary(l.oldid, p.diff));
if (p.diff === "prev") {
l.action += "&direction=prev";
revisionString = tprintf("the revision prior to revision %s of %s", oldidData);
}
if (getValueOf("popupRevertSummaryPrompt")) {
l.action += "&autosummaryprompt=true";
}
if (getValueOf("popupMinorReverts")) {
l.action += "&autominor=true";
}
log("revisionString is now ".concat(revisionString));
break;
}
case "nullEdit":
l.action = "edit&autoclick=wpSave&actoken=".concat(autoClickToken(), "&autoimpl=").concat(popupString("autoedit_version"), "&autosummary=null");
break;
case "historyfeed":
l.action = "history&feed=rss";
break;
case "markpatrolled":
l.action = "markpatrolled&rcid=".concat(l.rcid);
}
if (hint) {
hint = l.oldid ? simplePrintf(hint, [revisionString]) : simplePrintf(hint, [safeDecodeURI(l.article)]);
} else {
hint = safeDecodeURI("".concat(l.article, "&action=").concat(l.action)) + l.oldid ? "&oldid=".concat(l.oldid) : "";
}
return titledWikiLink({
article: l.article,
action: l.action,
text: l.text,
newWin: l.newWin,
title: hint,
oldid: l.oldid,
noPopup: l.noPopup,
onclick: l.onclick
});
};
const revertSummary = (oldid, diff2) => {
let ret = "";
ret = diff2 === "prev" ? getValueOf("popupQueriedRevertToPreviousSummary") : getValueOf("popupQueriedRevertSummary");
return "".concat(ret, "&autorv=").concat(oldid);
};
const titledWikiLink = (l) => {
if (l.article === void 0 || l.action === void 0) {
errlog("got undefined article or action in titledWikiLink");
return null;
}
const base = pg.wiki.titlebase + l.article.urlString();
let url = base;
if (l.actionName === void 0 || !l.actionName) {
l.actionName = "action";
}
if (l.action !== "view") {
url = "".concat(base, "&").concat(l.actionName, "=").concat(l.action);
}
if (l.oldid !== void 0 && l.oldid) {
url += "&oldid=".concat(l.oldid);
}
let cssClass = pg.misc.defaultNavlinkClassname;
if (l.className !== void 0 && l.className) {
cssClass = l.className;
}
return generalNavLink({
url,
newWin: l.newWin,
title: l.title === void 0 ? null : l.title,
text: l.text === void 0 ? null : l.text,
className: cssClass,
noPopup: l.noPopup,
onclick: l.onclick
});
};
pg.fn.getLastContrib = (wikipage, newWin) => {
getHistoryInfo(wikipage, (x) => {
processLastContribInfo(x, {
page: wikipage,
newWin
});
});
};
const processLastContribInfo = (info, stuff) => {
if (!info.edits || info.edits.length === 0) {
void mw.notify("Popups: an odd thing happened. Please retry.", {
tag: "popups",
type: "error"
});
return;
}
if (!info.firstNewEditor) {
void mw.notify(tprintf("Only found one editor: %s made %s edits", [info.edits[0].editor, info.edits.length]), {
tag: "popups",
type: "error"
});
return;
}
const newUrl = "".concat(pg.wiki.titlebase + new Title(stuff.page).urlString(), "&diff=cur&oldid=").concat(info.firstNewEditor.oldid);
displayUrl(newUrl, stuff.newWin);
};
pg.fn.getDiffSinceMyEdit = (wikipage, newWin) => {
getHistoryInfo(wikipage, (x) => {
processDiffSinceMyEdit(x, {
page: wikipage,
newWin
});
});
};
const processDiffSinceMyEdit = (info, stuff) => {
if (!info.edits || info.edits.length === 0) {
void mw.notify("Popups: something fishy happened. Please try again.", {
tag: "popups",
type: "error"
});
return;
}
const friendlyName = stuff.page.split("_").join(" ");
if (!info.myLastEdit) {
void mw.notify(tprintf("Couldn't find an edit by %s\nin the last %s edits to\n%s", [info.userName, getValueOf("popupHistoryLimit"), friendlyName]), {
tag: "popups",
type: "error"
});
return;
}
if (info.myLastEdit.index === 0) {
void mw.notify(tprintf("%s seems to be the last editor to the page %s", [info.userName, friendlyName]), {
type: "error"
});
return;
}
const newUrl = "".concat(pg.wiki.titlebase + new Title(stuff.page).urlString(), "&diff=cur&oldid=").concat(info.myLastEdit.oldid);
displayUrl(newUrl, stuff.newWin);
};
const displayUrl = (url, newWin) => {
if (newWin) {
window.open(url);
} else {
document.location = url;
}
};
pg.fn.purgePopups = () => {
processAllPopups(true);
setupCache();
pg.option = {};
abortAllDownloads();
};
const processAllPopups = (nullify, banish) => {
for (let i = 0; pg.current.links && i < pg.current.links.length; ++i) {
if (!pg.current.links[i].navpopup) {
continue;
}
if (nullify || banish) {
pg.current.links[i].navpopup.banish();
}
pg.current.links[i].simpleNoMore = false;
if (nullify) {
pg.current.links[i].navpopup = null;
}
}
};
pg.fn.disablePopups = () => {
processAllPopups(false, true);
setupTooltips(null, true);
};
pg.fn.togglePreviews = () => {
processAllPopups(true, true);
pg.option.simplePopups = !pg.option.simplePopups;
abortAllDownloads();
};
const magicWatchLink = function magicWatchLink2(l) {
l.onclick = simplePrintf("pg.fn.modifyWatchlist('%s','%s');return false;", [l.article.toString(true).split("\\").join("\\\\").split("'").join(String.raw(_templateObject6 || (_templateObject6 = _taggedTemplateLiteral(["'"], ["\\'"])))), this.id]);
return wikiLink(l);
};
pg.fn.modifyWatchlist = /* @__PURE__ */ (function() {
var _ref = _asyncToGenerator(function* (title, action) {
const reqData = {
action: "watch",
formatversion: "2",
titles: title,
uselang: mw.config.get("wgUserLanguage")
};
if (action === "unwatch") {
reqData.unwatch = true;
}
const mwTitle = mw.Title.newFromText(title);
let messageName;
if (mwTitle && mwTitle.getNamespaceId() > 0 && mwTitle.getNamespaceId() % 2 === 1) {
messageName = action === "watch" ? "addedwatchtext-talk" : "removedwatchtext-talk";
} else {
messageName = action === "watch" ? "addedwatchtext" : "removedwatchtext";
}
yield getMwApi().postWithToken("watch", reqData);
yield getMwApi().loadMessagesIfMissing([messageName]);
void mw.notify(mw.message(messageName, title).parseDom(), {
tag: "popups"
});
});
return function(_x2, _x3) {
return _ref.apply(this, arguments);
};
})();
const magicHistoryLink = (l) => {
let title = "";
let onClick = "";
switch (l.id) {
case "lastContrib":
onClick = simplePrintf("pg.fn.getLastContrib('%s',%s)", [l.article.toString(true).split("\\").join("\\\\").split("'").join(String.raw(_templateObject7 || (_templateObject7 = _taggedTemplateLiteral(["'"], ["\\'"])))), l.newWin]);
title = popupString("lastContribHint");
break;
case "sinceMe":
onClick = simplePrintf("pg.fn.getDiffSinceMyEdit('%s',%s)", [l.article.toString(true).split("\\").join("\\\\").split("'").join(String.raw(_templateObject8 || (_templateObject8 = _taggedTemplateLiteral(["'"], ["\\'"])))), l.newWin]);
title = popupString("sinceMeHint");
break;
}
onClick += ";return false;";
return generalNavLink({
newWin: false,
title,
text: l.text,
noPopup: l.noPopup,
onclick: onClick
});
};
const popupMenuLink = (l) => {
const title = popupString(simplePrintf("%sHint", [l.id]));
const onClick = simplePrintf("pg.fn.%s();return false;", [l.id]);
return generalNavLink({
newWin: false,
title,
text: l.text,
noPopup: l.noPopup,
onclick: onClick
});
};
const specialLink = (l) => {
var _l$sep;
if (l.specialpage === void 0 || !l.specialpage) {
return null;
}
const base = "".concat(pg.wiki.titlebase + mw.config.get("wgFormattedNamespaces")[pg.nsSpecialId], ":").concat(l.specialpage);
(_l$sep = l.sep) !== null && _l$sep !== void 0 ? _l$sep : l.sep = "&target=";
let article = l.article.urlString({
keepSpaces: l.specialpage === "Search"
});
let hint = popupString("".concat(l.specialpage, "Hint"));
switch (l.specialpage) {
case "Log":
switch (l.sep) {
case "&user=":
hint = popupString("userLogHint");
break;
case "&type=block&page=":
hint = popupString("blockLogHint");
break;
case "&page=":
hint = popupString("pageLogHint");
break;
case "&type=protect&page=":
hint = popupString("protectLogHint");
break;
case "&type=delete&page=":
hint = popupString("deleteLogHint");
break;
default:
log("Unknown log type, sep=".concat(l.sep));
hint = "Missing hint (FIXME)";
}
break;
case "PrefixIndex":
article += "/";
break;
}
hint = hint ? simplePrintf(hint, [safeDecodeURI(l.article)]) : safeDecodeURI("".concat(l.specialpage, ":").concat(l.article));
const url = base + l.sep + article;
return generalNavLink({
url,
title: hint,
text: l.text,
newWin: l.newWin,
noPopup: l.noPopup
});
};
const generalLink = (l) => {
let ret = "<a";
if (l.url) {
const url = l.url.split('"').join("%22");
ret += ' href="'.concat(url, '"');
}
if (l.title !== void 0 && l.title) {
ret += ' title="'.concat(pg.escapeQuotesHTML(l.title), '"');
}
if (l.onclick !== void 0 && l.onclick) {
ret += ' onclick="'.concat(pg.escapeQuotesHTML(l.onclick), '"');
}
if (l.noPopup) {
ret += " noPopup=1";
}
let newWin;
if (l.newWin === void 0 || l.newWin === null) {
newWin = getValueOf("popupNewWindows");
} else {
({
newWin
} = l);
}
if (newWin) {
ret += ' rel="noopener" target="_blank"';
}
if (l.className !== void 0 && l.className) {
ret += ' class="'.concat(l.className, '"');
}
ret += ">";
if (typeof l.text === "string") {
ret += pg.escapeQuotesHTML(pg.unescapeQuotesHTML(l.text));
}
ret += "</a>";
return ret;
};
const appendParamsToLink = (linkstr, params) => {
const sp = linkstr.split(/(href="[^"]+?)"/i);
if (sp.length < 2) {
return null;
}
let ret = sp.shift() + sp.shift();
ret += "&".concat(params, '"');
ret += sp.join("");
return ret;
};
const changeLinkTargetLink = (x) => {
if (x.newTarget) {
log("changeLinkTargetLink: newTarget=".concat(x.newTarget));
}
if (x.oldTarget !== decodeURIComponent(x.oldTarget)) {
log("This might be an input problem: ".concat(x.oldTarget));
}
const cA = mw.util.escapeRegExp(x.oldTarget);
let chs = cA.charAt(0).toUpperCase();
chs = "[".concat(chs).concat(chs.toLowerCase(), "]");
let currentArticleRegexBit = chs + cA.slice(1);
currentArticleRegexBit = currentArticleRegexBit.split(/[ _]+|%20/g).join("(?:[_ ]+|%20)").split(String.raw(_templateObject9 || (_templateObject9 = _taggedTemplateLiteral(["("], ["\\("])))).join(String.raw(_templateObject0 || (_templateObject0 = _taggedTemplateLiteral(["(?:%28|()"], ["(?:%28|\\()"])))).split(String.raw(_templateObject1 || (_templateObject1 = _taggedTemplateLiteral([")"], ["\\)"])))).join(String.raw(_templateObject10 || (_templateObject10 = _taggedTemplateLiteral(["(?:%29|))"], ["(?:%29|\\))"]))));
currentArticleRegexBit = "\\s*(".concat(currentArticleRegexBit, "(?:#[^\\[\\|]*)?)\\s*");
const title = x.title || mw.config.get("wgPageName").split("_").join(" ");
const lk = titledWikiLink({
article: new Title(title),
newWin: x.newWin,
action: "edit",
text: x.text,
title: x.hint,
className: "popup_change_title_link"
});
let cmd = "";
if (x.newTarget) {
const t = x.newTarget;
const s = mw.util.escapeRegExp(x.newTarget);
if (x.alsoChangeLabel) {
cmd += "s~\\[\\[".concat(currentArticleRegexBit, "\\]\\]~[[").concat(t, "]]~g;");
cmd += "s~\\[\\[".concat(currentArticleRegexBit, "[|]~[[").concat(t, "|~g;");
cmd += "s~\\[\\[".concat(s, "\\|").concat(s, "\\]\\]~[[").concat(t, "]]~g");
} else {
cmd += "s~\\[\\[".concat(currentArticleRegexBit, "\\]\\]~[[").concat(t, "|$1]]~g;");
cmd += "s~\\[\\[".concat(currentArticleRegexBit, "[|]~[[").concat(t, "|~g;");
cmd += "s~\\[\\[".concat(s, "\\|").concat(s, "\\]\\]~[[").concat(t, "]]~g");
}
} else {
cmd += "s~\\[\\[".concat(currentArticleRegexBit, "\\]\\]~$1~g;");
cmd += "s~\\[\\[".concat(currentArticleRegexBit, "[|](.*?)\\]\\]~$2~g");
}
cmd = "autoedit=".concat(encodeURIComponent(cmd));
cmd += "&autoclick=".concat(encodeURIComponent(x.clickButton), "&actoken=").concat(encodeURIComponent(autoClickToken()));
cmd += x.minor === null ? "" : "&autominor=".concat(encodeURIComponent(x.minor));
cmd += x.watch === null ? "" : "&autowatch=".concat(encodeURIComponent(x.watch));
cmd += "&autosummary=".concat(encodeURIComponent(x.summary));
cmd += "&autoimpl=".concat(encodeURIComponent(popupString("autoedit_version")));
return appendParamsToLink(lk, cmd);
};
const redirLink = (redirMatch, article) => {
let ret = "";
if (getValueOf("popupAppendRedirNavLinks") && getValueOf("popupNavLinks")) {
ret += "<hr>";
if (getValueOf("popupFixRedirs") && autoEdit !== void 0 && autoEdit) {
ret += popupString("Redirects to: (Fix ");
log("redirLink: newTarget=".concat(redirMatch));
ret += addPopupShortcut(changeLinkTargetLink({
newTarget: redirMatch,
text: popupString("target"),
hint: popupString("Fix this redirect, changing just the link target"),
summary: simplePrintf(getValueOf("popupFixRedirsSummary"), [article.toString(), redirMatch]),
oldTarget: article.toString(),
clickButton: getValueOf("popupRedirAutoClick"),
minor: true,
watch: getValueOf("popupWatchRedirredPages")
}), "R");
ret += popupString(" or ");
ret += addPopupShortcut(changeLinkTargetLink({
newTarget: redirMatch,
text: popupString("target & label"),
hint: popupString("Fix this redirect, changing the link target and label"),
summary: simplePrintf(getValueOf("popupFixRedirsSummary"), [article.toString(), redirMatch]),
oldTarget: article.toString(),
clickButton: getValueOf("popupRedirAutoClick"),
minor: true,
watch: getValueOf("popupWatchRedirredPages"),
alsoChangeLabel: true
}), "R");
ret += popupString(")");
} else {
ret += popupString("Redirects") + popupString(" to ");
}
return ret;
}
return "<br> ".concat(popupString("Redirects")).concat(popupString(" to ")).concat(titledWikiLink({
article: new Title().fromWikiText(redirMatch),
action: "view",
text: safeDecodeURI(redirMatch),
title: popupString("Bypass redirect")
}));
};
const arinLink = (l) => {
if (!saneLinkCheck(l)) {
return null;
}
if (!l.article.isIpUser() || !pg.wiki.wikimedia) {
return null;
}
const uN = l.article.userName();
return generalNavLink({
url: "http://ws.arin.net/cgi-bin/whois.pl?queryinput=".concat(encodeURIComponent(uN)),
newWin: l.newWin,
title: tprintf("Look up %s in ARIN whois database", [uN]),
text: l.text,
noPopup: 1
});
};
const toolDbName = (cookieStyle) => {
let ret = mw.config.get("wgDBname");
if (!cookieStyle) {
ret += "_p";
}
return ret;
};
const saneLinkCheck = (l) => {
if (typeof l.article !== typeof {} || typeof l.text !== "string") {
return false;
}
return true;
};
const editCounterLink = (l) => {
if (!saneLinkCheck(l)) {
return null;
}
if (!pg.wiki.wikimedia) {
return null;
}
const uN = l.article.userName();
const tool = getValueOf("popupEditCounterTool");
let url;
const defaultToolUrl = "//tools.wmflabs.org/supercount/index.php?user=$1&project=$2.$3";
switch (tool) {
case "custom":
url = simplePrintf(getValueOf("popupEditCounterUrl"), [encodeURIComponent(uN), toolDbName()]);
break;
default: {
const theWiki = pg.wiki.hostname.split(".");
url = simplePrintf(defaultToolUrl, [encodeURIComponent(uN), theWiki[0], theWiki[1]]);
}
}
return generalNavLink({
url,
title: tprintf("editCounterLinkHint", [uN]),
newWin: l.newWin,
text: l.text,
noPopup: 1
});
};
const editorListLink = (l) => {
if (!saneLinkCheck(l)) {
return null;
}
const article = l.article.articleFromTalkPage() || l.article;
const url = "https://xtools.wmflabs.org/articleinfo/".concat(encodeURI(pg.wiki.hostname), "/").concat(article.urlString(), "?uselang=").concat(mw.config.get("wgUserLanguage"));
return generalNavLink({
url,
title: tprintf("editorListHint", [article]),
newWin: l.newWin,
text: l.text,
noPopup: 1
});
};
const generalNavLink = (l) => {
l.className = l.className === null ? "popupNavLink" : l.className;
return generalLink(l);
};
const getHistoryInfo = (wikipage, whatNext) => {
log("getHistoryInfo");
getHistory(wikipage, whatNext ? (d) => {
whatNext(processHistory(d));
} : processHistory);
};
const getHistory = (wikipage, onComplete) => {
log("getHistory");
const url = "".concat(pg.wiki.apiwikibase, "?format=json&formatversion=2&action=query&prop=revisions&titles=").concat(new Title(wikipage).urlString(), "&rvlimit=").concat(getValueOf("popupHistoryLimit"));
log("getHistory: url=".concat(url));
return startDownload(url, "".concat(pg.idNumber, "history"), onComplete);
};
const processHistory = (download) => {
const jsobj = getJsObj(download.data);
try {
const {
revisions
} = anyChild(jsobj.query.pages);
const edits = [];
var _iterator25 = _createForOfIteratorHelper(revisions), _step25;
try {
for (_iterator25.s(); !(_step25 = _iterator25.n()).done; ) {
const revision = _step25.value;
edits.push({
oldid: revision.revid,
editor: revision.user
});
}
} catch (err) {
_iterator25.e(err);
} finally {
_iterator25.f();
}
log("processed ".concat(edits.length, " edits"));
return finishProcessHistory(edits, mw.config.get("wgUserName"));
} catch {
log("Something went wrong with JSON business");
return finishProcessHistory([]);
}
};
const finishProcessHistory = (edits, userName) => {
const histInfo = {};
histInfo.edits = edits;
histInfo.userName = userName;
for (let i = 0; i < edits.length; ++i) {
if (histInfo.myLastEdit === void 0 && userName && edits[i].editor === userName) {
histInfo.myLastEdit = {
index: i,
oldid: edits[i].oldid,
previd: i === 0 ? null : edits[i - 1].oldid
};
}
if (histInfo.firstNewEditor === void 0 && edits[i].editor !== edits[0].editor) {
histInfo.firstNewEditor = {
index: i,
oldid: edits[i].oldid,
previd: i === 0 ? null : edits[i - 1].oldid
};
}
}
return histInfo;
};
const defaultize = (x) => {
var _pg$option, _pg$option$x;
(_pg$option$x = (_pg$option = pg.option)[x]) !== null && _pg$option$x !== void 0 ? _pg$option$x : _pg$option[x] = window[x] === void 0 ? pg.optionDefault[x] : window[x];
};
const newOption = (x, def) => {
pg.optionDefault[x] = def;
};
const setDefault = (x, def) => {
return newOption(x, def);
};
const getValueOf = (varName) => {
defaultize(varName);
return pg.option[varName];
};
const setOptions = () => {
let userIsSysop = false;
if (mw.config.get("wgUserGroups")) {
for (let g = 0; g < mw.config.get("wgUserGroups").length; ++g) {
if (mw.config.get("wgUserGroups")[g] === "sysop") {
userIsSysop = true;
}
if (mw.config.get("wgUserGroups")[g] === "steward") {
userIsSysop = true;
}
}
}
newOption("popupDelay", 0.5);
newOption("popupHideDelay", 0.5);
newOption("simplePopups", false);
newOption("popupStructure", "shortmenus");
newOption("popupActionsMenu", true);
newOption("popupSetupMenu", true);
newOption("popupAdminLinks", userIsSysop);
newOption("popupShortcutKeys", false);
newOption("popupHistoricalLinks", true);
newOption("popupOnlyArticleLinks", true);
newOption("removeTitles", true);
newOption("popupMaxWidth", 350);
newOption("popupSimplifyMainLink", true);
newOption("popupAppendRedirNavLinks", true);
newOption("popupTocLinks", false);
newOption("popupSubpopups", true);
newOption(
"popupDragHandle",
false
/* 'popupTopLinks' */
);
newOption("popupLazyPreviews", true);
newOption("popupLazyDownloads", true);
newOption("popupAllDabsStubs", false);
newOption("popupDebugging", false);
newOption("popupActiveNavlinks", true);
newOption("popupModifier", false);
newOption("popupModifierAction", "enable");
newOption("popupDraggable", true);
newOption("popupReview", false);
newOption("popupLocale", false);
newOption("popupDateTimeFormatterOptions", {
year: "numeric",
month: "long",
day: "numeric",
hour12: false,
hour: "2-digit",
minute: "2-digit",
second: "2-digit"
});
newOption("popupDateFormatterOptions", {
year: "numeric",
month: "long",
day: "numeric"
});
newOption("popupTimeFormatterOptions", {
hour12: false,
hour: "2-digit",
minute: "2-digit",
second: "2-digit"
});
newOption("popupImages", true);
newOption("imagePopupsForImages", true);
newOption("popupNeverGetThumbs", false);
newOption("popupThumbAction", "imagepage");
newOption("popupImageSize", 60);
newOption("popupImageSizeLarge", 200);
newOption("popupFixRedirs", false);
newOption("popupRedirAutoClick", "wpDiff");
newOption("popupFixDabs", false);
newOption("popupDabsAutoClick", "wpDiff");
newOption("popupRevertSummaryPrompt", false);
newOption("popupMinorReverts", false);
newOption("popupRedlinkRemoval", false);
newOption("popupRedlinkAutoClick", "wpDiff");
newOption("popupWatchDisambiggedPages", null);
newOption("popupWatchRedirredPages", null);
newOption("popupDabWiktionary", "last");
newOption("popupNavLinks", true);
newOption("popupNavLinkSeparator", " ⋅ ");
newOption("popupLastEditLink", true);
newOption("popupEditCounterTool", "supercount");
newOption("popupEditCounterUrl", "");
newOption("popupPreviews", true);
newOption("popupSummaryData", true);
newOption("popupMaxPreviewSentences", 5);
newOption("popupMaxPreviewCharacters", 600);
newOption("popupLastModified", true);
newOption("popupPreviewKillTemplates", true);
newOption("popupPreviewRawTemplates", true);
newOption("popupPreviewFirstParOnly", true);
newOption("popupPreviewCutHeadings", true);
newOption("popupPreviewButton", false);
newOption("popupPreviewButtonEvent", "click");
newOption("popupPreviewDiffs", true);
newOption("popupDiffMaxLines", 100);
newOption("popupDiffContextLines", 2);
newOption("popupDiffContextCharacters", 40);
newOption("popupDiffDates", true);
newOption("popupDiffDatePrinter", "toLocaleString");
newOption("popupReviewedSummary", popupString("defaultpopupReviewedSummary"));
newOption("popupFixDabsSummary", popupString("defaultpopupFixDabsSummary"));
newOption("popupExtendedRevertSummary", popupString("defaultpopupExtendedRevertSummary"));
newOption("popupRevertSummary", popupString("defaultpopupRevertSummary"));
newOption("popupRevertToPreviousSummary", popupString("defaultpopupRevertToPreviousSummary"));
newOption("popupQueriedRevertSummary", popupString("defaultpopupQueriedRevertSummary"));
newOption("popupQueriedRevertToPreviousSummary", popupString("defaultpopupQueriedRevertToPreviousSummary"));
newOption("popupFixRedirsSummary", popupString("defaultpopupFixRedirsSummary"));
newOption("popupRedlinkSummary", popupString("defaultpopupRedlinkSummary"));
newOption("popupRmDabLinkSummary", popupString("defaultpopupRmDabLinkSummary"));
newOption("popupHistoryLimit", 50);
newOption("popupFilters", [popupFilterStubDetect, popupFilterDisambigDetect, popupFilterPageSize, popupFilterCountLinks, popupFilterCountImages, popupFilterCountCategories, popupFilterLastModified]);
newOption("extraPopupFilters", []);
newOption("popupOnEditSelection", "cursor");
newOption("popupPreviewHistory", true);
newOption("popupImageLinks", true);
newOption("popupCategoryMembers", true);
newOption("popupUserInfo", true);
newOption("popupHistoryPreviewLimit", 25);
newOption("popupContribsPreviewLimit", 25);
newOption("popupRevDelUrl", "//en.wikipedia.org/wiki/Wikipedia:Revision_deletion");
newOption("popupShowGender", true);
newOption("popupNewWindows", false);
newOption("popupLinksNewWindow", {
lastContrib: true,
sinceMe: true
});
newOption("popupDabRegexp", String.raw(_templateObject11 || (_templateObject11 = _taggedTemplateLiteral(["{{s*(d(ab|isamb(ig(uation)?)?)|(((geo|hn|road?|school|number)dis)|[234][lc][acw]|(road|ship)index))s*(|[^}]*)?}}|is a .*disambiguation.*page"], ["\\{\\{\\s*(d(ab|isamb(ig(uation)?)?)|(((geo|hn|road?|school|number)dis)|[234][lc][acw]|(road|ship)index))\\s*(\\|[^}]*)?\\}\\}|is a .*disambiguation.*page"]))));
newOption("popupAnchorRegexp", "anchors?");
newOption("popupStubRegexp", "(sect)?stub[}][}]|This .*-related article is a .*stub");
newOption("popupImageVarsRegexp", "image|image_(?:file|skyline|name|flag|seal)|cover|badge|logo");
};
pg.string = {
// summary data, searching etc.
article: "article",
category: "category",
categories: "categories",
image: "image",
images: "images",
stub: "stub",
"section stub": "section stub",
"Empty page": "Empty page",
kB: "kB",
bytes: "bytes",
day: "day",
days: "days",
hour: "hour",
hours: "hours",
minute: "minute",
minutes: "minutes",
second: "second",
seconds: "seconds",
week: "week",
weeks: "weeks",
search: "search",
SearchHint: "Find English Wikipedia articles containing %s",
web: "web",
global: "global",
// article-related actions and info
// (some actions also apply to user pages)
actions: "actions",
popupsMenu: "popups",
togglePreviewsHint: "Toggle preview generation in popups on this page",
"enable previews": "enable previews",
"disable previews": "disable previews",
"toggle previews": "toggle previews",
"show preview": "show preview",
reset: "reset",
"more...": "more...",
disable: "disable popups",
disablePopupsHint: "Disable popups on this page. Reload page to re-enable.",
historyfeedHint: "RSS feed of recent changes to this page",
purgePopupsHint: "Reset popups, clearing all cached popup data.",
PopupsHint: "Reset popups, clearing all cached popup data.",
spacebar: "space",
view: "view",
"view article": "view article",
viewHint: "Go to %s",
talk: "talk",
"talk page": "talk page",
"this revision": "this revision",
"revision %s of %s": "revision %s of %s",
"Revision %s of %s": "Revision %s of %s",
"the revision prior to revision %s of %s": "the revision prior to revision %s of %s",
"Toggle image size": "Click to toggle image size",
del: "del",
delete: "delete",
deleteHint: "Delete %s",
undeleteShort: "un",
UndeleteHint: "Show the deletion history for %s",
protect: "protect",
protectHint: "Restrict editing rights to %s",
unprotectShort: "un",
unprotectHint: "Allow %s to be edited by anyone again",
"send thanks": "send thanks",
ThanksHint: "Send a thank you notification to this user",
move: "move",
"move page": "move page",
MovepageHint: "Change the title of %s",
edit: "edit",
"edit article": "edit article",
editHint: "Change the content of %s",
"edit talk": "edit talk",
new: "new",
"new topic": "new topic",
newSectionHint: "Start a new section on %s",
"null edit": "null edit",
nullEditHint: "Submit an edit to %s, making no changes ",
hist: "hist",
history: "history",
historyHint: "List the changes made to %s",
last: "prev",
lastEdit: "lastEdit",
"mark patrolled": "mark patrolled",
markpatrolledHint: "Mark this edit as patrolled",
"Could not marked this edit as patrolled": "Could not marked this edit as patrolled",
"show last edit": "most recent edit",
"Show the last edit": "Show the effects of the most recent change",
lastContrib: "lastContrib",
"last set of edits": "latest edits",
lastContribHint: "Show the net effect of changes made by the last editor",
cur: "cur",
diffCur: "diffCur",
"Show changes since revision %s": "Show changes since revision %s",
"%s old": "%s old",
oldEdit: "oldEdit",
purge: "purge",
purgeHint: "Demand a fresh copy of %s",
raw: "source",
rawHint: "Download the source of %s",
render: "simple",
renderHint: "Show a plain HTML version of %s",
"Show the edit made to get revision": "Show the edit made to get revision",
sinceMe: "sinceMe",
"changes since mine": "diff my edit",
sinceMeHint: "Show changes since my last edit",
"Couldn't find an edit by %s\nin the last %s edits to\n%s": "Couldn't find an edit by %s\nin the last %s edits to\n%s",
eds: "eds",
editors: "editors",
editorListHint: "List the users who have edited %s",
related: "related",
relatedChanges: "relatedChanges",
"related changes": "related changes",
RecentchangeslinkedHint: "Show changes in articles related to %s",
editOld: "editOld",
rv: "rv",
revert: "revert",
revertHint: "Revert to %s",
defaultpopupReviewedSummary: "Accepted by reviewing the [[Special:diff/%s/%s|difference]] between this version and previously accepted version using [[:enwiki:Wikipedia:Tools/Navigation_popups|popups]]",
defaultpopupRedlinkSummary: "Removing link to empty page [[%s]] using [[:enwiki:Wikipedia:Tools/Navigation_popups|popups]]",
defaultpopupFixDabsSummary: "Disambiguate [[%s]] to [[%s]] using [[:enwiki:Wikipedia:Tools/Navigation_popups|popups]]",
defaultpopupFixRedirsSummary: "Redirect bypass from [[%s]] to [[%s]] using [[:enwiki:Wikipedia:Tools/Navigation_popups|popups]]",
defaultpopupExtendedRevertSummary: "Revert to revision dated %s by %s, oldid %s using [[:enwiki:Wikipedia:Tools/Navigation_popups|popups]]",
defaultpopupRevertToPreviousSummary: "Revert to the revision prior to revision %s using [[:enwiki:Wikipedia:Tools/Navigation_popups|popups]]",
defaultpopupRevertSummary: "Revert to revision %s using [[:enwiki:Wikipedia:Tools/Navigation_popups|popups]]",
defaultpopupQueriedRevertToPreviousSummary: "Revert to the revision prior to revision $1 dated $2 by $3 using [[:enwiki:Wikipedia:Tools/Navigation_popups|popups]]",
defaultpopupQueriedRevertSummary: "Revert to revision $1 dated $2 by $3 using [[:enwiki:Wikipedia:Tools/Navigation_popups|popups]]",
defaultpopupRmDabLinkSummary: "Remove link to dab page [[%s]] using [[:enwiki:Wikipedia:Tools/Navigation_popups|popups]]",
Redirects: "Redirects",
" to ": " to ",
"Bypass redirect": "Bypass redirect",
"Fix this redirect": "Fix this redirect",
disambig: "disambig",
disambigHint: "Disambiguate this link to [[%s]]",
"Click to disambiguate this link to:": "Click to disambiguate this link to:",
"remove this link": "remove this link",
"remove all links to this page from this article": "remove all links to this page from this article",
"remove all links to this disambig page from this article": "remove all links to this disambig page from this article",
mainlink: "mainlink",
wikiLink: "wikiLink",
wikiLinks: "wikiLinks",
"links here": "links here",
whatLinksHere: "whatLinksHere",
"what links here": "what links here",
WhatlinkshereHint: "List the pages that are hyperlinked to %s",
unwatchShort: "un",
watchThingy: "watch",
watchHint: "Add %s to my watchlist",
unwatchHint: "Remove %s from my watchlist",
"Only found one editor: %s made %s edits": "Only found one editor: %s made %s edits",
"%s seems to be the last editor to the page %s": "%s seems to be the last editor to the page %s",
rss: "rss",
// diff previews
"Diff truncated for performance reasons": "Diff truncated for performance reasons",
"Old revision": "Old revision",
"New revision": "New revision",
"Something went wrong :-(": "Something went wrong :-(",
"Empty revision, maybe non-existent": "Empty revision, maybe non-existent",
"Unknown date": "Unknown date",
// other special previews
"Empty category": "Empty category",
"Category members (%s shown)": "Category members (%s shown)",
"No image links found": "No image links found",
"File links": "File links",
"No image found": "No image found",
"Image from Commons": "Image from Commons",
"Description page": "Description page",
"Alt text:": "Alt text:",
revdel: "Hidden revision",
// user-related actions and info
user: "user",
"user page": "user page",
"user talk": "user talk",
"edit user talk": "edit user talk",
"leave comment": "leave comment",
email: "email",
"email user": "email user",
EmailuserHint: "Send an email to %s",
space: "space",
PrefixIndexHint: "Show pages in the userspace of %s",
count: "count",
"edit counter": "edit counter",
editCounterLinkHint: "Count the contributions made by %s",
contribs: "contribs",
contributions: "contributions",
deletedContribs: "deleted contributions",
DeletedcontributionsHint: "List deleted edits made by %s",
ContributionsHint: "List the contributions made by %s",
log: "log",
"user log": "user log",
userLogHint: "Show %s's user log",
arin: "ARIN lookup",
"Look up %s in ARIN whois database": "Look up %s in the ARIN whois database",
unblockShort: "un",
block: "block",
"block user": "block user",
IpblocklistHint: "Unblock %s",
BlockipHint: "Prevent %s from editing",
"block log": "block log",
blockLogHint: "Show the block log for %s",
protectLogHint: "Show the protection log for %s",
pageLogHint: "Show the page log for %s",
deleteLogHint: "Show the deletion log for %s",
"Invalid %s %s": "The option %s is invalid: %s",
"No backlinks found": "No backlinks found",
" and more": " and more",
undo: "undo",
undoHint: "undo this edit",
"Download preview data": "Download preview data",
"Invalid or IP user": "Invalid or IP user",
"Not a registered username": "Not a registered username",
BLOCKED: "BLOCKED",
"Has blocks": "Has blocks",
" edits since: ": " edits since: ",
"last edit on ": "last edit on ",
"he/him": "he/him",
"she/her": "she/her",
// Autoediting
"Enter a non-empty edit summary or press cancel to abort": "Enter a non-empty edit summary or press cancel to abort",
"Failed to get revision information, please edit manually.\n\n": "Failed to get revision information, please edit manually.\n\n",
"The %s button has been automatically clicked. Please wait for the next page to load.": "The %s button has been automatically clicked. Please wait for the next page to load.",
"Could not find button %s. Please check the settings in your javascript file.": "Could not find button %s. Please check the settings in your javascript file.",
// Popups setup
"Open full-size image": "Open full-size image",
autoedit_version: "np20140416"
};
const popupString = (str) => {
if (message !== void 0 && message && message[str]) {
return message[str];
}
if (pg.string[str]) {
return pg.string[str];
}
return str;
};
const tprintf = (str, subs) => {
if (typeof subs !== typeof []) {
subs = [subs];
}
return simplePrintf(popupString(str), subs);
};
if (document.readyState === "complete") {
autoEdit();
} else {
$(window).on("load", autoEdit);
}
(() => {
let once = true;
const dynamicContentHandler = ($content) => {
if ($content.attr("id") === "mw-content-text" && once) {
once = false;
return;
}
const registerHooksForVisibleNavpops = () => {
for (let i = 0; pg.current.links && i < pg.current.links.length; i++) {
const navpop = pg.current.links[i].navpopup;
if (!navpop || !navpop.isVisible()) {
continue;
}
Navpopup.tracker.addHook(posCheckerHook(navpop));
}
};
const doIt = () => {
registerHooksForVisibleNavpops();
$content.each((_index, element) => {
element.ranSetupTooltipsAlready = false;
setupTooltips(element);
});
};
setupPopups(doIt);
};
mw.hook("wikipage.content").add(dynamicContentHandler);
mw.hook("ext.echo.overlay.beforeShowingOverlay").add(($overlay) => {
dynamicContentHandler($overlay.find(".mw-echo-state"));
});
})();
};
//! src/Navigation_popups/Navigation_popups.ts
$(popups);
})();
/* </nowiki> */