مدیاویکی:Gadget-twinkleprod-2022.js
نکته: برای دیدن تغییرات، ممکن است نیاز باشد که حافظهٔ نهانی مرورگر خود را پس از انتشار پاکسازی کنید. گوگل کروم، فایرفاکس، مایکروسافت اج و سافاری: کلید ⇧ Shift را نگه دارید و روی دکمهٔ Reload در نوار ابزار مرورگر کلیک کنید. برای آگاهی از جزئیات و نحوهٔ پاکسازی حافظهٔ نهانی سایر مرورگرها، صفحهٔ ویکیپدیا:میانگیر مرورگرتان را خالی کنید را ببینید.
// <nowiki>
(function($) {
/*
****************************************
*** twinkleprod.js: PROD module
****************************************
* Mode of invocation: Tab ("PROD")
* Active on: Existing articles, files which are not redirects
*/
Twinkle.prod = function twinkleprod() {
if (([0, 6].indexOf(mw.config.get('wgNamespaceNumber')) === -1) ||
!mw.config.get('wgCurRevisionId') ||
Morebits.isPageRedirect()) {
return;
}
Twinkle.addPortletLink(Twinkle.prod.callback, 'حذف زماندار', 'tw-prod', 'پیشنهاد حذف از طریق وپ:حز');
};
// Used in edit summaries, for comparisons, etc.
var namespace;
Twinkle.prod.callback = function twinkleprodCallback() {
Twinkle.prod.defaultReason = Twinkle.getPref('prodReasonDefault');
switch (mw.config.get('wgNamespaceNumber')) {
case 0:
namespace = 'مقاله';
break;
case 6:
namespace = 'پرونده';
break;
// no default
}
var Window = new Morebits.simpleWindow(800, 410);
Window.setTitle('حذف زماندار (حز)');
Window.setScriptName('توینکل');
var form = new Morebits.quickForm(Twinkle.prod.callback.evaluate);
if (namespace === 'مقاله') {
Window.addFooterLink('سیاست حذف زماندار', 'وپ:حز');
Window.addFooterLink('سیاست حذف زماندار زندگینامه', 'وپ:حزز');
} else { // if file
Window.addFooterLink('سیاست حذف زماندار', 'وپ:حز');
}
var field = form.append({
type: 'field',
label: 'نوع حذف زماندار',
id: 'prodtype_fieldset'
});
field.append({
type: 'div',
label: '', // Added later by Twinkle.makeFindSourcesDiv()
id: 'twinkle-prod-findsources',
style: 'margin-bottom: 5px; margin-top: -5px;'
});
field.append({
type: 'radio',
name: 'prodtype',
event: Twinkle.prod.callback.prodtypechanged,
list: [
{
label: 'حز (حذف زماندار)',
value: 'prod',
checked: true,
tooltip: 'حذف زماندار معمولی، طبق [[وپ:حز]]'
},
{
label: 'حزز (حذف زماندار زندگینامه زندگان بدون منبع)',
value: 'prodblp',
tooltip: 'حذف زماندار زندگینامههای افراد زندهٔ کاملاً بدون منبع طبق [[وپ:حزز]]'
}
]
});
// Placeholder fieldset to be replaced in Twinkle.prod.callback.prodtypechanged
form.append({
type: 'field',
name: 'parameters'
});
Window.addFooterLink('ترجیحات حذف زماندار', 'وپ:توینکل/ترجیحات#prod');
Window.addFooterLink('راهنمای توینکل', 'وپ:توینکل/توضیحات#prod');
Window.addFooterLink('ارائهٔ بازخورد', 'بوپ:توینکل');
form.append({ type: 'submit', label: 'پیشنهاد حذف' });
var result = form.render();
Window.setContent(result);
Window.display();
// Hide fieldset for File PROD type since only normal PROD is allowed
if (namespace !== 'مقاله') {
$(result).find('#prodtype_fieldset').hide();
}
// Fake a change event on the first prod type radio, to initialize the type-dependent controls
var evt = document.createEvent('Event');
evt.initEvent('change', true, true);
result.prodtype[0].dispatchEvent(evt);
};
Twinkle.prod.callback.prodtypechanged = function(event) {
// prepare frame for prod type dependant controls
var field = new Morebits.quickForm.element({
type: 'field',
label: 'پارامترها',
name: 'parameters'
});
// create prod type dependant controls
switch (event.target.values) {
case 'prod':
field.append({
type: 'checkbox',
list: [
{
label: 'آگاهسازی ایجادکنندهٔ صفحه در صورت امکان',
value: 'notify',
name: 'notify',
tooltip: 'در صورت فعال بودن این گزینه، یک الگوی آگاهسازی در صفحهٔ بحث کاربر ایجادکننده قرار داده خواهد شد.',
checked: true
}
]
});
field.append({
type: 'textarea',
name: 'reason',
label: 'دلیل پیشنهاد حذف زماندار:',
value: Twinkle.prod.defaultReason
});
break;
case 'prodblp':
// first, remember the prod value that the user entered in the textarea, in case they want to switch back. We can abuse the config field for that.
if (event.target.form.reason) {
Twinkle.prod.defaultReason = event.target.form.reason.value;
}
field.append({
type: 'checkbox',
list: [
{
label: 'آگاهسازی ایجادکنندهٔ صفحه در صورت امکان',
value: 'notify',
name: 'notify',
tooltip: 'ایجادکنندهٔ مقاله باید از این پیشنهاد حذف آگاه شود.',
checked: true,
disabled: true
}
]
});
// temp warning, can be removed down the line once BLPPROD is more established. Amalthea, May 2010.
var boldtext = document.createElement('b');
boldtext.appendChild(document.createTextNode('لطفاً دقت داشته باشید که تنها زندگینامههای بدون منبع افراد زنده برای این برچسب مناسب هستند.'));
field.append({
type: 'div',
label: boldtext
});
break;
default:
break;
}
Twinkle.makeFindSourcesDiv('#twinkle-prod-findsources');
event.target.form.replaceChild(field.render(), $(event.target.form).find('fieldset[name="parameters"]')[0]);
};
// global params object, initially set in evaluate(), and
// modified in various callback functions
var params = {};
Twinkle.prod.callbacks = {
checkPriors: function twinkleprodcheckPriors() {
var talk_title = new mw.Title(mw.config.get('wgPageName')).getTalkPage().getPrefixedText();
// Talk page templates for PROD-able discussions
var blocking_templates = 'الگو:Old XfD multi|الگو:Old MfD|الگو:Oldffdfull|' + // Common prior XfD talk page templates
'الگو:Oldpuffull|' + // Legacy prior XfD template
'الگو:Olddelrev|' + // Prior DRV template
'الگو:Old prod' +
'الگو:پیشینه حذف زماندار|' +
'الگو:پیشینه حذف زماندار|' +
'الگو:حذف زماندار قبلی|' +
'الگو:پیشحذف قبلی|' +
'الگو:پیشینه حذف زمان دار|' +
'الگو:Old prod full';
var query = {
action: 'query',
titles: talk_title,
prop: 'templates',
tltemplates: blocking_templates,
format: 'json',
tllimit: 12 // 12 templates above
};
var wikipedia_api = new Morebits.wiki.api('در حال بررسی صفحهٔ بحث برای نامزدیهای پیشین', query);
return wikipedia_api.post().then(function(apiobj) {
var statelem = apiobj.statelem;
// Check talk page for templates indicating prior XfD or PROD
var templates = apiobj.getResponse().query.pages[0].templates;
var numTemplates = templates && templates.length;
if (numTemplates) {
var template = templates[0].title;
if (numTemplates === 1 && (
template === 'الگو:Old prod' ||
template === 'الگو:پیشینه حذف زماندار' ||
template === 'الگو:پیشینه حذف زماندار' ||
template === 'الگو:پیشینه حذف زمان دار' ||
template === 'الگو:حذف زماندار قبلی' ||
template === 'الگو:پیشحذف قبلی' ||
template === 'الگو:Old prod full'
)) {
params.oldProdPresent = true; // Mark for reference later, when deciding if to endorse
// if there are multiple templates, at least one of them would be a prior xfd template
} else {
statelem.warn('الگوی نبح پیشین در صفحهٔ بحث یافت شد؛ در حال صرف نظر از فرایند');
return $.Deferred().reject();
}
}
});
},
fetchCreationInfo: function twinkleprodFetchCreationInfo() {
var def = $.Deferred();
var ts = new Morebits.wiki.page(mw.config.get('wgPageName'), 'در حال جستجو برای ایجادکنندهٔ صفحه');
ts.setFollowRedirect(true); // for NPP, and also because redirects are ineligible for PROD
ts.setLookupNonRedirectCreator(true); // Look for author of first non-redirect revision
ts.lookupCreation(function(pageobj) {
params.initialContrib = pageobj.getCreator();
params.creation = pageobj.getCreationTimestamp();
pageobj.getStatusElement().info('انجام شد، ' + params.initialContrib + ' یافت شد');
def.resolve();
}, def.reject);
return def;
},
taggingPage: function twinkleprodTaggingPage() {
var def = $.Deferred();
var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), 'در حال برچسب زدن به صفحه');
wikipedia_page.setFollowRedirect(true); // for NPP, and also because redirects are ineligible for PROD
wikipedia_page.load(function(pageobj) {
var statelem = pageobj.getStatusElement();
if (!pageobj.exists()) {
statelem.error("بهنظر میرسد که صفحه موجود نیست. شاید پیش از این حذف شده باشد.");
// reject, so that all dependent actions like notifyAuthor() and
// addToLog() are cancelled
return def.reject();
}
var text = pageobj.getPageText();
// Check for already existing deletion tags
var tag_re = /{{(?:(db|حس)-?|(delete|حذف)\b|(article for deletion|نظرخواهی برای حذف)\/(dated|تاریخدار)|AfDM|(ffd|پیشنهاد حذف تصویر)\b)|#invoke:RfD/i;
if (tag_re.test(text)) {
statelem.warn('این صفحه از پیش با یک الگوی حذف برچسب خورده است؛ در حال صرف نظر از فرایند');
return def.reject();
}
// Remove tags that become superfluous with this action
text = text.replace(/{{\s*(userspace draft|پیشنویس صفحه کاربری|mtc|(copy|move|انتقال) (to wikimedia commons|به ویکیانبار|به انبار)|(copy |move )?to ?commons)\s*(\|(?:{{[^{}]*}}|[^{}])*)?}}\s*/gi, '');
var prod_re = /{{\s*(?:Prod blp|حز زنز|Proposed deletion|حذف زماندار)\/(dated|پیغام)(?: files)?\s*\|(?:{{[^{}]*}}|[^{}])*}}/i;
var summaryText;
if (!prod_re.test(text)) {
// Page previously PROD-ed
if (params.oldProdPresent) {
if (params.blp) {
if (!confirm('نامزدی پیشین برای حذف زماندار در صفحهٔ بحث یافت شد. آیا همچنان میخواهید به نامزد کردن صفحه برای حذف زماندار زندگینامه زندگان ادامه دهید؟ ')) {
statelem.warn('حذف زماندار پیشین در صفحهٔ بحث یافت شد؛ توسط کاربر لغو شد');
return def.reject();
}
statelem.info('حذف زماندار پیشین در صفحهٔ بحث یافت شد؛ در حال ادامه دادن');
} else {
statelem.warn('حذف زماندار پیشین در صفحهٔ بحث یافت شد؛ در حال صرف نظر از فرایند');
return def.reject();
}
}
var tag;
if (params.blp) {
summaryText = 'پیشنهاد حذف مقاله طبق [[وپ:حزز]].';
tag = '{{جا:حز زنز' + (params.usertalk ? '|help=off' : '') + '}}';
} else {
summaryText = 'پیشنهاد حذف ' + namespace + ' طبق [[وپ:حز]].';
tag = '{{جا:حذف زماندار|1=' + Morebits.string.formatReasonText(params.reason) + (params.usertalk ? '|help=off' : '') + '}}';
}
// Insert tag after short description or any hatnotes
var wikipage = new Morebits.wikitext.page(text);
text = wikipage.insertAfterTemplates(tag + '\n', Twinkle.hatnoteRegex).getText();
} else { // already tagged for PROD, so try endorsing it
var prod2_re = /{{(?:تأیید حذف زماندار|prod-?2|حذف زماندار تأییدشده).*?}}/i;
if (prod2_re.test(text)) {
statelem.warn('صفحه از پیش با الگوهای {{حذف زماندار}} و {{تأیید حذف زماندار}} برچسب خورده است؛ در حال صرف نظر از فرایند');
return def.reject();
}
var confirmtext = 'یک برچسب {{حذف زماندار}} از پیش در این صفحه موجود است. \nآیا میخواهید یک برچسب {{تأیید حذف زماندار}} بههمراه توضیحات خود را به آن بیافزایید؟';
if (params.blp && !/{{\s*(Prod blp\/dated|حذف زماندار\/پیغام)/.test(text)) {
confirmtext = 'یک برچسب غیرزندگینامهای {{حذف زماندار}} در این مقاله یافت شد.\nآیا میخواهید یک برچسب {{تأیید حذف زماندار}} با این توضیح که «این مقاله زندگینامهٔ یک فرد زنده است که هیچ منبعی ندارد» به آن بیافزایید؟';
}
if (!confirm(confirmtext)) {
statelem.warn('به درخواست کاربر لغو شد');
return def.reject();
}
summaryText = 'تأیید حذف زماندار بر پایهٔ [[وپ:حز' + (params.blp ? ' زنز' : '') + ']].';
text = text.replace(prod_re, text.match(prod_re) + '\n{{تأیید حذف زماندار|1=' + (params.blp ?
'این مقاله [[وپ:حز زنز|زندگینامهٔ یک فرد زنده است که هیچ منبعی ندارد]]' :
Morebits.string.formatReasonText(params.reason)) + '}}\n');
params.logEndorsing = true;
}
// curate/patrol the page
if (Twinkle.getPref('markProdPagesAsPatrolled')) {
pageobj.patrol();
}
pageobj.setPageText(text);
pageobj.setEditSummary(summaryText);
pageobj.setChangeTags(Twinkle.changeTags);
pageobj.setWatchlist(Twinkle.getPref('watchProdPages'));
pageobj.setCreateOption('nocreate');
pageobj.save(def.resolve, def.reject);
}, def.reject);
return def;
},
addOldProd: function twinkleprodAddOldProd() {
var def = $.Deferred();
if (params.oldProdPresent || params.blp) {
return def.resolve();
}
// Add {{Old prod}} to the talk page
var oldprodfull = '{{پیشینه حذف زماندار|نامزدکننده=' + mw.config.get('wgUserName') + '|تاریخ نامزدی={{جا:#زمان: j F Y}}}}\n';
var talktitle = new mw.Title(mw.config.get('wgPageName')).getTalkPage().getPrefixedText();
var talkpage = new Morebits.wiki.page(talktitle, 'در حال قرار دادن {{پیشینه حذف زماندار}} در صفحهٔ بحث');
talkpage.setPrependText(oldprodfull);
talkpage.setEditSummary('افزودن {{پیشینه حذف زماندار}}');
talkpage.setChangeTags(Twinkle.changeTags);
talkpage.setFollowRedirect(true); // match behavior for page tagging
talkpage.setCreateOption('recreate');
talkpage.prepend(def.resolve, def.reject);
return def;
},
notifyAuthor: function twinkleprodNotifyAuthor() {
var def = $.Deferred();
if (!params.blp && !params.usertalk) {
return def.resolve();
}
// Disallow warning yourself
if (params.initialContrib === mw.config.get('wgUserName')) {
Morebits.status.info('آگاهسازی ایجادکننده', 'خودتان (' + params.initialContrib + ') این صفحه را ایجاد کردهاید؛ در حال چشمپوشی از آگاهسازی');
return def.resolve();
}
// [[Template:Proposed deletion notify]] supports File namespace
var notifyTemplate;
if (params.blp) {
notifyTemplate = 'هشدار حذف زماندار زندگینامه زندگان';
} else {
notifyTemplate = 'هشدار حذف زماندار';
}
var notifytext = '\n{{جا:' + notifyTemplate + '|1=' + Morebits.pageNameNorm + '|اهمیت=' + params.reason + '}} ~~~~';
var usertalkpage = new Morebits.wiki.page('بحث کاربر:' + params.initialContrib, 'در حال آگاهسازی مشارکتکنندهٔ اولیه (' + params.initialContrib + ')');
usertalkpage.setAppendText(notifytext);
usertalkpage.setEditSummary('آگاهسازی: پیشنهاد حذف [[:' + Morebits.pageNameNorm + ']].');
usertalkpage.setChangeTags(Twinkle.changeTags);
usertalkpage.setCreateOption('recreate');
usertalkpage.setFollowRedirect(true, false);
usertalkpage.append(function onNotifySuccess() {
// add nomination to the userspace log, if the user has enabled it
params.logInitialContrib = params.initialContrib;
def.resolve();
}, def.resolve); // resolves even if notification was unsuccessful
return def;
},
addToLog: function twinkleprodAddToLog() {
if (!Twinkle.getPref('logProdPages')) {
return $.Deferred().resolve();
}
var usl = new Morebits.userspaceLogger(Twinkle.getPref('prodLogPageName'));
usl.initialText =
"این صفحه فهرستی از مواردی که این کاربر با استفاده از [[وپ:توینکل|توینکل]] برای [[وپ:حز|حذف زماندار]] نامزد کردهاست را نشان میدهد.\n\n" + // localized
'اگر نمیخواهید موارد جدید به این سیاهه اضافه شوند، آن را از طریق [[وپ:توینکل تر|ترجیحات توینکل]] غیرفعال کنید' + // localized
' و اگر میخواهید سیاهه کلاً حذف شود آن را بر اساس معیار [[وپ:محس#ک۱|ک۱]] نامزد حذف سریع کنید.\n'; // localized
var logText = '# [[:' + Morebits.pageNameNorm + ']]';
var summaryText;
// If a logged file is deleted but exists on commons, the wikilink will be blue, so provide a link to the log
logText += namespace === 'پرونده' ? ' ([{{نشانیکامل:ویژه:سیاههها|page=' + mw.util.wikiUrlencode(mw.config.get('wgPageName')) + '}} سیاهه]): ' : ': ';
if (params.logEndorsing) {
logText += 'تأیید حذف زماندار' + (params.blp ? 'زندگینامه زندگان' : '') + '. ~~~~~';
if (params.reason) {
logText += "\n#* '''دلیل''': " + params.reason + '\n';
}
summaryText = 'ثبت سیاههٔ نامزد کردن [[:' + Morebits.pageNameNorm + ']] برای حذف زماندار.';
} else {
logText += ' – حذف زماندار' + (params.blp ? ' زندگینامه زندگان' : '');
if (params.logInitialContrib) {
logText += '؛ {{userv|' + params.logInitialContrib + '}} آگاه شد';
}
logText += ' ~~~~~\n';
if (!params.blp && params.reason) {
logText += "#* '''دلیل''': " + Morebits.string.formatReasonForLog(params.reason) + '\n';
}
summaryText = 'ثبت سیاههٔ نامزد کردن [[:' + Morebits.pageNameNorm + ']] برای حذف زماندار.';
}
usl.changeTags = Twinkle.changeTags;
return usl.log(logText, summaryText);
}
};
Twinkle.prod.callback.evaluate = function twinkleprodCallbackEvaluate(e) {
var form = e.target;
var input = Morebits.quickForm.getInputData(form);
params = {
usertalk: input.notify || input.prodtype === 'prodblp',
blp: input.prodtype === 'prodblp',
reason: input.reason || '' // using an empty string here as fallback will help with prod-2.
};
if (!params.blp && !params.reason) {
if (!confirm('شما فیلد دلیل را خالی گذاشتهاید؛ آیا واقعاً میخواهید بدون ارائهٔ دلیل ادامه دهید؟')) {
return;
}
}
Morebits.simpleWindow.setButtonsEnabled(false);
Morebits.status.init(form);
var tm = new Morebits.taskManager();
var cbs = Twinkle.prod.callbacks; // shortcut reference, cbs for `callbacks`
// Disable Morebits.wiki.numberOfActionsLeft system
Morebits.wiki.numberOfActionsLeft = 1000;
// checkPriors() and fetchCreationInfo() have no dependencies, they'll run first
tm.add(cbs.checkPriors, []);
tm.add(cbs.fetchCreationInfo, []);
// tag the page once we're clear of the pre-requisites
tm.add(cbs.taggingPage, [ cbs.checkPriors, cbs.fetchCreationInfo ]);
// notify the author once we know who's the author, and also wait for the
// taggingPage() as we don't need to notify if tagging was not done, such as
// there was already a tag and the user chose not to endorse.
tm.add(cbs.notifyAuthor, [ cbs.fetchCreationInfo, cbs.taggingPage ]);
// oldProd needs to be added only if there wasn't one before, so need to wait
// for checkPriors() to finish. Also don't add oldProd if tagging itself was
// aborted or unsuccessful
tm.add(cbs.addOldProd, [ cbs.taggingPage, cbs.checkPriors ]);
// add to log only after notifying author so that the logging can be adjusted if
// notification wasn't successful. Also, don't run if tagging was not done.
tm.add(cbs.addToLog, [ cbs.notifyAuthor, cbs.taggingPage ]);
// All set, go!
tm.execute().then(function() {
Morebits.status.actionCompleted('برچسب زدن کامل شد');
setTimeout(function () {
window.location.href = mw.util.getUrl(mw.config.get('wgPageName'));
}, Morebits.wiki.actionCompleted.timeOut);
});
};
Twinkle.addInitCallback(Twinkle.prod, 'prod');
})(jQuery);
// </nowiki>