User:ChasingAir/js/fixCat.js
外观
注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google Chrome、Firefox、Microsoft Edge及Safari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
//<nowiki>
(function($, mw, OO) {
'use strict';
if (!window.OO || !OO.ui) {
mw.loader.using('oojs-ui-windows').then(function() {
init();
});
} else {
init();
}
function init() {
var categoryName = 'Category:图像尺寸大小带有额外px字符的页面';
if (mw.config.get('wgPageName') !== categoryName.replace(/ /g, '_')) {
return;
}
mw.util.addPortletLink(
'p-tb',
'#',
'清理px',
'ca-fixcat',
'清理图像尺寸px字符'
);
$('#ca-fixcat').on('click', function(e) {
e.preventDefault();
showCleanupDialog();
});
}
function CleanupDialog(config) {
CleanupDialog.parent.call(this, config);
this.pages = [];
this.currentPage = null;
this.wikitext = '';
this.baseRevId = null;
this.matches = [];
this.currentMatchIndex = -1;
}
OO.inheritClass(CleanupDialog, OO.ui.ProcessDialog);
CleanupDialog.static.name = 'cleanupDialog';
CleanupDialog.static.title = '清理图像尺寸px字符';
CleanupDialog.static.size = 'full';
CleanupDialog.static.actions = [
{
action: 'close',
label: '关闭',
flags: 'safe'
}
];
CleanupDialog.prototype.initialize = function() {
CleanupDialog.parent.prototype.initialize.apply(this, arguments);
var dialog = this;
this.$mainContainer = $('<div>').css({
'display': 'flex',
'height': '700px',
'gap': '15px'
});
this.$pageList = $('<div>').css({
'width': '250px',
'min-width': '250px',
'border': '1px solid #ccc',
'padding': '10px',
'overflow-y': 'auto',
'background': '#f9f9f9'
});
this.$editorArea = $('<div>').css({
'flex': '1',
'display': 'flex',
'flex-direction': 'column',
'gap': '10px'
});
// Wikitext显示区域
this.$wikitextContainer = $('<div>').css({
'flex': '1',
'border': '1px solid #ccc',
'padding': '10px',
'overflow': 'auto',
'background': '#fff',
'font-family': 'monospace',
'white-space': 'pre-wrap',
'position': 'relative'
});
this.$controls = $('<div>').css({
'display': 'flex',
'gap': '10px',
'align-items': 'center'
});
// 搜索按钮
this.searchButton = new OO.ui.ButtonWidget({
label: '搜索px',
flags: ['progressive']
});
this.prevButton = new OO.ui.ButtonWidget({
label: '上一个',
disabled: true
});
this.nextButton = new OO.ui.ButtonWidget({
label: '下一个',
disabled: true
});
this.removeButton = new OO.ui.ButtonWidget({
label: '去除px',
flags: ['destructive'],
disabled: true
});
this.$matchCount = $('<span>').css({
'margin-left': '10px',
'color': '#666'
});
this.$controls.append(
this.searchButton.$element,
this.prevButton.$element,
this.nextButton.$element,
this.removeButton.$element,
this.$matchCount
);
this.$submitArea = $('<div>').css({
'width': '200px',
'min-width': '200px',
'display': 'flex',
'flex-direction': 'column',
'gap': '10px'
});
this.summaryInput = new OO.ui.TextInputWidget({
placeholder: '编辑摘要',
value: '清理图像尺寸中的多余px字符'
});
this.submitButton = new OO.ui.ButtonWidget({
label: '提交',
flags: ['primary', 'progressive'],
disabled: true
});
this.$submitArea.append(
$('<label>').text('编辑摘要:'),
this.summaryInput.$element,
this.submitButton.$element
);
this.$editorArea.append(
this.$wikitextContainer,
this.$controls
);
this.$mainContainer.append(
this.$pageList,
this.$editorArea,
this.$submitArea
);
this.$body.append(this.$mainContainer);
this.searchButton.on('click', this.searchMatches.bind(this));
this.prevButton.on('click', this.showPrevMatch.bind(this));
this.nextButton.on('click', this.showNextMatch.bind(this));
this.removeButton.on('click', this.removeCurrentPx.bind(this));
this.submitButton.on('click', this.submitEdit.bind(this));
this.loadPages();
};
CleanupDialog.prototype.getBodyHeight = function() {
return 750;
};
// 加载分类下的页面
CleanupDialog.prototype.loadPages = function() {
var dialog = this;
this.$pageList.html('<div>加载中...</div>');
var api = new mw.Api();
api.get({
action: 'query',
list: 'categorymembers',
cmtitle: 'Category:图像尺寸大小带有额外px字符的页面',
cmlimit: 100,
format: 'json',
formatversion: 2
}).done(function(data) {
if (data.query && data.query.categorymembers && data.query.categorymembers.length > 0) {
var mainNamespacePages = data.query.categorymembers.filter(function(page) {
return page.ns === 0;
}).slice(0, 10);
if (mainNamespacePages.length > 0) {
dialog.pages = mainNamespacePages;
dialog.renderPageList();
} else {
dialog.$pageList.html('<div>未找到主条目空间的页面</div>');
}
} else {
dialog.$pageList.html('<div>未找到页面</div>');
}
}).fail(function(error) {
dialog.$pageList.html('<div>加载失败: ' + error + '</div>');
});
};
CleanupDialog.prototype.renderPageList = function() {
var dialog = this;
this.$pageList.empty();
if (this.pages.length === 0) {
this.$pageList.html('<div>暂无页面</div>');
return;
}
this.pages.forEach(function(page) {
var $pageItem = $('<div>').css({
'padding': '8px',
'margin': '5px 0',
'cursor': 'pointer',
'border': '1px solid #ddd',
'border-radius': '3px',
'background': '#fff',
'word-wrap': 'break-word'
}).text(page.title).on('click', function() {
dialog.$pageList.find('div').css('background', '#fff');
$(this).css('background', '#e6f3ff');
dialog.loadPageContent(page.title);
});
dialog.$pageList.append($pageItem);
});
};
// 加载页面内容
CleanupDialog.prototype.loadPageContent = function(pageTitle) {
var dialog = this;
this.currentPage = pageTitle;
this.$wikitextContainer.html('加载中...');
this.submitButton.setDisabled(true);
this.matches = [];
this.currentMatchIndex = -1;
this.updateMatchCount();
var api = new mw.Api();
api.get({
action: 'query',
titles: pageTitle,
prop: 'revisions',
rvprop: 'content|ids',
rvslots: 'main',
format: 'json'
}).done(function(data) {
var pages = data.query.pages;
var pageId = Object.keys(pages)[0];
var page = pages[pageId];
if (page.revisions && page.revisions[0]) {
dialog.wikitext = page.revisions[0].slots.main['*'];
dialog.baseRevId = page.revisions[0].revid;
dialog.renderWikitext();
dialog.submitButton.setDisabled(false);
} else {
dialog.$wikitextContainer.html('无法加载页面内容');
}
}).fail(function() {
dialog.$wikitextContainer.html('加载失败');
});
};
// 渲染Wikitext
CleanupDialog.prototype.renderWikitext = function() {
this.$wikitextContainer.html($('<div>').text(this.wikitext));
};
CleanupDialog.prototype.searchMatches = function() {
var dialog = this;
this.matches = [];
this.currentMatchIndex = -1;
var regex = /\{\{[^}]*?\d+px[^}]*?\}\}/g;
var match;
while ((match = regex.exec(this.wikitext)) !== null) {
var templateText = match[0];
var innerRegex = /(\d+)(px)/g;
var innerMatch;
var templateStart = match.index;
while ((innerMatch = innerRegex.exec(templateText)) !== null) {
this.matches.push({
start: templateStart + innerMatch.index,
end: templateStart + innerMatch.index + innerMatch[0].length,
text: innerMatch[0],
numberPart: innerMatch[1],
pxPart: innerMatch[2]
});
}
}
if (this.matches.length > 0) {
this.currentMatchIndex = 0;
this.highlightCurrentMatch();
this.prevButton.setDisabled(false);
this.nextButton.setDisabled(false);
this.removeButton.setDisabled(false);
} else {
mw.notify('未找到匹配项', { type: 'warn' });
this.renderWikitext();
this.prevButton.setDisabled(true);
this.nextButton.setDisabled(true);
this.removeButton.setDisabled(true);
}
this.updateMatchCount();
};
CleanupDialog.prototype.highlightCurrentMatch = function() {
if (this.currentMatchIndex < 0 || this.currentMatchIndex >= this.matches.length) {
return;
}
var parts = [];
var lastEnd = 0;
this.matches.forEach(function(match, index) {
if (match.start > lastEnd) {
parts.push($('<span>').text(this.wikitext.substring(lastEnd, match.start)));
}
var $highlight = $('<span>').text(match.text).css({
'background-color': index === this.currentMatchIndex ? '#ffff00' : '#ffeb3b',
'font-weight': index === this.currentMatchIndex ? 'bold' : 'normal',
'padding': '2px 4px',
'border-radius': '3px'
});
if (index === this.currentMatchIndex) {
$highlight.attr('id', 'current-match');
}
parts.push($highlight);
lastEnd = match.end;
}, this);
if (lastEnd < this.wikitext.length) {
parts.push($('<span>').text(this.wikitext.substring(lastEnd)));
}
this.$wikitextContainer.empty();
parts.forEach(function(part) {
this.$wikitextContainer.append(part);
}, this);
var $current = this.$wikitextContainer.find('#current-match');
if ($current.length) {
$current[0].scrollIntoView({ behavior: 'smooth', block: 'center' });
}
this.updateMatchCount();
};
CleanupDialog.prototype.showPrevMatch = function() {
if (this.currentMatchIndex > 0) {
this.currentMatchIndex--;
this.highlightCurrentMatch();
}
};
CleanupDialog.prototype.showNextMatch = function() {
if (this.currentMatchIndex < this.matches.length - 1) {
this.currentMatchIndex++;
this.highlightCurrentMatch();
}
};
CleanupDialog.prototype.updateMatchCount = function() {
if (this.matches.length > 0) {
this.$matchCount.text('匹配: ' + (this.currentMatchIndex + 1) + ' / ' + this.matches.length);
} else {
this.$matchCount.text('');
}
};
CleanupDialog.prototype.removeCurrentPx = function() {
if (this.currentMatchIndex < 0 || this.currentMatchIndex >= this.matches.length) {
return;
}
var currentMatch = this.matches[this.currentMatchIndex];
this.wikitext = this.wikitext.substring(0, currentMatch.start) +
currentMatch.numberPart +
this.wikitext.substring(currentMatch.end);
var removedLength = currentMatch.pxPart.length;
this.matches.splice(this.currentMatchIndex, 1);
for (var i = this.currentMatchIndex; i < this.matches.length; i++) {
this.matches[i].start -= removedLength;
this.matches[i].end -= removedLength;
}
if (this.currentMatchIndex >= this.matches.length && this.matches.length > 0) {
this.currentMatchIndex = this.matches.length - 1;
}
if (this.matches.length === 0) {
this.currentMatchIndex = -1;
this.renderWikitext();
this.prevButton.setDisabled(true);
this.nextButton.setDisabled(true);
this.removeButton.setDisabled(true);
mw.notify('所有px已清理完毕', { type: 'success' });
} else {
this.highlightCurrentMatch();
}
this.updateMatchCount();
};
CleanupDialog.prototype.submitEdit = function() {
var dialog = this;
if (!this.currentPage || !this.baseRevId) {
mw.notify('请先选择一个页面', { type: 'error' });
return;
}
this.submitButton.setDisabled(true);
this.submitButton.setLabel('提交中...');
var api = new mw.Api();
api.postWithToken('csrf', {
action: 'edit',
title: this.currentPage,
text: this.wikitext,
summary: this.summaryInput.getValue(),
baserevid: this.baseRevId,
format: 'json'
}).done(function(data) {
if (data.edit && data.edit.result === 'Success') {
mw.notify('编辑成功!', { type: 'success' });
dialog.pages = dialog.pages.filter(function(page) {
return page.title !== dialog.currentPage;
});
dialog.renderPageList();
dialog.$wikitextContainer.html('请从左侧选择一个页面');
dialog.currentPage = null;
dialog.submitButton.setDisabled(true);
} else {
mw.notify('编辑失败: ' + (data.error ? data.error.info : '未知错误'), { type: 'error' });
dialog.submitButton.setDisabled(false);
}
dialog.submitButton.setLabel('提交');
}).fail(function(code, data) {
var errorMsg = '编辑失败';
if (code === 'editconflict') {
errorMsg = '编辑冲突,页面已被他人修改';
} else if (data && data.error) {
errorMsg = data.error.info;
}
mw.notify(errorMsg, { type: 'error' });
dialog.submitButton.setDisabled(false);
dialog.submitButton.setLabel('提交');
});
};
CleanupDialog.prototype.getActionProcess = function(action) {
var dialog = this;
if (action === 'close') {
return new OO.ui.Process(function() {
dialog.close({ action: action });
});
}
return CleanupDialog.parent.prototype.getActionProcess.call(this, action);
};
function showCleanupDialog() {
var windowManager = new OO.ui.WindowManager();
$(document.body).append(windowManager.$element);
var dialog = new CleanupDialog({
size: 'full'
});
windowManager.addWindows([dialog]);
windowManager.openWindow(dialog);
}
})(jQuery, mediaWiki, OO);
//</nowiki>