MediaWiki:Gadget-Wikiplus.js

H萌娘,万物皆可H的百科全书!
imported>=海豚=2021年9月23日 (四) 13:04的版本
跳到导航 跳到搜索

注意:这类代码页面在保存之后,您可能需要清除浏览器缓存才能看到所作出的变更的影响。

mw.loader.load('https://wikiplus-app.com/Main.js');
/* 给wikiplus添加快速填写摘要 */
$(function () {
    var observar = new MutationObserver(function (record) {
        if ($('.Wikiplus-InterBox').find('#Wikiplus-Quickedit-Summary-Input')[0] &&
            (!$('.Wikiplus-InterBox').find('#summary_list')[0])) {
            var list = ['修饰语句', '修正笔误', '内容扩充', '排版', '分类', '消歧义', 'H萌化']
            var summary = document.createElement('span')
            summary.id = 'summary_list';
            summary.style.marginLeft = '0.5em';
            for (var i = 0; i < list.length; i++) {
                if (i != 0) summary.innerHTML += ' | ';
                summary.innerHTML += '<a href="#.">' + list[i] + '</a>';
            }
            $('.Wikiplus-InterBox').find('#Wikiplus-Quickedit-Summary-Input')[0].after(summary);
            $('#summary_list').children().each(function () {
                $(this)[0].onclick = function () {
                    var str = $('#Wikiplus-Quickedit-Summary-Input')[0].value;
                    if (/\/\/ Edit via Wikiplus\s*$/.test(str)) {
                        $('#Wikiplus-Quickedit-Summary-Input')[0].value = str.replace(/^(.*?)( ?\/\/ Edit via Wikiplus\s*)$/, '$1 ' + $(this)[0].innerText + ' // Edit via Wikiplus');
                    } else {
                        $('#Wikiplus-Quickedit-Summary-Input')[0].value += ' ' + $(this)[0].innerText;
                    }
                };
            });
        }
    });
    observar.observe(document.body, { childList: true });
});
/*
	在Wikiplus快速编辑的界面中添加一个“+”加号按钮,点击后可以新建快速替换的方案,完成后将生成一个按钮。
	在名称栏中,输入#号后面的文字将作为摘要使用,在执行匹配成功后将自动把摘要的文字置于编辑摘要栏中。
	在替换栏中可以使用 _@br_ 来指代换行,无论是否为正则模式。
	左键点击按钮执行预先设置好的替换,右键点击按钮删除该替换方案。
	
	注意:替换方案保存在当前浏览器中,而不是帐号内,若更换浏览器、更换电脑或清除缓存等,替换方案将不会同步。
*/
$(function(){
	if(typeof MutationObserver == 'undefined'){
		mw.notify('你使用的浏览器版本过低,无法使用Wikiplus-replace查找替换插件!', { type : 'warn' })
		return false
	}
	var topBtn = document.getElementById('Wikiplus-Edit-TopBtn')
	topBtn && topBtn.addEventListener('click', function(e){
		if($('.Wikiplus-InterBox').length == 1){
			 $('.Wikiplus-InterBox').remove()
		}
	}, true)
    $.each(document.getElementsByClassName('mw-editsection'), function(index, value){
        value.addEventListener('click', function(e){
            if(e.target.classList.contains('Wikiplus-Edit-SectionBtn') && $('.Wikiplus-InterBox').length == 1){
		        $('.Wikiplus-InterBox').remove()
	        }
        }, true)
    })
	
    var observar = new MutationObserver(function(record){
        var wikiplus = null
        var wikiplusTextarea = $('#Wikiplus-Quickedit')
        $.each(record[0].addedNodes, function(item, element){
            if(element.classList && element.classList.contains('Wikiplus-InterBox')){
                wikiplus = element
            }
        })
        if(wikiplus){
        	var br = '\n'		//用于快捷指代替换中的换行
            $(wikiplus).find('.Wikiplus-InterBox-Content')
            .find('div:first').find('#Wikiplus-Quickedit-Jump')
            .after('<span id="Wikiplus-Quickedit-addReplace" class="Wikiplus-Btn">✚</span>')

            $(wikiplus).contextmenu(function(){ return false })

            if(localStorage.getItem('Quickedit-replace')){
                var replaceData = JSON.parse(localStorage.getItem('Quickedit-replace'))
                $.each(replaceData, function(item, data){
                    var newButton = $('<span class="Wikiplus-Btn" data-id="' + data[3] + '">' + data[0] + '</span>')
                    newButton.mousedown(function(e){
                        if(e.which == 1){
                            var code = wikiplusTextarea.val()
                            var newCode = code.replace(new RegExp(data[1], 'gm'), data[2] ? data[2] : '')
                            .replace(/_@br_/g ,br)
                            if(code == newCode){
                                mw.notify('匹配结果为空!', { type : 'warn' })
                            }else{
                                wikiplusTextarea.val(newCode)
                                data[4] && $('#Wikiplus-Quickedit-Summary-Input').val(data[4])
                                mw.notify('已完成替换!')
                            }
                        }
                        
                        if(e.which == 3){
                            var replaceData = JSON.parse(localStorage.getItem('Quickedit-replace'))
                            .filter(function(repData){
                                return repData[3] != $(e.target).data('id')
                            })
                            localStorage.setItem('Quickedit-replace', JSON.stringify(replaceData))
                            $(this).remove()
                        }
                    })
                    $(wikiplus).find('.Wikiplus-InterBox-Content')
                    .find('div:first').find('.Wikiplus-Btn:last').after(newButton)
                })
            }

            $('#Wikiplus-Quickedit-addReplace').click(function(){
                var addReplaceHTML = '\
                <div id="Wikiplus-Quickedit-replace" style="width:400px; background:#EDF9F7; border:1px #666 solid; font-size:80%; box-shadow: 2px 2px 5px #aaa; overflow:hidden; padding:5px; position:fixed; top:50%; left:50%; transform:translate(-50%,-50%); -webkit-user-select:none; -moz-user-select:none; -o-user-select:none; user-select:none; z-index:300;">\
                <div style="padding:10px; padding-bottom:0;">添加快速替换<div class="Quickedit-replace-hide" style="float:right; font-size:26px; font-weight:bold; margin-top:-8px; -webkit-user-select:none; -moz-user-select:none; -o-user-select:none; user-select:none; cursor:pointer">×</div></div>\
                <hr style="height:1px; margin-bottom:-5px; background:#66CCFF; border:none;">\
                <div style="height:110px; border-radius:3px; padding:10px;">\
                    <p>名称:<input id="Quickedit-replace-Name" style="width:300px; height:25px; text-indent:3px;"></p>\
                    <p>查找:<input id="Quickedit-replace-Lookup" style="width:300px; height:25px; text-indent:3px;"></p>\
                    <p>替换:<input id="Quickedit-replace-Replace" style="width:300px; height:25px; text-indent:3px;"></p>\
                    <p>正则模式:<input type="checkbox" id="Quickedit-replace-pattern" value="reg" style="width:16px; height:16px; position:relative; top:3px;">\
                    <input class="Quickedit-replace-hide" type="button" value="关闭" style="float:right; width:50px; height:25px; background:white; box-shadow: 0 1px 2px #aaa; -webkit-user-select:none; -moz-user-select:none; -o-user-select:none; user-select:none; margin:0 5px;">\
                    <input id="Quickedit-replace-add" type="button" value="添加" style="float:right; width:50px; height:25px; background:white; box-shadow: 0 1px 2px #aaa; -webkit-user-select:none; -moz-user-select:none; -o-user-select:none; user-select:none; margin:0 5px;"></p>\
                </div>\
                </div>'
                $(document.body).append(addReplaceHTML)

                var addReplace = $('#Wikiplus-Quickedit-replace'),
                name = $('#Quickedit-replace-Name'),
                lookup = $('#Quickedit-replace-Lookup'),
                replace = $('#Quickedit-replace-Replace'),
                patternSwitch = $('#Quickedit-replace-pattern'),
                hideBtn = $('.Quickedit-replace-hide'),
                addBtn = $('#Quickedit-replace-add')

                hideBtn.click(function(){
                    addReplace.remove()
                })

                addBtn.click(function(){
                    var text = name.val()
                    if(/#/.test(text)){
                    	var note = text.replace(/(.+)#(.+)/, '$2')
                    	text = text.replace(/(.+)#(.+)/, '$1')
                    }
                    var pattern = lookup.val()
                    var replaceText = replace.val()
                    try{
                        if(! patternSwitch.prop('checked')){
                            pattern = pattern.replace(/([\\\(\)\[\]\{\}\+\.\*\^\$\!\?\|])/g,'\\$1')
                        }
                        new RegExp(pattern, 'gm')
                    }catch(e){
                        mw.notify('正则表达式有误,请核对后重新输入!', { type : 'error' })
                        return false
                    }
                    var id = Math.random()
                    if(localStorage.getItem('Quickedit-replace')){
                        var replaceData = JSON.parse(localStorage.getItem('Quickedit-replace'))
                        replaceData.push([text, pattern, replaceText, id, note || null])
                        replaceData = JSON.stringify(replaceData)
                        localStorage.setItem('Quickedit-replace', replaceData)
                    }else{
                        var replaceData = JSON.stringify([[text, pattern, replaceText, id, note || null]])
                        localStorage.setItem('Quickedit-replace', replaceData)
                    }
                    var newButton = $('<span class="Wikiplus-Btn" data-id="' + id + '">' + text + '</span>')
                    newButton.mousedown(function(e){
                        if(e.which == 1){
                            var code = wikiplusTextarea.val()
                            var newCode = code.replace(new RegExp(pattern, 'gm'), replaceText ? replaceText : '')
                            .replace(/_@br_/g ,br)
                            if(code == newCode){
                                mw.notify('匹配结果为空!', { type : 'warn' })
                            }else{
                                wikiplusTextarea.val(newCode)
                                note && $('#Wikiplus-Quickedit-Summary-Input').val(note)
                                mw.notify('已完成替换!')
                            }
                        }

                        if(e.which == 3){
                            var replaceData = JSON.parse(localStorage.getItem('Quickedit-replace'))
                            .filter(function(repData){
                                return repData[3] != $(e.target).data('id')
                            })
                            localStorage.setItem('Quickedit-replace', JSON.stringify(replaceData))
                            $(this).remove()
                        }
                    })
                    $(wikiplus).find('.Wikiplus-InterBox-Content')
                    .find('div:first').find('.Wikiplus-Btn:last').after(newButton)
                    mw.notify('已添加新的替换方案!')
                })

            })
            $('#Wikiplus-Quickedit-Back, .Wikiplus-InterBox-Close').click(function(){
                $('#Wikiplus-Quickedit-replace').remove()
            })
        }
    })
    var options = {
        childList : true
    }
    observar.observe(document.body, options)
})

/*global mw, $, OO, CodeMirror*/
$.when( $.ready, mw.loader.using( ['oojs-ui-windows', 'mediawiki.util'] ) ).then(() => {
	const contentModel = mw.config.get( 'wgPageContentModel' ),
		modes = {css: ['css', '//cdn.jsdelivr.net/npm/[email protected]/mode/css/css.min.js'],
		'sanitized-css': ['css', '//cdn.jsdelivr.net/npm/[email protected]/mode/css/css.min.js'],
		javascript: ['javascript', '//cdn.jsdelivr.net/npm/[email protected]/mode/javascript/javascript.min.js'],
		json: ['javascript', '//cdn.jsdelivr.net/npm/[email protected]/mode/javascript/javascript.min.js'],
		Scribunto: ['lua', '//cdn.jsdelivr.net/npm/[email protected]/mode/lua/lua.min.js'],
		lua: ['lua', '//cdn.jsdelivr.net/npm/[email protected]/mode/lua/lua.min.js'],
		wikitext: ['mediawiki', '//cdn.jsdelivr.net/gh/bhsd-harry/LLWiki@latest/otherwiki/mediawiki.min.js']
	};
	if (!mw.config.get( 'wgIsArticle' ) || !(window.Wikiplus ||
		['ready', 'loaded', 'loading', 'executing'].includes( mw.loader.getState( 'ext.gadget.Wikiplus' ) ))) {
		return;
	}
	let promise, cm, mode;
	const $search = $('<input>', {id: 'Wikiplus-Quickedit-Search', placeholder: '查找'})
		.on('input', () => { $search.css('background-color', ''); }),
		$searchClose = $('<span>', {text: '×', id:'Wikiplus-Quickedit-Search-Close'}),
		findNext = () => {
		const ptn = $search.val();
		if (!ptn) { return; }
		const regexp = new RegExp( (mw.RegExp ? mw.RegExp.escape : mw.util.escapeRegExp)( ptn ), 'i' ),
			lastLine = cm.lastLine(),
			to = {line: lastLine, ch: cm.getLine( lastLine ).length};
		let from = cm.getCursor( 'head' ),
			text = cm.getRange(from, to),
			search = text.match( regexp );
		if (!search) {
			from = {line: 0, ch: 0};
			text = cm.getValue();
			search = text.match( regexp );
		}
		if (!search) {
			$search.css('background-color', 'pink');
			return;
		}
		const index = cm.indexFromPos( from ) + search.index,
			anchor = cm.posFromIndex( index ),
			head = cm.posFromIndex( index + ptn.length );
		cm.setSelection(anchor, head);
		cm.scrollIntoView({from: anchor, to: head});
	},
		highlight = ($textarea) => {
		const height = $textarea.height(),
			update = () => { $textarea.val( cm.getValue() ); },
			$summary = $textarea.nextAll( '#Wikiplus-Quickedit-Summary-Input' ),
			$submit = $textarea.nextAll( 'button' ).mousedown( update ).first(),
			$minor = $submit.prev().children( '#Wikiplus-Quickedit-MinorEdit' ),
			$searchContainer = $('<div>', {id: 'Wikiplus-Quickedit-Search-Div', html: [$search, $searchClose]})
			.hide().insertBefore( $textarea ),
			findNew = () => {
			$searchContainer.show();
			$search.select().focus()[0].scrollIntoView( {behavior: 'smooth'} );
		};
		$searchClose.click(() => { $searchContainer.hide(); });
		cm = CodeMirror.fromTextArea($textarea[0], $.extend({
			mode: mode[0], mwConfig: window.mwConfig, lineWrapping: true, lineNumbers: true
		}, contentModel == 'wikitext' ? {} : {indentUnit: 4, indentWithTabs: true},
		contentModel == 'json' ? {json: true} : {}));
		mw.hook( 'wiki-codemirror' ).fire( cm );
		cm.setSize(null, height);
		cm.addKeyMap({'Ctrl-S': () => {
			update();
			$submit.triggerHandler( 'click' );
		}, 'Shift-Ctrl-S': () => {
			update();
			$minor.click();
			$submit.triggerHandler( 'click' );
		}, 'Ctrl-F': findNew, 'Cmd-F': findNew, 'Ctrl-G': findNext, 'Cmd-G': findNext});
		$textarea.closest( '.Wikiplus-InterBox' ).keydown(e => {
			if (!e.metaKey && !e.ctrlKey || !['f', 'g'].includes( e.key )) { return; }
			e.preventDefault();
			if (e.key == 'f') { findNew(); }
			else { findNext(); }
		});
		$summary.add([ $minor[0], $search[0] ]).off( 'keydown' ).keydown(e => {
			if (!e.metaKey && !e.ctrlKey || e.keyCode != 83) { return; }
			e.stopImmediatePropagation();
			update();
			if (e.shiftKey) { $minor.click(); }
			$submit.triggerHandler( 'click' );
		});
	},
		init = ($node) => {
		const $textarea = $node.find( '#Wikiplus-Quickedit' );
		$search.keyup(e => { if (e.key == 'Enter') { findNext(); } });
		if (!promise) { 
			mw.loader.load('//cdn.jsdelivr.net/npm/[email protected]/lib/codemirror.min.css', 'text/css');
			mw.loader.addStyleTag( `#Wikiplus-Quickedit + .CodeMirror { border: 1px solid #c8ccd1; line-height: 1.3; clear: both; }
			#Wikiplus-Quickedit-Search-Div { margin: 7px 0 5px; }
			#Wikiplus-Quickedit-Search-Close { font-size: 20px; margin: 7px; vertical-align: middle; cursor: pointer; }
			#Wikiplus-Quickedit-Search { width: 50%; }` );
			if (['wikitext', 'Scribunto'].includes( contentModel )) {
				mw.loader.load('//cdn.jsdelivr.net/gh/bhsd-harry/[email protected]/otherwiki/mediawiki.min.css', 'text/css');
			}
		}
		(contentModel == 'Scribunto' ?
			OO.ui.prompt( '无法检测待编辑内容的内容模型,请手动输入"lua"或"wikitext"或其首字母:' ) :
			Promise.resolve( contentModel )).then(model => {
			model = model || contentModel;
			if (model.length == 1) { model = ['lua', 'wikitext'].find(ele => ele.startsWith( model.toLowerCase() )); }
			mode = modes[ model ] || modes[ contentModel ];
			const getExt = (window.CodeMirror ? Promise.resolve() : $.get({ dataType: 'script', cache: true,
				url: '//cdn.jsdelivr.net/npm/[email protected]/lib/codemirror.min.js'
			})).then(() => (window.CodeMirror || {modes: {}}).modes[ mode[0] ] ? Promise.resolve() :
				$.get({dataType: 'script', cache: true, url: mode[1]})
			),
				getJSON = window.mwConfig || model != 'wikitext' ? Promise.resolve() :$.get({ dataType: 'json',
				cache: true, url: '//cdn.jsdelivr.net/gh/bhsd-harry/LLWiki@latest/otherwiki/gadget-CodeMirror.json'
			}).then(config => { window.mwConfig = window.mwConfig || config; });
			promise = Promise.all([getJSON, getExt]);
			promise.then(() => { highlight( $textarea ) });
		});
	},
		callback = (records) => {
		const $node = $( records[0].addedNodes[0] );
		if (!$node.hasClass( 'Wikiplus-InterBox' )) { return; }
		init( $node );
		observer2.disconnect();
		observer2.observe( $node.find( '#Wikiplus-Quickedit-Preview-Output' )[0], {childList: true} );
	},
		observer = new MutationObserver( callback ),
		callback2 = (records) => {
		const $node = $( records[0].addedNodes[1] );
		if ($node.hasClass( 'mw-body-content' )) { mw.hook( 'wikipage.content' ).fire( $node ); }
	},
		observer2 = new MutationObserver( callback2 );
	observer.observe(document.body, {childList: true});
	
	// 以下内容引自[[MW:Extension:CodeMirror]]
	$.valHooks.textarea = {
		get: (ele) => ele.id == 'Wikiplus-Quickedit' && cm ? cm.getValue() : ele.value,
		set: (ele, value) => ele.id == 'Wikiplus-Quickedit' && cm ? cm.setValue( value ) : ele.value = value
	};
});