![刷新 刷新](/images/thumb/b/b0/OOjs_UI_icon_reload-progressive.svg/55px-OOjs_UI_icon_reload-progressive.svg.png)
请注意:更新本页面后,您可能需要清除浏览器缓存才能看到所作变更的影响。
Google Chrome、Microsoft Edge、Mozilla Firefox、Safari:按住⇧ Shift,同时单击“刷新”。
Google Chrome、Microsoft Edge、Mozilla Firefox、Safari:按住⇧ Shift,同时单击“刷新”。
![Cc.logo.circle.svg](/images/thumb/5/5d/CC_Logo.svg/40px-CC_Logo.svg.png)
![署名 署名](/images/thumb/1/11/Cc-by_new_white.svg/24px-Cc-by_new_white.svg.png)
![相同方式共享 相同方式共享](/images/thumb/d/df/Cc-sa_white.svg/24px-Cc-sa_white.svg.png)
本文件采用知识共享署名-相同方式共享 4.0 国际(CC BY-SA 4.0)许可协议授权。
- 您可以自由地:
- 分享 – 在任何媒介以任何形式复制、发行本作品
- 演绎 – 修改、转换或以本作品为基础进行创作
- 惟须遵守下列条件:
- 署名 – 您必须给出适当的署名(标明原作者),提供指向本许可协议的链接,同时标明是否(对原始作品)作了修改。您可以用任何合理的方式来署名,但是不得以任何方式暗示许可人为您或您的使用背书(即诱导原作者在不了解协议情况下给你授权)。
- 相同方式共享 – 如果您再混合、转换或者基于本作品进行创作,您必须基于与原先许可协议相同或相兼容的许可协议分发您贡献的作品。
/**
* SPDX-License-Identifier: CC-BY-SA-4.0
* _addText: '{{Gadget Header|license=CC-BY-SA-4.0}}'
*
* @base <https://en.wikipedia.org/wiki/MediaWiki:Gadget-markblocked.js>
* @source <https://git.qiuwen.net.cn/InterfaceAdmin/Gadgets/src/branch/master/src/Gadgets/Markblocked>
* @dependency ext.gadget.i18n, mediawiki.util
*/
/**
* +--------------------------------------------------------+
* | === WARNING: GLOBAL GADGET FILE === |
* +--------------------------------------------------------+
* | All changes should be made in the repository, |
* | otherwise they will be lost. |
* +--------------------------------------------------------+
* | Changes to this page affect many users. |
* | Please discuss changes at Talk page before editing. |
* +--------------------------------------------------------+
*/
/* <nowiki> */
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, 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 normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
/**
* This gadget will pull the user accounts and IPs from the history page
* and will strike out the users that are currently blocked.
*/
(function markBlocked($, mw) {
var _i18n = i18n,
localize = _i18n.localize;
var markBlockedUser = function markBlockedUser(container) {
var ipv6Regex = /^((?=.*::)(?!.*::.+::)(::)?([\da-f]{1,4}:(:|\b)|){5}|([\da-f]{1,4}:){6})((([\da-f]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i;
// Collect all the links in the page's content
var contentLinks = $(container).find('a');
var markBlockedTooltip = localize({
en: '; blocked ($1) by $2: $3 ($4 ago)',
'zh-hans': ';由$2封禁$1:$3($4前)',
'zh-hant': ';由$2封鎖$1:$3($4前)'
});
// Get all aliases for user: & user_talk:
var userNamespace = [];
for (var namespace in mw.config.get('wgNamespaceIds')) {
if (mw.config.get('wgNamespaceIds')[namespace] === 2 || mw.config.get('wgNamespaceIds')[namespace] === 3) {
userNamespace.push("".concat(mw.util.escapeRegExp(namespace.replace(/_/g, ' ')), ":"));
}
}
// Let wikis that are importing this gadget specify the local alias of Special:Contributions
var specialContribs = 'Special:Contributions';
// RegExp for all titles that are User:| User_talk: | Special:Contributions/ (for userscripts)
var userTitleRegex = new RegExp("^(".concat(userNamespace.join('|'), "|").concat(specialContribs, "\\/)+([^\\/#]+)$"), 'i');
// RegExp for links
// articleRegex also matches external links in order to support the noping template
var articleRegex = new RegExp("".concat(mw.config.get('wgArticlePath').replace('$1', ''), "([^#]+)"));
var scriptRegex = new RegExp("^".concat(mw.config.get('wgScript'), "\\?title=([^#&]+)"));
var userLinks = {};
var user;
var url;
var match;
var pageTitle;
// Find all "user" links and save them in userLinks : { 'users': [<link1>, <link2>, ...], 'user2': [<link3>, <link3>, ...], ... }
contentLinks.each(function (_index, link) {
if ($(link).hasClass('mw-changeslist-date') || $(link).parent('span').hasClass('mw-history-undo') || $(link).parent('span').hasClass('mw-rollback-link')) {
return;
}
url = $(link).attr('href');
if (!url) {
return;
}
if (articleRegex.test(url)) {
match = articleRegex.exec(url);
pageTitle = match[1];
} else if (scriptRegex.test(url)) {
match = scriptRegex.exec(url);
pageTitle = match[1];
} else {
return;
}
pageTitle = decodeURIComponent(pageTitle).replace(/_/g, ' ');
user = userTitleRegex.exec(pageTitle);
if (!user) {
return;
}
user = user[2].slice(0, 1).toUpperCase() + user[2].slice(1);
if (ipv6Regex.test(user)) {
user = user.toUpperCase();
}
$(link).addClass('userlink');
if (!userLinks[user]) {
userLinks[user] = [];
}
userLinks[user].push(link);
});
// Convert users into array
var users = [];
for (var u in userLinks) {
users.push(u);
}
if (users.length === 0) {
return;
}
// API request
var serverTime;
var apiRequests = 0;
container.addClass('markblocked-loading');
while (users.length > 0) {
apiRequests++;
$.post("".concat(mw.util.wikiScript('api'), "?format=json&action=query"), {
list: 'blocks',
bklimit: 100,
bkusers: users.splice(0, 50).join('|'),
bkprop: 'user|by|timestamp|expiry|reason|restrictions'
// no need for 'id|flags'
}, markLinks);
}
return; // the end
// Callback: receive data and mark links
function markLinks(response, _status, xhr) {
serverTime = new Date(xhr.getResponseHeader('Date'));
var list;
var block;
var tip;
var links;
var link;
if (!response || !(list = response.query) || !(list = list.blocks)) {
return;
}
var _iterator = _createForOfIteratorHelper(list),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var element = _step.value;
block = element;
var partial = block.restrictions && !Array.isArray(block.restrictions); // Partial block
var cssClass = void 0;
var blockTime = void 0;
if (block.expiry.startsWith('in')) {
cssClass = partial ? 'user-blocked-partial' : 'user-blocked-indef';
blockTime = block.expiry;
} else {
cssClass = partial ? 'user-blocked-partial' : 'user-blocked-temp';
blockTime = inHours(parseTS(block.expiry) - parseTS(block.timestamp));
}
tip = markBlockedTooltip;
if (partial) {
tip = tip.replace('封禁', '部分封禁').replace('封鎖', '部分封鎖');
}
tip = tip.replace('$1', blockTime).replace('$2', block.by).replace('$3', block.reason).replace('$4', inHours(serverTime - parseTS(block.timestamp)));
links = userLinks[block.user];
if (links) {
for (var k = 0; k < links.length; k++) {
link = $(links[k]);
link = link.addClass(cssClass);
link.attr('title', link.attr('title') + tip);
}
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
if (--apiRequests === 0) {
// last response
container.removeClass('markblocked-loading');
$('#ca-showblocks').parent().remove(); // remove added portlet link
}
}
// --------AUX functions
// 20081226220605 or 2008-01-26T06:34:19Z -> date
function parseTS(string) {
var m = string.replace(/\D/g, '').match(/(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/);
return new Date(Date.UTC(m[1], m[2] - 1, m[3], m[4], m[5], m[6]));
}
function inHours(ms) {
var mm = Math.floor(ms / 6e4);
if (!mm) {
return "".concat(Math.floor(ms / 1e3), "s");
}
var hh = Math.floor(mm / 60);
mm = mm % 60;
var dd = Math.floor(hh / 24);
hh = hh % 24;
if (dd) {
return "".concat(dd + (dd < 10 ? ".".concat(zz(hh)) : ''), "d");
}
return "".concat(hh, ":").concat(zz(mm));
}
function zz(v) {
if (v <= 9) {
v = "0".concat(v);
}
return v;
}
};
switch (mw.config.get('wgAction')) {
case 'edit':
case 'submit':
break;
default:
{
// 'view', 'history', 'purge', ...
var maybeAutostart = $.Deferred();
maybeAutostart.resolve();
$.when($.ready, maybeAutostart).then(function () {
var firstTime = true;
mw.hook('wikipage.content').add(function ($content) {
// On the first call after initial page load, container is mw.util.$content
// Used to limit mainspace activity to just the diff definitions
if (mw.config.get('wgAction') === 'view' && mw.config.get('wgNamespaceNumber') === 0) {
$content = $content.find('.diff-title');
}
if (firstTime) {
firstTime = false;
// On page load, also update the namespace tab
$content = $content.add('#ca-nstab-user');
mw.util.addCSS('.markblocked-loading a.userlink{opacity:.85}' + 'a.user-blocked-temp{text-decoration:line-through;opacity:.7}' + 'a.user-blocked-indef{text-decoration:line-through;font-style:italic;opacity:.4}' + 'a.user-blocked-partial{text-decoration:underline;text-decoration-style:dotted}' + '.user-blocked-tipbox{padding:0 .3em;border:1px solid #fea;background:ivory;color:#aaa;font-size:smaller}');
}
markBlockedUser($content);
});
});
}
}
})($, mw);
/* </nowiki> */