注意:在保存之后,您可能需要清除浏览器缓存才能看到所作出的变更的影响。
?_=1
来访问最新页面。https://zh.moegirl.org.cn/User:%E6%9D%B1%E6%9D%B1%E5%90%9B/common.js?_=1
// Wikiplus快速替换
// mw.loader.load('/index.php?title=User:東東君/js/Wikiplus-replace.js&action=raw&ctype=text/javascript')
// 查找与替换
mw.loader.load('/index.php?title=User:東東君/js/replace.js&action=raw&ctype=text/javascript')
// 标签补全
mw.loader.load('/index.php?title=User:東東君/js/pair.js&action=raw&ctype=text/javascript')
// 实时通知
// mw.loader.load('/index.php?title=User:東東君/js/notification.js&action=raw&ctype=text/javascript')
// 代码生成按钮
mw.loader.load('/index.php?title=User:東東君/js/charinsert.js&action=raw&ctype=text/javascript')
// 编辑内容备份
mw.loader.load('/index.php?title=User:東東君/js/contentBackup.js&action=raw&ctype=text/javascript')
// 歌词注音
mw.loader.load('/index.php?title=User:東東君/js/ruby.js&action=raw&ctype=text/javascript')
// 快速对比版本差异 By: User:Nzh21
mw.loader.load('/index.php?title=User:Nzh21/js/QuickDiff.js&action=raw&ctype=text/javascript')
// 小工具集
mw.loader.load('/index.php?title=User:東東君/js/utils.js&action=raw&ctype=text/javascript')
// 上传工具
mw.loader.load('/index.php?title=User:東東君/js/uploader.js&action=raw&ctype=text/javascript')
// 摘要锁
// mw.loader.load('/index.php?title=User:東東君/js/lockSummary.js&action=raw&ctype=text/javascript')
// api测试沙盒
// mw.loader.load('/index.php?title=User:東東君/apiTest.js&action=raw&ctype=text/javascript')
mw.loader.load('https://cdn.jsdelivr.net/gh/koharubiyori/moegirlMMDPreviewerProducts/uploader.js')
// window.RLQ.push(function() {
// window.__WIDGET_MMD_PREVIEWER_WORKER_PATH = 'https://' + location.hostname + mw.config.get("wgScriptPath") + '/index.php?title=MediaWiki:MMDPreviewerForMoegirl.worker.js&action=raw&ctype=text/javascript';
// $.getScript('https://zh.moegirl.org.cn'+mw.config.get("wgScriptPath")+'/index.php?title=MediaWiki:MMDPreviewerForMoegirl.main.js&action=raw&ctype=text/javascript').then(function() { $(window.__mmdPreviewerWidgetInit) })
// })
/*
注意:该插件必须依附于Wikiplus才能生效。
载入后将在Wikiplus快速编辑的界面中添加一个“+”加号按钮,点击后可以新建快速替换的方案,完成后将生成一个按钮。
在名称栏中,输入#号后面的文字将作为摘要使用,在执行匹配成功后将自动把摘要的文字置于编辑摘要栏中。
在替换栏中可以使用 _@br_ 来指代换行,无论是否为正则模式。
左键点击按钮执行预先设置好的替换,右键点击按钮删除该替换方案。
注意:替换方案保存在当前浏览器中,而不是帐号内,若更换浏览器、更换电脑或清除缓存等,替换方案将不会同步。
*/
/**
@typedef {Object} Patterns
@prop {string} name
@prop {string} pattern
@prop {string} replaceVal
@prop {boolean} useRegex
@prop {string} summary
*/
var LOCAL_STORAGE_NAMESPACE = 'quickEdit-replace:'
var LOCAL_STORAGE_PATTERNS = LOCAL_STORAGE_NAMESPACE + 'patterns'
var patternManager = {
/**
* @type {Patterns[]}
*/
patterns: JSON.parse(localStorage.getItem(LOCAL_STORAGE_PATTERNS) || '[]'),
update: function() {
localStorage.setItem(LOCAL_STORAGE_PATTERNS, JSON.stringify(this.patterns))
renderButtons()
},
/**
* @param {Object} options
* @param {string} options.name
* @param {string} options.pattern
* @param {string} options.replaceVal
* @param {boolean} options.useRegex
* @param {string} [options.summary = '']
*/
add: function(options) {
if (options.useRegex) {
try {
new RegExp(options.pattern, 'g')
} catch(e) {
return false
}
}
options.summary = options.summary || ''
var foundIndex = this.patterns.find(function(item) { return item.name === options.name })
if (foundIndex) {
// 如果name相同的,直接覆盖那一条数据
this.patterns[foundIndex] = options
this.update()
return 2
} else {
// 如果没有,push一个新的
this.patterns.push(options)
this.update()
return 1
}
},
/**
* @param {string} name
*/
remove: function(name) {
var foundIndex = this.patterns.findIndex(function(item) { return item.name === name })
this.patterns.splice(foundIndex, 1)
this.update()
}
}
function renderButtons() {
var buttons = patternManager.patterns.map(function(item) {
var button = $('<div class="Wikiplus-Btn quickEdit-replace__replaceBtn">')
.attr('title', item.summary)
.data('name', item.name)
.data('pattern', item.pattern)
.data('useRegex', item.useRegex)
.data('replaceVal', item.replaceVal)
button.append($('<span>').text(item.name))
.click(function(e) {
if (e.target === this) {
var pattern = $(this).data('pattern')
var useRegex = $(this).data('useRegex')
var replaceVal = $(this).data('replaceVal')
if (!useRegex) {
pattern = pattern.replace(/([\\\(\)\[\]\{\}\+\.\*\^\$\!\?\|])/g,'\\$1')
}
editorManager.replace(new RegExp(pattern, 'g'), replaceVal)
}
})
var editBtn = $('<div class="quickEdit-replace__editPattern">').text('修改')
.click(function() {
var name = button.data('name')
var pattern = button.data('pattern')
var summary = button.attr('title')
var useRegex = button.data('useRegex')
var replaceVal = button.data('replaceVal')
addPatternDialogManager.show({
name: name,
pattern: pattern,
summary: summary,
useRegex: useRegex,
replaceVal: replaceVal
})
})
var removeBtn = $('<div class="quickEdit-replace__removePattern">').text('×')
.click((function(name){
return function() {
patternManager.remove(name)
mw.notify('删除成功')
}
})(item.name))
button.append(editBtn, removeBtn)
return button
})
var buttonContainer = $('.quickEdit-replace__replaceButtonContainer')
buttonContainer.empty().append.apply(buttonContainer, buttons)
}
var editorManager = {
textarea: null,
replaceBackup: null,
/**
* @param {RegExp} regex
* @param {string} replaceVal
*/
replace: function(regex, replaceVal) {
var currentContent = this.replaceBackup = this.textarea.text()
this.textarea.val(currentContent.replace(regex, replaceVal))
},
undo: function() {
if (this.replaceBackup === null) return false
this.textarea.text(this.replaceBackup)
this.replaceBackup = null
}
}
var addPatternDialogManager = {
html: [' <style>',
' .quickEdit-replace {',
' position: fixed;',
' top: 50%;',
' left: 50%;',
' transform: translate(-50%, -50%);',
' width: 350px;',
' border: 1px #ccc solid;',
' box-shadow: 0 0 3px #ccc;',
' padding: 5px;',
' z-index: 10000;',
' background-color: white;',
' }',
' #quickEdit-replace__hideBtn {',
' position: absolute;',
' top: 5px;',
' right: 5px;',
' font-size: 26px;',
' font-weight: bold;',
' cursor: pointer;',
' }',
' .quickEdit-replace h4 {',
' border-bottom: 2px #ccc solid;',
' padding-bottom: 5px;',
' margin: 5px;',
' padding-top: 0;',
' }',
' .quickEdit-replace main {',
' padding: 5px;',
' box-sizing: border-box;',
' }',
' .quickEdit-replace__formItem {',
' margin-top: 5px;',
' text-align: center;',
' }',
' .quickEdit-replace__formItem:first-child {',
' margin-top: 0;',
' }',
' .quickEdit-replace__formItem input[type="text"] {',
' width: 220px;',
' height: 22px;',
' text-indent: 5px;',
' border: 1px #ABABAB solid;',
' }',
' .quickEdit-replace footer {',
' display: flex;',
' justify-content: space-between;',
' margin-top: 10px;',
' }',
' .quickEdit-replace__buttons {',
' display: flex;',
' }',
' .quickEdit-replace__buttons button {',
' margin: 0 2px;',
' }',
' .quickEdit-replace__replaceButtonContainer {',
' display: flex;',
' }',
' .quickEdit-replace__editPattern {',
' border-left:1px #ccc solid;',
' margin: 0 5px;',
' display: inline-block;',
' }',
' .quickEdit-replace__replaceBtn {',
' position: relative',
' }',
' .quickEdit-replace__replaceBtn > .quickEdit-replace__removePattern {',
' display: none',
' }',
' .quickEdit-replace__replaceBtn:hover .quickEdit-replace__removePattern {',
' display: block',
' }',
' .quickEdit-replace__removePattern {',
' width: 12px;',
' height: 12px;',
' border-radius: 50%;',
' background-color: #ccc;',
' position: absolute;',
' top:0;',
' right:0;',
' transform: translate(50%, -50%);',
' }',
' </style>',
' <div class="quickEdit-replace" style="display:none">',
' <div id="quickEdit-replace__hideBtn">×</div>',
' <h4>添加替换规则</h4>',
' <main>',
' <div class="quickEdit-replace__formItem">',
' <label>',
' <span>名称:</span>',
' <input type="text" name="name">',
' </label>',
' </div>',
' ',
' <div class="quickEdit-replace__formItem">',
' <label>',
' <span>摘要:</span>',
' <input type="text" name="summary" placeholder="鼠标置于按钮上时显示,可以留空">',
' </label>',
' </div>',
' <div class="quickEdit-replace__formItem">',
' <label>',
' <span>查找:</span>',
' <input type="text" name="pattern">',
' </label>',
' </div>',
' <div class="quickEdit-replace__formItem">',
' <label>',
' <span>替换:</span>',
' <input type="text" name="replaceVal">',
' </label>',
' </div>',
' <footer>',
' <label>',
' <span>正则模式</span>',
' <input type="checkbox" id="quickEdit-replace__useRegex" style="vertical-align: middle;">',
' </label>',
' <div class="quickEdit-replace__buttons">',
' <button id="quickEdit-replace__addPatternBtn">添加</button>',
' <button id="quickEdit-replace__testBtn">测试</button>',
' <button id="quickEdit-replace__undoBtn">撤销</button>',
' </div>',
' </footer>',
' </main>',
' </div>'].join(''),
instance: null,
init: function() {
$(document.body).append(this.html)
renderButtons()
this.instance = $('.quickEdit-replace').eq(0)
var nameInput = $('.quickEdit-replace__formItem input[name="name"]').eq(0)
var summaryInput = $('.quickEdit-replace__formItem input[name="summary"]').eq(0)
var patternInput = $('.quickEdit-replace__formItem input[name="pattern"]').eq(0)
var replaceValInput = $('.quickEdit-replace__formItem input[name="replaceVal"]').eq(0)
var useRegexCheckbox = $('#quickEdit-replace__useRegex')
var hideBtn = $('#quickEdit-replace__hideBtn')
var addBtn = $('#quickEdit-replace__addPatternBtn')
var testBtn = $('#quickEdit-replace__testBtn')
var undoBtn = $('#quickEdit-replace__undoBtn')
var _this = this
hideBtn.click(function() {
_this.instance.hide()
})
addBtn.click(function(e) {
var name = nameInput.val().trim()
var summary = summaryInput.val().trim()
var pattern = patternInput.val()
var replaceVal = replaceValInput.val()
var useRegex = useRegexCheckbox.prop('checked')
if (name === '') return mw.notify('名称不能为空', { type: 'warn' })
if (pattern === '') return mw.notify('查找不能为空', { type: 'warn' })
var addedResult = patternManager.add({
name: name,
summary: summary,
pattern: pattern,
replaceVal: replaceVal,
useRegex: useRegex
})
if (addedResult) {
renderButtons()
mw.notify(addedResult === 1 ? '添加成功' : '修改成功')
} else {
mw.notify('输入的正则有误!', { type: 'error' })
}
})
testBtn.click(function(e) {
var pattern = patternInput.val()
var replaceVal = replaceValInput.val()
console.log(useRegexCheckbox)
var useRegex = useRegexCheckbox.prop('checked')
if (pattern === '') return mw.notify('查找条件不能为空')
console.log(pattern, replaceVal, useRegex)
try {
useRegex && new RegExp(pattern, 'g')
} catch(e) {
return mw.notify('正则表达式有误!')
}
if (!useRegex) {
pattern = pattern.replace(/([\\\(\)\[\]\{\}\+\.\*\^\$\!\?\|])/g,'\\$1')
}
editorManager.replace(new RegExp(pattern, 'g'), replaceVal)
})
undoBtn.click(function(e) {
editorManager.undo()
})
},
hide: function() {
this.instance.hide()
},
/**
* @param {Object} [options] 如果传options,代表是编辑(将options中的数据填到表单里)
* @param {string} options.name
* @param {string} options.pattern
* @param {string} options.replaceVal
* @param {boolean} options.useRegex
* @param {string} [options.summary = '']
*/
show: function(options) {
if (options) {
var nameInput = $('.quickEdit-replace__formItem input[name="name"]').eq(0)
var summaryInput = $('.quickEdit-replace__formItem input[name="summary"]').eq(0)
var patternInput = $('.quickEdit-replace__formItem input[name="pattern"]').eq(0)
var replaceValInput = $('.quickEdit-replace__formItem input[name="replaceVal"]').eq(0)
var useRegexCheckbox = $('#quickEdit-replace__useRegex')
nameInput.val(options.name)
summaryInput.val(options.summary)
patternInput.val(options.pattern)
replaceValInput.val(options.replaceVal)
useRegexCheckbox.prop('checked', options.useRegex)
}
this.instance.show()
}
}
function checkRequiredApi() {
if(typeof MutationObserver == 'undefined'){
mw.notify('你使用的浏览器版本过低或不符合规范,无法使用Wikiplus-replace插件!', { type : 'warn' })
return false
} else {
return true
}
}
function injectOpenDialogButton() {
var openDialogButton = $('<div class="Wikiplus-Btn quickEdit-replace__openDialog">✚</div>')
.click(function() {
addPatternDialogManager.show()
})
$('.Wikiplus-InterBox-Content > div:first > #Wikiplus-Quickedit-Jump').after(openDialogButton)
$('.quickEdit-replace__openDialog').after('<div class="quickEdit-replace__replaceButtonContainer">') // 替换按钮容器
}
// 因为如果正在显示quickEdit的窗口,再次点击快速编辑不会重新创建dom,这个函数将所有快速编辑按钮在打开quickEdit前销毁页面上的已有的quickEdit
function rebindEventForOpenQuickEditBtn() {
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)
})
}
function observerCb(record) {
var quickEdit = null
var quickEditTextarea = $('#Wikiplus-Quickedit')
$.each(record[0].addedNodes, function(item, element){
if(element.classList && element.classList.contains('Wikiplus-InterBox')){
quickEdit = element
}
})
if (quickEdit === null) { return }
editorManager.textarea = quickEditTextarea
injectOpenDialogButton()
}
function main() {
if (checkRequiredApi() === false) {
alert('你使用的浏览器暂不支持该插件,请更换浏览器或将该插件移除!')
return
}
// 初始化dom变化观察者对象,监听Wikiplus-Quickedit的插入
var observer = new MutationObserver(observerCb)
observer.observe(document.body, { childList: true })
addPatternDialogManager.init()
rebindEventForOpenQuickEditBtn()
}
$(main)