注意:在您儲存之後您必須清除瀏覽器快取才可看到最新的變動。
?_=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('http://zh.moegirl.tw'+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)