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

MediaWiki:Gadget-definitions-core.js

来自LLWiki
跳转到导航 跳转到搜索

注意:在发布之后,您可能需要清除浏览器缓存才能看到所作出的更改的影响。

  • Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5Ctrl-R(Mac为⌘-R
  • Google Chrome:Ctrl-Shift-R(Mac为⌘-Shift-R
  • Edge:按住Ctrl的同时单击刷新,或按Ctrl-F5
//<nowiki>
// 由[[mediawiki:gadget-definitions.js]]调用,可以使用ES6语法
/**
 * @Function: 使用表格界面显示和编辑小工具定义
 * @Dependencies: mediawiki.api, jquery.tablesorter, oojs-ui-widgets
 * @Author: [[User:Bhsd]]
 * @Warning: 未添加繁体中文
 */
"use strict";
/* global OO */
$(() => {
	// 1. 最基本的工具函数,用于text、HTML、data三种状态间转换
	const Keys = ['name', 'type', 'default', 'peers', 'dependencies', 'actions', 'rights', 'skins', 'hidden', 'pages'],
		dictionary = { type: {general: '通常', styles: '纯CSS'},
		skins: {vector: '桌面版', minerva: '手机版', 'vector,minerva': '通用'}
	},
		text2data = (text) => {
		const parts = text.match( /^(.+)\[(.+)]\|(.+)$/ ),
			params = $.extend({name: parts[1], pages: parts[3], type: 'general', skins: 'vector,minerva'},
			Object.fromEntries( parts[2].split( '|' ).map(s => s.includes( '=' ) ? s.split( '=' ) : [s, true]) ));
		delete params.ResourceLoader;
		['peers', 'dependencies', 'rights', 'actions', 'pages'].forEach(key => {
			params[key] = params[key] ? params[key].split(key == 'pages' ? '|' : ',').sort() : [];
		});
		return params;
	},
		data2html = (params, key) => {
		const val = params[key];
		switch(key) {
			case 'name':
				return $('<span>', {id: val, html: [ val,
					$('<a>', {href: '#', title: '删除', html: $('<i>', {class: 'far fa-minus-square'})})
				]});
			case 'type':
			case 'skins':
				return dictionary[key][val];
			case 'default':
			case 'hidden':
				return val ? '是' : '否';
			case 'peers':
				return val.map(ele => $('<div>', {html: $('<a>', {text: ele, href: `#${ele}`})}));
			case 'dependencies':
				return val.map(ele => $('<div>', ele.startsWith('ext.gadget.') ? {html: $('<a>', {text: ele, href: `#${ele.slice(11)}`})} : {text: ele}));
			case 'rights':
			case 'actions':
				return val.map(ele => $('<div>', {text: ele}));
			case 'pages':
				return val.map(ele => $('<div>', {html: $('<a>', {text: ele,
					href: mw.util.getUrl( `mediawiki:gadget-${ele}` )})}));
		}
	},
		data2text = (params) => {
		return `* ${ params.name }[${ params.type == 'general' ? 'ResourceLoader' : 'type=styles' }` +
			['default', 'hidden'].map(key => params[key] ? `|${key}` : '').join( '' ) +
			['peers', 'dependencies', 'rights', 'actions'].map(key =>
				params[key].length ? `|${key}=${ params[key].join(',') }` : '').join( '' ) +
			(params.skins == 'vector,minerva' ? '' : `|skins=${params.skins}`) +
			`]|${ params.pages.join( '|' ) }`;
	},
	// 2. 使用表格显示小工具定义
		insertRow = function() {
		const params = text2data( this.textContent );
		return $('<tr>', {class: 'defTr', html: Keys.map(key => $('<td>', {html: data2html(params, key)}))})
			.data('params', params)[0];
	},
	// 3. 使用表格修改小工具定义
		api = new mw.Api(),
		btns = [ new OO.ui.ButtonWidget({label: '保存', flags: ['primary', 'progressive']}),
		new OO.ui.ButtonWidget({label: '添加', flags: 'progressive'})
	],
		$tr = $('<tr>', {html: $('<td>', {colspan: 9, html: btns.map(ele => ele.$element)})}),
		boolWidget = new OO.ui.DropdownInputWidget({options: [{data: 'true', label: '是'}, {data: '', label: '否'}]}),
		freeWidget = new OO.ui.TagMultiselectWidget({allowArbitrary: true}),
		getOptions = (key) => Object.entries( dictionary[key] ).map(ele => ({data: ele[0], label: ele[1]})),
		widgets = [],
		endEdit = (widget) => {
		if (!document.body.contains( widget.$element[0] )) { return; }
		const $oldTd = widget.$element.closest( 'td' ),
			params = $oldTd.closest( '.defTr' ).data( 'params' ),
			key = Keys[ $oldTd.index() ];
		params[key] = widget.getValue();
		widget.$element.detach();
		$oldTd.html( data2html(params, key) );
	},
		save = () => {
		btns[0].setDisabled( true );
		widgets.forEach( endEdit );
		const $table = $tr.closest( 'table' ),
			pageid = mw.config.get( 'wgArticleId' ),
			section = $table.index( '.defTable' ) + 1,
			// 注意可能标题自动编号
			sectionName = $( '.mw-headline' ).eq( section - 1 ).contents().last().text().trim(),
			text = `==${ sectionName }==\n` +
			[...$table.find( '.defTr' )].map(ele => data2text( $(ele).data( 'params' ) )).join( '\n' );
		mw.safeEdit(api, {pageid, section, text, summary: `/*${sectionName}*/ 使用definitions小工具编辑`})
			.then(() => { location.reload(); },
			reason => { btns[0].setDisabled( reason == 'editConflict' ); });
	},
		edit = function(e) {
		if (widgets.length === 0) {
			widgets.push(...[ new OO.ui.TextInputWidget(),
				new OO.ui.DropdownInputWidget({options: getOptions( 'type' )}),
				boolWidget,
				new OO.ui.MenuTagMultiselectWidget({allowArbitrary: true, options: [...$('.defTr')].map(ele =>
					$(ele).data( 'params' )).filter(ele => ele.type == 'styles').map(ele => ({data: ele.name}))}),
				freeWidget,
				freeWidget,
				freeWidget,
				new OO.ui.DropdownInputWidget({options: getOptions( 'skins' )}),
				boolWidget,
				freeWidget
			]);
		}
		const $td = $(this),
			i = $td.index(),
			params = $td.closest( '.defTr' ).data( 'params' ),
			widget = widgets[i],
			table = e.delegateTarget;
		if (!params) { return; }
		if (!table.contains( $tr[0] )) { $tr.appendTo( table ); }
		if ($td[0].contains( widget.$element[0] )) { return; }
		endEdit( widget );
		widget.setValue( params[ Keys[i] ] || '' );
		$td.html( widget.$element );
	},
		deleteRow = function(e) {
		e.preventDefault();
		$(this).closest( '.defTr' ).detach();
	};
	$('h2:has( .mw-editsection )').next().children( 'ul' ).addBack( 'ul' ).replaceWith(function() {
		return $('<table>', {class: 'wikitable sortable defTable', html: $('<tbody>', {html: $('<tr>', {html:
			['名称', '类型', '默认', 'Peers', 'Dependencies', '操作', '权限', '范围', '隐藏', '链接']
				.map(ele => $('<th>', {text: ele}))
		}).add( $(this).children().map( insertRow ) )})}).tablesorter()
			.on('dblclick', 'td', edit).on('click', 'i', deleteRow);
	});
	btns[0].on('click', save);
	btns[1].$element.click(function() {
		const params = {name: '', type: 'general', peers: [], dependencies: [], actions: [], rights: [], skins: 'vector,minerva',
			pages: []};
		$('<tr>', {class: 'defTr', html: Keys.map(key => $('<td>', {html: data2html(params, key)}))})
			.data('params', params).insertBefore( $(this).closest( 'tr' ) );
	});
});
//</nowiki>