User:逆襲的天邪鬼/Twinkle-lzh/friendlytag.js: Difference between revisions

No edit summary
No edit summary
 
(11 intermediate revisions by the same user not shown)
Line 43: Line 43:
}
}


Window.setTitle( "條目维护標記" );
Window.setTitle( "條目維護標記" );


form.append({
form.append({ type: 'header', label: '常因' });
type: 'div',
id: 'tagWorkArea',
className: 'morebits-scrollbox',
style: 'max-height: 28em'
});

form.append( { type:'submit' } );


console.log('A');
var container = new Morebits.quickForm.element({ type: "fragment" });


// function to generate a checkbox, with appropriate subgroup if needed
// function to generate a checkbox, with appropriate subgroup if needed
Line 66: Line 55:
switch (tag) {
switch (tag) {
case "併":
case "併":
var otherTagName = "併";
checkbox.subgroup = [
checkbox.subgroup = [
{
{
Line 72: Line 60:
type: 'input',
type: 'input',
label: '目標:',
label: '目標:',
},
{
name: 'mergeTagOther',
type: 'checkbox',
list: [
{
label: '用{{' + otherTagName + '}}標記其他條目',
checked: true,
}
]
}
}
];
];
Line 93: Line 71:
}
}
break;
break;
case "文未準":
case "":
//checkbox.subgroup = {};
break;
default:
break;
}
return checkbox;
};

var checkboxes = [];
$.each(Twinkle.tag.article.tags, function(tag, description) {
checkboxes.push(makeCheckbox(tag, description));
});
container.append({
type: "checkbox",
name: "articleTags",
list: checkboxes
});
console.log('B');

// append any custom tags
if (Twinkle.getFriendlyPref('customTagList').length) {
container.append({ type: 'header', label: '自定義模板' });
container.append({ type: 'checkbox', name: 'articleTags', list: Twinkle.getFriendlyPref('customTagList') });
}

var $workarea = $(form).find("div#tagWorkArea");
var rendered = container.render();
$workarea.empty().append(rendered);

// style adjustments
$workarea.find("h5").css({ 'font-size': '110%' });
$workarea.find("h5:not(:first-child)").css({ 'margin-top': '1em' });
$workarea.find("div").filter(":has(span.quickformDescription)").css({ 'margin-top': '0.4em' });
console.log('C');


// add a link to each template's description page
$.each(Morebits.quickForm.getElements(form, "articleTags"), function(index, checkbox) {
var $checkbox = $(checkbox);
var link = Morebits.htmlNode("a", ">");
link.setAttribute("class", "tag-template-link");
link.setAttribute("href", mw.util.getUrl("Template:" +
Morebits.string.toUpperCaseFirstChar(checkbox.values)));
link.setAttribute("target", "_blank");
$checkbox.parent().append(["\u00A0", link]);
});

console.log('D');

var result = form.render();
Window.setContent( result );
Window.display();

// fake a change event on the sort dropdown, to initialize the tag list
var evt = document.createEvent("Event");
evt.initEvent("change", true, true);
};

Twinkle.tag.checkedTags = [];

