MediaWiki:Gadget-Cat-a-lot.js:修订间差异
外观
删除的内容 添加的内容
移植自 Qiuwen v6.0;修复搜索默认分类、URL 正则、移除不存在的 change tag |
|||
| 第1行: | 第1行: | ||
/** |
/** |
||
* SPDX-License-Identifier: CC-BY-SA-4.0 |
|||
* Cat-A-Lot |
|||
* _addText: '{{Gadget Header|title1=Cat-a-lot.js|license=CC-BY-SA-4.0}}' |
|||
* Changes category of multiple files |
|||
* |
* |
||
* Cat-a-lot |
|||
* Originally by Magnus Manske |
|||
* RegExes by Ilmari Karonen |
|||
* Completely rewritten by DieBuche |
|||
* |
* |
||
* @base {@link https://zh.wikipedia.org/wiki/MediaWiki:Gadget-Cat-a-lot.js} |
|||
* Requires [[MediaWiki:Gadget-SettingsManager.js]] and [[MediaWiki:Gadget-SettingsUI.js]] (properly registered) for per-user-settings |
|||
* @base {@link https://commons.wikimedia.org/wiki/MediaWiki:Gadget-Cat-a-lot.js} |
|||
* |
|||
* @source {@link https://git.qiuwen.net.cn/InterfaceAdmin/QiuwenGadgets/src/branch/master/src/Cat-a-lot/modules/core.ts} |
|||
* READ THIS PAGE IF YOU WANT TO TRANSLATE OR USE THIS ON ANOTHER SITE: |
|||
* @author Magnus Manske, Ilmari Karonen, DieBuche, 安忆 <i@anyi.in> |
|||
* http://commons.wikimedia.org/wiki/MediaWiki:Gadget-Cat-a-lot.js/translating |
|||
* @license CC-BY-SA-4.0 {@link https://www.qiuwenbaike.cn/wiki/H:CC-BY-SA-4.0} |
|||
* <nowiki> |
|||
*/ |
*/ |
||
/*global jQuery:false, mediaWiki:false, alert:false, importStylesheet:false */ |
|||
/*jshint curly:false, unused:true, unused:true, forin:false, smarttabs:true, loopfunc:true, browser:true */ |
|||
( function( $, mw ) { |
|||
'use strict'; |
|||
var nsNumber = mw.config.get( 'wgNamespaceNumber' ), |
|||
nsCat = 14, |
|||
currentCat = mw.config.get( 'wgTitle' ), |
|||
formattedNS = mw.config.get( 'wgFormattedNamespaces' ), |
|||
nsIDs = mw.config.get( 'wgNamespaceIds' ), |
|||
catALot; |
|||
var msgs = { |
|||
// Preferences |
|||
// new: added 2012-09-19. Please translate. |
|||
// Use user language for i18n |
|||
'cat-a-lot-watchlistpref': "Watchlist preference concerning files edited with Cat-A-Lot", |
|||
'cat-a-lot-watch_pref': "According to your general preferences", |
|||
'cat-a-lot-watch_nochange': "Do not change watchstatus", |
|||
'cat-a-lot-watch_watch': "Watch pages edited with Cat-A-Lot", |
|||
'cat-a-lot-watch_unwatch': "Remove pages while editing with Cat-A-Lot from your watchlist", |
|||
'cat-a-lot-minorpref': "Mark edits as minor (if you generally mark your edits as minor, this won't change anything)", |
|||
'cat-a-lot-editpagespref': "Allow categorising pages (including categories) that are not files", |
|||
'cat-a-lot-docleanuppref': "Remove {{Check categories}} and other minor cleanup", |
|||
'cat-a-lot-subcatcountpref': "Sub-categories to show at most", |
|||
'cat-a-lot-config-settings': "Preferences", |
|||
// Use site language for i18n |
|||
'cat-a-lot-pref-save-summary': "[[Help:Gadget-Cat-a-lot|Cat-a-lot]] is updating user preferences", |
|||
//Progress |
|||
'cat-a-lot-loading': 'Loading...', |
|||
'cat-a-lot-editing': 'Editing page', |
|||
'cat-a-lot-of': 'of ', |
|||
'cat-a-lot-skipped-already': 'The following {{PLURAL:$1|page was|$1 pages were}} skipped, because the page was already in the category:', |
|||
'cat-a-lot-skipped-not-found': 'The following {{PLURAL:$1|page was|$1 pages were}} skipped, because the old category could not be found:', |
|||
'cat-a-lot-skipped-server': 'The following {{PLURAL:$1|page|$1 pages}} couldn\'t be changed, since there were problems connecting to the server:', |
|||
'cat-a-lot-all-done': 'All pages are processed.', |
|||
'cat-a-lot-done': 'Done!', |
|||
'cat-a-lot-added-cat': 'Added category $1', |
|||
'cat-a-lot-copied-cat': 'Copied to category $1', |
|||
'cat-a-lot-moved-cat': 'Moved to category $1', |
|||
'cat-a-lot-removed-cat': 'Removed from category $1', |
|||
'cat-a-lot-return-to-page': 'Return to page', |
|||
'cat-a-lot-cat-not-found': 'Category not found.', |
|||
//as in 17 files selected |
|||
'cat-a-lot-files-selected': '{{PLURAL:$1|One file|$1 files}} selected.', |
|||
//Actions |
|||
'cat-a-lot-copy': 'Copy', |
|||
'cat-a-lot-move': 'Move', |
|||
'cat-a-lot-add': 'Add', |
|||
'cat-a-lot-remove-from-cat': 'Remove from this category', |
|||
'cat-a-lot-enter-name': 'Enter category name', |
|||
'cat-a-lot-select': 'Select', |
|||
'cat-a-lot-all': 'all', |
|||
'cat-a-lot-none': 'none', |
|||
'cat-a-lot-none-selected': 'No files selected!', |
|||
//Summaries: |
|||
'cat-a-lot-summary-add': '[[Help:Cat-a-lot|Cat-a-lot]]: Adding [[Category:$1]]', |
|||
'cat-a-lot-summary-copy': '[[Help:Cat-a-lot|Cat-a-lot]]: Copying from [[Category:$1]] to [[Category:$2]]', |
|||
'cat-a-lot-summary-move': '[[Help:Cat-a-lot|Cat-a-lot]]: Moving from [[Category:$1]] to [[Category:$2]]', |
|||
'cat-a-lot-summary-remove': '[[Help:Cat-a-lot|Cat-a-lot]]: Removing from [[Category:$1]]' |
|||
}; |
|||
mw.messages.set( msgs ); |
|||
function msg( /*params*/ ) { |
|||
var args = Array.prototype.slice.call( arguments, 0 ); |
|||
args[0] = 'cat-a-lot-' + args[0]; |
|||
return mw.message.apply( mw.message, args ).parse(); |
|||
} |
|||
function msgPlain( key ) { |
|||
return mw.message( 'cat-a-lot-' + key ).plain(); |
|||
} |
|||
// There is only one cat-a-lot on one page |
|||
var $removeLink, |
|||
$body, $container, $dataContainer, $searchInputContainer, $searchInput, $resultList, $markCounter, |
|||
$selections, $selectAll, $selectNone, $settingsWrapper, $settingsLink, $head, $link; |
|||
catALot = window.catALot = { |
|||
apiUrl: mw.util.wikiScript( 'api' ), |
|||
searchmode: false, |
|||
version: 3.5, |
|||
setHeight: 450, |
|||
settings: {}, |
|||
_variantCache: {}, |
|||
init: function() { |
|||
this._initSettings(); |
|||
$body = $( document.body ); |
|||
$container = $( '<div id="cat_a_lot"></div>' ) |
|||
.appendTo( $body ); |
|||
$dataContainer = $( '<div id="cat_a_lot_data"></div>' ) |
|||
.appendTo( $container ); |
|||
$searchInputContainer = $( '<div>' ) |
|||
.appendTo( $dataContainer ); |
|||
$searchInput = $( '<input type="text" id="cat_a_lot_searchcatname" />' ) |
|||
.attr( 'placeholder', msgPlain( 'enter-name' ) ) |
|||
.appendTo( $searchInputContainer ); |
|||
$resultList = $( '<div id="cat_a_lot_category_list"></div>' ) |
|||
.appendTo( $dataContainer ); |
|||
$markCounter = $( '<div id="cat_a_lot_mark_counter"> </div>' ) |
|||
.appendTo( $dataContainer ); |
|||
$selections = $( '<div id="cat_a_lot_selections"></div>' ) |
|||
.text( msgPlain( 'select' ) ) |
|||
.appendTo( $dataContainer ); |
|||
$selectAll = $( '<a id="cat_a_lot_select_all"></a>' ) |
|||
.text( msgPlain( 'all' ) ) |
|||
.appendTo( $selections.append(' ') ); |
|||
$selectNone = $( '<a id="cat_a_lot_select_none"></a>' ) |
|||
.text( msgPlain( 'none' ) ) |
|||
.appendTo( $selections.append(' • ') ); |
|||
$settingsWrapper = $( '<div id="cat_a_lot_settings"></div>' ) |
|||
.appendTo( $dataContainer ); |
|||
$settingsLink = $( '<a id="cat_a_lot_config_settings"></a>' ) |
|||
.text( msgPlain( 'config-settings' ) ) |
|||
.appendTo( $settingsWrapper ); |
|||
$head = $( '<div id="cat_a_lot_head"></div>' ) |
|||
.appendTo( $container ); |
|||
$link = $( '<a id="cat_a_lot_toggle"></a>' ) |
|||
.text( 'Cat-a-lot' ) |
|||
.appendTo( $head ); |
|||
if ( !this.searchmode ) { |
|||
$removeLink = $( '<a id="cat_a_lot_remove"></a>' ) |
|||
.html( msg( 'remove-from-cat' ) ) |
|||
.appendTo( $selections ) |
|||
.click( function() { |
|||
catALot.remove(); |
|||
} ); |
|||
} |
|||
if ( ( 'MediaWiki:Gadget-Cat-a-lot.js' === mw.util.getParamValue( 'withJS' ) && |
|||
!mw.util.getParamValue( 'withCSS' ) ) || |
|||
mw.loader.getState('ext.gadget.Cat-a-lot') === 'registered' ) { |
|||
importStylesheet( 'MediaWiki:Gadget-Cat-a-lot.css' ); |
|||
} |
|||
var reCat = new RegExp( '^\\s*' + catALot.localizedRegex( nsCat, 'Category' ) + ':', '' ); |
|||
$searchInput.keypress( function( e ) { |
|||
if ( e.which === 13 ) { |
|||
catALot.updateCats( $.trim( $( this ) |
|||
.val() ) ); |
|||
} |
|||
} ) |
|||
.on( 'input keyup', function() { |
|||
var oldVal = this.value, |
|||
newVal = oldVal.replace( reCat, '' ); |
|||
if ( newVal !== oldVal ) this.value = newVal; |
|||
} ); |
|||
if ( this.searchmode ) { |
|||
$searchInput.val( mw.util.getParamValue( 'search' ) ); |
|||
} |
|||
function initAutocomplete() { |
|||
if ( catALot.autoCompleteIsEnabled ) return; |
|||
catALot.autoCompleteIsEnabled = true; |
|||
$searchInput.autocomplete( { |
|||
source: function( request, response ) { |
|||
catALot.doAPICall( { |
|||
action: 'opensearch', |
|||
search: request.term, |
|||
namespace: nsCat |
|||
}, function( data ) { |
|||
if ( data[ 1 ] ) response( $( data[ 1 ] ) |
|||
.map( function( index, item ) { |
|||
return item.replace( reCat, '' ); |
|||
} ) ); |
|||
} ); |
|||
}, |
|||
open: function() { |
|||
$( ".ui-autocomplete" ) |
|||
.position( { |
|||
my: $( 'body' ) |
|||
.is( '.rtl' ) ? "left bottom" : "right bottom", |
|||
at: $( 'body' ) |
|||
.is( '.rtl' ) ? "left top" : "right top", |
|||
of: $searchInput |
|||
} ); |
|||
}, |
|||
appendTo: '#cat_a_lot' |
|||
} ); |
|||
} |
|||
$selectAll |
|||
.click( function() { |
|||
catALot.toggleAll( true ); |
|||
} ); |
|||
$selectNone |
|||
.click( function() { |
|||
catALot.toggleAll( false ); |
|||
} ); |
|||
$link |
|||
.click( function() { |
|||
$( this ).toggleClass( 'cat_a_lot_enabled' ); |
|||
// Load autocomplete on demand |
|||
mw.loader.using( ['jquery.ui'], initAutocomplete ); |
|||
catALot.run(); |
|||
} ); |
|||
$settingsLink |
|||
.click( function() { |
|||
catALot.manageSettings(); |
|||
} ); |
|||
this.localCatName = formattedNS[ nsCat ]; |
|||
}, |
|||
findAllLabels: function() { |
|||
// It's possible to allow any kind of pages as well but what happens if you click on "select all" and don't expect it |
|||
if ( this.searchmode ) { |
|||
this.labels = $( 'table.searchResultImage' ) |
|||
.find( 'tr>td:eq(1)' ); |
|||
if ( this.settings.editpages ) { |
|||
this.labels = this.labels.add( 'div.mw-search-result-heading' ); |
|||
} |
|||
} else { |
|||
this.labels = $( 'div.gallerytext' ) |
|||
.add( $( 'div#mw-category-media' ) |
|||
.find( 'li[class!="gallerybox"]' ) ); |
|||
if ( this.settings.editpages ) { |
|||
var $pgs = $( 'div#mw-pages, div#mw-subcategories' ) |
|||
.find( 'li' ); |
|||
this.labels = this.labels.add( $pgs ); |
|||
} |
|||
} |
|||
}, |
|||
getTitleFromLink: function( href ) { |
|||
try { |
|||
return decodeURIComponent( href ) |
|||
.match( /wiki\/(.+?)(?:#.+)?$/ )[ 1 ].replace( /_/g, ' ' ); |
|||
} catch ( ex ) { |
|||
return ''; |
|||
} |
|||
}, |
|||
getMarkedLabels: function() { |
|||
var marked = []; |
|||
this.selectedLabels = this.labels.filter( '.cat_a_lot_selected' ); |
|||
this.selectedLabels.each( function() { |
|||
var file = $( this ) |
|||
.find( 'a[title]' ), |
|||
title = file.attr( 'title' ) || catALot.getTitleFromLink( file.attr( 'href' ) ) || catALot.getTitleFromLink( $( this ) |
|||
.find( 'a' ) |
|||
.attr( 'href' ) ); |
|||
marked.push( [ title, $( this ) ] ); |
|||
} ); |
|||
return marked; |
|||
}, |
|||
updateSelectionCounter: function() { |
|||
this.selectedLabels = this.labels.filter( '.cat_a_lot_selected' ); |
|||
$markCounter |
|||
.show() |
|||
.html( msg( 'files-selected', this.selectedLabels.length ) ); |
|||
}, |
|||
makeClickable: function() { |
|||
this.findAllLabels(); |
|||
this.labels.catALotShiftClick( function() { |
|||
catALot.updateSelectionCounter(); |
|||
} ) |
|||
.addClass( 'cat_a_lot_label' ); |
|||
}, |
|||
toggleAll: function( select ) { |
|||
this.labels.toggleClass( 'cat_a_lot_selected', select ); |
|||
this.updateSelectionCounter(); |
|||
}, |
|||
getSubCats: function() { |
|||
var data = { |
|||
action: 'query', |
|||
list: 'categorymembers', |
|||
cmtype: 'subcat', |
|||
cmlimit: this.settings.subcatcount, |
|||
cmtitle: 'Category:' + this.currentCategory |
|||
}; |
|||
this.doAPICall( data, function( result ) { |
|||
var cats = result.query.categorymembers; |
|||
catALot.subCats = []; |
|||
for ( var i = 0; i < cats.length; i++ ) { |
|||
catALot.subCats.push( cats[ i ].title.replace( /^[^:]+:/, "" ) ); |
|||
} |
|||
catALot.catCounter++; |
|||
if ( catALot.catCounter === 2 ) catALot.showCategoryList(); |
|||
} ); |
|||
}, |
|||
getParentCats: function() { |
|||
var data = { |
|||
action: 'query', |
|||
prop: 'categories', |
|||
titles: 'Category:' + this.currentCategory |
|||
}; |
|||
this.doAPICall( data, function( result ) { |
|||
catALot.parentCats = []; |
|||
var cats, pages = result.query.pages; |
|||
if ( pages[ -1 ] && pages[ -1 ].missing === '' ) { |
|||
$resultList.html( '<span id="cat_a_lot_no_found">' + msg( 'cat-not-found' ) + '</span>' ); |
|||
document.body.style.cursor = 'auto'; |
|||
$resultList.append( '<table></table>' ); |
|||
catALot.createCatLinks( "→", [ catALot.currentCategory ] ); |
|||
return; |
|||
} |
|||
// there should be only one, but we don't know its ID |
|||
for ( var id in pages ) { |
|||
cats = pages[ id ].categories; |
|||
} |
|||
for ( var i = 0; i < cats.length; i++ ) { |
|||
catALot.parentCats.push( cats[ i ].title.replace( /^[^:]+:/, "" ) ); |
|||
} |
|||
catALot.catCounter++; |
|||
if ( catALot.catCounter === 2 ) catALot.showCategoryList(); |
|||
} ); |
|||
}, |
|||
localizedRegex: function( namespaceNumber, fallback ) { |
|||
//Copied from HotCat. Thanks Lupo. |
|||
var wikiTextBlank = '[\\t _\\xA0\\u1680\\u180E\\u2000-\\u200A\\u2028\\u2029\\u202F\\u205F\\u3000]+'; |
|||
var wikiTextBlankRE = new RegExp( wikiTextBlank, 'g' ); |
|||
var createRegexStr = function( name ) { |
|||
if ( !name || name.length === 0 ) return ""; |
|||
var regex_name = ""; |
|||
for ( var i = 0; i < name.length; i++ ) { |
|||
var initial = name.substr( i, 1 ); |
|||
var ll = initial.toLowerCase(); |
|||
var ul = initial.toUpperCase(); |
|||
if ( ll === ul ) { |
|||
regex_name += initial; |
|||
} else { |
|||
regex_name += '[' + ll + ul + ']'; |
|||
} |
|||
} |
|||
return regex_name.replace( /([\\\^\$\.\?\*\+\(\)])/g, '\\$1' ) |
|||
.replace( wikiTextBlankRE, wikiTextBlank ); |
|||
}; |
|||
fallback = fallback.toLowerCase(); |
|||
var canonical = formattedNS[ namespaceNumber ].toLowerCase(); |
|||
var RegexString = createRegexStr( canonical ); |
|||
if ( fallback && canonical !== fallback ) RegexString += '|' + createRegexStr( fallback ); |
|||
for ( var catName in nsIDs ) { |
|||
if ( typeof( catName ) === 'string' && catName.toLowerCase() !== canonical && catName.toLowerCase() !== fallback && nsIDs[ catName ] === namespaceNumber ) { |
|||
RegexString += '|' + createRegexStr( catName ); |
|||
} |
|||
} |
|||
return ( '(?:' + RegexString + ')' ); |
|||
}, |
|||
findAllVariants: function( category ) { |
|||
var result = [], |
|||
baseUrl = '/w/api.php?action=parse&text=' + encodeURIComponent(category) + '&title=temp&format=json&variant='; |
|||
if ( this._variantCache[category] !== undefined ) { |
|||
return this._variantCache[category]; |
|||
} |
|||
$.each( ['zh-hans', 'zh-hant', 'zh-cn', 'zh-tw', 'zh-hg', 'zh-mo'], function( idx, variant ) { |
|||
var r = ( $( $.ajax( { url: baseUrl + variant, async: false } ) |
|||
.responseJSON.parse.text['*'] ) |
|||
.get( 0 ).textContent.trim() ); |
|||
if ( result.indexOf( r ) === -1 ) { |
|||
result.push( r ); |
|||
} |
|||
} ); |
|||
this._variantCache[category] = result; |
|||
return result; |
|||
}, |
|||
regexBuilder: function( category ) { |
|||
var variants, |
|||
catname = this.localizedRegex( nsCat, 'Category' ); |
|||
// Build a regexp string for matching the given category: |
|||
// trim leading/trailing whitespace and underscores |
|||
category = category.replace( /^[\s_]+/, "" ) |
|||
.replace( /[\s_]+$/, "" ); |
|||
// Find all variants |
|||
variants = this.findAllVariants( category ); |
|||
// escape regexp metacharacters (= any ASCII punctuation except _) |
|||
category = []; |
|||
$.each( variants, function( idx, variant ) { |
|||
variant = mw.RegExp.escape( variant ); |
|||
// any sequence of spaces and underscores should match any other |
|||
variant = variant.replace( /[\s_]+/g, '[\\s_]+' ); |
|||
// Make the first character case-insensitive: |
|||
var first = variant.substr( 0, 1 ); |
|||
if ( first.toUpperCase() !== first.toLowerCase() ) { |
|||
variant = '[' + first.toUpperCase() + first.toLowerCase() + ']' + variant.substr( 1 ); |
|||
} |
|||
category.push( variant ); |
|||
} ); |
|||
// Compile it into a RegExp that matches MediaWiki category syntax (yeah, it looks ugly): |
|||
// XXX: the first capturing parens are assumed to match the sortkey, if present, including the | but excluding the ]] |
|||
return new RegExp( '\\[\\[[\\s_]*' + catname + '[\\s_]*:[\\s_]*(?:' + category.join( '|' ) + ')[\\s_]*(\\|[^\\]]*(?:\\][^\\]]+)*)?\\]\\]', 'g' ); |
|||
}, |
|||
getContent: function( file, targetcat, mode ) { |
|||
var data = { |
|||
action: 'query', |
|||
prop: 'info|revisions', |
|||
rvprop: 'content|timestamp', |
|||
meta: 'tokens', |
|||
titles: file[ 0 ] |
|||
}; |
|||
this.doAPICall( data, function( result ) { |
|||
catALot.editCategories( result, file, targetcat, mode ); |
|||
} ); |
|||
}, |
|||
// Remove {{Uncategorized}}. No need to replace it with anything. |
|||
removeUncat: function( text ) { |
|||
return text.replace( /\{\{\s*[Uu]ncategorized\s*(\|?.*?)\}\}/, "" ); |
|||
}, |
|||
doCleanup: function( text ) { |
|||
if ( this.settings.docleanup ) { |
|||
return text.replace( /\{\{\s*[Ch]eck categories\s*(\|?.*?)\}\}/, "" ); |
|||
} else { |
|||
return text; |
|||
} |
|||
}, |
|||
editCategories: function( result, file, targetcat, mode ) { |
|||
var otext, starttimestamp, timestamp; |
|||
if ( !result ) { |
|||
//Happens on unstable wifi connections.. |
|||
this.connectionError.push( file[ 0 ] ); |
|||
this.updateCounter(); |
|||
return; |
|||
} |
|||
this.edittoken = result.query.tokens.csrftoken; |
|||
var pages = result.query.pages; |
|||
// there should be only one, but we don't know its ID |
|||
for ( var id in pages ) { |
|||
otext = pages[ id ].revisions[ 0 ][ '*' ]; |
|||
starttimestamp = pages[ id ].starttimestamp; |
|||
timestamp = pages[ id ].revisions[ 0 ].timestamp; |
|||
} |
|||
var sourcecat = currentCat; |
|||
// Check if that file is already in that category |
|||
if ( mode !== "remove" && this.regexBuilder( targetcat ) |
|||
.test( otext ) ) { |
|||
//If the new cat is already there, just remove the old one. |
|||
if ( mode === 'move' ) { |
|||
mode = 'remove'; |
|||
} else { |
|||
this.alreadyThere.push( file[ 0 ] ); |
|||
this.updateCounter(); |
|||
return; |
|||
} |
|||
} |
|||
var text = otext; |
|||
var comment; |
|||
// Fix text |
|||
switch ( mode ) { |
|||
case 'add': |
|||
text += "\n[[" + this.localCatName + ":" + targetcat + "]]\n"; |
|||
comment = msgPlain( 'summary-add' ).replace( '$1', targetcat ); |
|||
break; |
|||
case 'copy': |
|||
text = text.replace( this.regexBuilder( sourcecat ), "[[" + this.localCatName + ":" + sourcecat + "$1]]\n[[" + this.localCatName + ":" + targetcat + "$1]]" ); |
|||
comment = msgPlain( 'summary-copy' ).replace( '$1', sourcecat ).replace( '$2', targetcat ); |
|||
//If category is added through template: |
|||
if ( otext === text ) { |
|||
text += "\n[[" + this.localCatName + ":" + targetcat + "]]"; |
|||
} |
|||
break; |
|||
case 'move': |
|||
text = text.replace( this.regexBuilder( sourcecat ), "[[" + this.localCatName + ":" + targetcat + "$1]]" ); |
|||
comment = msgPlain( 'summary-move' ).replace( '$1', sourcecat ).replace( '$2', targetcat ); |
|||
break; |
|||
case 'remove': |
|||
text = text.replace( this.regexBuilder( sourcecat ), "" ); |
|||
comment = msgPlain( 'summary-remove' ).replace( '$1', sourcecat ); |
|||
break; |
|||
} |
|||
if ( text === otext ) { |
|||
this.notFound.push( file[ 0 ] ); |
|||
this.updateCounter(); |
|||
return; |
|||
} |
|||
// Remove uncat after we checked whether we changed the text successfully. |
|||
// Otherwise we might fail to do the changes, but still replace {{uncat}} |
|||
if ( mode !== 'remove' ) { |
|||
text = this.doCleanup( this.removeUncat( text ) ); |
|||
} |
|||
var data = { |
|||
action: 'edit', |
|||
summary: comment, |
|||
title: file[ 0 ], |
|||
text: text, |
|||
bot: true, |
|||
starttimestamp: starttimestamp, |
|||
basetimestamp: timestamp, |
|||
watchlist: this.settings.watchlist, |
|||
token: this.edittoken |
|||
}; |
|||
if ( this.settings.minor ) data.minor = true; |
|||
this.doAPICall( data, function() { |
|||
catALot.updateCounter(); |
|||
} ); |
|||
this.markAsDone( file[ 1 ], mode, targetcat ); |
|||
}, |
|||
markAsDone: function( label, mode, targetcat ) { |
|||
label.addClass( 'cat_a_lot_markAsDone' ); |
|||
switch ( mode ) { |
|||
case 'add': |
|||
label.append( '<br>' + msg( 'added-cat', targetcat ) ); |
|||
break; |
|||
case 'copy': |
|||
label.append( '<br>' + msg( 'copied-cat', targetcat ) ); |
|||
break; |
|||
case 'move': |
|||
label.append( '<br>' + msg( 'moved-cat', targetcat ) ); |
|||
break; |
|||
case 'remove': |
|||
label.append( '<br>' + msg( 'removed-cat' ) ); |
|||
break; |
|||
} |
|||
}, |
|||
updateCounter: function() { |
|||
this.counterCurrent++; |
|||
if ( this.counterCurrent > this.counterNeeded ) this.displayResult(); |
|||
else this.domCounter.text( this.counterCurrent ); |
|||
}, |
|||
displayResult: function() { |
|||
document.body.style.cursor = 'auto'; |
|||
$( '.cat_a_lot_feedback' ) |
|||
.addClass( 'cat_a_lot_done' ); |
|||
$( '.ui-dialog-content' ) |
|||
.height( 'auto' ); |
|||
var rep = this.domCounter.parent(); |
|||
rep.html( '<h3>' + msg( 'done' ) + '</h3>' ); |
|||
rep.append( msg( 'all-done' ) + '<br />' ); |
|||
var close = $( '<a>' ) |
|||
.text( msgPlain( 'return-to-page' ) ); |
|||
close.click( function() { |
|||
catALot.progressDialog.remove(); |
|||
catALot.toggleAll( false ); |
|||
} ); |
|||
rep.append( close ); |
|||
if ( this.alreadyThere.length ) { |
|||
rep.append( '<h5>' + msg( 'skipped-already', this.alreadyThere.length ) + '</h5>' ); |
|||
rep.append( this.alreadyThere.join( '<br>' ) ); |
|||
} |
|||
if ( this.notFound.length ) { |
|||
rep.append( '<h5>' + msg( 'skipped-not-found', this.notFound.length ) + '</h5>' ); |
|||
rep.append( this.notFound.join( '<br>' ) ); |
|||
} |
|||
if ( this.connectionError.length ) { |
|||
rep.append( '<h5>' + msg( 'skipped-server', this.connectionError.length ) + '</h5>' ); |
|||
rep.append( this.connectionError.join( '<br>' ) ); |
|||
} |
|||
}, |
|||
moveHere: function( targetcat ) { |
|||
this.doSomething( targetcat, 'move' ); |
|||
}, |
|||
copyHere: function( targetcat ) { |
|||
this.doSomething( targetcat, 'copy' ); |
|||
}, |
|||
addHere: function( targetcat ) { |
|||
this.doSomething( targetcat, 'add' ); |
|||
}, |
|||
remove: function() { |
|||
this.doSomething( '', 'remove' ); |
|||
}, |
|||
doSomething: function( targetcat, mode ) { |
|||
var files = this.getMarkedLabels(); |
|||
if ( files.length === 0 ) { |
|||
alert( msgPlain( 'none-selected' ) ); |
|||
return; |
|||
} |
|||
this.notFound = []; |
|||
this.alreadyThere = []; |
|||
this.connectionError = []; |
|||
this.counterCurrent = 1; |
|||
this.counterNeeded = files.length; |
|||
mw.loader.using( ['jquery.ui', 'mediawiki.util'], function() { |
|||
catALot.showProgress(); |
|||
for ( var i = 0; i < files.length; i++ ) { |
|||
catALot.getContent( files[ i ], targetcat, mode ); |
|||
} |
|||
} ); |
|||
}, |
|||
doAPICall: function( params, callback ) { |
|||
params.format = 'json'; |
|||
var i = 0; |
|||
var apiUrl = this.apiUrl; |
|||
var version = this.version; |
|||
var handleError = function( jqXHR, textStatus, errorThrown ) { |
|||
if ( window.console && $.isFunction( window.console.log ) ) { |
|||
window.console.log( 'Error: ', jqXHR, textStatus, errorThrown ); |
|||
} |
|||
if ( i < 4 ) { |
|||
window.setTimeout( doCall, 300 ); |
|||
i++; |
|||
} else if ( params.title ) { |
|||
this.connectionError.push( params.title ); |
|||
this.updateCounter(); |
|||
return; |
|||
} |
|||
}; |
|||
var doCall = function() { |
|||
$.ajax( { |
|||
headers: { |
|||
'Api-User-Agent': 'Cat-a-lot/' + version + ' (' + mw.config.get('wgWikiID') + ')' |
|||
}, |
|||
url: apiUrl, |
|||
cache: false, |
|||
dataType: 'json', |
|||
data: params, |
|||
type: 'POST', |
|||
success: callback, |
|||
error: handleError |
|||
} ); |
|||
}; |
|||
doCall(); |
|||
}, |
|||
createCatLinks: function( symbol, list ) { |
|||
list.sort(); |
|||
var domlist = $resultList.find( 'table' ); |
|||
for ( var i = 0; i < list.length; i++ ) { |
|||
var $tr = $( '<tr>' ); |
|||
var $link = $( '<a>' ), |
|||
$add, $move, $copy; |
|||
$link.text( list[ i ] ); |
|||
$tr.data( 'cat', list[ i ] ); |
|||
$link.click( function() { |
|||
catALot.updateCats( $( this ).closest('tr').data( 'cat' ) ); |
|||
} ); |
|||
if ( this.searchmode ) { |
|||
$add = $( '<a class="cat_a_lot_action"></a>' ) |
|||
.text( msgPlain( 'add' ) ) |
|||
.click( function() { |
|||
catALot.addHere( $( this ).closest('tr').data( 'cat' ) ); |
|||
} ); |
|||
} else { |
|||
$move = $( '<a class="cat_a_lot_move"></a>' ) |
|||
.text( msgPlain( 'move' ) ) |
|||
.click( function() { |
|||
catALot.moveHere( $( this ).closest('tr').data( 'cat' ) ); |
|||
} ); |
|||
$copy = $( '<a class="cat_a_lot_action"></a>' ) |
|||
.text( msgPlain( 'copy' ) ) |
|||
.click( function() { |
|||
catALot.copyHere( $( this ).closest('tr').data( 'cat' ) ); |
|||
} ); |
|||
} |
|||
$tr.append( $('<td>').text( symbol ) ) |
|||
.append( $('<td>').append( $link ) ); |
|||
// Can't move to source category |
|||
if ( list[ i ] !== currentCat && this.searchmode ) { |
|||
$tr.append( $('<td>').append( $add ) ); |
|||
} else if ( list[ i ] !== currentCat && !this.searchmode ) { |
|||
$tr.append( $('<td>').append( $move ), $('<td>').append( $copy ) ); |
|||
} |
|||
domlist.append( $tr ); |
|||
} |
|||
}, |
|||
getCategoryList: function() { |
|||
this.catCounter = 0; |
|||
this.getParentCats(); |
|||
this.getSubCats(); |
|||
}, |
|||
showCategoryList: function() { |
|||
var thiscat = [ this.currentCategory ]; |
|||
$resultList.empty(); |
|||
$resultList.append( '<table></table>' ); |
|||
this.createCatLinks( "↑", this.parentCats ); |
|||
this.createCatLinks( "→", thiscat ); |
|||
this.createCatLinks( "↓", this.subCats ); |
|||
document.body.style.cursor = 'auto'; |
|||
//Reset width |
|||
$container.width( '' ); |
|||
$container.height( '' ); |
|||
$container.width( Math.min( $container.width() * 1.1 + 15, $( window ).width() - 10 ) ); |
|||
$resultList.css( { |
|||
maxHeight: this.setHeight + 'px', |
|||
height: '' |
|||
} ); |
|||
}, |
|||
updateCats: function( newcat ) { |
|||
document.body.style.cursor = 'wait'; |
|||
this.currentCategory = newcat; |
|||
$resultList.html( '<div class="cat_a_lot_loading"></div>' ).text( msgPlain( 'loading' ) ); |
|||
this.getCategoryList(); |
|||
}, |
|||
showProgress: function() { |
|||
document.body.style.cursor = 'wait'; |
|||
this.progressDialog = $( '<div></div>' ) |
|||
.html( msg( 'editing' ) + ' <span id="cat_a_lot_current">' + this.counterCurrent + '</span> ' + msg( 'of' ) + this.counterNeeded ) |
|||
.dialog( { |
|||
width: 450, |
|||
height: 90, |
|||
minHeight: 90, |
|||
modal: true, |
|||
resizable: false, |
|||
draggable: false, |
|||
closeOnEscape: false, |
|||
dialogClass: "cat_a_lot_feedback" |
|||
} ); |
|||
$( '.ui-dialog-titlebar' ) |
|||
.hide(); |
|||
this.domCounter = $( '#cat_a_lot_current' ); |
|||
}, |
|||
run: function() { |
|||
if ( $( '.cat_a_lot_enabled' ).length ) { |
|||
this.makeClickable(); |
|||
$dataContainer |
|||
.show(); |
|||
$container |
|||
.resizable( { |
|||
handles: 'n', |
|||
alsoResize: '#cat_a_lot_category_list', |
|||
resize: function() { |
|||
$( this ) |
|||
.css( { |
|||
left: '', |
|||
top: '' |
|||
} ); |
|||
catALot.setHeight = $( this ) |
|||
.height(); |
|||
$resultList |
|||
.css( { |
|||
maxHeight: '', |
|||
width: '' |
|||
} ); |
|||
} |
|||
} ); |
|||
$resultList |
|||
.css( { |
|||
maxHeight: '450px' |
|||
} ); |
|||
if ( this.searchmode ) this.updateCats( "Pictures and images" ); |
|||
else this.updateCats( currentCat ); |
|||
} else { |
|||
$dataContainer |
|||
.hide(); |
|||
$container |
|||
.resizable( "destroy" ); |
|||
//Unbind click handlers |
|||
this.labels.off( 'click.catALot' ); |
|||
} |
|||
}, |
|||
manageSettings: function() { |
|||
mw.loader.using( [ 'ext.gadget.SettingsManager', 'ext.gadget.SettingsUI', 'jquery.ui' ], function() { |
|||
catALot._manageSettings(); |
|||
} ); |
|||
}, |
|||
_manageSettings: function() { |
|||
window.mw.libs.SettingsUI( this.defaults, "Cat-A-Lot" ) |
|||
.show() |
|||
.done( function( s, verbose, loc, settingsOut, $dlg ) { |
|||
var mustRestart = false, |
|||
_restart = function() { |
|||
if ( !mustRestart ) return; |
|||
$container.remove(); |
|||
catALot.labels.off( 'click.catALot' ); |
|||
catALot.init(); |
|||
}, |
|||
_saveToJS = function() { |
|||
var opt = mw.libs.settingsManager.option( { |
|||
optionName: 'catALotPrefs', |
|||
value: catALot.settings, |
|||
encloseSignature: 'catALot', |
|||
encloseBlock: '////////// Cat-A-Lot user preferences //////////\n', |
|||
triggerSaveAt: /Cat.?A.?Lot/i, |
|||
editSummary: msgPlain( 'pref-save-summary' ) |
|||
} ), |
|||
oldHeight = $dlg.height(), |
|||
$prog = $( '<div>' ); |
|||
$dlg.css( 'height', oldHeight ) |
|||
.html( '' ); |
|||
$prog.css( { |
|||
'height': Math.round( oldHeight / 8 ), |
|||
'margin-top': Math.round( ( 7 * oldHeight ) / 16 ) |
|||
} ) |
|||
.appendTo( $dlg ); |
|||
$dlg.parent() |
|||
.find( '.ui-dialog-buttonpane button' ) |
|||
.button( 'option', 'disabled', true ); |
|||
opt.save() |
|||
.done( function( text, progress ) { |
|||
$prog.progressbar( { |
|||
value: progress |
|||
} ); |
|||
$prog.fadeOut( function() { |
|||
$dlg.dialog( 'close' ); |
|||
_restart(); |
|||
} ); |
|||
} ) |
|||
.progress( function( text, progress ) { |
|||
$prog.progressbar( { |
|||
value: progress |
|||
} ); |
|||
// TODO: Add "details" to progressbar |
|||
} ) |
|||
.fail( function( text ) { |
|||
$prog.addClass( 'ui-state-error' ); |
|||
$dlg.prepend( $( '<p>' ) |
|||
.text( text ) ); |
|||
} ); |
|||
}; |
|||
$.each( settingsOut, function( n, v ) { |
|||
if ( v.forcerestart && catALot.settings[ v.name ] !== v.value ) { |
|||
mustRestart = true; |
|||
} |
|||
catALot.settings[ v.name ] = v.value; |
|||
window.catALotPrefs[ v.name ] = v.value; |
|||
} ); |
|||
switch ( loc ) { |
|||
case 'page': |
|||
$dlg.dialog( 'close' ); |
|||
_restart(); |
|||
break; |
|||
case 'account-publicly': |
|||
_saveToJS(); |
|||
break; |
|||
} |
|||
} ); |
|||
}, |
|||
_initSettings: function() { |
|||
if ( this.settings.watchlist ) return; |
|||
if ( !window.catALotPrefs ) window.catALotPrefs = {}; |
|||
$.each( this.defaults, function( n, v ) { |
|||
v.value = catALot.settings[ v.name ] = ( window.catALotPrefs[ v.name ] || v[ 'default' ] ); |
|||
v.label = msgPlain( v.label_i18n ); |
|||
if ( v.select_i18n ) { |
|||
v.select = {}; |
|||
$.each( v.select_i18n, function( i18nk, val ) { |
|||
v.select[ msgPlain( i18nk ) ] = val; |
|||
} ); |
|||
} |
|||
} ); |
|||
}, |
|||
defaults: [ { |
|||
name: 'watchlist', |
|||
'default': 'preferences', |
|||
label_i18n: 'watchlistpref', |
|||
select_i18n: { |
|||
'watch_pref': 'preferences', |
|||
'watch_nochange': 'nochange', |
|||
'watch_watch': 'watch', |
|||
'watch_unwatch': 'unwatch' |
|||
} |
|||
}, { |
|||
name: 'minor', |
|||
'default': false, |
|||
label_i18n: 'minorpref' |
|||
}, { |
|||
name: 'editpages', |
|||
'default': true, |
|||
label_i18n: 'editpagespref', |
|||
forcerestart: true |
|||
}, { |
|||
name: 'docleanup', |
|||
'default': false, |
|||
label_i18n: 'docleanuppref' |
|||
}, { |
|||
name: 'subcatcount', |
|||
'default': 50, |
|||
'min': 5, |
|||
'max': 500, |
|||
label_i18n: 'subcatcountpref', |
|||
forcerestart: true |
|||
} ] |
|||
}; |
|||
if ( ( nsNumber === -1 && mw.config.get( 'wgCanonicalSpecialPageName' ) === "Search" ) || nsNumber === nsCat ) { |
|||
if ( nsNumber === -1 ) { |
|||
catALot.searchmode = true; |
|||
} |
|||
var loadingLocalizations = 1; |
|||
var loadLocalization = function( lang, cb ) { |
|||
loadingLocalizations++; |
|||
switch ( lang ) { |
|||
case 'zh-hk': |
|||
case 'zh-mo': |
|||
case 'zh-tw': |
|||
lang = 'zh-hant'; |
|||
break; |
|||
case 'zh': |
|||
case 'zh-cn': |
|||
case 'zh-my': |
|||
case 'zh-sg': |
|||
lang = 'zh-hans'; |
|||
break; |
|||
} |
|||
$.ajax( { |
|||
url: '//commons.wikimedia.org/w/index.php', |
|||
dataType: 'script', |
|||
data: { |
|||
title: 'MediaWiki:Gadget-Cat-a-lot.js/' + lang, |
|||
action: 'raw', |
|||
ctype: 'text/javascript', |
|||
// Allow caching for 28 days |
|||
maxage: 2419200, |
|||
smaxage: 2419200 |
|||
}, |
|||
cache: true, |
|||
success: cb, |
|||
error: cb |
|||
} ); |
|||
}; |
|||
var maybeLaunch = function() { |
|||
loadingLocalizations--; |
|||
function init() { |
|||
$( document ).ready( function() { |
|||
catALot.init(); |
|||
} ); |
|||
} |
|||
if ( 0 === loadingLocalizations ) { |
|||
mw.loader.using( [ 'user' ], init, init ); |
|||
} |
|||
}; |
|||
if ( mw.config.get( 'wgUserLanguage' ) !== 'en' ) { |
|||
loadLocalization( mw.config.get( 'wgUserLanguage' ), maybeLaunch ); |
|||
} |
|||
maybeLaunch(); |
|||
} |
|||
} )( jQuery, mediaWiki ); |
|||
/** |
/** |
||
* SPDX-License-Identifier: CC-BY-SA-4.0 |
|||
* Derivative work of |
|||
* _addText: '{{Gadget Header|title2=Cat-a-lot Messages|license2=CC-BY-SA-4.0}}' |
|||
* (replace "checkboxes" with cat-a-lot labels in your mind) |
|||
* |
|||
* Cat-a-lot messages |
|||
* |
|||
* @base {@link https://commons.wikimedia.org/wiki/MediaWiki:Gadget-Cat-a-lot.js/zh-hans} |
|||
* @base {@link https://commons.wikimedia.org/wiki/MediaWiki:Gadget-Cat-a-lot.js/zh-hant} |
|||
* @source {@link https://git.qiuwen.net.cn/InterfaceAdmin/QiuwenGadgets/src/branch/master/src/Cat-a-lot/modules/messages.ts} |
|||
* @license CC-BY-SA-4.0 {@link https://www.qiuwenbaike.cn/wiki/H:CC-BY-SA-4.0} |
|||
*/ |
*/ |
||
/** |
/** |
||
* SPDX-License-Identifier: CC-BY-SA-4.0 |
|||
* _addText: '{{Gadget Header|title3=jQuery checkboxShiftClick|license3=CC-BY-SA-4.0}}' |
|||
* |
|||
* jQuery checkboxShiftClick |
* jQuery checkboxShiftClick |
||
* |
* |
||
* This will enable checkboxes to be checked or unchecked in a row by clicking one, holding shift and clicking another one |
* @description This will enable checkboxes to be checked or unchecked in a row by clicking one, holding shift and clicking another one |
||
* @base {@link https://commons.wikimedia.org/wiki/MediaWiki:Gadget-Cat-a-lot.js} |
|||
* |
|||
* @source {@link https://git.qiuwen.net.cn/InterfaceAdmin/QiuwenGadgets/src/branch/master/src/Cat-a-lot/modules/extendJQueryPrototype.ts} |
|||
* @author Krinkle <krinklemail@gmail.com> |
* @author Krinkle <krinklemail@gmail.com> |
||
* @license CC-BY-SA-4.0 {@link https://www.qiuwenbaike.cn/wiki/H:CC-BY-SA-4.0} |
|||
* @license GPL v2 |
|||
*/ |
*/ |
||
( function( $ ) { |
|||
$.fn.catALotShiftClick = function( cb ) { |
|||
var prevCheckbox = null, |
|||
$box = this; |
|||
// When our boxes are clicked.. |
|||
$box.on( 'click.catALot', function( e ) { |
|||
/** |
|||
// Highlight last selected |
|||
* Hereby releasing jquery.checkboxShiftClick into CC BY-SA 3.0, |
|||
$( '#cat_a_lot_last_selected' ) |
|||
* CC BY 4.0, CC-0 and for all intends and purpose in the public |
|||
.removeAttr( 'id' ); |
|||
* domain, so as to not need this annotation. |
|||
var $thisControl = $( e.target ), |
|||
* |
|||
method; |
|||
* @source {@link https://commons.wikimedia.org/w/index.php?oldid=365723751} |
|||
if ( !$thisControl.hasClass( 'cat_a_lot_label' ) ) { |
|||
*/ |
|||
$thisControl = $thisControl.parents( '.cat_a_lot_label' ); |
|||
/** |
|||
} |
|||
* +------------------------------------------------------------+ |
|||
$thisControl.attr( 'id', 'cat_a_lot_last_selected' ) |
|||
* | === WARNING: GLOBAL GADGET FILE === | |
|||
.toggleClass( 'cat_a_lot_selected' ); |
|||
* +------------------------------------------------------------+ |
|||
* | All changes should be made in the repository, | |
|||
* | otherwise they will be lost. | |
|||
* +------------------------------------------------------------+ |
|||
* | Changes to this page may affect many users. | |
|||
* | Please discuss changes by opening an issue before editing. | |
|||
* +------------------------------------------------------------+ |
|||
*/ |
|||
/* <nowiki> */ |
|||
(() => { |
|||
// And one has been clicked before... |
|||
if ( prevCheckbox !== null && e.shiftKey ) { |
|||
// Prevent selection |
|||
e.preventDefault(); |
|||
"use strict"; |
|||
method = $thisControl.hasClass( 'cat_a_lot_selected' ) ? 'addClass' : 'removeClass'; |
|||
// dist/Cat-a-lot/Cat-a-lot.js |
|||
// Check or uncheck this one and all in-between checkboxes |
|||
var _templateObject; |
|||
$box.slice( |
|||
var _templateObject2; |
|||
Math.min( $box.index( prevCheckbox ), $box.index( $thisControl ) ), |
|||
var _templateObject3; |
|||
Math.max( $box.index( prevCheckbox ), $box.index( $thisControl ) ) + 1 |
|||
function _taggedTemplateLiteral(e, t) { |
|||
)[ method ]( 'cat_a_lot_selected' ); |
|||
return t || (t = e.slice(0)), Object.freeze(Object.defineProperties(e, { raw: { value: Object.freeze(t) } })); |
|||
} |
|||
} |
|||
// Either way, update the prevCheckbox variable to the one clicked now |
|||
function asyncGeneratorStep(n, t, e, r, o, a, c) { |
|||
prevCheckbox = $thisControl; |
|||
try { |
|||
var i = n[a](c), u = i.value; |
|||
} catch (n2) { |
|||
return void e(n2); |
|||
} |
|||
i.done ? t(u) : Promise.resolve(u).then(r, o); |
|||
} |
|||
function _asyncToGenerator(n) { |
|||
return function() { |
|||
var t = this, e = arguments; |
|||
return new Promise(function(r, o) { |
|||
var a = n.apply(t, e); |
|||
function _next(n2) { |
|||
asyncGeneratorStep(a, r, o, _next, _throw, "next", n2); |
|||
} |
|||
function _throw(n2) { |
|||
asyncGeneratorStep(a, r, o, _next, _throw, "throw", n2); |
|||
} |
|||
_next(void 0); |
|||
}); |
|||
}; |
|||
} |
|||
function _createForOfIteratorHelper(r, e) { |
|||
var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; |
|||
if (!t) { |
|||
if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { |
|||
t && (r = t); |
|||
var n = 0, F = function() { |
|||
}; |
|||
return { s: F, n: function() { |
|||
return n >= r.length ? { done: true } : { done: false, value: r[n++] }; |
|||
}, e: function(r2) { |
|||
throw r2; |
|||
}, f: F }; |
|||
} |
|||
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); |
|||
} |
|||
var o, a = true, u = false; |
|||
return { s: function() { |
|||
t = t.call(r); |
|||
}, n: function() { |
|||
var r2 = t.next(); |
|||
return a = r2.done, r2; |
|||
}, e: function(r2) { |
|||
u = true, o = r2; |
|||
}, f: function() { |
|||
try { |
|||
a || null == t.return || t.return(); |
|||
} finally { |
|||
if (u) throw o; |
|||
} |
|||
} }; |
|||
} |
|||
function _unsupportedIterableToArray(r, a) { |
|||
if (r) { |
|||
if ("string" == typeof r) return _arrayLikeToArray(r, a); |
|||
var t = {}.toString.call(r).slice(8, -1); |
|||
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; |
|||
} |
|||
} |
|||
function _arrayLikeToArray(r, a) { |
|||
(null == a || a > r.length) && (a = r.length); |
|||
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; |
|||
return n; |
|||
} |
|||
var __create = Object.create; |
|||
var __defProp = Object.defineProperty; |
|||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; |
|||
var __getOwnPropNames = Object.getOwnPropertyNames; |
|||
var __getProtoOf = Object.getPrototypeOf; |
|||
var __hasOwnProp = Object.prototype.hasOwnProperty; |
|||
var __copyProps = (to, from, except, desc) => { |
|||
if (from && typeof from === "object" || typeof from === "function") { |
|||
var _iterator = _createForOfIteratorHelper(__getOwnPropNames(from)), _step; |
|||
try { |
|||
for (_iterator.s(); !(_step = _iterator.n()).done; ) { |
|||
let key = _step.value; |
|||
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { |
|||
get: () => from[key], |
|||
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable |
|||
}); |
|||
} |
|||
} catch (err) { |
|||
_iterator.e(err); |
|||
} finally { |
|||
_iterator.f(); |
|||
} |
|||
} |
|||
return to; |
|||
}; |
|||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( |
|||
// If the importer is in node compatibility mode or this is not an ESM |
|||
// file that has been converted to a CommonJS file using a Babel- |
|||
// compatible transform (i.e. "__esModule" has not been set), then set |
|||
// "default" to the CommonJS "module.exports" for node compatibility. |
|||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { |
|||
value: mod, |
|||
enumerable: true |
|||
}) : target, |
|||
mod |
|||
)); |
|||
//! src/Cat-a-lot/options.json |
|||
var apiTag = ""; |
|||
var targetNamespace = 14; |
|||
var version = "6.0"; |
|||
var storageKey = "ext.gadget.Cat-a-Lot_results-"; |
|||
//! src/Cat-a-lot/modules/constant.ts |
|||
var CLASS_NAME = "gadget-cat_a_lot"; |
|||
var CLASS_NAME_CONTAINER = "".concat(CLASS_NAME, "-container"); |
|||
var CLASS_NAME_CONTAINER_DATA = "".concat(CLASS_NAME_CONTAINER, "__data"); |
|||
var CLASS_NAME_CONTAINER_DATA_CATEGORY_LIST = "".concat(CLASS_NAME_CONTAINER_DATA, "__category-list"); |
|||
var CLASS_NAME_CONTAINER_DATA_CATEGORY_LIST_ACTION = "".concat(CLASS_NAME_CONTAINER_DATA_CATEGORY_LIST, "__action"); |
|||
var CLASS_NAME_CONTAINER_DATA_CATEGORY_LIST_NO_FOUND = "".concat(CLASS_NAME_CONTAINER_DATA_CATEGORY_LIST, "--no-found"); |
|||
var CLASS_NAME_CONTAINER_DATA_MARK_COUNTER = "".concat(CLASS_NAME_CONTAINER_DATA, "__mark-counter"); |
|||
var CLASS_NAME_CONTAINER_DATA_SEARCH_INPUT_CONTAINER_INPUT = "".concat(CLASS_NAME_CONTAINER_DATA, "__search-input-container__input"); |
|||
var CLASS_NAME_CONTAINER_DATA_SELECTIONS = "".concat(CLASS_NAME_CONTAINER_DATA, "__selections"); |
|||
var CLASS_NAME_CONTAINER_DATA_SELECTIONS_ALL = "".concat(CLASS_NAME_CONTAINER_DATA_SELECTIONS, "__all"); |
|||
var CLASS_NAME_CONTAINER_DATA_SELECTIONS_NONE = "".concat(CLASS_NAME_CONTAINER_DATA_SELECTIONS, "__none"); |
|||
var CLASS_NAME_CONTAINER_HEAD = "".concat(CLASS_NAME_CONTAINER, "__head"); |
|||
var CLASS_NAME_CONTAINER_HEAD_LINK = "".concat(CLASS_NAME_CONTAINER_HEAD, "__link"); |
|||
var CLASS_NAME_CONTAINER_HEAD_LINK_ENABLED = "".concat(CLASS_NAME_CONTAINER_HEAD_LINK, "--enabled"); |
|||
var CLASS_NAME_CURRENT_COUNTER = "".concat(CLASS_NAME, "-current_counter"); |
|||
var CLASS_NAME_FEEDBACK = "".concat(CLASS_NAME, "-feedback"); |
|||
var CLASS_NAME_FEEDBACK_DONE = "".concat(CLASS_NAME_FEEDBACK, "--done"); |
|||
var CLASS_NAME_LABEL = "".concat(CLASS_NAME, "-label"); |
|||
var CLASS_NAME_LABEL_DONE = "".concat(CLASS_NAME_LABEL, "--done"); |
|||
var CLASS_NAME_LABEL_LAST_SELECTED = "".concat(CLASS_NAME_LABEL, "--last-selected"); |
|||
var CLASS_NAME_LABEL_SELECTED = "".concat(CLASS_NAME_LABEL, "--selected"); |
|||
var DEFAULT_SETTING = { |
|||
docleanup: { |
|||
default: false, |
|||
label_i18n: "docleanuppref" |
|||
}, |
|||
editpages: { |
|||
default: true, |
|||
label_i18n: "editpagespref" |
|||
}, |
|||
minor: { |
|||
default: false, |
|||
label_i18n: "minorpref" |
|||
}, |
|||
subcatcount: { |
|||
default: 50, |
|||
label_i18n: "subcatcountpref" |
|||
}, |
|||
watchlist: { |
|||
default: "preferences", |
|||
label_i18n: "watchlistpref", |
|||
select_i18n: { |
|||
watch_nochange: "nochange", |
|||
watch_pref: "preferences", |
|||
watch_unwatch: "unwatch", |
|||
watch_watch: "watch" |
|||
} |
|||
} |
|||
}; |
|||
var VARIANTS = ["zh-hans", "zh-hant", "zh-cn", "zh-my", "zh-sg", "zh-hk", "zh-mo", "zh-tw"]; |
|||
//! src/Cat-a-lot/modules/messages.ts |
|||
var { |
|||
wgUserLanguage |
|||
} = mw.config.get(); |
|||
var DEFAULT_MESSAGES = { |
|||
// as in 17 files selected |
|||
"cat-a-lot-files-selected": "{{PLURAL:$1|One file|$1 files}} selected.", |
|||
// Actions |
|||
"cat-a-lot-copy": "Copy", |
|||
"cat-a-lot-move": "Move", |
|||
"cat-a-lot-add": "Add", |
|||
"cat-a-lot-remove-from-cat": "Remove from this category", |
|||
"cat-a-lot-enter-name": "Enter category name", |
|||
"cat-a-lot-select": "Select", |
|||
"cat-a-lot-all": "all", |
|||
"cat-a-lot-none": "none", |
|||
"cat-a-lot-none-selected": "No files selected!", |
|||
// Preferences |
|||
"cat-a-lot-watchlistpref": "Watchlist preference concerning files edited with Cat-A-Lot", |
|||
"cat-a-lot-watch_pref": "According to your general preferences", |
|||
"cat-a-lot-watch_nochange": "Do not change watchstatus", |
|||
"cat-a-lot-watch_watch": "Watch pages edited with Cat-A-Lot", |
|||
"cat-a-lot-watch_unwatch": "Remove pages while editing with Cat-A-Lot from your watchlist", |
|||
"cat-a-lot-minorpref": "Mark edits as minor (if you generally mark your edits as minor, this won't change anything)", |
|||
"cat-a-lot-editpagespref": "Allow categorising pages (including categories) that are not files", |
|||
"cat-a-lot-docleanuppref": "Remove {{Check categories}} and other minor cleanup", |
|||
"cat-a-lot-subcatcountpref": "Sub-categories to show at most", |
|||
// Progress |
|||
"cat-a-lot-loading": "Loading...", |
|||
"cat-a-lot-editing": "Editing page", |
|||
"cat-a-lot-of": "of ", |
|||
"cat-a-lot-skipped-already": "The following {{PLURAL:$1|page was|$1 pages were}} skipped, because the page was already in the category:", |
|||
"cat-a-lot-skipped-not-found": "The following {{PLURAL:$1|page was|$1 pages were}} skipped, because the old category could not be found:", |
|||
"cat-a-lot-skipped-server": "The following {{PLURAL:$1|page|$1 pages}} couldn't be changed, since there were problems connecting to the server:", |
|||
"cat-a-lot-all-done": "All pages are processed.", |
|||
"cat-a-lot-done": "Done!", |
|||
"cat-a-lot-added-cat": "Added category $1", |
|||
"cat-a-lot-copied-cat": "Copied to category $1", |
|||
"cat-a-lot-moved-cat": "Moved to category $1", |
|||
"cat-a-lot-removed-cat": "Removed from category $1", |
|||
"cat-a-lot-return-to-page": "Return to page", |
|||
"cat-a-lot-cat-not-found": "Category not found.", |
|||
// Summaries: |
|||
"cat-a-lot-summary-add": "[[Help:Cat-a-lot|Cat-a-lot]]: Adding [[Category:$1]]", |
|||
"cat-a-lot-summary-copy": "[[Help:Cat-a-lot|Cat-a-lot]]: Copying from [[Category:$1]] to [[Category:$2]]", |
|||
"cat-a-lot-summary-move": "[[Help:Cat-a-lot|Cat-a-lot]]: Moving from [[Category:$1]] to [[Category:$2]]", |
|||
"cat-a-lot-summary-remove": "[[Help:Cat-a-lot|Cat-a-lot]]: Removing from [[Category:$1]]" |
|||
}; |
|||
var setMessages = () => { |
|||
/*! Cat-a-lot messages | CC-BY-SA-4.0 <https://qwbk.cc/H:CC-BY-SA-4.0> */ |
|||
if (wgUserLanguage === "en") { |
|||
return; |
|||
} |
|||
if (["zh-hant", "zh-hk", "zh-mo", "zh-tw"].includes(wgUserLanguage)) { |
|||
mw.messages.set({ |
|||
// as in 17 files selected |
|||
"cat-a-lot-files-selected": "$1個文件已選擇", |
|||
// Actions |
|||
"cat-a-lot-copy": "複製", |
|||
"cat-a-lot-move": "移動", |
|||
"cat-a-lot-add": "增加", |
|||
"cat-a-lot-remove-from-cat": "從此分類移除", |
|||
"cat-a-lot-enter-name": "輸入分類名稱", |
|||
"cat-a-lot-select": "選擇", |
|||
"cat-a-lot-all": "全部", |
|||
"cat-a-lot-none": "無", |
|||
"cat-a-lot-none-selected": "沒有選擇文件!", |
|||
// Preferences |
|||
"cat-a-lot-watchlistpref": "使用Cat-A-Lot編輯文件時的監視列表選項", |
|||
"cat-a-lot-watch_pref": "與系統參數設置相同", |
|||
"cat-a-lot-watch_nochange": "不要更改監視狀態", |
|||
"cat-a-lot-watch_watch": "監視使用Cat-A-Lot編輯的頁面", |
|||
"cat-a-lot-watch_unwatch": "將使用Cat-A-Lot編輯的頁面從監視列表移除", |
|||
"cat-a-lot-minorpref": "將編輯標記爲小修改(若您在系統參數設置中已設置將所有編輯標記爲小修改,此選項不會對現有行爲進行改動)", |
|||
"cat-a-lot-editpagespref": "允許對不是文件的頁面和子分類進行分類操作", |
|||
"cat-a-lot-docleanuppref": "移除{{Check categories}}並進行其他細節清理", |
|||
"cat-a-lot-subcatcountpref": "最多顯示的子分類數量", |
|||
// Progress |
|||
"cat-a-lot-loading": "正在加載……", |
|||
"cat-a-lot-editing": "正在編輯頁面", |
|||
"cat-a-lot-of": ",共有", |
|||
"cat-a-lot-skipped-already": "以下頁面已跳過,因爲頁面已經在分類中:", |
|||
"cat-a-lot-skipped-not-found": "以下頁面已跳過,因爲找不到現有分類:", |
|||
"cat-a-lot-skipped-server": "以下頁面無法編輯,因爲連接服務器出錯:", |
|||
"cat-a-lot-all-done": "全部頁面已處理。", |
|||
"cat-a-lot-done": "已完成!", |
|||
"cat-a-lot-added-cat": "已加入分類", |
|||
"cat-a-lot-copied-cat": "已複製到分類", |
|||
"cat-a-lot-moved-cat": "已移動到分類", |
|||
"cat-a-lot-removed-cat": "已從分類移除", |
|||
"cat-a-lot-return-to-page": "返回到頁面", |
|||
"cat-a-lot-cat-not-found": "找不到分類。", |
|||
// Summaries |
|||
"cat-a-lot-summary-add": "[[Help:Cat-a-lot|Cat-a-lot]]:加入分類[[Category:$1]]", |
|||
"cat-a-lot-summary-copy": "[[Help:Cat-a-lot|Cat-a-lot]]:分類間複製:從[[Category:$1]]到[[Category:$2]]", |
|||
"cat-a-lot-summary-move": "[[Help:Cat-a-lot|Cat-a-lot]]:分類間移動:從[[Category:$1]]到[[Category:$2]]", |
|||
"cat-a-lot-summary-remove": "[[Help:Cat-a-lot|Cat-a-lot]]:從分類移除:[[Category:$1]]" |
|||
}); |
|||
} else { |
|||
mw.messages.set({ |
|||
// as in 17 files selected |
|||
"cat-a-lot-files-selected": "已选择$1个页面或文件", |
|||
// Actions |
|||
"cat-a-lot-copy": "复制", |
|||
"cat-a-lot-move": "移动", |
|||
"cat-a-lot-add": "增加", |
|||
"cat-a-lot-remove-from-cat": "从此分类移除", |
|||
"cat-a-lot-enter-name": "输入分类名称", |
|||
"cat-a-lot-select": "选择", |
|||
"cat-a-lot-all": "全部", |
|||
"cat-a-lot-none": "无", |
|||
"cat-a-lot-none-selected": "没有选择任何页面或文件!", |
|||
// Preferences |
|||
"cat-a-lot-watchlistpref": "使用Cat-a-lot编辑文件时的监视列表选项", |
|||
"cat-a-lot-watch_pref": "与系统参数设置相同", |
|||
"cat-a-lot-watch_nochange": "不要更改监视状态", |
|||
"cat-a-lot-watch_watch": "监视使用Cat-a-lot编辑的页面", |
|||
"cat-a-lot-watch_unwatch": "将使用Cat-a-lot编辑的页面从监视列表移除", |
|||
"cat-a-lot-minorpref": "将编辑标记为小修改(若您在系统参数设置中已设置将所有编辑标记为小修改,此选项不会对现有行为进行改动)", |
|||
"cat-a-lot-editpagespref": "允许对不是文件的页面和子分类进行分类操作", |
|||
"cat-a-lot-docleanuppref": "移除{{Check categories}}并进行其他细节清理", |
|||
"cat-a-lot-subcatcountpref": "最多显示的子分类数量", |
|||
// Progress |
|||
"cat-a-lot-loading": "正在加载……", |
|||
"cat-a-lot-editing": "正在编辑页面", |
|||
"cat-a-lot-of": ",共有", |
|||
"cat-a-lot-skipped-already": "以下页面已跳过,因为页面已经在分类中:", |
|||
"cat-a-lot-skipped-not-found": "以下页面已跳过,因为找不到现有分类:", |
|||
"cat-a-lot-skipped-server": "以下页面无法编辑,因为连接服务器出错:", |
|||
"cat-a-lot-all-done": "全部页面已处理。", |
|||
"cat-a-lot-done": "已完成!", |
|||
"cat-a-lot-added-cat": "已加入分类", |
|||
"cat-a-lot-copied-cat": "已复制到分类", |
|||
"cat-a-lot-moved-cat": "已移动到分类", |
|||
"cat-a-lot-removed-cat": "已从分类移除", |
|||
"cat-a-lot-return-to-page": "返回到页面", |
|||
"cat-a-lot-cat-not-found": "找不到分类。", |
|||
// Summaries |
|||
"cat-a-lot-summary-add": "[[Help:Cat-a-lot|Cat-a-lot]]:加入分类[[Category:$1]]", |
|||
"cat-a-lot-summary-copy": "[[Help:Cat-a-lot|Cat-a-lot]]:分类间复制:从[[Category:$1]]到[[Category:$2]]", |
|||
"cat-a-lot-summary-move": "[[Help:Cat-a-lot|Cat-a-lot]]:分类间移动:从[[Category:$1]]到[[Category:$2]]", |
|||
"cat-a-lot-summary-remove": "[[Help:Cat-a-lot|Cat-a-lot]]:从分类移除:[[Category:$1]]" |
|||
}); |
|||
} |
|||
}; |
|||
//! src/Cat-a-lot/modules/core.tsx |
|||
var import_ext_gadget2 = require("ext.gadget.Util"); |
|||
var import_ext_gadget3 = __toESM(require("ext.gadget.JSX"), 1); |
|||
//! src/Cat-a-lot/modules/api.ts |
|||
var import_ext_gadget = require("ext.gadget.Util"); |
|||
var api = (0, import_ext_gadget.initMwApi)("Cat-a-lot/".concat(version)); |
|||
//! src/Cat-a-lot/modules/getCachedKeys.ts |
|||
var getCachedKeys = () => { |
|||
const variantCache = {}; |
|||
for (var _i = 0, _Object$entries = Object.entries(mw.storage["store"]); _i < _Object$entries.length; _i++) { |
|||
const [key, value] = _Object$entries[_i]; |
|||
if (key.startsWith(storageKey) && Array.isArray(value)) { |
|||
const cacheKey = key.replace(storageKey, ""); |
|||
variantCache[cacheKey] = value; |
|||
} |
|||
} |
|||
return variantCache; |
|||
}; |
|||
//! src/Cat-a-lot/modules/core.tsx |
|||
var { |
|||
wgCanonicalSpecialPageName, |
|||
wgFormattedNamespaces, |
|||
wgNamespaceIds, |
|||
wgNamespaceNumber, |
|||
wgTitle |
|||
} = mw.config.get(); |
|||
var catALot = /* @__PURE__ */ (function() { |
|||
var _ref = _asyncToGenerator(function* () { |
|||
/*! Cat-a-lot | CC-BY-SA-4.0 <https://qwbk.cc/H:CC-BY-SA-4.0> */ |
|||
class CAL { |
|||
static isSearchMode = false; |
|||
static MESSAGES = DEFAULT_MESSAGES; |
|||
static DEFAULT_SETTING = DEFAULT_SETTING; |
|||
static API_TAG = apiTag; |
|||
static TARGET_NAMESPACE = targetNamespace; |
|||
static CURRENT_CATEGROY = wgTitle; |
|||
static wgFormattedNamespaces = wgFormattedNamespaces; |
|||
static wgNamespaceIds = wgNamespaceIds; |
|||
static isAutoCompleteInit = false; |
|||
static api = api; |
|||
static alreadyThere = []; |
|||
static connectionError = []; |
|||
static notFound = []; |
|||
static counterCurrent = 0; |
|||
static counterNeeded = 0; |
|||
static counterCat = 0; |
|||
static currentCategory = ""; |
|||
static dialogHeight = 450; |
|||
static editToken = ""; |
|||
static localCatName = wgFormattedNamespaces[CAL.TARGET_NAMESPACE]; |
|||
static parentCats = []; |
|||
static subCats = []; |
|||
static settings = {}; |
|||
static variantCache = {}; |
|||
static $counter = $(); |
|||
static $progressDialog = $(); |
|||
static $labels = $(); |
|||
static $selectedLabels = $(); |
|||
$body; |
|||
$container; |
|||
$dataContainer; |
|||
$markCounter; |
|||
$resultList; |
|||
$searchInput; |
|||
$head; |
|||
$link; |
|||
constructor($body) { |
|||
var _mw$util$getParamValu; |
|||
if (!mw.message("cat-a-lot-loading").parse()) { |
|||
mw.messages.set(CAL.MESSAGES); |
|||
} |
|||
this.$body = $body; |
|||
CAL.initSettings(); |
|||
const container = /* @__PURE__ */ import_ext_gadget3.default.createElement("div", { |
|||
className: [CLASS_NAME, CLASS_NAME_CONTAINER, "noprint"] |
|||
}, /* @__PURE__ */ import_ext_gadget3.default.createElement("div", { |
|||
className: CLASS_NAME_CONTAINER_DATA |
|||
}, /* @__PURE__ */ import_ext_gadget3.default.createElement("div", { |
|||
className: CLASS_NAME_CONTAINER_DATA_MARK_COUNTER |
|||
}), /* @__PURE__ */ import_ext_gadget3.default.createElement("div", { |
|||
className: CLASS_NAME_CONTAINER_DATA_CATEGORY_LIST |
|||
}), /* @__PURE__ */ import_ext_gadget3.default.createElement("div", null, /* @__PURE__ */ import_ext_gadget3.default.createElement("input", { |
|||
className: CLASS_NAME_CONTAINER_DATA_SEARCH_INPUT_CONTAINER_INPUT, |
|||
placeholder: CAL.msg("enter-name"), |
|||
type: "text", |
|||
value: CAL.isSearchMode ? (_mw$util$getParamValu = mw.util.getParamValue("search")) !== null && _mw$util$getParamValu !== void 0 ? _mw$util$getParamValu : "" : "", |
|||
onKeyDown: (event) => { |
|||
const $element = $(event.currentTarget); |
|||
if (event.key === "Enter") { |
|||
var _$element$val$trim, _$element$val; |
|||
const cat = (_$element$val$trim = (_$element$val = $element.val()) === null || _$element$val === void 0 ? void 0 : _$element$val.trim()) !== null && _$element$val$trim !== void 0 ? _$element$val$trim : ""; |
|||
if (cat) { |
|||
this.updateCats(cat); |
|||
} |
|||
} |
|||
} |
|||
})), /* @__PURE__ */ import_ext_gadget3.default.createElement("div", { |
|||
className: CLASS_NAME_CONTAINER_DATA_SELECTIONS |
|||
}, [CAL.msg("select"), " "], /* @__PURE__ */ import_ext_gadget3.default.createElement("a", { |
|||
className: CLASS_NAME_CONTAINER_DATA_SELECTIONS_ALL, |
|||
onClick: () => { |
|||
this.toggleAll(true); |
|||
} |
|||
}, CAL.msg("all")), " • ", /* @__PURE__ */ import_ext_gadget3.default.createElement("a", { |
|||
className: CLASS_NAME_CONTAINER_DATA_SELECTIONS_NONE, |
|||
onClick: () => { |
|||
this.toggleAll(false); |
|||
} |
|||
}, CAL.msg("none")))), /* @__PURE__ */ import_ext_gadget3.default.createElement("div", { |
|||
className: CLASS_NAME_CONTAINER_HEAD |
|||
}, /* @__PURE__ */ import_ext_gadget3.default.createElement("a", { |
|||
className: CLASS_NAME_CONTAINER_HEAD_LINK |
|||
}, "Cat-a-lot"))); |
|||
this.$container = $(container); |
|||
this.$container.appendTo(this.$body); |
|||
this.$dataContainer = this.$container.find(".".concat(CLASS_NAME_CONTAINER_DATA)); |
|||
this.$markCounter = this.$dataContainer.find(".".concat(CLASS_NAME_CONTAINER_DATA_MARK_COUNTER)); |
|||
this.$resultList = this.$dataContainer.find(".".concat(CLASS_NAME_CONTAINER_DATA_CATEGORY_LIST)); |
|||
this.$searchInput = this.$dataContainer.find(".".concat(CLASS_NAME_CONTAINER_DATA_SEARCH_INPUT_CONTAINER_INPUT)); |
|||
this.$head = this.$container.find(".".concat(CLASS_NAME_CONTAINER_HEAD)); |
|||
this.$link = this.$head.find(".".concat(CLASS_NAME_CONTAINER_HEAD_LINK)); |
|||
} |
|||
buildElements() { |
|||
const regexCat = new RegExp("^\\s*".concat(CAL.localizedRegex(CAL.TARGET_NAMESPACE, "Category"), ":"), ""); |
|||
let isCompositionStart; |
|||
this.$searchInput.on("compositionstart", () => { |
|||
isCompositionStart = true; |
|||
}); |
|||
this.$searchInput.on("compositionend", () => { |
|||
isCompositionStart = false; |
|||
}); |
|||
this.$searchInput.on("input keyup", (event) => { |
|||
if (isCompositionStart) { |
|||
return; |
|||
} |
|||
const { |
|||
currentTarget |
|||
} = event; |
|||
const { |
|||
value: oldVal |
|||
} = currentTarget; |
|||
const newVal = oldVal.replace(regexCat, ""); |
|||
if (newVal !== oldVal) { |
|||
currentTarget.value = newVal; |
|||
} |
|||
}); |
|||
const initAutocomplete = () => { |
|||
if (CAL.isAutoCompleteInit) { |
|||
return; |
|||
} |
|||
CAL.isAutoCompleteInit = true; |
|||
this.$searchInput.autocomplete({ |
|||
source: (request, response) => { |
|||
this.doAPICall({ |
|||
action: "opensearch", |
|||
namespace: CAL.TARGET_NAMESPACE, |
|||
redirects: "resolve", |
|||
search: request.term |
|||
}, (result) => { |
|||
if (result[1]) { |
|||
response($(result[1]).map((_index, item) => item.replace(regexCat, ""))); |
|||
} |
|||
}); |
|||
}, |
|||
position: { |
|||
my: "right bottom", |
|||
at: "right top", |
|||
of: this.$searchInput |
|||
}, |
|||
appendTo: ".".concat(CLASS_NAME_CONTAINER) |
|||
}); |
|||
}; |
|||
this.$link.on("click", (event) => { |
|||
$(event.currentTarget).toggleClass(CLASS_NAME_CONTAINER_HEAD_LINK_ENABLED); |
|||
initAutocomplete(); |
|||
this.run(); |
|||
}); |
|||
} |
|||
static initSettings() { |
|||
var _window$CatALotPrefs; |
|||
let catALotPrefs = (_window$CatALotPrefs = window.CatALotPrefs) !== null && _window$CatALotPrefs !== void 0 ? _window$CatALotPrefs : {}; |
|||
const typeOfCatALotPrefs = typeof catALotPrefs; |
|||
if (typeOfCatALotPrefs === "object" && !Array.isArray(catALotPrefs) || typeOfCatALotPrefs !== "object") { |
|||
catALotPrefs = {}; |
|||
} |
|||
for (var _i2 = 0, _Object$keys = Object.keys(CAL.DEFAULT_SETTING); _i2 < _Object$keys.length; _i2++) { |
|||
var _catALotPrefs$setting; |
|||
const settingKey = _Object$keys[_i2]; |
|||
const setting = CAL.DEFAULT_SETTING[settingKey]; |
|||
CAL.settings[settingKey] = (_catALotPrefs$setting = catALotPrefs[settingKey]) !== null && _catALotPrefs$setting !== void 0 ? _catALotPrefs$setting : setting.default; |
|||
if (!setting.select_i18n) { |
|||
continue; |
|||
} |
|||
setting.select = {}; |
|||
for (var _i3 = 0, _Object$keys2 = Object.keys(setting.select_i18n); _i3 < _Object$keys2.length; _i3++) { |
|||
const messageKey = _Object$keys2[_i3]; |
|||
const message = setting.select_i18n[messageKey]; |
|||
setting.select[CAL.msg(messageKey)] = message; |
|||
} |
|||
} |
|||
} |
|||
static msg(key, ...args) { |
|||
const fullKey = "cat-a-lot-".concat(key); |
|||
return args.length ? mw.message(fullKey, ...args).parse() : mw.message(fullKey).plain(); |
|||
} |
|||
static localizedRegex(namespaceNumber, fallback) { |
|||
var _CAL$wgFormattedNames; |
|||
const wikiTextBlank = String.raw(_templateObject || (_templateObject = _taggedTemplateLiteral(["[ _ - \u2028\u2029 ]+"], ["[\\t _\\xA0\\u1680\\u180E\\u2000-\\u200A\\u2028\\u2029\\u202F\\u205F\\u3000]+"]))); |
|||
const wikiTextBlankRE = new RegExp(wikiTextBlank, "g"); |
|||
const createRegexStr = (name) => { |
|||
if (!(name !== null && name !== void 0 && name.length)) { |
|||
return ""; |
|||
} |
|||
let regexName = ""; |
|||
for (let i = 0; i < name.length; i++) { |
|||
const initial = name.slice(i, i + 1); |
|||
const ll = initial.toLowerCase(); |
|||
const ul = initial.toUpperCase(); |
|||
regexName += ll === ul ? initial : "[".concat(ll).concat(ul, "]"); |
|||
} |
|||
return regexName.replace(/([$()*+.?\\^])/g, String.raw(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["$1"], ["\\$1"])))).replace(wikiTextBlankRE, wikiTextBlank); |
|||
}; |
|||
fallback = fallback.toLowerCase(); |
|||
const canonical = (_CAL$wgFormattedNames = CAL.wgFormattedNamespaces[namespaceNumber]) === null || _CAL$wgFormattedNames === void 0 ? void 0 : _CAL$wgFormattedNames.toLowerCase(); |
|||
let regexString = createRegexStr(canonical); |
|||
if (fallback && canonical !== fallback) { |
|||
regexString += "|".concat(createRegexStr(fallback)); |
|||
} |
|||
for (var _i4 = 0, _Object$keys3 = Object.keys(CAL.wgNamespaceIds); _i4 < _Object$keys3.length; _i4++) { |
|||
const catName = _Object$keys3[_i4]; |
|||
if (catName.toLowerCase() !== canonical && catName.toLowerCase() !== fallback && CAL.wgNamespaceIds[catName] === namespaceNumber) { |
|||
regexString += "|".concat(createRegexStr(catName)); |
|||
} |
|||
} |
|||
return "(?:".concat(regexString, ")"); |
|||
} |
|||
updateSelectionCounter() { |
|||
CAL.$selectedLabels = CAL.$labels.filter(".".concat(CLASS_NAME_LABEL_SELECTED)); |
|||
this.$markCounter.show().html(CAL.msg("files-selected", CAL.$selectedLabels.length.toString())); |
|||
} |
|||
toggleAll(select) { |
|||
CAL.$labels.toggleClass(CLASS_NAME_LABEL_SELECTED, select); |
|||
this.updateSelectionCounter(); |
|||
} |
|||
static findAllVariants(category) { |
|||
return _asyncToGenerator(function* () { |
|||
if (CAL.variantCache[category] !== void 0 && Array.isArray(CAL.variantCache[category])) { |
|||
return CAL.variantCache[category]; |
|||
} |
|||
if (mw.storage.getObject(storageKey + category) !== void 0 && Array.isArray(mw.storage.getObject(storageKey + category))) { |
|||
CAL.variantCache[category] = mw.storage.getObject(storageKey + category); |
|||
return CAL.variantCache[category]; |
|||
} |
|||
const results = [category]; |
|||
const params = { |
|||
action: "parse", |
|||
format: "json", |
|||
formatversion: "2", |
|||
text: category, |
|||
title: "temp" |
|||
}; |
|||
for (var _i5 = 0, _VARIANTS = VARIANTS; _i5 < _VARIANTS.length; _i5++) { |
|||
const variant = _VARIANTS[_i5]; |
|||
try { |
|||
const { |
|||
parse |
|||
} = yield CAL.api.get({ |
|||
...params, |
|||
variant |
|||
}); |
|||
const { |
|||
text |
|||
} = parse; |
|||
const result = $(text).eq(0).text().trim(); |
|||
results[results.length] = result; |
|||
} catch { |
|||
} |
|||
} |
|||
CAL.variantCache[category] = (0, import_ext_gadget2.uniqueArray)(results); |
|||
mw.storage.setObject(storageKey + category, CAL.variantCache[category], 60 * 60 * 24); |
|||
return CAL.variantCache[category]; |
|||
})(); |
|||
} |
|||
static regexBuilder(category) { |
|||
return _asyncToGenerator(function* () { |
|||
const catName = CAL.localizedRegex(CAL.TARGET_NAMESPACE, "Category"); |
|||
category = category.replace(/^[\s_]+/, "").replace(/[\s_]+$/, ""); |
|||
const variants = yield CAL.findAllVariants(category); |
|||
const variantRegExps = []; |
|||
var _iterator2 = _createForOfIteratorHelper(variants), _step2; |
|||
try { |
|||
for (_iterator2.s(); !(_step2 = _iterator2.n()).done; ) { |
|||
let variant = _step2.value; |
|||
variant = mw.util.escapeRegExp(variant); |
|||
variant = variant.replace(/[\s_]+/g, String.raw(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["[s_]+"], ["[\\s_]+"])))); |
|||
const first = variant.slice(0, 1); |
|||
if (first.toUpperCase() !== first.toLowerCase()) { |
|||
variant = "[".concat(first.toUpperCase()).concat(first.toLowerCase(), "]").concat(variant.slice(1)); |
|||
} |
|||
variantRegExps[variantRegExps.length] = variant; |
|||
} |
|||
} catch (err) { |
|||
_iterator2.e(err); |
|||
} finally { |
|||
_iterator2.f(); |
|||
} |
|||
return new RegExp("\\[\\[[\\s_]*".concat(catName, "[\\s_]*:[\\s_]*(?:").concat(variantRegExps.join("|"), ")[\\s_]*(\\|[^\\]]*(?:\\][^\\]]+)*)?\\]\\]"), "g"); |
|||
})(); |
|||
} |
|||
doAPICall(_params, callback) { |
|||
const params = _params; |
|||
params["format"] = "json"; |
|||
params["formatversion"] = "2"; |
|||
let i = 0; |
|||
const doCall = () => { |
|||
const handleError = (error) => { |
|||
mw.log.error("[Cat-a-lot] Ajax error:", error); |
|||
if (i < 4) { |
|||
setTimeout(doCall, 300); |
|||
i++; |
|||
} else if (params["title"]) { |
|||
CAL.connectionError[CAL.connectionError.length] = params["title"]; |
|||
this.updateCounter(); |
|||
} |
|||
}; |
|||
if (params["action"] === "query") { |
|||
CAL.api.get(params).then(callback).catch(handleError); |
|||
} else { |
|||
CAL.api.post(params).then(callback).catch(handleError); |
|||
} |
|||
}; |
|||
doCall(); |
|||
} |
|||
static markAsDone($markedLabel, targetCategory, mode) { |
|||
$markedLabel.addClass(CLASS_NAME_LABEL_DONE); |
|||
switch (mode) { |
|||
case "add": |
|||
$markedLabel.append(/* @__PURE__ */ import_ext_gadget3.default.createElement(import_ext_gadget3.default.Fragment, null, /* @__PURE__ */ import_ext_gadget3.default.createElement("br", null), CAL.msg("added-cat", targetCategory))); |
|||
break; |
|||
case "copy": |
|||
$markedLabel.append(/* @__PURE__ */ import_ext_gadget3.default.createElement(import_ext_gadget3.default.Fragment, null, /* @__PURE__ */ import_ext_gadget3.default.createElement("br", null), CAL.msg("copied-cat", targetCategory))); |
|||
break; |
|||
case "move": |
|||
$markedLabel.append(/* @__PURE__ */ import_ext_gadget3.default.createElement(import_ext_gadget3.default.Fragment, null, /* @__PURE__ */ import_ext_gadget3.default.createElement("br", null), CAL.msg("moved-cat", targetCategory))); |
|||
break; |
|||
case "remove": |
|||
$markedLabel.append(/* @__PURE__ */ import_ext_gadget3.default.createElement(import_ext_gadget3.default.Fragment, null, /* @__PURE__ */ import_ext_gadget3.default.createElement("br", null), CAL.msg("removed-cat", targetCategory))); |
|||
break; |
|||
} |
|||
} |
|||
static doCleanup(text) { |
|||
return CAL.settings.docleanup ? text.replace(/{{\s*[Cc]heck categories\s*(\|?.*?)}}/, "") : text; |
|||
} |
|||
// Remove {{Uncategorized}} (also with comment). No need to replace it with anything |
|||
static removeUncat(text) { |
|||
return text.replace(/\{\{\s*[Uu]ncategorized\s*(\|?.*?)\}\}/, ""); |
|||
} |
|||
displayResult() { |
|||
this.$body.css({ |
|||
cursor: "", |
|||
overflow: "" |
|||
}); |
|||
this.$body.find(".".concat(CLASS_NAME_FEEDBACK)).addClass(CLASS_NAME_FEEDBACK_DONE); |
|||
const $parent = CAL.$counter.parent(); |
|||
$parent.html(/* @__PURE__ */ import_ext_gadget3.default.createElement("h3", null, CAL.msg("done"))); |
|||
$parent.append(/* @__PURE__ */ import_ext_gadget3.default.createElement(import_ext_gadget3.default.Fragment, null, CAL.msg("all-done"), /* @__PURE__ */ import_ext_gadget3.default.createElement("br", null))); |
|||
$parent.append(/* @__PURE__ */ import_ext_gadget3.default.createElement("a", { |
|||
onClick: () => { |
|||
CAL.$progressDialog.remove(); |
|||
this.toggleAll(false); |
|||
} |
|||
}, CAL.msg("return-to-page"))); |
|||
if (CAL.alreadyThere.length) { |
|||
$parent.append(/* @__PURE__ */ import_ext_gadget3.default.createElement(import_ext_gadget3.default.Fragment, null, /* @__PURE__ */ import_ext_gadget3.default.createElement("h5", null, CAL.msg("skipped-already", CAL.alreadyThere.length.toString())), CAL.alreadyThere.reduce((pre, cur, index) => index < CAL.alreadyThere.length - 1 ? [...pre, cur, /* @__PURE__ */ import_ext_gadget3.default.createElement("br", { |
|||
key: index |
|||
})] : [...pre, cur], []))); |
|||
} |
|||
if (CAL.notFound.length) { |
|||
$parent.append(/* @__PURE__ */ import_ext_gadget3.default.createElement(import_ext_gadget3.default.Fragment, null, /* @__PURE__ */ import_ext_gadget3.default.createElement("h5", null, CAL.msg("skipped-not-found", CAL.notFound.length.toString())), CAL.notFound.reduce((pre, cur, index) => index < CAL.notFound.length - 1 ? [...pre, cur, /* @__PURE__ */ import_ext_gadget3.default.createElement("br", { |
|||
key: index |
|||
})] : [...pre, cur], []))); |
|||
} |
|||
if (CAL.connectionError.length) { |
|||
$parent.append(/* @__PURE__ */ import_ext_gadget3.default.createElement(import_ext_gadget3.default.Fragment, null, /* @__PURE__ */ import_ext_gadget3.default.createElement("h5", null, CAL.msg("skipped-server", CAL.connectionError.length.toString())), CAL.connectionError.reduce((pre, cur, index) => index < CAL.connectionError.length - 1 ? [...pre, cur, /* @__PURE__ */ import_ext_gadget3.default.createElement("br", { |
|||
key: index |
|||
})] : [...pre, cur], []))); |
|||
} |
|||
} |
|||
updateCounter() { |
|||
CAL.counterCurrent++; |
|||
if (CAL.counterCurrent > CAL.counterNeeded) { |
|||
this.displayResult(); |
|||
} else { |
|||
CAL.$counter.text(CAL.counterCurrent); |
|||
} |
|||
} |
|||
editCategories(result, markedLabel, targetCategory, mode) { |
|||
var _this = this; |
|||
return _asyncToGenerator(function* () { |
|||
var _page$revisions; |
|||
const [markedLabelTitle, $markedLabel] = markedLabel; |
|||
if (!(result !== null && result !== void 0 && result["query"])) { |
|||
CAL.connectionError[CAL.connectionError.length] = markedLabelTitle; |
|||
_this.updateCounter(); |
|||
return; |
|||
} |
|||
let originText = ""; |
|||
let starttimestamp = 0; |
|||
let timestamp = 0; |
|||
CAL.editToken = result["query"].tokens.csrftoken; |
|||
const { |
|||
pages |
|||
} = result["query"]; |
|||
const [page] = pages; |
|||
originText = page === null || page === void 0 || (_page$revisions = page.revisions) === null || _page$revisions === void 0 ? void 0 : _page$revisions[0].slots.main.content; |
|||
({ |
|||
starttimestamp |
|||
} = page); |
|||
[{ timestamp }] = page.revisions; |
|||
const sourcecat = CAL.CURRENT_CATEGROY; |
|||
const targetRegExp = yield CAL.regexBuilder(targetCategory); |
|||
if (mode !== "remove" && targetRegExp.test(originText) && mode !== "move") { |
|||
CAL.alreadyThere[CAL.alreadyThere.length] = markedLabelTitle; |
|||
_this.updateCounter(); |
|||
return; |
|||
} |
|||
let text = originText; |
|||
let summary; |
|||
const sourceCatRegExp = yield CAL.regexBuilder(sourcecat); |
|||
switch (mode) { |
|||
case "add": |
|||
text += "\n[[".concat(CAL.localCatName, ":").concat(targetCategory, "]]\n"); |
|||
summary = CAL.msg("summary-add").replace("$1", targetCategory); |
|||
break; |
|||
case "copy": |
|||
text = text.replace(sourceCatRegExp, "[[".concat(CAL.localCatName, ":").concat(sourcecat, "$1]]\n[[").concat(CAL.localCatName, ":").concat(targetCategory, "$1]]")); |
|||
summary = CAL.msg("summary-copy").replace("$1", sourcecat).replace("$2", targetCategory); |
|||
if (originText === text) { |
|||
text += "\n[[".concat(CAL.localCatName, ":").concat(targetCategory, "]]"); |
|||
} |
|||
break; |
|||
case "move": |
|||
text = text.replace(sourceCatRegExp, "[[".concat(CAL.localCatName, ":").concat(targetCategory, "$1]]")); |
|||
summary = CAL.msg("summary-move").replace("$1", sourcecat).replace("$2", targetCategory); |
|||
break; |
|||
case "remove": |
|||
text = text.replace(sourceCatRegExp, ""); |
|||
summary = CAL.msg("summary-remove").replace("$1", sourcecat); |
|||
break; |
|||
} |
|||
if (text === originText) { |
|||
CAL.notFound[CAL.notFound.length] = markedLabelTitle; |
|||
_this.updateCounter(); |
|||
return; |
|||
} |
|||
if (mode !== "remove") { |
|||
text = CAL.doCleanup(CAL.removeUncat(text)); |
|||
} |
|||
_this.doAPICall({ |
|||
action: "edit", |
|||
token: CAL.editToken, |
|||
title: markedLabelTitle, |
|||
assert: "user", |
|||
bot: true, |
|||
basetimestamp: timestamp, |
|||
watchlist: CAL.settings.watchlist, |
|||
text, |
|||
summary, |
|||
starttimestamp |
|||
}, () => { |
|||
_this.updateCounter(); |
|||
}); |
|||
CAL.markAsDone($markedLabel, targetCategory, mode); |
|||
})(); |
|||
} |
|||
getContent(markedLabel, targetCategory, mode) { |
|||
this.doAPICall({ |
|||
action: "query", |
|||
formatversion: "2", |
|||
meta: "tokens", |
|||
titles: markedLabel[0], |
|||
prop: "revisions", |
|||
rvprop: ["content", "timestamp"], |
|||
rvslots: "main" |
|||
}, (result) => { |
|||
void this.editCategories(result, markedLabel, targetCategory, mode); |
|||
}); |
|||
} |
|||
static getTitleFromLink(href) { |
|||
try { |
|||
var hrefDecoded = decodeURIComponent(href !== null && href !== void 0 ? href : ""); |
|||
var match = hrefDecoded.match(/wiki\/(.+?)(?:#.+)?$/) || hrefDecoded.match(/[?&]title=([^&#]+)/); |
|||
return (match ? match[1] : "").replace(/_/g, " "); |
|||
} catch (e) { |
|||
return ""; |
|||
} |
|||
} |
|||
getMarkedLabels() { |
|||
const markedLabels = []; |
|||
CAL.$selectedLabels = CAL.$labels.filter(".".concat(CLASS_NAME_LABEL_SELECTED)); |
|||
CAL.$selectedLabels.each((_index, label) => { |
|||
var _$labelLink$attr; |
|||
const $label = $(label); |
|||
const $labelLink = $label.find("a:not(.CategoryTreeToggle)[title]"); |
|||
const title = ((_$labelLink$attr = $labelLink.attr("title")) === null || _$labelLink$attr === void 0 ? void 0 : _$labelLink$attr.trim()) || CAL.getTitleFromLink($labelLink.attr("href")) || CAL.getTitleFromLink($label.find("a:not(.CategoryTreeToggle)").attr("href")); |
|||
markedLabels[markedLabels.length] = [title, $label]; |
|||
}); |
|||
return markedLabels; |
|||
} |
|||
showProgress() { |
|||
this.$body.css({ |
|||
cursor: "wait", |
|||
overflow: "hidden" |
|||
}); |
|||
CAL.$progressDialog = $(/* @__PURE__ */ import_ext_gadget3.default.createElement("div", null, CAL.msg("editing"), /* @__PURE__ */ import_ext_gadget3.default.createElement("span", { |
|||
className: CLASS_NAME_CURRENT_COUNTER |
|||
}, CAL.counterCurrent), [CAL.msg("of"), CAL.counterNeeded])).dialog({ |
|||
dialogClass: CLASS_NAME_FEEDBACK, |
|||
minHeight: 90, |
|||
height: 90, |
|||
width: 450, |
|||
modal: true, |
|||
closeOnEscape: false, |
|||
draggable: false, |
|||
resizable: false |
|||
}); |
|||
this.$body.find(".".concat(CLASS_NAME_FEEDBACK, " .ui-dialog-titlebar")).hide(); |
|||
this.$body.find(".".concat(CLASS_NAME_FEEDBACK, " .ui-dialog-content")).height("auto"); |
|||
CAL.$counter = this.$body.find(".".concat(CLASS_NAME_CURRENT_COUNTER)); |
|||
} |
|||
doSomething(targetCategory, mode) { |
|||
const markedLabels = this.getMarkedLabels(); |
|||
if (!markedLabels.length) { |
|||
void mw.notify(CAL.msg("none-selected"), { |
|||
tag: "catALot" |
|||
}); |
|||
return; |
|||
} |
|||
CAL.alreadyThere = []; |
|||
CAL.connectionError = []; |
|||
CAL.notFound = []; |
|||
CAL.counterCurrent = 1; |
|||
CAL.counterNeeded = markedLabels.length; |
|||
this.showProgress(); |
|||
var _iterator3 = _createForOfIteratorHelper(markedLabels), _step3; |
|||
try { |
|||
for (_iterator3.s(); !(_step3 = _iterator3.n()).done; ) { |
|||
const markedLabel = _step3.value; |
|||
this.getContent(markedLabel, targetCategory, mode); |
|||
} |
|||
} catch (err) { |
|||
_iterator3.e(err); |
|||
} finally { |
|||
_iterator3.f(); |
|||
} |
|||
} |
|||
addHere(targetCategory) { |
|||
this.doSomething(targetCategory, "add"); |
|||
} |
|||
copyHere(targetCategory) { |
|||
this.doSomething(targetCategory, "copy"); |
|||
} |
|||
moveHere(targetCategory) { |
|||
this.doSomething(targetCategory, "move"); |
|||
} |
|||
createCatLinks(symbol, categories) { |
|||
categories.sort(); |
|||
var _iterator4 = _createForOfIteratorHelper(categories), _step4; |
|||
try { |
|||
for (_iterator4.s(); !(_step4 = _iterator4.n()).done; ) { |
|||
const category = _step4.value; |
|||
const $tr = $(/* @__PURE__ */ import_ext_gadget3.default.createElement("tr", { |
|||
dataset: { |
|||
category |
|||
} |
|||
}, /* @__PURE__ */ import_ext_gadget3.default.createElement("td", null, symbol), /* @__PURE__ */ import_ext_gadget3.default.createElement("td", null, /* @__PURE__ */ import_ext_gadget3.default.createElement("a", { |
|||
onClick: (event) => { |
|||
const $element = $(event.currentTarget); |
|||
this.updateCats($element.closest("tr").data("category")); |
|||
} |
|||
}, category)))); |
|||
if (category !== CAL.CURRENT_CATEGROY && CAL.isSearchMode) { |
|||
$tr.append(/* @__PURE__ */ import_ext_gadget3.default.createElement("td", null, /* @__PURE__ */ import_ext_gadget3.default.createElement("a", { |
|||
className: CLASS_NAME_CONTAINER_DATA_CATEGORY_LIST_ACTION, |
|||
onClick: (event) => { |
|||
const $element = $(event.currentTarget); |
|||
this.addHere($element.closest("tr").data("category")); |
|||
} |
|||
}, CAL.msg("add")))); |
|||
} else if (category !== CAL.CURRENT_CATEGROY && !CAL.isSearchMode) { |
|||
$tr.append(/* @__PURE__ */ import_ext_gadget3.default.createElement(import_ext_gadget3.default.Fragment, null, /* @__PURE__ */ import_ext_gadget3.default.createElement("td", null, /* @__PURE__ */ import_ext_gadget3.default.createElement("a", { |
|||
className: CLASS_NAME_CONTAINER_DATA_CATEGORY_LIST_ACTION, |
|||
onClick: (event) => { |
|||
const $element = $(event.currentTarget); |
|||
this.copyHere($element.closest("tr").data("category")); |
|||
} |
|||
}, CAL.msg("copy"))), /* @__PURE__ */ import_ext_gadget3.default.createElement("td", null, /* @__PURE__ */ import_ext_gadget3.default.createElement("a", { |
|||
className: CLASS_NAME_CONTAINER_DATA_CATEGORY_LIST_ACTION, |
|||
onClick: (event) => { |
|||
const $element = $(event.currentTarget); |
|||
this.moveHere($element.closest("tr").data("category")); |
|||
} |
|||
}, CAL.msg("move"))))); |
|||
} |
|||
this.$resultList.find("table").append($tr); |
|||
} |
|||
} catch (err) { |
|||
_iterator4.e(err); |
|||
} finally { |
|||
_iterator4.f(); |
|||
} |
|||
} |
|||
showCategoryList() { |
|||
var _this$$container$widt, _$$width; |
|||
this.$body.css("cursor", ""); |
|||
const currentCategories = [CAL.currentCategory]; |
|||
this.$resultList.empty(); |
|||
this.$resultList.append(/* @__PURE__ */ import_ext_gadget3.default.createElement("table", null)); |
|||
this.createCatLinks("↑", CAL.parentCats); |
|||
this.createCatLinks("→", currentCategories); |
|||
this.createCatLinks("↓", CAL.subCats); |
|||
this.$container.width(""); |
|||
this.$container.height(""); |
|||
this.$container.width(Math.min(((_this$$container$widt = this.$container.width()) !== null && _this$$container$widt !== void 0 ? _this$$container$widt : 0) * 1.1 + 15, ((_$$width = $(window).width()) !== null && _$$width !== void 0 ? _$$width : 0) - 10)); |
|||
this.$resultList.css({ |
|||
"max-height": "".concat(CAL.dialogHeight, "px"), |
|||
height: "" |
|||
}); |
|||
} |
|||
getParentCats() { |
|||
this.doAPICall({ |
|||
action: "query", |
|||
titles: "Category:".concat(CAL.currentCategory), |
|||
prop: "categories" |
|||
}, (result) => { |
|||
var _pages$, _pages$2; |
|||
if (!result) { |
|||
return; |
|||
} |
|||
CAL.parentCats = []; |
|||
const { |
|||
pages |
|||
} = result.query; |
|||
if ((_pages$ = pages[0]) !== null && _pages$ !== void 0 && _pages$.missing) { |
|||
this.$body.css("cursor", ""); |
|||
this.$resultList.html(/* @__PURE__ */ import_ext_gadget3.default.createElement("span", { |
|||
className: CLASS_NAME_CONTAINER_DATA_CATEGORY_LIST_NO_FOUND |
|||
}, CAL.msg("cat-not-found"))); |
|||
this.createCatLinks("→", [CAL.currentCategory]); |
|||
return; |
|||
} |
|||
let categories = []; |
|||
if ((_pages$2 = pages[0]) !== null && _pages$2 !== void 0 && _pages$2.categories) { |
|||
[{ |
|||
categories |
|||
}] = pages; |
|||
} |
|||
var _iterator5 = _createForOfIteratorHelper(categories), _step5; |
|||
try { |
|||
for (_iterator5.s(); !(_step5 = _iterator5.n()).done; ) { |
|||
const cat = _step5.value; |
|||
const catTitle = cat.title.replace(/^[^:]+:/, ""); |
|||
CAL.parentCats[CAL.parentCats.length] = catTitle; |
|||
} |
|||
} catch (err) { |
|||
_iterator5.e(err); |
|||
} finally { |
|||
_iterator5.f(); |
|||
} |
|||
CAL.counterCat++; |
|||
if (CAL.counterCat === 2) { |
|||
this.showCategoryList(); |
|||
} |
|||
}); |
|||
} |
|||
getSubCats() { |
|||
this.doAPICall({ |
|||
action: "query", |
|||
list: "categorymembers", |
|||
cmtype: "subcat", |
|||
cmlimit: CAL.settings.subcatcount, |
|||
cmtitle: "Category:".concat(CAL.currentCategory) |
|||
}, (result) => { |
|||
var _result$query; |
|||
const cats = (result === null || result === void 0 || (_result$query = result.query) === null || _result$query === void 0 ? void 0 : _result$query.categorymembers) || []; |
|||
CAL.subCats = []; |
|||
var _iterator6 = _createForOfIteratorHelper(cats), _step6; |
|||
try { |
|||
for (_iterator6.s(); !(_step6 = _iterator6.n()).done; ) { |
|||
const cat = _step6.value; |
|||
const catTitle = cat.title.replace(/^[^:]+:/, ""); |
|||
CAL.subCats[CAL.subCats.length] = catTitle; |
|||
} |
|||
} catch (err) { |
|||
_iterator6.e(err); |
|||
} finally { |
|||
_iterator6.f(); |
|||
} |
|||
CAL.counterCat++; |
|||
if (CAL.counterCat === 2) { |
|||
this.showCategoryList(); |
|||
} |
|||
}); |
|||
} |
|||
getCategoryList() { |
|||
CAL.counterCat = 0; |
|||
this.getParentCats(); |
|||
this.getSubCats(); |
|||
} |
|||
updateCats(cat) { |
|||
this.$body.css("cursor", "wait"); |
|||
CAL.currentCategory = cat; |
|||
this.$resultList.html(/* @__PURE__ */ import_ext_gadget3.default.createElement("div", null, CAL.msg("loading"))); |
|||
this.getCategoryList(); |
|||
} |
|||
findAllLabels() { |
|||
if (CAL.isSearchMode) { |
|||
CAL.$labels = this.$body.find("table.searchResultImage").find("tr>td").eq(1); |
|||
if (CAL.settings.editpages) { |
|||
CAL.$labels = CAL.$labels.add("div.mw-search-result-heading"); |
|||
} |
|||
} else { |
|||
CAL.$labels = this.$body.find("div.gallerytext").add(this.$body.find("div#mw-category-media").find('li[class!="gallerybox"]')); |
|||
if (CAL.settings.editpages) { |
|||
const $pages = this.$body.find("div#mw-pages, div#mw-subcategories").find("li"); |
|||
CAL.$labels = CAL.$labels.add($pages); |
|||
} |
|||
} |
|||
} |
|||
makeClickable() { |
|||
this.findAllLabels(); |
|||
CAL.$labels.addClass(CLASS_NAME_LABEL).onCatALotShiftClick(() => { |
|||
this.updateSelectionCounter(); |
|||
}); |
|||
} |
|||
run() { |
|||
if (this.$link.hasClass(CLASS_NAME_CONTAINER_HEAD_LINK_ENABLED)) { |
|||
this.makeClickable(); |
|||
this.$dataContainer.show(); |
|||
this.$container.resizable({ |
|||
alsoResize: this.$resultList, |
|||
handles: "n", |
|||
resize: (event) => { |
|||
var _$currentTarget$heigh; |
|||
const $currentTarget = $(event.currentTarget); |
|||
$currentTarget.css({ |
|||
left: "", |
|||
top: "" |
|||
}); |
|||
CAL.dialogHeight = (_$currentTarget$heigh = $currentTarget.height()) !== null && _$currentTarget$heigh !== void 0 ? _$currentTarget$heigh : CAL.dialogHeight; |
|||
this.$resultList.css({ |
|||
maxHeight: "", |
|||
width: "" |
|||
}); |
|||
} |
|||
}); |
|||
this.$resultList.css("max-height", "450px"); |
|||
if (CAL.isSearchMode) { |
|||
this.updateCats(mw.util.getParamValue("search") || ""); |
|||
} else { |
|||
this.updateCats(CAL.CURRENT_CATEGROY); |
|||
} |
|||
} else { |
|||
this.$dataContainer.hide(); |
|||
this.$container.resizable("destroy"); |
|||
this.$container.css("width", ""); |
|||
CAL.$labels.off("click.catALot"); |
|||
} |
|||
} |
|||
} |
|||
if (wgNamespaceNumber === -1 && wgCanonicalSpecialPageName === "Search" || wgNamespaceNumber === targetNamespace) { |
|||
if (wgNamespaceNumber === -1) { |
|||
CAL.isSearchMode = true; |
|||
} |
|||
CAL["variantCache"] = getCachedKeys(); |
|||
if (wgNamespaceNumber === targetNamespace) { |
|||
const category = mw.config.get("wgTitle").replace(/^Category:/, ""); |
|||
CAL["variantCache"][category] = [...yield CAL.findAllVariants(category)]; |
|||
} |
|||
/*! Cat-a-lot messages | CC-BY-SA-4.0 <https://qwbk.cc/H:CC-BY-SA-4.0> */ |
|||
setMessages(); |
|||
void (0, import_ext_gadget2.getBody)().then(($body) => { |
|||
new CAL($body).buildElements(); |
|||
}); |
|||
} |
|||
}); |
|||
return function catALot2() { |
|||
return _ref.apply(this, arguments); |
|||
}; |
|||
})(); |
|||
//! src/Cat-a-lot/modules/extendJQueryPrototype.ts |
|||
var extendJQueryPrototype = () => { |
|||
$.fn.extend({ |
|||
onCatALotShiftClick: function(callback) { |
|||
let prevCheckbox; |
|||
this.on("click.catALot", (event) => { |
|||
if (!event.ctrlKey) { |
|||
event.preventDefault(); |
|||
} |
|||
this.parents("body").find(".".concat(CLASS_NAME_LABEL_LAST_SELECTED)).removeClass(CLASS_NAME_LABEL_LAST_SELECTED); |
|||
let $thisControl = $(event.target); |
|||
if (!$thisControl.hasClass(CLASS_NAME_LABEL)) { |
|||
$thisControl = $thisControl.parents(".".concat(CLASS_NAME_LABEL)); |
|||
} |
|||
$thisControl.addClass(CLASS_NAME_LABEL_LAST_SELECTED).toggleClass(CLASS_NAME_LABEL_SELECTED); |
|||
if (prevCheckbox && event.shiftKey) { |
|||
const method = $thisControl.hasClass(CLASS_NAME_LABEL_SELECTED) ? "addClass" : "removeClass"; |
|||
this.slice(Math.min(this.index(prevCheckbox), this.index($thisControl)), Math.max(this.index(prevCheckbox), this.index($thisControl)) + 1)[method](CLASS_NAME_LABEL_SELECTED); |
|||
} |
|||
prevCheckbox = $thisControl; |
|||
if (typeof callback === "function") { |
|||
callback(); |
|||
} |
|||
}); |
|||
return this; |
|||
} |
|||
}); |
|||
}; |
|||
//! src/Cat-a-lot/Cat-a-lot.ts |
|||
/*! Cat-a-lot | CC-BY-SA-4.0 <https://qwbk.cc/H:CC-BY-SA-4.0> */ |
|||
extendJQueryPrototype(); |
|||
void catALot(); |
|||
})(); |
|||
if ( $.isFunction( cb ) ) cb(); |
|||
} ); |
|||
return $box; |
|||
}; |
|||
}( jQuery ) ); |
|||
/ |
/* </nowiki> */ |
||
2026年6月18日 (四) 18:20的最新版本
/**
* SPDX-License-Identifier: CC-BY-SA-4.0
* _addText: '{{Gadget Header|title1=Cat-a-lot.js|license=CC-BY-SA-4.0}}'
*
* Cat-a-lot
*
* @base {@link https://zh.wikipedia.org/wiki/MediaWiki:Gadget-Cat-a-lot.js}
* @base {@link https://commons.wikimedia.org/wiki/MediaWiki:Gadget-Cat-a-lot.js}
* @source {@link https://git.qiuwen.net.cn/InterfaceAdmin/QiuwenGadgets/src/branch/master/src/Cat-a-lot/modules/core.ts}
* @author Magnus Manske, Ilmari Karonen, DieBuche, 安忆 <i@anyi.in>
* @license CC-BY-SA-4.0 {@link https://www.qiuwenbaike.cn/wiki/H:CC-BY-SA-4.0}
*/
/**
* SPDX-License-Identifier: CC-BY-SA-4.0
* _addText: '{{Gadget Header|title2=Cat-a-lot Messages|license2=CC-BY-SA-4.0}}'
*
* Cat-a-lot messages
*
* @base {@link https://commons.wikimedia.org/wiki/MediaWiki:Gadget-Cat-a-lot.js/zh-hans}
* @base {@link https://commons.wikimedia.org/wiki/MediaWiki:Gadget-Cat-a-lot.js/zh-hant}
* @source {@link https://git.qiuwen.net.cn/InterfaceAdmin/QiuwenGadgets/src/branch/master/src/Cat-a-lot/modules/messages.ts}
* @license CC-BY-SA-4.0 {@link https://www.qiuwenbaike.cn/wiki/H:CC-BY-SA-4.0}
*/
/**
* SPDX-License-Identifier: CC-BY-SA-4.0
* _addText: '{{Gadget Header|title3=jQuery checkboxShiftClick|license3=CC-BY-SA-4.0}}'
*
* jQuery checkboxShiftClick
*
* @description This will enable checkboxes to be checked or unchecked in a row by clicking one, holding shift and clicking another one
* @base {@link https://commons.wikimedia.org/wiki/MediaWiki:Gadget-Cat-a-lot.js}
* @source {@link https://git.qiuwen.net.cn/InterfaceAdmin/QiuwenGadgets/src/branch/master/src/Cat-a-lot/modules/extendJQueryPrototype.ts}
* @author Krinkle <krinklemail@gmail.com>
* @license CC-BY-SA-4.0 {@link https://www.qiuwenbaike.cn/wiki/H:CC-BY-SA-4.0}
*/
/**
* Hereby releasing jquery.checkboxShiftClick into CC BY-SA 3.0,
* CC BY 4.0, CC-0 and for all intends and purpose in the public
* domain, so as to not need this annotation.
*
* @source {@link https://commons.wikimedia.org/w/index.php?oldid=365723751}
*/
/**
* +------------------------------------------------------------+
* | === WARNING: GLOBAL GADGET FILE === |
* +------------------------------------------------------------+
* | All changes should be made in the repository, |
* | otherwise they will be lost. |
* +------------------------------------------------------------+
* | Changes to this page may affect many users. |
* | Please discuss changes by opening an issue before editing. |
* +------------------------------------------------------------+
*/
/* <nowiki> */
(() => {
"use strict";
// dist/Cat-a-lot/Cat-a-lot.js
var _templateObject;
var _templateObject2;
var _templateObject3;
function _taggedTemplateLiteral(e, t) {
return t || (t = e.slice(0)), Object.freeze(Object.defineProperties(e, { raw: { value: Object.freeze(t) } }));
}
function asyncGeneratorStep(n, t, e, r, o, a, c) {
try {
var i = n[a](c), u = i.value;
} catch (n2) {
return void e(n2);
}
i.done ? t(u) : Promise.resolve(u).then(r, o);
}
function _asyncToGenerator(n) {
return function() {
var t = this, e = arguments;
return new Promise(function(r, o) {
var a = n.apply(t, e);
function _next(n2) {
asyncGeneratorStep(a, r, o, _next, _throw, "next", n2);
}
function _throw(n2) {
asyncGeneratorStep(a, r, o, _next, _throw, "throw", n2);
}
_next(void 0);
});
};
}
function _createForOfIteratorHelper(r, e) {
var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
if (!t) {
if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) {
t && (r = t);
var n = 0, F = function() {
};
return { s: F, n: function() {
return n >= r.length ? { done: true } : { done: false, value: r[n++] };
}, e: function(r2) {
throw r2;
}, f: F };
}
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
var o, a = true, u = false;
return { s: function() {
t = t.call(r);
}, n: function() {
var r2 = t.next();
return a = r2.done, r2;
}, e: function(r2) {
u = true, o = r2;
}, f: function() {
try {
a || null == t.return || t.return();
} finally {
if (u) throw o;
}
} };
}
function _unsupportedIterableToArray(r, a) {
if (r) {
if ("string" == typeof r) return _arrayLikeToArray(r, a);
var t = {}.toString.call(r).slice(8, -1);
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
}
}
function _arrayLikeToArray(r, a) {
(null == a || a > r.length) && (a = r.length);
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
return n;
}
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
var _iterator = _createForOfIteratorHelper(__getOwnPropNames(from)), _step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done; ) {
let key = _step.value;
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: () => from[key],
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target,
mod
));
//! src/Cat-a-lot/options.json
var apiTag = "";
var targetNamespace = 14;
var version = "6.0";
var storageKey = "ext.gadget.Cat-a-Lot_results-";
//! src/Cat-a-lot/modules/constant.ts
var CLASS_NAME = "gadget-cat_a_lot";
var CLASS_NAME_CONTAINER = "".concat(CLASS_NAME, "-container");
var CLASS_NAME_CONTAINER_DATA = "".concat(CLASS_NAME_CONTAINER, "__data");
var CLASS_NAME_CONTAINER_DATA_CATEGORY_LIST = "".concat(CLASS_NAME_CONTAINER_DATA, "__category-list");
var CLASS_NAME_CONTAINER_DATA_CATEGORY_LIST_ACTION = "".concat(CLASS_NAME_CONTAINER_DATA_CATEGORY_LIST, "__action");
var CLASS_NAME_CONTAINER_DATA_CATEGORY_LIST_NO_FOUND = "".concat(CLASS_NAME_CONTAINER_DATA_CATEGORY_LIST, "--no-found");
var CLASS_NAME_CONTAINER_DATA_MARK_COUNTER = "".concat(CLASS_NAME_CONTAINER_DATA, "__mark-counter");
var CLASS_NAME_CONTAINER_DATA_SEARCH_INPUT_CONTAINER_INPUT = "".concat(CLASS_NAME_CONTAINER_DATA, "__search-input-container__input");
var CLASS_NAME_CONTAINER_DATA_SELECTIONS = "".concat(CLASS_NAME_CONTAINER_DATA, "__selections");
var CLASS_NAME_CONTAINER_DATA_SELECTIONS_ALL = "".concat(CLASS_NAME_CONTAINER_DATA_SELECTIONS, "__all");
var CLASS_NAME_CONTAINER_DATA_SELECTIONS_NONE = "".concat(CLASS_NAME_CONTAINER_DATA_SELECTIONS, "__none");
var CLASS_NAME_CONTAINER_HEAD = "".concat(CLASS_NAME_CONTAINER, "__head");
var CLASS_NAME_CONTAINER_HEAD_LINK = "".concat(CLASS_NAME_CONTAINER_HEAD, "__link");
var CLASS_NAME_CONTAINER_HEAD_LINK_ENABLED = "".concat(CLASS_NAME_CONTAINER_HEAD_LINK, "--enabled");
var CLASS_NAME_CURRENT_COUNTER = "".concat(CLASS_NAME, "-current_counter");
var CLASS_NAME_FEEDBACK = "".concat(CLASS_NAME, "-feedback");
var CLASS_NAME_FEEDBACK_DONE = "".concat(CLASS_NAME_FEEDBACK, "--done");
var CLASS_NAME_LABEL = "".concat(CLASS_NAME, "-label");
var CLASS_NAME_LABEL_DONE = "".concat(CLASS_NAME_LABEL, "--done");
var CLASS_NAME_LABEL_LAST_SELECTED = "".concat(CLASS_NAME_LABEL, "--last-selected");
var CLASS_NAME_LABEL_SELECTED = "".concat(CLASS_NAME_LABEL, "--selected");
var DEFAULT_SETTING = {
docleanup: {
default: false,
label_i18n: "docleanuppref"
},
editpages: {
default: true,
label_i18n: "editpagespref"
},
minor: {
default: false,
label_i18n: "minorpref"
},
subcatcount: {
default: 50,
label_i18n: "subcatcountpref"
},
watchlist: {
default: "preferences",
label_i18n: "watchlistpref",
select_i18n: {
watch_nochange: "nochange",
watch_pref: "preferences",
watch_unwatch: "unwatch",
watch_watch: "watch"
}
}
};
var VARIANTS = ["zh-hans", "zh-hant", "zh-cn", "zh-my", "zh-sg", "zh-hk", "zh-mo", "zh-tw"];
//! src/Cat-a-lot/modules/messages.ts
var {
wgUserLanguage
} = mw.config.get();
var DEFAULT_MESSAGES = {
// as in 17 files selected
"cat-a-lot-files-selected": "{{PLURAL:$1|One file|$1 files}} selected.",
// Actions
"cat-a-lot-copy": "Copy",
"cat-a-lot-move": "Move",
"cat-a-lot-add": "Add",
"cat-a-lot-remove-from-cat": "Remove from this category",
"cat-a-lot-enter-name": "Enter category name",
"cat-a-lot-select": "Select",
"cat-a-lot-all": "all",
"cat-a-lot-none": "none",
"cat-a-lot-none-selected": "No files selected!",
// Preferences
"cat-a-lot-watchlistpref": "Watchlist preference concerning files edited with Cat-A-Lot",
"cat-a-lot-watch_pref": "According to your general preferences",
"cat-a-lot-watch_nochange": "Do not change watchstatus",
"cat-a-lot-watch_watch": "Watch pages edited with Cat-A-Lot",
"cat-a-lot-watch_unwatch": "Remove pages while editing with Cat-A-Lot from your watchlist",
"cat-a-lot-minorpref": "Mark edits as minor (if you generally mark your edits as minor, this won't change anything)",
"cat-a-lot-editpagespref": "Allow categorising pages (including categories) that are not files",
"cat-a-lot-docleanuppref": "Remove {{Check categories}} and other minor cleanup",
"cat-a-lot-subcatcountpref": "Sub-categories to show at most",
// Progress
"cat-a-lot-loading": "Loading...",
"cat-a-lot-editing": "Editing page",
"cat-a-lot-of": "of ",
"cat-a-lot-skipped-already": "The following {{PLURAL:$1|page was|$1 pages were}} skipped, because the page was already in the category:",
"cat-a-lot-skipped-not-found": "The following {{PLURAL:$1|page was|$1 pages were}} skipped, because the old category could not be found:",
"cat-a-lot-skipped-server": "The following {{PLURAL:$1|page|$1 pages}} couldn't be changed, since there were problems connecting to the server:",
"cat-a-lot-all-done": "All pages are processed.",
"cat-a-lot-done": "Done!",
"cat-a-lot-added-cat": "Added category $1",
"cat-a-lot-copied-cat": "Copied to category $1",
"cat-a-lot-moved-cat": "Moved to category $1",
"cat-a-lot-removed-cat": "Removed from category $1",
"cat-a-lot-return-to-page": "Return to page",
"cat-a-lot-cat-not-found": "Category not found.",
// Summaries:
"cat-a-lot-summary-add": "[[Help:Cat-a-lot|Cat-a-lot]]: Adding [[Category:$1]]",
"cat-a-lot-summary-copy": "[[Help:Cat-a-lot|Cat-a-lot]]: Copying from [[Category:$1]] to [[Category:$2]]",
"cat-a-lot-summary-move": "[[Help:Cat-a-lot|Cat-a-lot]]: Moving from [[Category:$1]] to [[Category:$2]]",
"cat-a-lot-summary-remove": "[[Help:Cat-a-lot|Cat-a-lot]]: Removing from [[Category:$1]]"
};
var setMessages = () => {
/*! Cat-a-lot messages | CC-BY-SA-4.0 <https://qwbk.cc/H:CC-BY-SA-4.0> */
if (wgUserLanguage === "en") {
return;
}
if (["zh-hant", "zh-hk", "zh-mo", "zh-tw"].includes(wgUserLanguage)) {
mw.messages.set({
// as in 17 files selected
"cat-a-lot-files-selected": "$1個文件已選擇",
// Actions
"cat-a-lot-copy": "複製",
"cat-a-lot-move": "移動",
"cat-a-lot-add": "增加",
"cat-a-lot-remove-from-cat": "從此分類移除",
"cat-a-lot-enter-name": "輸入分類名稱",
"cat-a-lot-select": "選擇",
"cat-a-lot-all": "全部",
"cat-a-lot-none": "無",
"cat-a-lot-none-selected": "沒有選擇文件!",
// Preferences
"cat-a-lot-watchlistpref": "使用Cat-A-Lot編輯文件時的監視列表選項",
"cat-a-lot-watch_pref": "與系統參數設置相同",
"cat-a-lot-watch_nochange": "不要更改監視狀態",
"cat-a-lot-watch_watch": "監視使用Cat-A-Lot編輯的頁面",
"cat-a-lot-watch_unwatch": "將使用Cat-A-Lot編輯的頁面從監視列表移除",
"cat-a-lot-minorpref": "將編輯標記爲小修改(若您在系統參數設置中已設置將所有編輯標記爲小修改,此選項不會對現有行爲進行改動)",
"cat-a-lot-editpagespref": "允許對不是文件的頁面和子分類進行分類操作",
"cat-a-lot-docleanuppref": "移除{{Check categories}}並進行其他細節清理",
"cat-a-lot-subcatcountpref": "最多顯示的子分類數量",
// Progress
"cat-a-lot-loading": "正在加載……",
"cat-a-lot-editing": "正在編輯頁面",
"cat-a-lot-of": ",共有",
"cat-a-lot-skipped-already": "以下頁面已跳過,因爲頁面已經在分類中:",
"cat-a-lot-skipped-not-found": "以下頁面已跳過,因爲找不到現有分類:",
"cat-a-lot-skipped-server": "以下頁面無法編輯,因爲連接服務器出錯:",
"cat-a-lot-all-done": "全部頁面已處理。",
"cat-a-lot-done": "已完成!",
"cat-a-lot-added-cat": "已加入分類",
"cat-a-lot-copied-cat": "已複製到分類",
"cat-a-lot-moved-cat": "已移動到分類",
"cat-a-lot-removed-cat": "已從分類移除",
"cat-a-lot-return-to-page": "返回到頁面",
"cat-a-lot-cat-not-found": "找不到分類。",
// Summaries
"cat-a-lot-summary-add": "[[Help:Cat-a-lot|Cat-a-lot]]:加入分類[[Category:$1]]",
"cat-a-lot-summary-copy": "[[Help:Cat-a-lot|Cat-a-lot]]:分類間複製:從[[Category:$1]]到[[Category:$2]]",
"cat-a-lot-summary-move": "[[Help:Cat-a-lot|Cat-a-lot]]:分類間移動:從[[Category:$1]]到[[Category:$2]]",
"cat-a-lot-summary-remove": "[[Help:Cat-a-lot|Cat-a-lot]]:從分類移除:[[Category:$1]]"
});
} else {
mw.messages.set({
// as in 17 files selected
"cat-a-lot-files-selected": "已选择$1个页面或文件",
// Actions
"cat-a-lot-copy": "复制",
"cat-a-lot-move": "移动",
"cat-a-lot-add": "增加",
"cat-a-lot-remove-from-cat": "从此分类移除",
"cat-a-lot-enter-name": "输入分类名称",
"cat-a-lot-select": "选择",
"cat-a-lot-all": "全部",
"cat-a-lot-none": "无",
"cat-a-lot-none-selected": "没有选择任何页面或文件!",
// Preferences
"cat-a-lot-watchlistpref": "使用Cat-a-lot编辑文件时的监视列表选项",
"cat-a-lot-watch_pref": "与系统参数设置相同",
"cat-a-lot-watch_nochange": "不要更改监视状态",
"cat-a-lot-watch_watch": "监视使用Cat-a-lot编辑的页面",
"cat-a-lot-watch_unwatch": "将使用Cat-a-lot编辑的页面从监视列表移除",
"cat-a-lot-minorpref": "将编辑标记为小修改(若您在系统参数设置中已设置将所有编辑标记为小修改,此选项不会对现有行为进行改动)",
"cat-a-lot-editpagespref": "允许对不是文件的页面和子分类进行分类操作",
"cat-a-lot-docleanuppref": "移除{{Check categories}}并进行其他细节清理",
"cat-a-lot-subcatcountpref": "最多显示的子分类数量",
// Progress
"cat-a-lot-loading": "正在加载……",
"cat-a-lot-editing": "正在编辑页面",
"cat-a-lot-of": ",共有",
"cat-a-lot-skipped-already": "以下页面已跳过,因为页面已经在分类中:",
"cat-a-lot-skipped-not-found": "以下页面已跳过,因为找不到现有分类:",
"cat-a-lot-skipped-server": "以下页面无法编辑,因为连接服务器出错:",
"cat-a-lot-all-done": "全部页面已处理。",
"cat-a-lot-done": "已完成!",
"cat-a-lot-added-cat": "已加入分类",
"cat-a-lot-copied-cat": "已复制到分类",
"cat-a-lot-moved-cat": "已移动到分类",
"cat-a-lot-removed-cat": "已从分类移除",
"cat-a-lot-return-to-page": "返回到页面",
"cat-a-lot-cat-not-found": "找不到分类。",
// Summaries
"cat-a-lot-summary-add": "[[Help:Cat-a-lot|Cat-a-lot]]:加入分类[[Category:$1]]",
"cat-a-lot-summary-copy": "[[Help:Cat-a-lot|Cat-a-lot]]:分类间复制:从[[Category:$1]]到[[Category:$2]]",
"cat-a-lot-summary-move": "[[Help:Cat-a-lot|Cat-a-lot]]:分类间移动:从[[Category:$1]]到[[Category:$2]]",
"cat-a-lot-summary-remove": "[[Help:Cat-a-lot|Cat-a-lot]]:从分类移除:[[Category:$1]]"
});
}
};
//! src/Cat-a-lot/modules/core.tsx
var import_ext_gadget2 = require("ext.gadget.Util");
var import_ext_gadget3 = __toESM(require("ext.gadget.JSX"), 1);
//! src/Cat-a-lot/modules/api.ts
var import_ext_gadget = require("ext.gadget.Util");
var api = (0, import_ext_gadget.initMwApi)("Cat-a-lot/".concat(version));
//! src/Cat-a-lot/modules/getCachedKeys.ts
var getCachedKeys = () => {
const variantCache = {};
for (var _i = 0, _Object$entries = Object.entries(mw.storage["store"]); _i < _Object$entries.length; _i++) {
const [key, value] = _Object$entries[_i];
if (key.startsWith(storageKey) && Array.isArray(value)) {
const cacheKey = key.replace(storageKey, "");
variantCache[cacheKey] = value;
}
}
return variantCache;
};
//! src/Cat-a-lot/modules/core.tsx
var {
wgCanonicalSpecialPageName,
wgFormattedNamespaces,
wgNamespaceIds,
wgNamespaceNumber,
wgTitle
} = mw.config.get();
var catALot = /* @__PURE__ */ (function() {
var _ref = _asyncToGenerator(function* () {
/*! Cat-a-lot | CC-BY-SA-4.0 <https://qwbk.cc/H:CC-BY-SA-4.0> */
class CAL {
static isSearchMode = false;
static MESSAGES = DEFAULT_MESSAGES;
static DEFAULT_SETTING = DEFAULT_SETTING;
static API_TAG = apiTag;
static TARGET_NAMESPACE = targetNamespace;
static CURRENT_CATEGROY = wgTitle;
static wgFormattedNamespaces = wgFormattedNamespaces;
static wgNamespaceIds = wgNamespaceIds;
static isAutoCompleteInit = false;
static api = api;
static alreadyThere = [];
static connectionError = [];
static notFound = [];
static counterCurrent = 0;
static counterNeeded = 0;
static counterCat = 0;
static currentCategory = "";
static dialogHeight = 450;
static editToken = "";
static localCatName = wgFormattedNamespaces[CAL.TARGET_NAMESPACE];
static parentCats = [];
static subCats = [];
static settings = {};
static variantCache = {};
static $counter = $();
static $progressDialog = $();
static $labels = $();
static $selectedLabels = $();
$body;
$container;
$dataContainer;
$markCounter;
$resultList;
$searchInput;
$head;
$link;
constructor($body) {
var _mw$util$getParamValu;
if (!mw.message("cat-a-lot-loading").parse()) {
mw.messages.set(CAL.MESSAGES);
}
this.$body = $body;
CAL.initSettings();
const container = /* @__PURE__ */ import_ext_gadget3.default.createElement("div", {
className: [CLASS_NAME, CLASS_NAME_CONTAINER, "noprint"]
}, /* @__PURE__ */ import_ext_gadget3.default.createElement("div", {
className: CLASS_NAME_CONTAINER_DATA
}, /* @__PURE__ */ import_ext_gadget3.default.createElement("div", {
className: CLASS_NAME_CONTAINER_DATA_MARK_COUNTER
}), /* @__PURE__ */ import_ext_gadget3.default.createElement("div", {
className: CLASS_NAME_CONTAINER_DATA_CATEGORY_LIST
}), /* @__PURE__ */ import_ext_gadget3.default.createElement("div", null, /* @__PURE__ */ import_ext_gadget3.default.createElement("input", {
className: CLASS_NAME_CONTAINER_DATA_SEARCH_INPUT_CONTAINER_INPUT,
placeholder: CAL.msg("enter-name"),
type: "text",
value: CAL.isSearchMode ? (_mw$util$getParamValu = mw.util.getParamValue("search")) !== null && _mw$util$getParamValu !== void 0 ? _mw$util$getParamValu : "" : "",
onKeyDown: (event) => {
const $element = $(event.currentTarget);
if (event.key === "Enter") {
var _$element$val$trim, _$element$val;
const cat = (_$element$val$trim = (_$element$val = $element.val()) === null || _$element$val === void 0 ? void 0 : _$element$val.trim()) !== null && _$element$val$trim !== void 0 ? _$element$val$trim : "";
if (cat) {
this.updateCats(cat);
}
}
}
})), /* @__PURE__ */ import_ext_gadget3.default.createElement("div", {
className: CLASS_NAME_CONTAINER_DATA_SELECTIONS
}, [CAL.msg("select"), " "], /* @__PURE__ */ import_ext_gadget3.default.createElement("a", {
className: CLASS_NAME_CONTAINER_DATA_SELECTIONS_ALL,
onClick: () => {
this.toggleAll(true);
}
}, CAL.msg("all")), " • ", /* @__PURE__ */ import_ext_gadget3.default.createElement("a", {
className: CLASS_NAME_CONTAINER_DATA_SELECTIONS_NONE,
onClick: () => {
this.toggleAll(false);
}
}, CAL.msg("none")))), /* @__PURE__ */ import_ext_gadget3.default.createElement("div", {
className: CLASS_NAME_CONTAINER_HEAD
}, /* @__PURE__ */ import_ext_gadget3.default.createElement("a", {
className: CLASS_NAME_CONTAINER_HEAD_LINK
}, "Cat-a-lot")));
this.$container = $(container);
this.$container.appendTo(this.$body);
this.$dataContainer = this.$container.find(".".concat(CLASS_NAME_CONTAINER_DATA));
this.$markCounter = this.$dataContainer.find(".".concat(CLASS_NAME_CONTAINER_DATA_MARK_COUNTER));
this.$resultList = this.$dataContainer.find(".".concat(CLASS_NAME_CONTAINER_DATA_CATEGORY_LIST));
this.$searchInput = this.$dataContainer.find(".".concat(CLASS_NAME_CONTAINER_DATA_SEARCH_INPUT_CONTAINER_INPUT));
this.$head = this.$container.find(".".concat(CLASS_NAME_CONTAINER_HEAD));
this.$link = this.$head.find(".".concat(CLASS_NAME_CONTAINER_HEAD_LINK));
}
buildElements() {
const regexCat = new RegExp("^\\s*".concat(CAL.localizedRegex(CAL.TARGET_NAMESPACE, "Category"), ":"), "");
let isCompositionStart;
this.$searchInput.on("compositionstart", () => {
isCompositionStart = true;
});
this.$searchInput.on("compositionend", () => {
isCompositionStart = false;
});
this.$searchInput.on("input keyup", (event) => {
if (isCompositionStart) {
return;
}
const {
currentTarget
} = event;
const {
value: oldVal
} = currentTarget;
const newVal = oldVal.replace(regexCat, "");
if (newVal !== oldVal) {
currentTarget.value = newVal;
}
});
const initAutocomplete = () => {
if (CAL.isAutoCompleteInit) {
return;
}
CAL.isAutoCompleteInit = true;
this.$searchInput.autocomplete({
source: (request, response) => {
this.doAPICall({
action: "opensearch",
namespace: CAL.TARGET_NAMESPACE,
redirects: "resolve",
search: request.term
}, (result) => {
if (result[1]) {
response($(result[1]).map((_index, item) => item.replace(regexCat, "")));
}
});
},
position: {
my: "right bottom",
at: "right top",
of: this.$searchInput
},
appendTo: ".".concat(CLASS_NAME_CONTAINER)
});
};
this.$link.on("click", (event) => {
$(event.currentTarget).toggleClass(CLASS_NAME_CONTAINER_HEAD_LINK_ENABLED);
initAutocomplete();
this.run();
});
}
static initSettings() {
var _window$CatALotPrefs;
let catALotPrefs = (_window$CatALotPrefs = window.CatALotPrefs) !== null && _window$CatALotPrefs !== void 0 ? _window$CatALotPrefs : {};
const typeOfCatALotPrefs = typeof catALotPrefs;
if (typeOfCatALotPrefs === "object" && !Array.isArray(catALotPrefs) || typeOfCatALotPrefs !== "object") {
catALotPrefs = {};
}
for (var _i2 = 0, _Object$keys = Object.keys(CAL.DEFAULT_SETTING); _i2 < _Object$keys.length; _i2++) {
var _catALotPrefs$setting;
const settingKey = _Object$keys[_i2];
const setting = CAL.DEFAULT_SETTING[settingKey];
CAL.settings[settingKey] = (_catALotPrefs$setting = catALotPrefs[settingKey]) !== null && _catALotPrefs$setting !== void 0 ? _catALotPrefs$setting : setting.default;
if (!setting.select_i18n) {
continue;
}
setting.select = {};
for (var _i3 = 0, _Object$keys2 = Object.keys(setting.select_i18n); _i3 < _Object$keys2.length; _i3++) {
const messageKey = _Object$keys2[_i3];
const message = setting.select_i18n[messageKey];
setting.select[CAL.msg(messageKey)] = message;
}
}
}
static msg(key, ...args) {
const fullKey = "cat-a-lot-".concat(key);
return args.length ? mw.message(fullKey, ...args).parse() : mw.message(fullKey).plain();
}
static localizedRegex(namespaceNumber, fallback) {
var _CAL$wgFormattedNames;
const wikiTextBlank = String.raw(_templateObject || (_templateObject = _taggedTemplateLiteral(["[ _ - \u2028\u2029 ]+"], ["[\\t _\\xA0\\u1680\\u180E\\u2000-\\u200A\\u2028\\u2029\\u202F\\u205F\\u3000]+"])));
const wikiTextBlankRE = new RegExp(wikiTextBlank, "g");
const createRegexStr = (name) => {
if (!(name !== null && name !== void 0 && name.length)) {
return "";
}
let regexName = "";
for (let i = 0; i < name.length; i++) {
const initial = name.slice(i, i + 1);
const ll = initial.toLowerCase();
const ul = initial.toUpperCase();
regexName += ll === ul ? initial : "[".concat(ll).concat(ul, "]");
}
return regexName.replace(/([$()*+.?\\^])/g, String.raw(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["$1"], ["\\$1"])))).replace(wikiTextBlankRE, wikiTextBlank);
};
fallback = fallback.toLowerCase();
const canonical = (_CAL$wgFormattedNames = CAL.wgFormattedNamespaces[namespaceNumber]) === null || _CAL$wgFormattedNames === void 0 ? void 0 : _CAL$wgFormattedNames.toLowerCase();
let regexString = createRegexStr(canonical);
if (fallback && canonical !== fallback) {
regexString += "|".concat(createRegexStr(fallback));
}
for (var _i4 = 0, _Object$keys3 = Object.keys(CAL.wgNamespaceIds); _i4 < _Object$keys3.length; _i4++) {
const catName = _Object$keys3[_i4];
if (catName.toLowerCase() !== canonical && catName.toLowerCase() !== fallback && CAL.wgNamespaceIds[catName] === namespaceNumber) {
regexString += "|".concat(createRegexStr(catName));
}
}
return "(?:".concat(regexString, ")");
}
updateSelectionCounter() {
CAL.$selectedLabels = CAL.$labels.filter(".".concat(CLASS_NAME_LABEL_SELECTED));
this.$markCounter.show().html(CAL.msg("files-selected", CAL.$selectedLabels.length.toString()));
}
toggleAll(select) {
CAL.$labels.toggleClass(CLASS_NAME_LABEL_SELECTED, select);
this.updateSelectionCounter();
}
static findAllVariants(category) {
return _asyncToGenerator(function* () {
if (CAL.variantCache[category] !== void 0 && Array.isArray(CAL.variantCache[category])) {
return CAL.variantCache[category];
}
if (mw.storage.getObject(storageKey + category) !== void 0 && Array.isArray(mw.storage.getObject(storageKey + category))) {
CAL.variantCache[category] = mw.storage.getObject(storageKey + category);
return CAL.variantCache[category];
}
const results = [category];
const params = {
action: "parse",
format: "json",
formatversion: "2",
text: category,
title: "temp"
};
for (var _i5 = 0, _VARIANTS = VARIANTS; _i5 < _VARIANTS.length; _i5++) {
const variant = _VARIANTS[_i5];
try {
const {
parse
} = yield CAL.api.get({
...params,
variant
});
const {
text
} = parse;
const result = $(text).eq(0).text().trim();
results[results.length] = result;
} catch {
}
}
CAL.variantCache[category] = (0, import_ext_gadget2.uniqueArray)(results);
mw.storage.setObject(storageKey + category, CAL.variantCache[category], 60 * 60 * 24);
return CAL.variantCache[category];
})();
}
static regexBuilder(category) {
return _asyncToGenerator(function* () {
const catName = CAL.localizedRegex(CAL.TARGET_NAMESPACE, "Category");
category = category.replace(/^[\s_]+/, "").replace(/[\s_]+$/, "");
const variants = yield CAL.findAllVariants(category);
const variantRegExps = [];
var _iterator2 = _createForOfIteratorHelper(variants), _step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done; ) {
let variant = _step2.value;
variant = mw.util.escapeRegExp(variant);
variant = variant.replace(/[\s_]+/g, String.raw(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["[s_]+"], ["[\\s_]+"]))));
const first = variant.slice(0, 1);
if (first.toUpperCase() !== first.toLowerCase()) {
variant = "[".concat(first.toUpperCase()).concat(first.toLowerCase(), "]").concat(variant.slice(1));
}
variantRegExps[variantRegExps.length] = variant;
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
return new RegExp("\\[\\[[\\s_]*".concat(catName, "[\\s_]*:[\\s_]*(?:").concat(variantRegExps.join("|"), ")[\\s_]*(\\|[^\\]]*(?:\\][^\\]]+)*)?\\]\\]"), "g");
})();
}
doAPICall(_params, callback) {
const params = _params;
params["format"] = "json";
params["formatversion"] = "2";
let i = 0;
const doCall = () => {
const handleError = (error) => {
mw.log.error("[Cat-a-lot] Ajax error:", error);
if (i < 4) {
setTimeout(doCall, 300);
i++;
} else if (params["title"]) {
CAL.connectionError[CAL.connectionError.length] = params["title"];
this.updateCounter();
}
};
if (params["action"] === "query") {
CAL.api.get(params).then(callback).catch(handleError);
} else {
CAL.api.post(params).then(callback).catch(handleError);
}
};
doCall();
}
static markAsDone($markedLabel, targetCategory, mode) {
$markedLabel.addClass(CLASS_NAME_LABEL_DONE);
switch (mode) {
case "add":
$markedLabel.append(/* @__PURE__ */ import_ext_gadget3.default.createElement(import_ext_gadget3.default.Fragment, null, /* @__PURE__ */ import_ext_gadget3.default.createElement("br", null), CAL.msg("added-cat", targetCategory)));
break;
case "copy":
$markedLabel.append(/* @__PURE__ */ import_ext_gadget3.default.createElement(import_ext_gadget3.default.Fragment, null, /* @__PURE__ */ import_ext_gadget3.default.createElement("br", null), CAL.msg("copied-cat", targetCategory)));
break;
case "move":
$markedLabel.append(/* @__PURE__ */ import_ext_gadget3.default.createElement(import_ext_gadget3.default.Fragment, null, /* @__PURE__ */ import_ext_gadget3.default.createElement("br", null), CAL.msg("moved-cat", targetCategory)));
break;
case "remove":
$markedLabel.append(/* @__PURE__ */ import_ext_gadget3.default.createElement(import_ext_gadget3.default.Fragment, null, /* @__PURE__ */ import_ext_gadget3.default.createElement("br", null), CAL.msg("removed-cat", targetCategory)));
break;
}
}
static doCleanup(text) {
return CAL.settings.docleanup ? text.replace(/{{\s*[Cc]heck categories\s*(\|?.*?)}}/, "") : text;
}
// Remove {{Uncategorized}} (also with comment). No need to replace it with anything
static removeUncat(text) {
return text.replace(/\{\{\s*[Uu]ncategorized\s*(\|?.*?)\}\}/, "");
}
displayResult() {
this.$body.css({
cursor: "",
overflow: ""
});
this.$body.find(".".concat(CLASS_NAME_FEEDBACK)).addClass(CLASS_NAME_FEEDBACK_DONE);
const $parent = CAL.$counter.parent();
$parent.html(/* @__PURE__ */ import_ext_gadget3.default.createElement("h3", null, CAL.msg("done")));
$parent.append(/* @__PURE__ */ import_ext_gadget3.default.createElement(import_ext_gadget3.default.Fragment, null, CAL.msg("all-done"), /* @__PURE__ */ import_ext_gadget3.default.createElement("br", null)));
$parent.append(/* @__PURE__ */ import_ext_gadget3.default.createElement("a", {
onClick: () => {
CAL.$progressDialog.remove();
this.toggleAll(false);
}
}, CAL.msg("return-to-page")));
if (CAL.alreadyThere.length) {
$parent.append(/* @__PURE__ */ import_ext_gadget3.default.createElement(import_ext_gadget3.default.Fragment, null, /* @__PURE__ */ import_ext_gadget3.default.createElement("h5", null, CAL.msg("skipped-already", CAL.alreadyThere.length.toString())), CAL.alreadyThere.reduce((pre, cur, index) => index < CAL.alreadyThere.length - 1 ? [...pre, cur, /* @__PURE__ */ import_ext_gadget3.default.createElement("br", {
key: index
})] : [...pre, cur], [])));
}
if (CAL.notFound.length) {
$parent.append(/* @__PURE__ */ import_ext_gadget3.default.createElement(import_ext_gadget3.default.Fragment, null, /* @__PURE__ */ import_ext_gadget3.default.createElement("h5", null, CAL.msg("skipped-not-found", CAL.notFound.length.toString())), CAL.notFound.reduce((pre, cur, index) => index < CAL.notFound.length - 1 ? [...pre, cur, /* @__PURE__ */ import_ext_gadget3.default.createElement("br", {
key: index
})] : [...pre, cur], [])));
}
if (CAL.connectionError.length) {
$parent.append(/* @__PURE__ */ import_ext_gadget3.default.createElement(import_ext_gadget3.default.Fragment, null, /* @__PURE__ */ import_ext_gadget3.default.createElement("h5", null, CAL.msg("skipped-server", CAL.connectionError.length.toString())), CAL.connectionError.reduce((pre, cur, index) => index < CAL.connectionError.length - 1 ? [...pre, cur, /* @__PURE__ */ import_ext_gadget3.default.createElement("br", {
key: index
})] : [...pre, cur], [])));
}
}
updateCounter() {
CAL.counterCurrent++;
if (CAL.counterCurrent > CAL.counterNeeded) {
this.displayResult();
} else {
CAL.$counter.text(CAL.counterCurrent);
}
}
editCategories(result, markedLabel, targetCategory, mode) {
var _this = this;
return _asyncToGenerator(function* () {
var _page$revisions;
const [markedLabelTitle, $markedLabel] = markedLabel;
if (!(result !== null && result !== void 0 && result["query"])) {
CAL.connectionError[CAL.connectionError.length] = markedLabelTitle;
_this.updateCounter();
return;
}
let originText = "";
let starttimestamp = 0;
let timestamp = 0;
CAL.editToken = result["query"].tokens.csrftoken;
const {
pages
} = result["query"];
const [page] = pages;
originText = page === null || page === void 0 || (_page$revisions = page.revisions) === null || _page$revisions === void 0 ? void 0 : _page$revisions[0].slots.main.content;
({
starttimestamp
} = page);
[{ timestamp }] = page.revisions;
const sourcecat = CAL.CURRENT_CATEGROY;
const targetRegExp = yield CAL.regexBuilder(targetCategory);
if (mode !== "remove" && targetRegExp.test(originText) && mode !== "move") {
CAL.alreadyThere[CAL.alreadyThere.length] = markedLabelTitle;
_this.updateCounter();
return;
}
let text = originText;
let summary;
const sourceCatRegExp = yield CAL.regexBuilder(sourcecat);
switch (mode) {
case "add":
text += "\n[[".concat(CAL.localCatName, ":").concat(targetCategory, "]]\n");
summary = CAL.msg("summary-add").replace("$1", targetCategory);
break;
case "copy":
text = text.replace(sourceCatRegExp, "[[".concat(CAL.localCatName, ":").concat(sourcecat, "$1]]\n[[").concat(CAL.localCatName, ":").concat(targetCategory, "$1]]"));
summary = CAL.msg("summary-copy").replace("$1", sourcecat).replace("$2", targetCategory);
if (originText === text) {
text += "\n[[".concat(CAL.localCatName, ":").concat(targetCategory, "]]");
}
break;
case "move":
text = text.replace(sourceCatRegExp, "[[".concat(CAL.localCatName, ":").concat(targetCategory, "$1]]"));
summary = CAL.msg("summary-move").replace("$1", sourcecat).replace("$2", targetCategory);
break;
case "remove":
text = text.replace(sourceCatRegExp, "");
summary = CAL.msg("summary-remove").replace("$1", sourcecat);
break;
}
if (text === originText) {
CAL.notFound[CAL.notFound.length] = markedLabelTitle;
_this.updateCounter();
return;
}
if (mode !== "remove") {
text = CAL.doCleanup(CAL.removeUncat(text));
}
_this.doAPICall({
action: "edit",
token: CAL.editToken,
title: markedLabelTitle,
assert: "user",
bot: true,
basetimestamp: timestamp,
watchlist: CAL.settings.watchlist,
text,
summary,
starttimestamp
}, () => {
_this.updateCounter();
});
CAL.markAsDone($markedLabel, targetCategory, mode);
})();
}
getContent(markedLabel, targetCategory, mode) {
this.doAPICall({
action: "query",
formatversion: "2",
meta: "tokens",
titles: markedLabel[0],
prop: "revisions",
rvprop: ["content", "timestamp"],
rvslots: "main"
}, (result) => {
void this.editCategories(result, markedLabel, targetCategory, mode);
});
}
static getTitleFromLink(href) {
try {
var hrefDecoded = decodeURIComponent(href !== null && href !== void 0 ? href : "");
var match = hrefDecoded.match(/wiki\/(.+?)(?:#.+)?$/) || hrefDecoded.match(/[?&]title=([^&#]+)/);
return (match ? match[1] : "").replace(/_/g, " ");
} catch (e) {
return "";
}
}
getMarkedLabels() {
const markedLabels = [];
CAL.$selectedLabels = CAL.$labels.filter(".".concat(CLASS_NAME_LABEL_SELECTED));
CAL.$selectedLabels.each((_index, label) => {
var _$labelLink$attr;
const $label = $(label);
const $labelLink = $label.find("a:not(.CategoryTreeToggle)[title]");
const title = ((_$labelLink$attr = $labelLink.attr("title")) === null || _$labelLink$attr === void 0 ? void 0 : _$labelLink$attr.trim()) || CAL.getTitleFromLink($labelLink.attr("href")) || CAL.getTitleFromLink($label.find("a:not(.CategoryTreeToggle)").attr("href"));
markedLabels[markedLabels.length] = [title, $label];
});
return markedLabels;
}
showProgress() {
this.$body.css({
cursor: "wait",
overflow: "hidden"
});
CAL.$progressDialog = $(/* @__PURE__ */ import_ext_gadget3.default.createElement("div", null, CAL.msg("editing"), /* @__PURE__ */ import_ext_gadget3.default.createElement("span", {
className: CLASS_NAME_CURRENT_COUNTER
}, CAL.counterCurrent), [CAL.msg("of"), CAL.counterNeeded])).dialog({
dialogClass: CLASS_NAME_FEEDBACK,
minHeight: 90,
height: 90,
width: 450,
modal: true,
closeOnEscape: false,
draggable: false,
resizable: false
});
this.$body.find(".".concat(CLASS_NAME_FEEDBACK, " .ui-dialog-titlebar")).hide();
this.$body.find(".".concat(CLASS_NAME_FEEDBACK, " .ui-dialog-content")).height("auto");
CAL.$counter = this.$body.find(".".concat(CLASS_NAME_CURRENT_COUNTER));
}
doSomething(targetCategory, mode) {
const markedLabels = this.getMarkedLabels();
if (!markedLabels.length) {
void mw.notify(CAL.msg("none-selected"), {
tag: "catALot"
});
return;
}
CAL.alreadyThere = [];
CAL.connectionError = [];
CAL.notFound = [];
CAL.counterCurrent = 1;
CAL.counterNeeded = markedLabels.length;
this.showProgress();
var _iterator3 = _createForOfIteratorHelper(markedLabels), _step3;
try {
for (_iterator3.s(); !(_step3 = _iterator3.n()).done; ) {
const markedLabel = _step3.value;
this.getContent(markedLabel, targetCategory, mode);
}
} catch (err) {
_iterator3.e(err);
} finally {
_iterator3.f();
}
}
addHere(targetCategory) {
this.doSomething(targetCategory, "add");
}
copyHere(targetCategory) {
this.doSomething(targetCategory, "copy");
}
moveHere(targetCategory) {
this.doSomething(targetCategory, "move");
}
createCatLinks(symbol, categories) {
categories.sort();
var _iterator4 = _createForOfIteratorHelper(categories), _step4;
try {
for (_iterator4.s(); !(_step4 = _iterator4.n()).done; ) {
const category = _step4.value;
const $tr = $(/* @__PURE__ */ import_ext_gadget3.default.createElement("tr", {
dataset: {
category
}
}, /* @__PURE__ */ import_ext_gadget3.default.createElement("td", null, symbol), /* @__PURE__ */ import_ext_gadget3.default.createElement("td", null, /* @__PURE__ */ import_ext_gadget3.default.createElement("a", {
onClick: (event) => {
const $element = $(event.currentTarget);
this.updateCats($element.closest("tr").data("category"));
}
}, category))));
if (category !== CAL.CURRENT_CATEGROY && CAL.isSearchMode) {
$tr.append(/* @__PURE__ */ import_ext_gadget3.default.createElement("td", null, /* @__PURE__ */ import_ext_gadget3.default.createElement("a", {
className: CLASS_NAME_CONTAINER_DATA_CATEGORY_LIST_ACTION,
onClick: (event) => {
const $element = $(event.currentTarget);
this.addHere($element.closest("tr").data("category"));
}
}, CAL.msg("add"))));
} else if (category !== CAL.CURRENT_CATEGROY && !CAL.isSearchMode) {
$tr.append(/* @__PURE__ */ import_ext_gadget3.default.createElement(import_ext_gadget3.default.Fragment, null, /* @__PURE__ */ import_ext_gadget3.default.createElement("td", null, /* @__PURE__ */ import_ext_gadget3.default.createElement("a", {
className: CLASS_NAME_CONTAINER_DATA_CATEGORY_LIST_ACTION,
onClick: (event) => {
const $element = $(event.currentTarget);
this.copyHere($element.closest("tr").data("category"));
}
}, CAL.msg("copy"))), /* @__PURE__ */ import_ext_gadget3.default.createElement("td", null, /* @__PURE__ */ import_ext_gadget3.default.createElement("a", {
className: CLASS_NAME_CONTAINER_DATA_CATEGORY_LIST_ACTION,
onClick: (event) => {
const $element = $(event.currentTarget);
this.moveHere($element.closest("tr").data("category"));
}
}, CAL.msg("move")))));
}
this.$resultList.find("table").append($tr);
}
} catch (err) {
_iterator4.e(err);
} finally {
_iterator4.f();
}
}
showCategoryList() {
var _this$$container$widt, _$$width;
this.$body.css("cursor", "");
const currentCategories = [CAL.currentCategory];
this.$resultList.empty();
this.$resultList.append(/* @__PURE__ */ import_ext_gadget3.default.createElement("table", null));
this.createCatLinks("↑", CAL.parentCats);
this.createCatLinks("→", currentCategories);
this.createCatLinks("↓", CAL.subCats);
this.$container.width("");
this.$container.height("");
this.$container.width(Math.min(((_this$$container$widt = this.$container.width()) !== null && _this$$container$widt !== void 0 ? _this$$container$widt : 0) * 1.1 + 15, ((_$$width = $(window).width()) !== null && _$$width !== void 0 ? _$$width : 0) - 10));
this.$resultList.css({
"max-height": "".concat(CAL.dialogHeight, "px"),
height: ""
});
}
getParentCats() {
this.doAPICall({
action: "query",
titles: "Category:".concat(CAL.currentCategory),
prop: "categories"
}, (result) => {
var _pages$, _pages$2;
if (!result) {
return;
}
CAL.parentCats = [];
const {
pages
} = result.query;
if ((_pages$ = pages[0]) !== null && _pages$ !== void 0 && _pages$.missing) {
this.$body.css("cursor", "");
this.$resultList.html(/* @__PURE__ */ import_ext_gadget3.default.createElement("span", {
className: CLASS_NAME_CONTAINER_DATA_CATEGORY_LIST_NO_FOUND
}, CAL.msg("cat-not-found")));
this.createCatLinks("→", [CAL.currentCategory]);
return;
}
let categories = [];
if ((_pages$2 = pages[0]) !== null && _pages$2 !== void 0 && _pages$2.categories) {
[{
categories
}] = pages;
}
var _iterator5 = _createForOfIteratorHelper(categories), _step5;
try {
for (_iterator5.s(); !(_step5 = _iterator5.n()).done; ) {
const cat = _step5.value;
const catTitle = cat.title.replace(/^[^:]+:/, "");
CAL.parentCats[CAL.parentCats.length] = catTitle;
}
} catch (err) {
_iterator5.e(err);
} finally {
_iterator5.f();
}
CAL.counterCat++;
if (CAL.counterCat === 2) {
this.showCategoryList();
}
});
}
getSubCats() {
this.doAPICall({
action: "query",
list: "categorymembers",
cmtype: "subcat",
cmlimit: CAL.settings.subcatcount,
cmtitle: "Category:".concat(CAL.currentCategory)
}, (result) => {
var _result$query;
const cats = (result === null || result === void 0 || (_result$query = result.query) === null || _result$query === void 0 ? void 0 : _result$query.categorymembers) || [];
CAL.subCats = [];
var _iterator6 = _createForOfIteratorHelper(cats), _step6;
try {
for (_iterator6.s(); !(_step6 = _iterator6.n()).done; ) {
const cat = _step6.value;
const catTitle = cat.title.replace(/^[^:]+:/, "");
CAL.subCats[CAL.subCats.length] = catTitle;
}
} catch (err) {
_iterator6.e(err);
} finally {
_iterator6.f();
}
CAL.counterCat++;
if (CAL.counterCat === 2) {
this.showCategoryList();
}
});
}
getCategoryList() {
CAL.counterCat = 0;
this.getParentCats();
this.getSubCats();
}
updateCats(cat) {
this.$body.css("cursor", "wait");
CAL.currentCategory = cat;
this.$resultList.html(/* @__PURE__ */ import_ext_gadget3.default.createElement("div", null, CAL.msg("loading")));
this.getCategoryList();
}
findAllLabels() {
if (CAL.isSearchMode) {
CAL.$labels = this.$body.find("table.searchResultImage").find("tr>td").eq(1);
if (CAL.settings.editpages) {
CAL.$labels = CAL.$labels.add("div.mw-search-result-heading");
}
} else {
CAL.$labels = this.$body.find("div.gallerytext").add(this.$body.find("div#mw-category-media").find('li[class!="gallerybox"]'));
if (CAL.settings.editpages) {
const $pages = this.$body.find("div#mw-pages, div#mw-subcategories").find("li");
CAL.$labels = CAL.$labels.add($pages);
}
}
}
makeClickable() {
this.findAllLabels();
CAL.$labels.addClass(CLASS_NAME_LABEL).onCatALotShiftClick(() => {
this.updateSelectionCounter();
});
}
run() {
if (this.$link.hasClass(CLASS_NAME_CONTAINER_HEAD_LINK_ENABLED)) {
this.makeClickable();
this.$dataContainer.show();
this.$container.resizable({
alsoResize: this.$resultList,
handles: "n",
resize: (event) => {
var _$currentTarget$heigh;
const $currentTarget = $(event.currentTarget);
$currentTarget.css({
left: "",
top: ""
});
CAL.dialogHeight = (_$currentTarget$heigh = $currentTarget.height()) !== null && _$currentTarget$heigh !== void 0 ? _$currentTarget$heigh : CAL.dialogHeight;
this.$resultList.css({
maxHeight: "",
width: ""
});
}
});
this.$resultList.css("max-height", "450px");
if (CAL.isSearchMode) {
this.updateCats(mw.util.getParamValue("search") || "");
} else {
this.updateCats(CAL.CURRENT_CATEGROY);
}
} else {
this.$dataContainer.hide();
this.$container.resizable("destroy");
this.$container.css("width", "");
CAL.$labels.off("click.catALot");
}
}
}
if (wgNamespaceNumber === -1 && wgCanonicalSpecialPageName === "Search" || wgNamespaceNumber === targetNamespace) {
if (wgNamespaceNumber === -1) {
CAL.isSearchMode = true;
}
CAL["variantCache"] = getCachedKeys();
if (wgNamespaceNumber === targetNamespace) {
const category = mw.config.get("wgTitle").replace(/^Category:/, "");
CAL["variantCache"][category] = [...yield CAL.findAllVariants(category)];
}
/*! Cat-a-lot messages | CC-BY-SA-4.0 <https://qwbk.cc/H:CC-BY-SA-4.0> */
setMessages();
void (0, import_ext_gadget2.getBody)().then(($body) => {
new CAL($body).buildElements();
});
}
});
return function catALot2() {
return _ref.apply(this, arguments);
};
})();
//! src/Cat-a-lot/modules/extendJQueryPrototype.ts
var extendJQueryPrototype = () => {
$.fn.extend({
onCatALotShiftClick: function(callback) {
let prevCheckbox;
this.on("click.catALot", (event) => {
if (!event.ctrlKey) {
event.preventDefault();
}
this.parents("body").find(".".concat(CLASS_NAME_LABEL_LAST_SELECTED)).removeClass(CLASS_NAME_LABEL_LAST_SELECTED);
let $thisControl = $(event.target);
if (!$thisControl.hasClass(CLASS_NAME_LABEL)) {
$thisControl = $thisControl.parents(".".concat(CLASS_NAME_LABEL));
}
$thisControl.addClass(CLASS_NAME_LABEL_LAST_SELECTED).toggleClass(CLASS_NAME_LABEL_SELECTED);
if (prevCheckbox && event.shiftKey) {
const method = $thisControl.hasClass(CLASS_NAME_LABEL_SELECTED) ? "addClass" : "removeClass";
this.slice(Math.min(this.index(prevCheckbox), this.index($thisControl)), Math.max(this.index(prevCheckbox), this.index($thisControl)) + 1)[method](CLASS_NAME_LABEL_SELECTED);
}
prevCheckbox = $thisControl;
if (typeof callback === "function") {
callback();
}
});
return this;
}
});
};
//! src/Cat-a-lot/Cat-a-lot.ts
/*! Cat-a-lot | CC-BY-SA-4.0 <https://qwbk.cc/H:CC-BY-SA-4.0> */
extendJQueryPrototype();
void catALot();
})();
/* </nowiki> */