MediaWikiの[[File:~]]にAttachRefプラグイン風の添付ボタンを表示させる

PukiWikiのAttachRefプラグインをMediaWikiで再現するスクリプトです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102207/35b9bba0-10f9-9f63-ffc6-e3e0fade4abc.png)

WIKIWIKI.JPで採用されていてとても好きだったプラグインです。
シンプルで直感的なのでMediaWikiに馴染みのない人でもアップロードしてくれるかも？

## 仕様
[[File:～]]構文で``class=upload``を付けておくと、その画像が存在しない場合、直接アップロード可能な「添付」ボタンが表示されます。

また、ライセンステンプレート名をclassに同時に追加しておくと、アップロード時のライセンステンプレートを指定できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102207/f27250a4-cfdc-767e-b431-93533fc158aa.png)
※ライセンステンプレート名の空白文字は_に変更すること。またスラッシュ/などクラス文字列で使用できない文字が含まれるテンプレート名は指定できません。

## ソースコード
```javascript:MediaWiki:Gadget-attacheRef.js
// PukiWiki風 添付機能つきのFile構文にする uploadクラス
const default_license = "{" + "{License Mojang}}";
const button_caption = "添付";

$(function(){

	$(".upload").each(function(){
		var filetype = " " + this.getAttribute("typeof") + " ";
		if (filetype.indexOf(" mw:File") == -1 || filetype.indexOf(" mw:Error ") == -1) {
			return; //すでにアップロード済の場合はスキップ
		}
		var $this = $(this);

		// classにLisenseテンプレート名が含まれているならテンプレート構文を生成しておく
		var class_attr = this.getAttribute("class");
		var classes = class_attr.split(/\s/);
		var license = default_license;
		for(var i=0; i<classes.length; i++){
			if (classes[i].indexOf("License") > -1){
				license = "{{" + classes[i].replaceAll(/_/g, ' ') + "}}";
				break;
			}
		}

		// -------- wikitextを生成する ------------
		
		var $media = $this.find(".mw-broken-media");
		var filename = $media.text();

		var size = "", width = "", height = "", isThumb = (filetype.indexOf(' mw:File/Thumb ') != -1);
		if($media){
			if ($media.attr("data-width")) {
				width = $media.attr("data-width") + "px";
			}
			if ($media.attr("data-height")) {
				height = "x" + $media.attr("data-height") + "px";
			}

			if(width.length || height.length) {
				size = "|" + width + height;
			}
		}
		
		// ------ 添付ボタンを生成する -------------

		var id = generateID(); // クリックイベントが被らないようにランダムIDを付けておく
		
		var $input = $("<input/>", {type: "file", name: "fileupload", style: "display:none", id: id});

		var $label = $("<label/>", {for: id, text: filename + " ", style: "color:red"}).on("click", function(){});

		var $button = $("<button/>", {text: button_caption}).on("click", function(){
			$label.trigger("click");
		});

		var $span = $("<span/>", {style:"line-height:normal"}).append($input, $label, $button);
		
		$this.find("a").replaceWith( $span );

		// ------- クリックイベント ---------------

		$input.change(function(){
			if(!this.files.length){
				return; //no file selected
			}
		
			var file = this.files[0];

			// CSRF-tokenを取得
			new mw.Api().get({
				action: 'query',
				meta: 'tokens',
				format: 'json'
			}).done( function(result) {

				// アップロード処理
				new mw.Api().upload(
					file, {
					filename: filename,
					text: license,
					watchlist: 'nochange',
					ignorewarnings: 1,
					token: result.query.tokens.csrftoken,
					format: 'json'
				}).always(function(e) {
					
					// アップロード後に動的に画像をレンダリングさせる
					var wikitext = "[" + "[" + filename + size + (isThumb ? "|thumb": "") + "|class=" + class_attr + "]]";
					new mw.Api().parse(wikitext).done(function ( $html ) {
						$this.replaceWith( $html );
					});

					// ページのキャッシュをパージする
					new mw.Api().post({
						"action": "purge",
						"format": "json",
						"titles": mw.config.get('wgPageName'),
						"formatversion": "2"
					});
				});
			});
		});
		
	});
	
});

// ランダムなIDを生成
function generateID() {
	var chars = "xxxxxxxx".split("");
	for (var i = 0, len = chars.length; i < len; i++) {
		chars[i] = Math.floor(Math.random() * 16).toString(16);
	}
	return chars.join("");
}

```

## 補足
このスクリプトはユーザーの権限チェックはしていません。
もしログインユーザーのみに表示させたい場合は``mw.user.getGroups()``を使用してユーザーグループを取得する処理が必要です。
[MediaWikiにpcommentプラグイン風のコメント機能をつける](https://qiita.com/Urushibara01/items/ad388f621c3ca8385624) でユーザーグループの取得を行う処理がありますので参考にしてみてください。