LLWiki正在建设中,欢迎加入我们

“MediaWiki:Gadget-mainpage-edit.js”的版本间差异

来自LLWiki
跳转到导航 跳转到搜索
(// 使用Wikiplus小工具快速编辑)
标签移动版网页编辑 移动版编辑
Zth讨论 | 贡献
 
(未显示2个用户的6个中间版本)
第3行: 第3行:
/* global OO, wgULS */
/* global OO, wgULS */
mw.loader.using( ['mediawiki.api', 'oojs-ui-windows', 'ext.gadget.site-lib'] ).then(() => {
mw.loader.using( ['mediawiki.api', 'oojs-ui-windows', 'ext.gadget.site-lib'] ).then(() => {
mw.messages.set( $.extend( wgULS({
mw.messages.set( $.extend( wgULS({
'gadget-ma-summary': '使用Mainpage小工具快速编辑', 'gadget-ma-niji': '虹学会', 'gadget-ma-preview': '预览',
'gadget-ma-summary': '使用Mainpage小工具快速编辑', 'gadget-ma-niji': '虹学会', 'gadget-ma-preview': '预览',
'gadget-ma-prompt': '请输入新的行号(从1开始计数)顺序,以空格分隔。未包括的行将被删除,不存在的空行将被创建。',
'gadget-ma-prompt': '请输入新的行号(从1开始计数)顺序,以空格分隔。未包括的行将被删除,不存在的空行将被创建。',
'gadget-ma-error': '输入内容错误!只接受以空格分隔的正整数。', 'gadget-ma-topic': '首页/当年今日',
'gadget-ma-error': '输入内容错误!只接受以空格分隔的正整数。', 'gadget-ma-topic': '首页/当年今日',
'gadget-ma-protect': '保护页面失败!错误原因:$1', 'gadget-delete': '删除该行'
'gadget-ma-protect': '保护页面失败!错误原因:$1', 'gadget-delete': '删除该行',
'gadget-ma-hasunosora': '莲之空'
}, {
}, {
'gadget-ma-summary': '使用Mainpage小工具快速編輯', 'gadget-ma-niji': '虹學會', 'gadget-ma-preview': '預覽',
'gadget-ma-summary': '使用Mainpage小工具快速編輯', 'gadget-ma-niji': '虹學會', 'gadget-ma-preview': '預覽',
'gadget-ma-prompt': '請輸入新的行號(從1開始計數)順序,以空格分隔。未包括的行將被刪除,不存在的空行將被創建。',
'gadget-ma-prompt': '請輸入新的行號(從1開始計數)順序,以空格分隔。未包括的行將被刪除,不存在的空行將被創建。',
'gadget-ma-error': '輸入內容錯誤!只接受以空格分割的正整數。', 'gadget-ma-topic': '首頁/當年今日',
'gadget-ma-protect': '保護頁面失敗!錯誤原因:$1', 'gadget-delete': '刪除該行'
'gadget-ma-error': '輸入內容錯誤!只接受以空格分割的正整數。', 'gadget-ma-topic': '首頁/當年今日',
}), {'gadget-insertBefore': '在上方插入一行', 'gadget-insertAfter': '在下方插入一行'}) );
'gadget-ma-protect': '保護頁面失敗!錯誤原因:$1', 'gadget-delete': '刪除該行',
'gadget-ma-hasunosora': '蓮之空'
let items = [], $table, $tag, table, wikitext, $row, trIndex;
}), {'gadget-insertBefore': '在上方插入一行', 'gadget-insertAfter': '在下方插入一行'}) );
const menu = mw.menu([ {text: "µ's", data: 'muse'}, {text: 'Aqours', data: 'aqours'},
let items = [], $table, $tag, table, wikitext, $row, trIndex;
{text: 'Saint Snow', data: 'saint snow'}, {text: mw.msg( 'gadget-ma-niji' ), data: 'nijigaku'},
{text: 'Liella!', data: 'liella'}, {text: 'SIF', data: 'sif'}, {text: 'AS', data: 'as'}
const menu = mw.menu([ {text: 's", data: 'muse'}, {text: 'Aqours', data: 'aqours'},
{text: 'Saint Snow', data: 'saint snow'}, {text: mw.msg( 'gadget-ma-niji' ), data: 'nijigaku'},
]),
colors = { muse: '#e4007f', aqours: '#32aaff', 'saint snow': '#cb3935', nijigaku: '#f39800', liella: '#a5469c',
{text: 'Liella!', data: 'liella'}, {text: 'SIF/SIF2', data: 'sif'}, {text: 'AS', data: 'as'},
{text: 'Musical', data: 'musical'}, {text: mw.msg( 'gadget-ma-hasunosora'), data: 'hasunosora'},
sif: '#77d2af', as: '#ff91af'
{text: '幻日夜羽', data: 'yohane'}
},
]),
dict = {ll: 'muse', llss: 'aqours', llspst: 'liella'},
colors = { muse: '#E50080', aqours: '#32aaff', 'saint snow': '#cb3935', nijigaku: '#f39800', liella: '#a5469c',
id = mw.config.get( 'wgArticleId' ),
sif: '#77d2af', as: '#ff91af', musical: '#c40035', hasunosora: '#fb8a9b', yohane: '#19737d'
pagename = mw.config.get( 'wgPageName' ),
},
isMobile = mw.config.get( 'skin' ) == 'minerva',
dict = {ll: 'muse', llss: 'aqours', llspst: 'liella'},
mode = pagename.startsWith( 'LLWiki:首页/当年今日/' ),
id = mw.config.get( 'wgArticleId' ),
writeText = () => {
pagename = mw.config.get( 'wgPageName' ),
const result = items.map(ele =>
isMobile = mw.config.get( 'skin' ) == 'minerva',
'{{首页/标签|' + ele[0] + '}}' + (ele[2] ? ele[2].getValue() : ele[1] || '') + '\n').join(''),
mode = pagename.startsWith( 'LLWiki:首页/当年今日/' ),
colorMod = mode ? ['[Rr]in', '[Kk]eke'].filter(ch => new RegExp('{{' + ch + '\/').test( result )) : [];
writeText = () => {
return (mode ? '{{#widget:首页}}' : wikitext.slice(0, table.index)) +
const result = items.map(ele =>
(colorMod.length ? '{{colorMod|' + colorMod.map(chara => chara + '=1').join('|') + '}}' : '') +
'{{首页/标签|' + ele[0] + '}}' + (ele[2] ? ele[2].getValue() : ele[1] || '') + '\n').join(''),
'\n{|\n' + result + '|}' +
colorMod = mode ? ['rin', 'keke'].filter(ch => new RegExp('{{' + ch + '\/', 'i').test( result )) : [];
(mode ? '' : wikitext.slice( table.index + table[0].length ));
return (mode ? '{{#widget:首页}}' : wikitext.slice(0, table.index)) +
},
(colorMod.length ? '{{colorMod|' + colorMod.map(chara => chara + '=1').join('|') + '}}' : '') +
width = $('#mw-content-text').width() * (isMobile ? 1 : 0.49) - (isMobile ? 68 : 36),
'\n{|\n' + result + '|}' +
$newTr = $('<tr>', {html: [$('<td>', {html: $('<span>', {class: 'mainpage-tag'})}), '<td>']}),
(mode ? '' : wikitext.slice( table.index + table[0].length ));
api = new mw.Api(),
},
btns = [ new OO.ui.ButtonWidget({label: '保存', flags: ['primary', 'progressive']}).on('click', () => {
width = $('#mw-content-text').width() * (isMobile ? 1 : 0.49) - (isMobile ? 68 : 36),
btns[0].setDisabled( true );
$newTr = $('<tr>', {html: [$('<td>', {html: $('<span>', {class: 'mainpage-tag'})}), '<td>']}),
mw.safeEdit(api, null, {title: pagename, text: writeText(), section: 0, summary: mw.msg('gadget-ma-summary')})
api = new mw.Api(),
.then(() => {
btns = [ new OO.ui.ButtonWidget({label: '保存', flags: ['primary', 'progressive']}).on('click', () => {
(mw.config.get( 'wgRestrictionEdit' ) != 'sysop' || mw.config.get( 'wgRestrictionMove' ) != 'sysop' ?
btns[0].setDisabled( true );
api.postWithEditToken({action: 'protect', title: pagename, protections: 'edit=sysop|move=sysop'}) :
mw.safeEdit(api, {title: pagename, text: writeText(), section: 0, summary: mw.msg('gadget-ma-summary')})
Promise.resolve()
).then(() => { location.reload(); },
.then(() => {
(mw.config.get( 'wgRestrictionEdit' ) != 'sysop' || mw.config.get( 'wgRestrictionMove' ) != 'sysop' ?
reason => { mw.notify( mw.msg('gadget-ma-protect', reason), {type: 'error', autoHideSeconds: 'long'}); }
api.postWithEditToken({action: 'protect', title: pagename, protections: 'edit=sysop|move=sysop'}) :
);
Promise.resolve()
}, reason => { if (reason != 'editConflict') { btns[0].setDisabled( false ); } });
).then(() => { location.reload(); },
}),
new OO.ui.ButtonWidget({label: mw.msg( 'gadget-ma-preview' )}).on('click', () => {
reason => { mw.notify( mw.msg('gadget-ma-protect', reason), {type: 'error', autoHideSeconds: 'long'}); }
);
mw.timedParse(api, {text: writeText()}, mw.msg( 'gadget-ma-topic' )).then(data => {
}, reason => { if (reason != 'editConflict') { btns[0].setDisabled( false ); } });
$table.html( $(data.parse.text).find( 'tbody' ) );
}),
}, () => {});
new OO.ui.ButtonWidget({label: mw.msg( 'gadget-ma-preview' )}).on('click', () => {
}),
mw.timedParse(api, {text: writeText()}, mw.msg( 'gadget-ma-topic' )).then(data => {
new OO.ui.ButtonWidget({label: '更多'}).on('click', () => {
$table.html( $(data.parse.text).find( 'tbody' ) );
mw.prompt( mw.msg( 'gadget-ma-prompt' ), 'progressive' ).then(result => {
}, () => {});
if (result === null) { return; }
}),
if (/[^\d\s]/.test( result )) {
new OO.ui.ButtonWidget({label: '更多'}).on('click', () => {
mw.notify( mw.msg( 'gadget-ma-error' ), {type: 'error', autoHideSeconds: 'long'} );
mw.prompt( mw.msg( 'gadget-ma-prompt' ), 'progressive' ).then(result => {
return;
if (result === null) { return; }
}
if (/[^\d\s]/.test( result )) {
const order = result.split(' ').filter(i => i).map(i => i - 1),
mw.notify( mw.msg( 'gadget-ma-error' ), {type: 'error', autoHideSeconds: 'long'} );
$tr = $table.find( 'tr' );
return;
items = order.map(i => items[i] || ['muse', '']);
}
$table.children( 'tbody' ).html( order.map(i => $tr[i] || $newTr.clone()) );
const order = result.split(' ').filter(i => i).map(i => i - 1),
});
$tr = $table.find( 'tr' );
}) ],
items = order.map(i => items[i] || ['muse', '']);
insertRow = (flag) => {
$table.children( 'tbody' ).html( order.map(i => $tr[i] || $newTr.clone()) );
items.splice( trIndex + flag, 0, ['muse', '']);
});
if ($row.length) { $newTr.clone()[`insert${ flag ? 'After' : 'Before' }`]( $row ); }
}) ],
else { $newTr.clone().appendTo( $table ); }
insertRow = (flag) => {
},
items.splice( trIndex + flag, 0, ['muse', '']);
contextMenu = isMobile ? null : mw.menu([ {text: mw.msg( 'gadget-delete' ), click: () => {
if ($row.length) { $newTr.clone()[`insert${ flag ? 'After' : 'Before' }`]( $row ); }
items.splice( trIndex, 1 );
else { $newTr.clone().appendTo( $table ); }
$row.remove();
},
}}, {text: mw.msg( 'gadget-insertBefore' ), click: () => { insertRow(0); }},
{text: mw.msg( 'gadget-insertAfter' ), click: () => { insertRow(1); }}
contextMenu = isMobile ? null : mw.menu([ {text: mw.msg( 'gadget-delete' ), click: () => {
items.splice( trIndex, 1 );
], null, true),
$row.remove();
optDel = isMobile ? null : contextMenu.findFirstSelectableItem();
}}, {text: mw.msg( 'gadget-insertBefore' ), click: () => { insertRow(0); }},
if (id === 0) {
{text: mw.msg( 'gadget-insertAfter' ), click: () => { insertRow(1); }}
$table = $('<table>', {html: '<tbody>'});
], null, true),
$('.noarticletext').toggleClass( 'noarticletext mw-parser-output mainpage-flex' ).html( $table );
optDel = isMobile ? null : contextMenu.findFirstSelectableItem();
} else { $table = $('.mw-parser-output table').first(); }
if (id === 0) {
menu.$element.appendTo( '.mw-parser-output' );
$table = $('<table>', {html: '<tbody>'});
mw.loader.addStyleTag( '.mainpage-flex td:last-child { width: calc(' + width + 'px - 1.2em); }' );
$('.noarticletext').toggleClass( 'noarticletext mw-parser-output mainpage-flex' ).html( $table );
menu.on('choose', option => {
} else { $table = $('.mw-parser-output table').first(); }
$tag.css('background-color', colors[ option.getData() ]);
menu.$element.appendTo( '.mw-parser-output' );
items[ $tag.closest( 'tr' ).index() ][0] = option.getData();
mw.loader.addStyleTag( '.mainpage-flex td:last-child { width: calc(' + width + 'px - 1.2em); }' );
});
menu.on('choose', option => {
$table.on('dblclick', 'td:first-child', function() {
$tag.css('background-color', colors[ option.getData() ]);
const $this = $(this),
name = items[ $this.parent().index() ][0].toLowerCase();
items[ $tag.closest( 'tr' ).index() ][0] = option.getData();
});
$tag = $this.children( '.mainpage-tag' );
$table.on('dblclick', 'td:first-child', function() {
menu.setFloatableContainer( $tag );
const $this = $(this),
menu.selectItemByData( dict[name] || name );
name = items[ $this.parent().index() ][0].toLowerCase();
menu.toggle( true );
$tag = $this.children( '.mainpage-tag' );
}).on('dblclick', 'td:last-child', function() {
menu.setFloatableContainer( $tag );
const $this = $(this),
menu.selectItemByData( dict[name] || name );
item = items[ $this.parent().index() ];
menu.toggle( true );
item[2] = item[2] || new OO.ui.MultilineTextInputWidget({autosize: true, value: item[1]});
}).on('dblclick', 'td:last-child', function() {
$this.html( item[2].$element );
const $this = $(this),
}).on('contextmenu', function(e) {
item = items[ $this.parent().index() ];
if (isMobile) { return; }
item[2] = item[2] || new OO.ui.MultilineTextInputWidget({autosize: true, value: item[1]});
e.preventDefault();
$this.html( item[2].$element );
$row = $(e.target).closest( 'tr' );
}).on('contextmenu', function(e) {
trIndex = $row.index();
if (isMobile) { return; }
optDel.setDisabled( $row.length === 0 );
e.preventDefault();
contextMenu.$element.css({left: e.pageX + 1, top: e.pageY + 1});
$row = $(e.target).closest( 'tr' );
contextMenu.toggle( true ); // 先设定位置再显示
trIndex = $row.index();
});
optDel.setDisabled( $row.length === 0 );
(id ? mw.sectionQuery( api ) : Promise.resolve()).then(data => {
contextMenu.$element.css({left: e.pageX + 1, top: e.pageY + 1});
wikitext = data ? data.parse.wikitext : '';
contextMenu.toggle( true ); // 先设定位置再显示
table = wikitext.match( /\n?{\|\n[\s\S]+?\n\|}(?!})/ );
});
items = [...table[0].matchAll( /首[页頁]\/[标標][签籤]\|(.+?)}}(.+?)\n/g )]
(id ? mw.sectionQuery( api ) : Promise.resolve()).then(data => {
.map(ele => [ele[1].trim(), ele[2].trim()]);
wikitext = data ? data.parse.wikitext : '';
});
table = wikitext.match( /\n?{\|\n[\s\S]+?\n\|}(?!})/ ) || [''];
$('<div>', {id: 'mainpage-btns', html: btns.map(ele => ele.$element)}).appendTo( '.mw-parser-output' );
items = [...table[0].matchAll( /首[页頁]\/[标標][签籤]\|(.+?)}}(.+?)\n/g )]
.map(ele => [ele[1].trim(), ele[2].trim()]);
});
$('<div>', {id: 'mainpage-btns', html: btns.map(ele => ele.$element)}).insertAfter( $table );
});
});
//</nowiki>
//</nowiki>