Twinkle.tag.updateSortOrder = function(e) {
var sortorder = e.target.value;

Twinkle.tag.checkedTags = e.target.form.getChecked("articleTags");
if (!Twinkle.tag.checkedTags) {
Twinkle.tag.checkedTags = [];
}

var container = new Morebits.quickForm.element({ type: "fragment" });

// function to generate a checkbox, with appropriate subgroup if needed
var makeCheckbox = function(tag, description) {
var checkbox = { value: tag, label: "{{" + tag + "}}: " + description };
if (Twinkle.tag.checkedTags.indexOf(tag) !== -1) {
checkbox.checked = true;
}
switch (tag) {
case "併":
var otherTagName = "併";
checkbox.subgroup = [
checkbox.subgroup = [
{
{
name: 'mergeTarget',
name: 'moveTarget',
type: 'input',
type: 'input',
label: '目標:',
label: '目標:',
},
{
name: 'mergeTagOther',
type: 'checkbox',
list: [
{
label: '用{{' + otherTagName + '}}標記其他條目',
checked: true,
}
]
}
}
];
];
if (mw.config.get('wgNamespaceNumber') === 0) {
if (mw.config.get('wgNamespaceNumber') === 0) {
checkbox.subgroup.push({
checkbox.subgroup.push({
name: 'mergeReason',
name: 'moveReason',
type: 'textarea',
type: 'textarea',
label: '合併理由(會附在條目的討論頁):',
label: '移動理由(會附在條目的討論頁):',
tooltip: '請填寫理由。'
tooltip: '請填寫理由。'
});
});
Line 200: Line 89:
break;
break;
case "文未準":
case "文未準":
checkbox.subgroup = {};
var disputes = [];
for (var reason in Twinkle.tag.article.dispute) {
disputes.push({
value: reason,
label: reason + ':' + Twinkle.tag.article.dispute[reason]
});
}
checkbox.subgroup = [
{
name: 'disputeReason',
type: 'checkbox',
list: disputes
},
{
name: 'disputeCustomReason',
type: 'input',
label: '其他原因:'
}
];

break;
break;
default:
default:
Line 212: Line 120:
checkboxes.push(makeCheckbox(tag, description));
checkboxes.push(makeCheckbox(tag, description));
});
});
container.append({
form.append({
type: "checkbox",
type: "checkbox",
name: "articleTags",
name: "articleTags",
Line 220: Line 128:
// append any custom tags
// append any custom tags
if (Twinkle.getFriendlyPref('customTagList').length) {
if (Twinkle.getFriendlyPref('customTagList').length) {
container.append({ type: 'header', label: '自定義模板' });
form.append({ type: 'header', label: '自定義模板' });
container.append({ type: 'checkbox', name: 'articleTags', list: Twinkle.getFriendlyPref('customTagList') });
form.append({ type: 'checkbox', name: 'articleTags', list: Twinkle.getFriendlyPref('customTagList') });
}
}


form.append( { type:'submit' } );
var $workarea = $(e.target.form).find("div#tagWorkArea");
var rendered = container.render();
$workarea.empty().append(rendered);


var result = form.render();
// style adjustments
Window.setContent( result );
$workarea.find("h5").css({ 'font-size': '110%' });
Window.display();
$workarea.find("h5:not(:first-child)").css({ 'margin-top': '1em' });
$workarea.find("div").filter(":has(span.quickformDescription)").css({ 'margin-top': '0.4em' });


// fake a change event on the sort dropdown, to initialize the tag list
// add a link to each template's description page
var evt = document.createEvent("Event");
$.each(Morebits.quickForm.getElements(e.target.form, "articleTags"), function(index, checkbox) {
evt.initEvent("change", true, true);
var $checkbox = $(checkbox);
var link = Morebits.htmlNode("a", ">");
link.setAttribute("class", "tag-template-link");
link.setAttribute("href", mw.util.getUrl("Template:" +
Morebits.string.toUpperCaseFirstChar(checkbox.values)));
link.setAttribute("target", "_blank");
$checkbox.parent().append(["\u00A0", link]);
});
};
};


Twinkle.tag.checkedTags = [];


// Tags for ARTICLES start here
// Tags for ARTICLES start here
Line 256: Line 155:
'文白相雜': '文白相雜',
'文白相雜': '文白相雜',
'繁簡相雜': '繁簡相雜',
'繁簡相雜': '繁簡相雜',
'無據': '文章沒有任何參考來源',
'遷': '議遷',
'': '議併',
'殘章': '文章還沒寫完',
'文未準': '文章存在一些問題,需要修正。必須指出具體原因。選中此條後會顯示一些常用原因,另外也可以填寫自己的理由。',
'無據': '是文無引據',
'遷': '請求移動條目。請記得給出目標名稱和移動原因。',
'文未準': '是文未準,須辨真偽、正文辭'
'併': '請求與其他條目合併。請記得給出合併目標和原因。'
};

Twinkle.tag.article.tagaliases = {
'殘章': ['stub', '芻文'],
'文白相雜': ['NotClassicalChinese'],
'繁簡相雜': ['簡體'],
'無據': ['Unreferenced'],
'文未準': ['Disputed'],
'遷': ['Move'],
'併': ['Mergeto']
};
};


Twinkle.tag.article.dispute = {
Twinkle.tag.article.dispute = {
'引據未準,須審讀': '引用的準確性無法核實',
'引據不全': '引據不能覆蓋全文',
'引據未準,須細審讀': '引用的準確性無法核實',
'需纂以維基碼': '需要維基化',
'需纂以維基碼': '需要維基化',
'文辭未準,須辨真偽': '真實性存疑',
'存疑,須辨真偽': '真實性存疑',
'文中存纂者己見': '包含編者個人想法、原創研究等',
'文中存纂者己見': '包含編者個人想法、原創研究等',
'非中立': '中立性有問題'
'非大典文辭': '非百科全書語氣',
'非中立': '中立性有問題。注意:請仔細解釋原因否則標記可能無效。',
'分段、分節過於零碎': '[[:zh:Wikipedia:Jessechi]]愛做的事情。'
};
};


Line 273: Line 186:
main: function( pageobj ) {
main: function( pageobj ) {
var params = pageobj.getCallbackParameters(),
var params = pageobj.getCallbackParameters(),
tagRe, tagText = '', summaryText = '添加',
tagRe, tagText = '', summaryText = '',
tags = [], groupableTags = [], i, totalTags;
tags = [], i, totalTags;


// Remove tags that become superfluous with this action
// Remove tags that become superfluous with this action
Line 281: Line 194:
var addTag = function friendlytagAddTag( tagIndex, tagName ) {
var addTag = function friendlytagAddTag( tagIndex, tagName ) {
var currentTag = "";
var currentTag = "";
if( tagName === '文白相雜' ) {
pageText += '{{' + tagName + '|~~~~}}\n';
} else {
currentTag += '{{' + tagName;


switch (tagName) {
// prompt for other parameters, based on the tag
case '文白相雜':
switch( tagName ) {
currentTag += '{{文白相雜|~~~~~}}\n';
case 'merge':
case 'merge to':
break;
case 'merge from':
if (params.mergeTarget) {
// normalize the merge target for now and later
params.mergeTarget = Morebits.string.toUpperCaseFirstChar(params.mergeTarget.replace(/_/g, ' '));


case '文未準':
currentTag += '|' + params.mergeTarget;
currentTag += '{{文未準|';
currentTag += params.tagParameters.disputeReason.join(';');


if (params.tagParameters.disputeCustomReason) {
// link to the correct section on the talk page, for article space only
if (params.tagParameters.disputeReason.length > 0) {
if (mw.config.get('wgNamespaceNumber') === 0 && (params.mergeReason || params.discussArticle)) {
currentTag += ';';
if (!params.discussArticle) {
// discussArticle is the article whose talk page will contain the discussion
params.discussArticle = (tagName === "merge to" ? params.mergeTarget : mw.config.get('wgTitle'));
// nonDiscussArticle is the article which won't have the discussion
params.nonDiscussArticle = (tagName === "merge to" ? mw.config.get('wgTitle') : params.mergeTarget);
params.talkDiscussionTitle = '请求与' + params.nonDiscussArticle + '合併';
}
currentTag += '|discuss=Talk:' + params.discussArticle + '#' + params.talkDiscussionTitle;
}
}
}
currentTag += params.tagParameters.disputeCustomReason;
break;
default:
}
break;
currentTag += '}}\n';
}
break;

case '遷':
if (params.tagParameters.moveTarget) {
currentTag += '{{遷|';
// normalize the merge target for now and later
params.tagParameters.moveTarget = Morebits.string.toUpperCaseFirstChar(params.tagParameters.moveTarget.replace(/_/g, ' '));
currentTag += params.tagParameters.moveTarget + '}}\n';
}
break;

case '併':
if (params.tagParameters.mergeTarget) {
currentTag += '{{併|';
// normalize the merge target for now and later
params.tagParameters.mergeTarget = Morebits.string.toUpperCaseFirstChar(params.tagParameters.mergeTarget.replace(/_/g, ' '));
currentTag += params.tagParameters.mergeTarget + '}}\n';
}
break;

case '殘章':
pageText = pageText + '\n{{殘章}}';
break;


default:
currentTag += '}}\n';
tagText += currentTag;
currentTag += '{{' + tagName + '}}\n';
break;
}
}
tagText += currentTag;


if ( tagIndex > 0 ) {
if ( tagIndex > 0 ) {
Line 332: Line 255:


// Check for preexisting tags and separate tags into groupable and non-groupable arrays
// Check for preexisting tags and separate tags into groupable and non-groupable arrays
for( i = 0; i < params.tags.length; i++ ) {
for (i = 0; i < params.tags.length; i++) {
var found = false;

tagRe = new RegExp( '(\\{\\{' + params.tags[i] + '(\\||\\}\\})|\\|\\s*' + params.tags[i] + '\\s*=[a-z ]+\\d+)', 'im' );
tagRe = new RegExp( '(\\{\\{' + params.tags[i] + '(\\||\\}\\})|\\|\\s*' + params.tags[i] + '\\s*=[a-z ]+\\d+)', 'im' );
if( !tagRe.exec( pageText ) ) {
if (tagRe.exec(pageText)) {
found = true;
if( Twinkle.tag.multipleIssuesExceptions.indexOf(params.tags[i]) === -1 ) {
}
groupableTags = groupableTags.concat( params.tags[i] );

} else {
if (Twinkle.tag.article.tagaliases) {
tags = tags.concat( params.tags[i] );
var aliases = Twinkle.tag.article.tagaliases[params.tags[i]];
for (var j=0; j<aliases.length; j++) {
tagRe = new RegExp( '(\\{\\{' + aliases[j] + '(\\||\\}\\})|\\|\\s*' + aliases[j] + '\\s*=[a-z ]+\\d+)', 'im' );
if (tagRe.exec(pageText)) {
found = true;
break;
}
}
}
}

if (!found) {
tags = tags.concat( params.tags[i] );
} else {
} else {
Morebits.status.warn( '信息', '在頁面上找到{{' + params.tags[i] +
Morebits.status.warn( '信息', '在頁面上找到{{' + params.tags[i] +
'}}…跳过' );
'}}…跳过' );
// don't do anything else with merge tags
// don't do anything else with merge tags
if (params.tags[i] === "merge" || params.tags[i] === "merge from" ||
if (params.tags[i] === "") {
params.tagParameters.mergeTarget = params.tagParameters.mergeReason = false;
params.tags[i] === "merge to") {
}
params.mergeTarget = params.mergeReason = params.mergeTagOther = false;
if (params.tags[i] === "遷") {
params.tagParameters.moveTarget = params.tagParameters.moveReason = false;
}
}
}
}
}
}

var miTest = /\{\{(multiple ?issues|article ?issues|mi)[^}]+\{/im.exec(pageText);
var miOldStyleRegex = /\{\{(multiple ?issues|article ?issues|mi)\s*\|([^{]+)\}\}/im;
var miOldStyleTest = miOldStyleRegex.exec(pageText);

tags = tags.concat( groupableTags );


tags.sort();
tags.sort();
Line 364: Line 296:
// complicated than it'd need to be, to allow templates as parameters,
// complicated than it'd need to be, to allow templates as parameters,
// and to handle whitespace properly.
// and to handle whitespace properly.
pageText = pageText.replace(/^\s*(?:((?:\s*\{\{\s*(?:about|correct title|dablink|distinguish|for|other\s?(?:hurricaneuses|people|persons|places|uses(?:of)?)|redirect(?:-acronym)?|see\s?(?:also|wiktionary)|selfref|the)\d*\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\})+(?:\s*\n)?)\s*)?/i,
pageText = pageText.replace(/^\s*(?:((?:\s*\{\{\s*(?:外語不入題|非漢字不入題|釋義|釋義二|disambig|消歧義|otheruses)\d*\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\})+(?:\s*\n)?)\s*)?/i,
"$1" + tagText);
"$1" + tagText);


summaryText += ( tags.length > 0 ? '標記' : '' ) +
summaryText += ( tags.length > 0 ? '' : '' ) +
'至文';
'至文';


// avoid truncated summaries
// avoid truncated summaries
Line 381: Line 313:
pageobj.setCreateOption('nocreate');
pageobj.setCreateOption('nocreate');
pageobj.save(function() {
pageobj.save(function() {
var talkpageText;
var talkpage;
// special functions for merge tags
// special functions for merge tags
if (params.mergeReason) {
if (params.tagParameters.mergeReason) {
// post the rationale on the talk page (only operates in main namespace)
// post the rationale on the talk page (only operates in main namespace)
var talkpageText = "\n\n== 議[[" + params.nonDiscussArticle + "]]合併 ==\n\n";
talkpageText = "\n== 議併至[[" + params.tagParameters.mergeTarget + "]] ==\n";
talkpageText += params.mergeReason.trim() + "--~~~~";
talkpageText += params.tagParameters.mergeReason.trim() + "--~~~~";


var talkpage = new Morebits.wiki.page("Talk:" + params.discussArticle, "將理由貼进討論頁");
talkpage = new Morebits.wiki.page("Talk:" + mw.config.get('wgTitle'), "將理由貼进討論頁");
talkpage.setAppendText(talkpageText);
talkpage.setAppendText(talkpageText);
talkpage.setEditSummary('議將[[' + params.nonDiscussArticle + ']]' +
talkpage.setEditSummary('議將[[' + mw.config.get('wgTitle') + ']]' +
'併' + '[[' + params.discussArticle + ']]' +
'併' + '[[' + params.tagParameters.mergeTarget + ']]' +
Twinkle.getPref('summaryAd'));
Twinkle.getPref('summaryAd'));
talkpage.setWatchlist(Twinkle.getFriendlyPref('watchMergeDiscussions'));
talkpage.setWatchlist(Twinkle.getFriendlyPref('watchMergeDiscussions'));
Line 396: Line 330:
talkpage.append();
talkpage.append();
}
}
if (params.mergeTagOther) {
if (params.tagParameters.moveReason) {
// tag the target page if requested
// post the rationale on the talk page (only operates in main namespace)
talkpageText = "\n== 議遷至[[" + params.tagParameters.moveTarget + "]] ==\n";
var otherTagName = "merge";
talkpageText += params.tagParameters.moveReason.trim() + "--~~~~";
if (tags.indexOf("merge from") !== -1) {

otherTagName = "merge to";
talkpage = new Morebits.wiki.page("Talk:" + mw.config.get('wgTitle'), "將理由貼进討論頁");
} else if (tags.indexOf("merge to") !== -1) {
talkpage.setAppendText(talkpageText);
otherTagName = "merge from";
talkpage.setEditSummary('議將[[' + mw.config.get('wgTitle') + ']]' +
}
'遷至' + '[[' + params.tagParameters.moveTarget + ']]' +
var newParams = {
Twinkle.getPref('summaryAd'));
tags: [otherTagName],
talkpage.setWatchlist(Twinkle.getFriendlyPref('watchMergeDiscussions'));
mergeTarget: Morebits.pageNameNorm,
talkpage.setCreateOption('recreate');
discussArticle: params.discussArticle,
talkpage.append();
talkDiscussionTitle: params.talkDiscussionTitle
};
var otherpage = new Morebits.wiki.page(params.mergeTarget, "標記其他頁面(" +
params.mergeTarget + ")");
otherpage.setCallbackParameters(newParams);
otherpage.load(Twinkle.tag.callbacks.main);
}
}
});
});
Line 425: Line 354:
Twinkle.tag.callback.evaluate = function friendlytagCallbackEvaluate(e) {
Twinkle.tag.callback.evaluate = function friendlytagCallbackEvaluate(e) {
var form = e.target;
var form = e.target;

var params = {};
var params = {};
if (form.patrolPage) {
if (form.patrolPage) {
Line 431: Line 361:


params.tags = form.getChecked( 'articleTags' );
params.tags = form.getChecked( 'articleTags' );
params.group = form.group.checked;
params.tagParameters = {
params.tagParameters = {
notability: form["articleTags.notability"] ? form["articleTags.notability"].value : null
moveTarget: form['articleTags.moveTarget'] ? form['articleTags.moveTarget'].value : null,
moveReason: form['articleTags.moveReason'] ? form['articleTags.moveReason'].value : null,
mergeTarget: form['articleTags.mergeTarget'] ? form['articleTags.mergeTarget'].value : null,
mergeReason: form['articleTags.mergeReason'] ? form['articleTags.mergeReason'].value : null,
disputeReason: form.getChecked('articleTags.disputeReason'),
disputeCustomReason: form['articleTags.disputeCustomReason'] ? form['articleTags.disputeCustomReason'].value : null,
};
};
// common to {{merge}}, {{merge from}}, {{merge to}}
params.mergeTarget = form["articleTags.mergeTarget"] ? form["articleTags.mergeTarget"].value : null;
params.mergeReason = form["articleTags.mergeReason"] ? form["articleTags.mergeReason"].value : null;
params.mergeTagOther = form["articleTags.mergeTagOther"] ? form["articleTags.mergeTagOther"].checked : false;


// form validation
// form validation
if( !params.tags.length ) {
if( !params.tags.length ) {
alert( '必须选择至少一標記!' );
alert( '必須選擇至少一標記!' );
return;
}
if( ((params.tags.indexOf("merge") !== -1) + (params.tags.indexOf("merge from") !== -1) +
(params.tags.indexOf("merge to") !== -1)) > 1 ) {
alert( '请在{{merge}}、{{merge from}}和{{merge to}}中选择一个。如果需要多次合併,请使用{{merge}}并用管道符分隔條目名(但在这种情形中Twinkle不能自动標記其他條目)。' );
return;
}
if( (params.mergeTagOther || params.mergeReason) && params.mergeTarget.indexOf('|') !== -1 ) {
alert( '目前还不支持在一次合併中標記多个條目,与开启关于多个條目的讨论。请不要勾选“標記其他條目”和/或清理“理由”框,并重试。' );
return;
return;
}
}
Line 459: Line 380:


Morebits.wiki.actionCompleted.redirect = Morebits.pageNameNorm;
Morebits.wiki.actionCompleted.redirect = Morebits.pageNameNorm;
Morebits.wiki.actionCompleted.notice = "標記完成,在几秒内刷新頁面";
Morebits.wiki.actionCompleted.notice = "標記完成,在几秒內重載入頁面";


var wikipedia_page = new Morebits.wiki.page(Morebits.pageNameNorm, "正在標記條目");
var wikipedia_page = new Morebits.wiki.page(Morebits.pageNameNorm, "正在標記條目");

Latest revision as of 13:19, 6 June 2017

//<nowiki>
// vim: set noet sts=0 sw=8:


(function($) {


/*
 ****************************************
 *** friendlytag.js: Tag module
 ****************************************
 * Mode of invocation:     Tab ("Tag")
 * Active on:              Existing articles;
 *                         all redirects
 * Config directives in:   FriendlyConfig
 */

Twinkle.tag = function friendlytag() {
	// article/draft tagging
	if( !Morebits.wiki.isPageRedirect() && ( ( mw.config.get('wgNamespaceNumber') === 0 || mw.config.get('wgNamespaceNumber') === 118 ) && mw.config.get('wgCurRevisionId') ) || ( Morebits.pageNameNorm === '維基大典:沙盒' ) ) {
		Twinkle.addPortletLink( Twinkle.tag.callback, "標", "friendly-tag", "標記條目" );
	}
};

Twinkle.tag.callback = function friendlytagCallback() {
	var Window = new Morebits.simpleWindow( 630, 500 );
	Window.setScriptName( "Twinkle" );

	var form = new Morebits.quickForm( Twinkle.tag.callback.evaluate );

	if (document.getElementsByClassName("patrollink").length) {
		form.append( {
			type: 'checkbox',
			list: [
				{
					label: '標記頁面為已巡查',
					value: 'patrolPage',
					name: 'patrolPage',
					checked: Twinkle.getFriendlyPref('markTaggedPagesAsPatrolled')
				}
			]
		} );
	}

	Window.setTitle( "條目維護標記" );

	form.append({ type: 'header', label: '常因' });

	// function to generate a checkbox, with appropriate subgroup if needed
	var makeCheckbox = function(tag, description) {
		var checkbox = { value: tag, label: "{{" + tag + "}}: " + description };
		if (Twinkle.tag.checkedTags.indexOf(tag) !== -1) {
			checkbox.checked = true;
		}
		switch (tag) {
			case "併":
				checkbox.subgroup = [
					{
						name: 'mergeTarget',
						type: 'input',
						label: '目標:',
					}
				];
				if (mw.config.get('wgNamespaceNumber') === 0) {
					checkbox.subgroup.push({
						name: 'mergeReason',
						type: 'textarea',
						label: '合併理由(會附在條目的討論頁):',
						tooltip: '請填寫理由。'
					});
				}
				break;
			case "遷":
				checkbox.subgroup = [
					{
						name: 'moveTarget',
						type: 'input',
						label: '目標:',
					}
				];
				if (mw.config.get('wgNamespaceNumber') === 0) {
					checkbox.subgroup.push({
						name: 'moveReason',
						type: 'textarea',
						label: '移動理由(會附在條目的討論頁):',
						tooltip: '請填寫理由。'
					});
				}
				break;
			case "文未準":
				var disputes = [];
				for (var reason in Twinkle.tag.article.dispute) {
					disputes.push({
						value: reason,
						label: reason + ':' + Twinkle.tag.article.dispute[reason]
					});
				}
				checkbox.subgroup = [
					{
						name: 'disputeReason',
						type: 'checkbox',
						list: disputes
					},
					{
						name: 'disputeCustomReason',
						type: 'input',
						label: '其他原因:'
					}
				];

				break;
			default:
				break;
		}
		return checkbox;
	};

	var checkboxes = [];
	$.each(Twinkle.tag.article.tags, function(tag, description) {
		checkboxes.push(makeCheckbox(tag, description));
	});
	form.append({
		type: "checkbox",
		name: "articleTags",
		list: checkboxes
	});

	// append any custom tags
	if (Twinkle.getFriendlyPref('customTagList').length) {
		form.append({ type: 'header', label: '自定義模板' });
		form.append({ type: 'checkbox', name: 'articleTags', list: Twinkle.getFriendlyPref('customTagList') });
	}

	form.append( { type:'submit' } );

	var result = form.render();
	Window.setContent( result );
	Window.display();

	// fake a change event on the sort dropdown, to initialize the tag list
	var evt = document.createEvent("Event");
	evt.initEvent("change", true, true);
};

Twinkle.tag.checkedTags = [];

// Tags for ARTICLES start here

Twinkle.tag.article = {};

// A list of all article tags, in alphabetical order
// To ensure tags appear in the default "categorized" view, add them to the tagCategories hash below.

Twinkle.tag.article.tags = {
	'文白相雜': '文白相雜',
	'繁簡相雜': '繁簡相雜',
	'無據': '文章沒有任何參考來源',
	'殘章': '文章還沒寫完',
	'文未準': '文章存在一些問題,需要修正。必須指出具體原因。選中此條後會顯示一些常用原因,另外也可以填寫自己的理由。',
	'遷': '請求移動條目。請記得給出目標名稱和移動原因。',
	'併': '請求與其他條目合併。請記得給出合併目標和原因。'
};

Twinkle.tag.article.tagaliases = {
	'殘章': ['stub', '芻文'],
	'文白相雜': ['NotClassicalChinese'],
	'繁簡相雜': ['簡體'],
	'無據': ['Unreferenced'],
	'文未準': ['Disputed'],
	'遷': ['Move'],
	'併': ['Mergeto']
};

Twinkle.tag.article.dispute = {
	'引據不全': '引據不能覆蓋全文',
	'引據未準,須細審讀': '引用的準確性無法核實',
	'需纂以維基碼': '需要維基化',
	'是文存疑,須辨真偽': '真實性存疑',
	'文中存纂者己見': '包含編者個人想法、原創研究等',
	'非大典文辭': '非百科全書語氣',
	'非中立': '中立性有問題。注意:請仔細解釋原因否則標記可能無效。',
	'分段、分節過於零碎': '[[:zh:Wikipedia:Jessechi]]愛做的事情。'
};

Twinkle.tag.callbacks = {
	main: function( pageobj ) {
		var params = pageobj.getCallbackParameters(),
		    tagRe, tagText = '', summaryText = '增',
		    tags = [], i, totalTags;

		// Remove tags that become superfluous with this action
		var pageText = pageobj.getPageText().replace(/\{\{\s*([Nn]ew unreviewed article|[Uu]nreviewed|[Uu]serspace draft)\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\}\s*/g, "");

		var addTag = function friendlytagAddTag( tagIndex, tagName ) {
			var currentTag = "";

			switch (tagName) {
				case '文白相雜':
					currentTag += '{{文白相雜|~~~~~}}\n';
					break;

				case '文未準':
					currentTag += '{{文未準|';
					currentTag += params.tagParameters.disputeReason.join(';');

					if (params.tagParameters.disputeCustomReason) {
						if (params.tagParameters.disputeReason.length > 0) {
							currentTag += ';';
						}
						currentTag += params.tagParameters.disputeCustomReason;
					}
					currentTag += '}}\n';
					break;

				case '遷':
					if (params.tagParameters.moveTarget) {
						currentTag += '{{遷|';
						// normalize the merge target for now and later
						params.tagParameters.moveTarget = Morebits.string.toUpperCaseFirstChar(params.tagParameters.moveTarget.replace(/_/g, ' '));
						currentTag += params.tagParameters.moveTarget + '}}\n';
					}
					break;

				case '併':
					if (params.tagParameters.mergeTarget) {
						currentTag += '{{併|';
						// normalize the merge target for now and later
						params.tagParameters.mergeTarget = Morebits.string.toUpperCaseFirstChar(params.tagParameters.mergeTarget.replace(/_/g, ' '));
						currentTag += params.tagParameters.mergeTarget + '}}\n';
					}
					break;

				case '殘章':
					pageText = pageText + '\n{{殘章}}';
					break;

				default:
					currentTag += '{{' + tagName + '}}\n';
					break;
			}
			tagText += currentTag;

			if ( tagIndex > 0 ) {
				if( tagIndex === (totalTags - 1) ) {
					summaryText += '與';
				} else if ( tagIndex < (totalTags - 1) ) {
					summaryText += '、';
				}
			}

			summaryText += '{{[[';
			summaryText += (tagName.indexOf(":") !== -1 ? tagName : ("T:" + tagName + "|" + tagName));
			summaryText += ']]}}';
		};

		// Check for preexisting tags and separate tags into groupable and non-groupable arrays
		for (i = 0; i < params.tags.length; i++) {
			var found = false;

			tagRe = new RegExp( '(\\{\\{' + params.tags[i] + '(\\||\\}\\})|\\|\\s*' + params.tags[i] + '\\s*=[a-z ]+\\d+)', 'im' );
			if (tagRe.exec(pageText)) {
				found = true;
			}

			if (Twinkle.tag.article.tagaliases) {
				var aliases = Twinkle.tag.article.tagaliases[params.tags[i]];
				for (var j=0; j<aliases.length; j++) {
					tagRe = new RegExp( '(\\{\\{' + aliases[j] + '(\\||\\}\\})|\\|\\s*' + aliases[j] + '\\s*=[a-z ]+\\d+)', 'im' );
					if (tagRe.exec(pageText)) {
						found = true;
						break;
					}
				}
			}

			if (!found) {
				tags = tags.concat( params.tags[i] );
			} else {
				Morebits.status.warn( '信息', '在頁面上找到{{' + params.tags[i] +
					'}}…跳过' );
				// don't do anything else with merge tags
				if (params.tags[i] === "併") {
					params.tagParameters.mergeTarget = params.tagParameters.mergeReason = false;
				}
				if (params.tags[i] === "遷") {
					params.tagParameters.moveTarget = params.tagParameters.moveReason = false;
				}
			}
		}

		tags.sort();
		totalTags = tags.length;
		$.each(tags, addTag);

		// smartly insert the new tags after any hatnotes. Regex is a bit more
		// complicated than it'd need to be, to allow templates as parameters,
		// and to handle whitespace properly.
		pageText = pageText.replace(/^\s*(?:((?:\s*\{\{\s*(?:外語不入題|非漢字不入題|釋義|釋義二|disambig|消歧義|otheruses)\d*\s*(\|(?:\{\{[^{}]*\}\}|[^{}])*)?\}\})+(?:\s*\n)?)\s*)?/i,
				"$1" + tagText);

		summaryText += ( tags.length > 0 ? '模' : '' ) +
			'至文內';

		// avoid truncated summaries
		if (summaryText.length > (254 - Twinkle.getPref('summaryAd').length)) {
			summaryText = summaryText.replace(/\[\[[^\|]+\|([^\]]+)\]\]/g, "$1");
		}

		pageobj.setPageText(pageText);
		pageobj.setEditSummary(summaryText + Twinkle.getPref('summaryAd'));
		pageobj.setWatchlist(Twinkle.getFriendlyPref('watchTaggedPages'));
		pageobj.setMinorEdit(Twinkle.getFriendlyPref('markTaggedPagesAsMinor'));
		pageobj.setCreateOption('nocreate');
		pageobj.save(function() {
			var talkpageText;
			var talkpage;
			// special functions for merge tags
			if (params.tagParameters.mergeReason) {
				// post the rationale on the talk page (only operates in main namespace)
				talkpageText = "\n== 議併至[[" + params.tagParameters.mergeTarget + "]] ==\n";
				talkpageText += params.tagParameters.mergeReason.trim() + "--~~~~";

				talkpage = new Morebits.wiki.page("Talk:" + mw.config.get('wgTitle'), "將理由貼进討論頁");
				talkpage.setAppendText(talkpageText);
				talkpage.setEditSummary('議將[[' + mw.config.get('wgTitle') + ']]' +
					'併至' + '[[' + params.tagParameters.mergeTarget + ']]' +
					Twinkle.getPref('summaryAd'));
				talkpage.setWatchlist(Twinkle.getFriendlyPref('watchMergeDiscussions'));
				talkpage.setCreateOption('recreate');
				talkpage.append();
			}
			if (params.tagParameters.moveReason) {
				// post the rationale on the talk page (only operates in main namespace)
				talkpageText = "\n== 議遷至[[" + params.tagParameters.moveTarget + "]] ==\n";
				talkpageText += params.tagParameters.moveReason.trim() + "--~~~~";

				talkpage = new Morebits.wiki.page("Talk:" + mw.config.get('wgTitle'), "將理由貼进討論頁");
				talkpage.setAppendText(talkpageText);
				talkpage.setEditSummary('議將[[' + mw.config.get('wgTitle') + ']]' +
					'遷至' + '[[' + params.tagParameters.moveTarget + ']]' +
					Twinkle.getPref('summaryAd'));
				talkpage.setWatchlist(Twinkle.getFriendlyPref('watchMergeDiscussions'));
				talkpage.setCreateOption('recreate');
				talkpage.append();
			}
		});

		if( params.patrol ) {
			pageobj.patrol();
		}
	}
};

Twinkle.tag.callback.evaluate = function friendlytagCallbackEvaluate(e) {
	var form = e.target;

	var params = {};
	if (form.patrolPage) {
		params.patrol = form.patrolPage.checked;
	}

	params.tags = form.getChecked( 'articleTags' );
	params.tagParameters = {
		moveTarget: form['articleTags.moveTarget'] ? form['articleTags.moveTarget'].value : null,
		moveReason: form['articleTags.moveReason'] ? form['articleTags.moveReason'].value : null,
		mergeTarget: form['articleTags.mergeTarget'] ? form['articleTags.mergeTarget'].value : null,
		mergeReason: form['articleTags.mergeReason'] ? form['articleTags.mergeReason'].value : null,
		disputeReason: form.getChecked('articleTags.disputeReason'),
		disputeCustomReason: form['articleTags.disputeCustomReason'] ? form['articleTags.disputeCustomReason'].value : null,
	};

	// form validation
	if( !params.tags.length ) {
		alert( '必須選擇至少一個標記!' );
		return;
	}

	Morebits.simpleWindow.setButtonsEnabled( false );
	Morebits.status.init( form );

	Morebits.wiki.actionCompleted.redirect = Morebits.pageNameNorm;
	Morebits.wiki.actionCompleted.notice = "標記完成,在几秒內重新載入頁面";

	var wikipedia_page = new Morebits.wiki.page(Morebits.pageNameNorm, "正在標記條目");
	wikipedia_page.setCallbackParameters(params);
	wikipedia_page.load(Twinkle.tag.callbacks.main);
};
})(jQuery);


//</nowiki>