2024年1月11日 (四) 21:01的最新版本

//<nowiki>
"use strict";
/* global OO, wgULS */
mw.loader.using( ['mediawiki.api', 'oojs-ui-windows', 'ext.gadget.site-lib'] ).then(() => {
	mw.messages.set( $.extend( wgULS({
		'gadget-ma-summary': '使用Mainpage小工具快速编辑', 'gadget-ma-niji': '虹学会', 'gadget-ma-preview': '预览',
		'gadget-ma-prompt': '请输入新的行号(从1开始计数)顺序,以空格分隔。未包括的行将被删除,不存在的空行将被创建。',
		'gadget-ma-error': '输入内容错误!只接受以空格分隔的正整数。', 'gadget-ma-topic': '首页/当年今日',
		'gadget-ma-protect': '保护页面失败!错误原因:$1', 'gadget-delete': '删除该行',
		'gadget-ma-hasunosora': '莲之空'
	}, {
		'gadget-ma-summary': '使用Mainpage小工具快速編輯', 'gadget-ma-niji': '虹學會', 'gadget-ma-preview': '預覽',
		'gadget-ma-prompt': '請輸入新的行號(從1開始計數)順序,以空格分隔。未包括的行將被刪除,不存在的空行將被創建。',
		'gadget-ma-error': '輸入內容錯誤!只接受以空格分割的正整數。', 'gadget-ma-topic': '首頁/當年今日',
		'gadget-ma-protect': '保護頁面失敗!錯誤原因:$1', 'gadget-delete': '刪除該行',
		'gadget-ma-hasunosora': '蓮之空'
	}), {'gadget-insertBefore': '在上方插入一行', 'gadget-insertAfter': '在下方插入一行'}) );
	let items = [], $table, $tag, table, wikitext, $row, trIndex;
	const menu = mw.menu([ {text: "µ's", data: 'muse'}, {text: 'Aqours', data: 'aqours'},
		{text: 'Saint Snow', data: 'saint snow'}, {text: mw.msg( 'gadget-ma-niji' ), data: 'nijigaku'},
		{text: 'Liella!', data: 'liella'}, {text: 'SIF/SIF2', data: 'sif'}, {text: 'AS', data: 'as'},
		{text: 'Musical', data: 'musical'}, {text: mw.msg( 'gadget-ma-hasunosora'), data: 'hasunosora'}, 
		{text: '幻日夜羽', data: 'yohane'}
	]),
		colors = { muse: '#E50080', aqours: '#32aaff', 'saint snow': '#cb3935', nijigaku: '#f39800', liella: '#a5469c',
		sif: '#77d2af', as: '#ff91af', musical: '#c40035', hasunosora: '#fb8a9b', yohane: '#19737d'
	},
		dict = {ll: 'muse', llss: 'aqours', llspst: 'liella'},
		id = mw.config.get( 'wgArticleId' ),
		pagename = mw.config.get( 'wgPageName' ),
		isMobile = mw.config.get( 'skin' ) == 'minerva',
		mode = pagename.startsWith( 'LLWiki:首页/当年今日/' ),
		writeText = () => {
		const result = items.map(ele =>
			'{{首页/标签|' + ele[0] + '}}' + (ele[2] ? ele[2].getValue() : ele[1] || '') + '\n').join(''),
			colorMod = mode ? ['rin', 'keke'].filter(ch => new RegExp('{{' + ch + '\/', 'i').test( result )) : [];
		return (mode ? '{{#widget:首页}}' : wikitext.slice(0, table.index)) +
			(colorMod.length ? '{{colorMod|' + colorMod.map(chara => chara + '=1').join('|') + '}}' : '') +
			'\n{|\n' + result + '|}' +
			(mode ? '' : wikitext.slice( table.index + table[0].length ));
	},
		width = $('#mw-content-text').width() * (isMobile ? 1 : 0.49) - (isMobile ? 68 : 36),
		$newTr = $('<tr>', {html: [$('<td>', {html: $('<span>', {class: 'mainpage-tag'})}), '<td>']}),
		api = new mw.Api(),
		btns = [ new OO.ui.ButtonWidget({label: '保存', flags: ['primary', 'progressive']}).on('click', () => {
		btns[0].setDisabled( true );
		mw.safeEdit(api, {title: pagename, text: writeText(), section: 0, summary: mw.msg('gadget-ma-summary')})
			.then(() => {
			(mw.config.get( 'wgRestrictionEdit' ) != 'sysop' || mw.config.get( 'wgRestrictionMove' ) != 'sysop' ?
				api.postWithEditToken({action: 'protect', title: pagename, protections: 'edit=sysop|move=sysop'}) :
				Promise.resolve()
			).then(() => { location.reload(); },
				reason => { mw.notify( mw.msg('gadget-ma-protect', reason), {type: 'error', autoHideSeconds: 'long'}); }
			);
		}, reason => { if (reason != 'editConflict') { btns[0].setDisabled( false ); } });
	}),
		new OO.ui.ButtonWidget({label: mw.msg( 'gadget-ma-preview' )}).on('click', () => {
		mw.timedParse(api, {text: writeText()}, mw.msg( 'gadget-ma-topic' )).then(data => {
			$table.html( $(data.parse.text).find( 'tbody' ) );
		}, () => {});
	}),
		new OO.ui.ButtonWidget({label: '更多'}).on('click', () => {
		mw.prompt( mw.msg( 'gadget-ma-prompt' ), 'progressive' ).then(result => {
			if (result === null) { return; }
			if (/[^\d\s]/.test( result )) {
				mw.notify( mw.msg( 'gadget-ma-error' ), {type: 'error', autoHideSeconds: 'long'} );
				return;
			}
			const order = result.split(' ').filter(i => i).map(i => i - 1),
				$tr = $table.find( 'tr' );
			items = order.map(i => items[i] || ['muse', '']);
			$table.children( 'tbody' ).html( order.map(i => $tr[i] || $newTr.clone()) );
		});
	}) ],
		insertRow = (flag) => {
		items.splice( trIndex + flag, 0, ['muse', '']);
		if ($row.length) { $newTr.clone()[`insert${ flag ? 'After' : 'Before' }`]( $row ); }
		else { $newTr.clone().appendTo( $table ); }
	},
		contextMenu = isMobile ? null : mw.menu([ {text: mw.msg( 'gadget-delete' ), click: () => {
		items.splice( trIndex, 1 );
		$row.remove();
	}}, {text: mw.msg( 'gadget-insertBefore' ), click: () => { insertRow(0); }},
		{text: mw.msg( 'gadget-insertAfter' ), click: () => { insertRow(1); }}
	], null, true),
		optDel = isMobile ? null : contextMenu.findFirstSelectableItem();
	if (id === 0) {
		$table = $('<table>', {html: '<tbody>'});
		$('.noarticletext').toggleClass( 'noarticletext mw-parser-output mainpage-flex' ).html( $table );
	} else { $table = $('.mw-parser-output table').first(); }
	menu.$element.appendTo( '.mw-parser-output' );
	mw.loader.addStyleTag( '.mainpage-flex td:last-child { width: calc(' + width + 'px - 1.2em); }' );
	menu.on('choose', option => {
		$tag.css('background-color', colors[ option.getData() ]);
		items[ $tag.closest( 'tr' ).index() ][0] = option.getData();
	});
	$table.on('dblclick', 'td:first-child', function() {
		const $this = $(this),
			name = items[ $this.parent().index() ][0].toLowerCase();
		$tag = $this.children( '.mainpage-tag' );
		menu.setFloatableContainer( $tag );
		menu.selectItemByData( dict[name] || name );
		menu.toggle( true );
	}).on('dblclick', 'td:last-child', function() {
		const $this = $(this),
			item = items[ $this.parent().index() ];
		item[2] = item[2] || new OO.ui.MultilineTextInputWidget({autosize: true, value: item[1]});
		$this.html( item[2].$element );
	}).on('contextmenu', function(e) {
		if (isMobile) { return; }
		e.preventDefault();
		$row = $(e.target).closest( 'tr' );
		trIndex = $row.index();
		optDel.setDisabled( $row.length === 0 );
		contextMenu.$element.css({left: e.pageX + 1, top: e.pageY + 1});
		contextMenu.toggle( true ); // 先设定位置再显示
	});
	(id ? mw.sectionQuery( api ) : Promise.resolve()).then(data => {
		wikitext = data ? data.parse.wikitext : '';
		table = wikitext.match( /\n?{\|\n[\s\S]+?\n\|}(?!})/ ) || [''];
		items = [...table[0].matchAll( /首[页頁]\/[标標][签籤]\|(.+?)}}(.+?)\n/g )]
			.map(ele => [ele[1].trim(), ele[2].trim()]);
	});
	$('<div>', {id: 'mainpage-btns', html: btns.map(ele => ele.$element)}).insertAfter( $table );
});
//</nowiki>