বিষয়বস্তুতে চলুন

ব্যবহারকারী:রবি/common.js: সংশোধিত সংস্করণের মধ্যে পার্থক্য

ভারতপিডিয়া থেকে
রবি (আলোচনা | অবদান)
সম্পাদনা সারাংশ নেই
রবি (আলোচনা | অবদান)
Undo revision 63359 by রবি (talk)
১ নং লাইন: ১ নং লাইন:
/**
* AjaxQuickDelete from <https://commons.wikimedia.org/wiki/MediaWiki:Gadget-AjaxQuickDelete.js>
*
* Changelog:
* - 2010: Created in 2010 by [[User:Ilmari Karonen]] as Ajax-based replacement for [[MediaWiki:Quick-delete-code.js]].
* - Rewritten by [[User:DieBuche]].
* - Botdetection and encoding fixer by [[User:Lupo]].
* - 2011-2012: Validation and further development [[User:Rillke]], 2011-2012.
* - 2018: dropped IE8 support.
*
* TODO:
* - Fix problems with moves of videos.
* - Support move of timed text for videos.
*
* This pages has automated validation on save. Interested? See [[:commons:Commons:User scripts/reports]].
*/
// <nowiki>
/* eslint indent:[error,tab,{outerIIFEBody:0}] */
/* eslint-disable one-var, vars-on-top, camelcase, no-underscore-dangle, valid-jsdoc */
/* global $:false, mw:false, importScript:false */
( function () {
'use strict';
// Guard against multiple inclusions
if ( window.AjaxQuickDelete ) {
return;
}
var AQD,
conf = mw.config.get( [
'wgArticleId',
'wgCanonicalNamespace',
'wgCanonicalSpecialPageName',
'wgCategories',
'wgFormattedNamespaces',
'wgNamespaceNumber',
'wgPageName',
'wgRestrictionEdit',
'wgUserGroups',
'wgUserLanguage',
'wgUserName',
'wgIsRedirect'
] ),
nsNr = conf.wgNamespaceNumber,
pageName = conf.wgPageName;
// A bunch of helper functions
function _firstItem( o ) {
for ( var i in o ) {
if ( Object.prototype.hasOwnProperty.call( o, i ) ) {
return o[ i ];
}
}
}
$.ucFirst = function ( s ) {
return s[ 0 ].toUpperCase() + s.slice( 1 );
};
// Create the AjaxQuickDelete-singleton (object literal)
AQD = window.AjaxQuickDelete = {
// When maintaining this script always bump this number!
version: '1.1.3',
/**
* Runs before document ready and before translation is available
* (important event-binders should be attached as fast as possible)
*/
preinstall: function () {
// Promote our gadget when user opened old move page
if ( conf.wgCanonicalSpecialPageName === 'Movepage' && Number( $( 'select[name="wpNewTitleNs"]' ).val() ) === 6 ) {
$( '#mw-movepage-table' ).before(
'<div class="mw-message-box mw-message-box-warning">Consider using <i>Move & Replace</i> from the menu on file pages (open with a single click) when moving files to care for global usage and redirects.</div>'
);
}
this.doNothing = ( !conf.wgArticleId || nsNr < 0 || /^Commons:Deletion/.test( pageName ) );
if ( this.doNothing ) {
return;
}
// Check user group
if ( conf.wgUserGroups.indexOf( 'sysop' ) !== -1 ) {
this.userRights = 'sysop';
} else if ( conf.wgUserGroups.indexOf( 'filemover' ) !== -1 ) {
this.userRights = 'filemover';
} else {
this.userRights = [ 'autopatrolled', 'patroller', 'image-reviewer' ].filter( function ( g ) {
return conf.wgUserGroups.indexOf( g ) !== -1;
} )[ 0 ];
}
if ( [ 'filemover', 'sysop' ].indexOf( this.userRights ) !== -1 && nsNr === 6 ) {
// Change "Move" to "Move & Replace"
var $moveLink = $( '#ca-move' ),
$moveLanchor = $moveLink.find( 'a' );
this.$moveLink = $moveLink = $moveLanchor.length ? $moveLanchor : $moveLink;
$moveLink.text( $moveLink.text() + ' & Replace' )
.attr( 'title', 'Click in order to ' + $moveLink.attr( 'title' ) + ' and replace usage. Default form though new tab.' )
.on( 'click', function ( e ) {
e.preventDefault();
AQD.moveFile();
} );
}
},
/**
* Set up the AjaxQuickDelete object and add the toolbox link.  Called via document.ready during page loading.
*/
install: function () {
// Disallow performing operations on empty or special pages
if ( this.doNothing ) {
return;
}
// Check edit restrictions and do not install anything if protected
if ( conf.wgRestrictionEdit && conf.wgRestrictionEdit.length &&
conf.wgUserGroups.indexOf( conf.wgRestrictionEdit[ 0 ] ) === -1 ) {
return;
}
// Trigger a jQuery event for other scripts that like to know
// when this script has loaded all translations and is ready to install
$( document ).triggerHandler( 'scriptLoaded', [ 'AjaxQuickDelete' ] );
var link;
// Set up toolbox link
if ( nsNr === 14 ) {
// In categories the discuss-category link
link = mw.util.addPortletLink( 'p-tb', '#', this.i18n.toolboxLinkDiscuss, 't-ajaxquickdiscusscat' );
if ( link ) {
link.addEventListener( 'click', function ( e ) {
e.preventDefault();
mw.loader.using( 'jquery.ui' ).then( function () {
AQD.discussCategory();
} );
} );
}
} else {
// On other pages, the nominate-for-deletion link
link = mw.util.addPortletLink( 'p-tb', '#', this.i18n.toolboxLinkDelete, 't-ajaxquickdelete' );
if ( link ) {
link.addEventListener( 'click', function ( e ) {
e.preventDefault();
AQD.nominateForDeletion();
} );
}
}
// Install AjaxMoveButton for filemovers and administrators
if ( this.$moveLink ) {
// Change Move & Replace link to fully localized text
this.$moveLink.html( $( '<span>' ).text( this.i18n.dropdownMove ) );
// Add quicklinks to template
$( '#AjaxRenameLink' ).append( '<a href="javascript:AjaxQuickDelete.moveFile();">' + this.i18n.moveAndReplace + '</a>' )
.append( '<a href="javascript:AjaxQuickDelete.loadAndDeclineRequest(\'move\');" class="ajaxDeleteDeclineMove"><sup> ' + this.i18n.anyDecline + '</sup></a>' );
// Install x-To-DR. See [[Template:X-To-DR]]
$( '#mw-imagepage-content .convert-to-dr' )
.find( '.ctdr-btn-convert' ).on( 'click', this._convertToDR ).show().end()
// Currently filemover rights required
.find( '.ctdr-btn-remove' ).on( 'click', this._removeAnyTag ).show();
} else if ( this.userRights ) {
$( '#mw-imagepage-content .convert-to-dr .ctdr-btn-convert' ).on( 'click', this._convertToDR ).show();
}
// Install "Process Duplicates"-Link (either in template
// or if no template was detected and MediaWiki found dupes, behind the link in the dupe-section)
if ( this.userRights === 'sysop' && nsNr === 6 ) {
var dupeSection = $( '#AjaxDupeProcess' );
if ( dupeSection.length ) {
dupeSection.append( $( '<a>', {
href: '#',
text: this.i18n.processDupes,
style: 'font-weight:bold',
click: function ( e ) {
e.preventDefault();
AQD.processDupes();
}
} ) ).show();
} else {
dupeSection = $( '#mw-imagepage-section-duplicates .mw-imagepage-duplicates' );
if ( dupeSection.length ) {
dupeSection.find( 'li:first' )
.append( $( '<span>', {
style: 'display:none',
id: 'AjaxDupeDestination',
text: dupeSection.find( 'a' ).attr( 'title' )
} ) )
.append( ' ', $( '<sup>' ).append( $( '<a>', {
href: '#',
text: '[' + this.i18n.processDupes + ']',
style: 'background:#CEB',
click: function ( e ) {
e.preventDefault();
AQD.processDupes();
}
} ) ) );
}
}
}
// Extra buttons
// Wait until the user's js was loaded and executed
mw.loader.using( 'user', function () {
if ( mw.user.options.get( 'gadget-QuickDelete' ) ) {
mw.loader.using( 'ext.gadget.QuickDelete' ).always( function () {
AQD.doInsertTagButtons();
} );
}
} );
},
/**
* Ensure that all variables are in a good state
* You must call this method before doing anything!
* TODO: Never override pageName, always clean task queue
*/
initialize: function () {
pageName = conf.wgPageName;
this.tasks = [];
this.destination = undefined;
this.details = undefined;
this.declineReason = undefined;
this.notifyUser = true;
this.watchlist = 'preferences';
},
/**
* If a file exists, exchange the messages (very hackish)
* so the user is prompted to choose another destination
* TODO: Develop an improved solution
*/
fileExists: function () {
this.i18n.moveDestination = this.i18n.moveOtherDestination;
this.moveFile();
},
/**
* For moving files
*/
moveFile: function () {
var o = this;
o.initialize();
mw.loader.using( [ 'jquery.ui' ] ).then( function () {
o.showProgress();
if ( $( '#AjaxRenameLink' ).length ) {
o.possibleDestination = $( '#AjaxRenameDestination' ).text();
o.possibleReason = o.cleanReason( $( '#AjaxRenameReason' ).text() );
}
// Let's be sure we have a fresh token and the latest MIME-Info
o.addTask( 'getMoveToken' );
var linkstoimage = $( '#mw-imagepage-section-linkstoimage' );
if ( $( '#globalusage' ).length || (
linkstoimage.length &&
linkstoimage.find( 'a' ).not( '.mw-redirect' ).length -
linkstoimage.find( '.mw-imagepage-linkstoimage-ns2 a[href^="/wiki/User:OgreBot/Uploads"]' ).length
) ) {
o.inUse = true;
o.addTask( 'chkPreMoveDecline' );
}
o.addTask( 'promptForMoveTarget' );
o.addTask( 'doesFileExist' );
o.fileNameExistsCB = 'fileExists';
o.addTask( 'movePage' );
o.addTask( 'removeTemplate' );
o.addTask( 'queryRedirects' );
o.addTask( 'replaceUsage' );
// finally reload the page to show changed page
o.addTask( 'reloadPage' );
o.nextTask();
} );
},
promptForMoveTargetCB: function ( AQD ) {
if ( AQD.inUse ) {
$( '#AjaxQuestion2' ).prop( 'disabled', true );
}
},
promptForMoveTarget: function () {
var toAppend;
this.showProgress();
if ( mw.user.options.get( 'gadget-RenameLink' ) ) {
toAppend = [ $( '<a>' )
.text( this.i18n.moreInformation )
.on( 'click', function () {
if ( !AQD.rGetPolicy ) {
importScript( 'MediaWiki:RenameRequest.js' );
mw.hook( 'aqd.renamerequest.i18n' ).fire();
}
mw.hook( 'aqd.renamerequest.run' ).fire( { exec: this } );
} ).button( {
icons: { primary: 'ui-icon-script' },
showLabel: true,
text: false
} ).css( {
fontSize: '.6em',
margin: '0',
width: '2.5em',
'float': 'right'
} ), '<br>' ];
}
mw.hook( 'aqd.prompt' ).remove( this.promptForMoveTargetCB ).add( this.promptForMoveTargetCB );
this.prompt( [ {
message: this.i18n.moveDestination,
prefill: this.cleanFileName( this.possibleDestination || pageName ),
returnvalue: 'destination',
appendNode: toAppend,
cleanUp: true,
noEmpty: true
}, {
message: this.i18n.reasonForMove,
prefill: ( ( this.reason || this.possibleReason || '' ).trim().replace( /'{2,}/g, '' ).replace( /\s{2,}/g, ' ' ) ),
returnvalue: 'reason',
cleanUp: true,
noEmpty: false
}, {
message: this.i18n.leaveRedirect,
prefill: true,
returnvalue: 'wpLeaveRedirect',
// cleanUp: false,
noEmpty: false,
type: 'checkbox'
}, {
message: this.i18n.useCORSForReplace,
prefill: !window.aqdCORSOptOut,
returnvalue: 'replaceUsingCORS',
// cleanUp: false,
noEmpty: false,
type: 'checkbox'
}
], this.i18n.movingFile );
},
/* Warn other filemovers */
chkPreMoveDecline: function () {
$( '#mw-imagepage-section-linkstoimage' ).find( 'a' ).each( function () {
if ( $( this ).text() === 'Commons:File renaming/Recently declined rename requests' ) {
// eslint-disable-next-line no-alert
alert( AQD.i18n.warnRename );
return false;
}
} );
this.nextTask();
},
/**
* For loading jquery UI to decline a request
*/
loadAndDeclineRequest: function ( reason ) {
var that = this;
mw.loader.using('jquery.ui').then(function () {
that.declineRequest.call( that, reason );
} );
},
/**
* For declining a request
*/
declineRequest: function ( reason ) {
reason = reason || this.declineReason;
// No valid reason stated, see the rename guidelines or not an exact duplicate
this.initialize();
this.addTask( 'getMoveToken' );
this.addTask( 'removeTemplate' );
// finally reload the page to show the template was removed
this.addTask( 'reloadPage' );
// TODO extend the reason (for summary)
switch ( reason ) {
case 'move':
reason = 'rename request declined: does not comply with [[COM:FR|renaming guidelines]]';
if ( window.AjaxDeclineMoveWatchFile ) {
this.watchlist = 'watch';
}
break;
}
this.prompt( [ {
message: '',
prefill: reason || '',
returnvalue: 'declineReason',
cleanUp: false,
noEmpty: true,
byteLimit: 250
} ], this.i18n.declineRequest );
},
// This method is generlaly used directly by user scripts without going
// through other methods or setup functions. Needs to be standalone,
// and ensures loading of its own dependencies.
insertTagOnPage: function ( tag, img_summary, talk_tag, talk_summary, prompt_text, page, optin_notify ) {
var o = this;
this.initialize();
mw.loader.using( [ 'jquery.ui' ], function () {
o.pageName = ( page || pageName ).replace( /_/g, ' ' );
o.tag = tag.replace( '%USER%', conf.wgUserName ) + '\n';
o.img_summary = img_summary;
// first schedule some API queries to fetch the info we need…
// get token
o.addTask( 'findCreator' );
o.addTask( 'prependTemplate' );
if ( o.isMobile() && /(?:copyvio|nsd|npd|nld)/.test( tag ) ) {
o.addTask( 'listMobileUploadSpeedy' );
}
var prompt = [];
// Cave: insertTagOnPage is inserted as javascript link and therefore talk_tag can be "undefined"/string
if ( talk_tag && talk_tag !== 'undefined' ) {
o.talk_tag = talk_tag.replace( '%FILE%', o.pageName );
o.talk_summary = talk_summary.replace( '%FILE%', '[[:' + o.pageName + ']]' );
o.usersNeeded = true;
prompt.push( {
message: o.i18n.notifyUser,
prefill: true,
returnvalue: 'notifyUser',
type: 'checkbox'
} );
o.addTask( 'notifyUploaders' );
}
o.addTask( 'reloadPage' );
if ( tag.indexOf( '%PARAMETER%' ) !== -1 ) {
prompt.push( {
message: '',
prefill: '',
returnvalue: 'reason',
cleanUp: true,
noEmpty: true,
minLength: 1
} );
o.prompt( prompt, prompt_text || o.i18n.reasonForDeletion );
} else if ( optin_notify && prompt.length && o.talk_summary ) {
o.prompt( prompt, o.talk_summary );
} else {
o.nextTask();
}
} );
},
discussCategory: function () {
// reset task list in case an earlier error left it non-empty
this.initialize();
this.pageName = pageName.replace( /_/g, ' ' );
this.startDate = new Date();
// eslint-disable-next-line no-useless-escape
this.tag = '{{subst:cfd}}\n';
this.img_summary = 'This category needs discussion';
// eslint-disable-next-line no-useless-escape
this.talk_tag = '{{subst:cdw|1=' + pageName + '}}';
this.talk_summary = '[[:' + pageName + ']] needs discussion';
this.subpage_summary = 'Starting category discussion';
// set up some page names we'll need later
this.requestPage = 'Commons:Categories for discussion/' + this.formatDate( 'YYYY/MM/' ) + pageName;
this.dailyLogPage = 'Commons:Categories for discussion/' + this.formatDate( 'YYYY/MM' );
// first schedule some API queries to fetch the info we need…
this.addTask( 'findCreator' );
// …then schedule the actual edits
this.addTask( 'prependTemplate' );
this.addTask( 'createRequestSubpage' );
this.addTask( 'listRequestSubpage' );
this.addTask( 'notifyUploaders' );
// finally reload the page to show the deletion tag
this.addTask( 'reloadPage' );
var lazyLoadNode = this.createLazyLoadNode( this.i18n.moreInformation, 'MediaWiki:Gadget-AjaxQuickDelete.js/DiscussCategoryInfo', '#AjaxQuickDeleteCatInfo' );
this.prompt( [ {
message: '',
prefill: '',
returnvalue: 'reason',
cleanUp: true,
appendNode: lazyLoadNode,
noEmpty: true,
parseReason: true
}
], this.i18n.reasonForDiscussion );
},
nominateForDeletion: function ( page ) {
var o = this;
// reset task list in case an earlier error left it non-empty
this.initialize();
mw.loader.using( [ 'mediawiki.String', 'jquery.ui' ], function () {
o.pageName = ( page || pageName ).replace( /_/g, ' ' );
o.startDate = new Date();
// set up some page names we'll need later
var requestPage = o.pageName,
mwString = require( 'mediawiki.String' );
// MediaWiki has an ugly limit of 255 bytes per title, excluding the namespace
while ( mwString.byteLength( requestPage ) + mwString.byteLength( o.requestPagePrefix.replace( /^.+?:/, '' ) ) >= 255 ) {
requestPage = requestPage.slice( 0, requestPage.length - 1 ).trim();
}
o.requestPage = o.requestPagePrefix + requestPage;
o.dailyLogPage = o.requestPagePrefix + o.formatDate( 'YYYY/MM/DD' );
o.tag = '{{delete|reason=%PARAMETER%|subpage=' + requestPage + o.formatDate( '|year=YYYY|month=MON|day=DAY}}\n' );
switch ( nsNr ) {
// On MediaWiki pages, wrap inside comments (for css and js)
case 8:
o.tag = '/*' + o.tag + '*/';
break;
// On templates and creator/institution-templates: Wrap inside <noinclude>s.
case 10:
case 100:
case 106:
o.tag = '<noinclude>' + o.tag + '</noinclude>';
break;
case 828: // Lua comments
o.tag = '\n--[=[ ' + o.tag + ' ]=]\n';
}
if ( o.templateReplace ) {
o.declineReason = o.img_summary;
}
o.img_summary = 'Nominating for deletion';
// eslint-disable-next-line no-useless-escape
o.talk_tag = '{{subst:idw|1=' + requestPage + '}}';
o.talk_summary = '[[:' + o.pageName + ']] has been nominated for deletion';
o.subpage_summary = 'Starting deletion request';
// without \n it breaks the redirect syntax
if ( conf.wgIsRedirect ) {
o.tag += '\n';
}
// first schedule some API queries to fetch the info we need…
o.addTask( 'findCreator' );
// …then schedule the actual edits
o.addTask( o.templateReplace ? 'replaceTemplate' : 'prependTemplate' );
o.addTask( 'createRequestSubpage' );
o.addTask( 'listRequestSubpage' );
o.addTask( 'purge' );
o.addTask( 'notifyUploaders' );
if ( o.isMobile() ) {
o.addTask( 'listMobileUpload' );
}
// finally reload the page to show the deletion tag
o.addTask( 'reloadPage' );
var lazyLoadNode = o.createLazyLoadNode( o.i18n.moreInformation, 'MediaWiki:Gadget-AjaxQuickDelete.js/DeleteInfo', '#AjaxQuickDeleteDeleteInfo' );
o.prevDRNode = $( '<ul>' ).attr( 'id', 'AjaxDeletePrevRequests' );
o.secureCall( 'checkForFormerDR' );
var toAppend = $( '<div>' ).append( $( '<div>' ).attr( 'class', 'ajaxDeleteLazyLoad' ).css( {
'max-height': Math.max( Math.round( $( window ).height() / 2 ) - 250, 100 ),
'min-height': 0,
overflow: 'auto'
} ).append( o.prevDRNode ), '<br>', lazyLoadNode );
o.prompt( [ {
message: '',
prefill: o.reason || '',
returnvalue: 'reason',
cleanUp: true,
noEmpty: true,
appendNode: toAppend,
parseReason: true
}
], o.i18n.reasonForDeletion );
} );
},
// Check whether there was a deletion request for the same title in the past
checkForFormerDR: function () {
// Don't search for "kept" when nominating talk pages
if ( nsNr % 2 === 0 ) {
this.talkPage = conf.wgFormattedNamespaces[ nsNr + 1 ] + ':' + this.pageName.replace( conf.wgCanonicalNamespace + ':', '' );
this.queryAPI( {
prop: 'templates',
titles: this.talkPage,
tltemplates: 'Template:Kept',
tllimit: 1
}, 'formerDRTalk' );
}
this.queryAPI( {
list: 'backlinks',
bltitle: this.pageName,
blnamespace: 4,
blfilterredir: 'nonredirects',
bllimit: 500
}, 'formerDRRequestpage' );
},
formerDRTalk: function ( r ) {
var pgs = r.query.pages;
$.each( pgs, function ( id, pg ) {
if ( Array.isArray( pg.templates ) ) {
$( '<li>' ).append( $( '<a>', {
text: AQD.i18n.keptAfterDR,
href: mw.util.getUrl( AQD.talkPage )
} ) ).prependTo( AQD.prevDRNode );
} else if ( pg.missing === undefined ) {
$( '<li>' ).append( $( '<a>', {
text: AQD.i18n.hasTalkpage,
href: mw.util.getUrl( AQD.talkPage )
} ) ).appendTo( AQD.prevDRNode );
}
} );
},
formerDRRequestpage: function ( r ) {
var bls = r.query.backlinks,
_addItem = function ( t, m, bl ) {
$( '<li>' ).append( $( '<a>', {
text: t.replace( '%PAGE%', bl.title ),
href: mw.util.getUrl( bl.title )
} ) )[ m ]( AQD.prevDRNode );
};
$.each( bls, function ( i, bl ) {
if ( this.requestPage === bl.title ) {
_addItem( AQD.i18n.mentionedInDR, 'prependTo', bl );
} else if ( /^Commons:Deletion requests\/\D/.test( bl.title ) ) {
_addItem( AQD.i18n.mentionedInDR, 'appendTo', bl );
} else if ( /^Commons:Village pump\//.test( bl.title ) ) {
_addItem( AQD.i18n.mentionedInForum, 'appendTo', bl );
}
} );
},
renderNode: function ( $node, remotecontent, selector ) {
if ( selector ) {
selector = ' ' + selector;
}
$node.load( mw.util.wikiScript() + '?' + $.param( {
action: 'render',
title: remotecontent,
uselang: conf.wgUserLanguage
} ) + ( selector || '' ), function () {
$node.find( 'a' ).attr( 'href', function ( i, v ) {
return v.replace( 'MediaWiki:Anoneditwarning', conf.wgPageName );
} );
} );
return $node;
},
createLazyLoadNode: function ( label, page, selector ) {
return $( '<div>', { style: 'min-height:40px;' } ).append( $( '<a>', {
href: '#',
text: label
} ).on( 'click', function ( e ) {
e.preventDefault();
var $content = $( this ).parent().find( '.ajaxDeleteLazyLoad' ),
$contentInner = $content.find( '.ajax-quick-delete-loading' );
if ( $contentInner.length ) {
// first time invoked, do the XHR to load the content
AQD.renderNode( $content, $contentInner.data( 'aqdPage' ), selector );
}
$content.toggle( 'fast' );
} ), $( '<div>', {
// eslint-disable-next-line quote-props
'class': 'ajaxDeleteLazyLoad',
style: 'display:none;'
} ).append( $( '<span>', {
// eslint-disable-next-line quote-props
'class': 'ajax-quick-delete-loading',
text: this.i18n.loading
} ).data( 'aqdPage', page ) ) );
},
extractFromHTML: function ( $el ) {
$el = $( $el ).parent();
// …extract the regular expression from html
this.templateRegExp = $el.find( '.ctdr-regex' ).text();
var m = this.templateRegExp.match( /^\/(.+)\/(i)?$/ );
if ( !m || !m[ 1 ] ) {
m = new Error( this.i18n.templateRegExp );
this.fail( m );
throw m;
}
this.templateRegExp = new RegExp( m[ 1 ], m[ 2 ] );
// …and the decline reason
this.declineReason = $el.find( '.ctdr-template-decline-reason' ).text();
// …and the template name itself
m = $el.find( '.ctdr-template-name' ).text();
this.reason = 'This file was initially tagged by %USER%' + ( m ? ( ' as \'\'\'' + m + '\'\'\'' ) : '' );
},
removeProgress: function () {
this.showProgress();
return this.nextTask();
},
/**
* Remove any tag
* @context DOM-Element
* This function must be called with the DOM-Element as this-arg!
*/
_removeAnyTag: function ( e ) {
AQD.extractFromHTML( e.currentTarget || this );
AQD.removeAnyTag();
return false;
},
removeAnyTag: function () {
// this.initialize();
this.addTask( 'declineRequest' );
this.nextTask();
},
/**
* Convert any tag to a deletion request
* @context DOM-Element
* This function must be called with the DOM-Element as this-arg!
*/
_convertToDR: function ( e ) {
e = e.currentTarget || this;
AQD.extractFromHTML( e );
AQD.convertToDR( e );
return false;
},
convertToDR: function ( el ) {
// reset task list in case an earlier error left it non-empty
this.initialize();
this.declineReason = 'This file does not qualify for [[COM:SPEEDY|speedy-deletion]] and a regular deletion request will be started.';
this.templateReplace = true;
// first schedule a API query to fetch the info we need…
this.addTask( 'findTemplateAdder' );
this.addTask( 'getMoveToken' );
// prompt before conversion for user decision
this.addTask( 'removeTemplate' );
this.addTask( 'removeProgress' );
this.addTask( 'nominateForDeletion' );
// Hide the buttons to prevent attempts of duplicate removal
$( el ).closest( '.convert-to-dr' ).hide();
// … and go!
this.nextTask();
},
findTemplateAdder: function () {
var query = {
prop: 'revisions',
rvprop: 'content|user',
titles: pageName.replace( /_/g, ' ' ),
rvlimit: 50
};
this.queryAPI( query, 'findTemplateAdderCB' );
},
findTemplateAdderCB: function ( result ) {
var reason,
user,
pgRevs, // for debug
template;
$.each( result.query.pages, function ( id, pg ) {
pgRevs = pg.revisions;
pgRevs.forEach( function ( rv ) {
var m = rv[ '*' ].match( AQD.templateRegExp );
if ( m ) {
user = rv.user;
if ( m.length > 1 && !template ) {
template = m[ 1 ];
}
if ( m.length > 2 && !reason ) {
reason = m[ 2 ];
}
} else {
return false;
}
} );
} );
if ( !user ) {
mw.log.warn( pgRevs );
throw new Error( this.i18n.findTemplateAdderErr );
}
this.reason = this.reason.replace( '%USER%', '[[User:' + user + '|' + user + ']]' );
if ( template ) {
this.reason += ' (' + template + ')';
}
if ( reason ) {
this.reason += ' and the most recent rationale was: <tt>' + reason + '</tt>';
}
this.nextTask();
},
processDupes: function () {
// reset task list in case an earlier error left it non-empty
this.initialize();
if ( $( '#globalusage' ).length || !$( '#mw-imagepage-nolinkstoimage' ).length ) {
this.inUse = true;
}
this.addTask( 'getDupeDetails' );
this.addTask( 'compareDetails' );
this.addTask( 'mergeDescriptions' );
this.addTask( 'saveDescription' );
this.addTask( 'replaceUsage' );
this.addTask( 'queryRedirects' );
this.addTask( 'deletePage' );
this.addTask( 'redirectPage' );
this.addTask( 'reloadPage' );
this.destination = $( '#AjaxDupeDestination' ).text();
this.nextTask();
},
getDupeDetails: function () {
this.queryAPI( {
curtimestamp: 1,
meta: 'tokens',
prop: 'imageinfo|revisions|info',
rvprop: 'content|timestamp',
inprop: 'watched',
iiprop: 'sha1|size|url',
iiurlwidth: 365,
redirects: 1,
titles: pageName.replace( /_/g, ' ' ) + '|' + this.destination
}, 'getDupeDetailsCB' );
this.showProgress( 'Fetching details' );
},
getDupeDetailsCB: function ( result ) {
this.details = [];
if ( result ) {
var q = result.query,
id,
pg,
ii,
n,
pages = q.pages;
for ( id in pages ) {
if ( Object.prototype.hasOwnProperty.call( pages, id ) ) {
pg = pages[ id ];
if ( !pg.imageinfo ) {
// Nothing we can change so prevent users reporting
this.disableReport = true;
throw new Error( ( ( pg.title.trim() === '{{{1}}}' ) ?
this.i18n.dupeParaErr :
this.i18n.dupeExistErr.replace( '%TITLE%', pg.title ) ) + ' (pg.imageinfo is undefined)' );
}
ii = pg.imageinfo[ 0 ];
n = {
title: pg.title,
size: ii.size,
width: ii.width,
height: ii.height,
thumburl: ii.thumburl,
thumbwidth: ii.thumbwidth,
thumbheight: ii.thumbheight,
descriptionurl: ii.descriptionurl,
sha1: ii.sha1,
content: pg.revisions[ 0 ][ '*' ],
starttimestamp: result.curtimestamp
};
this.details.push( n );
this.csrftoken = q.tokens.csrftoken;
if ( pg.watched !== undefined ) {
this.pageWasWatched = true;
}
}
}
}
if ( this.details.length < 2 ) {
this.disableReport = true;
throw new Error( this.i18n.noPageFound );
}
// If order (old=0, new=1) is incorrect: Reverse
if ( this.details[ 0 ].title !== pageName.replace( /_/g, ' ' ) ) {
this.details.reverse();
}
this.nextTask();
},
/**
* Edit the current page to add the specified tag.  Assumes that the page hasn't
* been tagged yet; if it is, a duplicate tag will be added.
*/
prependTemplate: function () {
var page = {
title: this.pageName,
text: this.tag,
editType: 'prependtext',
watchlist: window.AjaxDeleteWatchFile ? 'watch' : this.watchlist,
minor: false
};
this.showProgress( this.i18n.addingAnyTemplate );
this.savePage( page, this.img_summary, 'nextTask' );
},
/**
* Edit the current page to add the specified tag and the changed content.
*/
replaceTemplate: function ( text ) {
var page = {
title: this.destination || pageName,
text: text || this.tag + this.pageContent,
editType: 'text',
starttimestamp: this.starttimestamp,
timestamp: this.timestamp,
watchlist: window.AjaxDeleteWatchFile ? 'watch' : this.watchlist,
minor: false
};
this.templateReplace = false;
this.showProgress( this.i18n.addingAnyTemplate );
this.savePage( page, ( this.declineReason || this.img_summary ), 'nextTask' );
},
/**
* Create the DR subpage (or append a new request to an existing subpage).
* The request page will always be watchlisted.
*/
createRequestSubpage: function () {
this.templateAdded = true; // we've got this far; if something fails, user can follow instructions on template to finish
var page = {
title: this.requestPage,
// eslint-disable-next-line no-useless-escape
text: '\n=== [[:' + this.pageName + ']] ===\n' + this.reason + ' ~~~~\n',
watchlist: 'watch',
editType: 'appendtext'
};
if ( this.isMobile() ) {
page.text += '\n<noinclude>[[Category:MobileUpload-related deletion requests]]</noinclude>';
}
this.showProgress( this.i18n.creatingNomination );
this.savePage( page, this.subpage_summary, 'nextTask' );
},
/**
* Transclude the nomination page onto today's DR log page, creating it if necessary.
* The log page will never be watchlisted (unless the user is already watching it).
*/
listRequestSubpage: function () {
var page = {};
page.title = this.dailyLogPage;
// Impossible when using appendtext. Shouldn't not be severe though, since DRBot creates those pages before they are needed.
// if (!page.text) page.text = "{{"+"subst:" + this.requestPagePrefix + "newday}}";  // add header to new log pages
page.text = '\n{{' + this.requestPage + '}}\n';
page.watchlist = 'preferences';
page.editType = 'appendtext';
this.showProgress( this.i18n.listingNomination );
this.savePage( page, 'Listing [[' + this.requestPage + ']]', 'nextTask' );
},
isMobile: function () {
var isMobile = false,
cats = conf.wgCategories;
for ( var i = 0, len = cats.length; i < len; i++ ) {
isMobile = isMobile || /^Uploaded with Mobile/.test( cats[ i ] );
}
return isMobile;
},
listMobileUpload: function () {
var page = {
title: 'Commons:Deletion requests/mobile tracking',
text: '\n{{' + this.requestPage + '}}\n',
watchlist: 'preferences',
editType: 'appendtext'
};
this.showProgress( this.i18n.listingMobile );
this.savePage( page, 'Listing [[' + this.requestPage + ']]', 'nextTask' );
},
listMobileUploadSpeedy: function () {
var page = {
title: 'Commons:Mobile app/deletion request tracking',
text: '\n# [[:' + this.pageName + ']]',
watchlist: 'preferences',
editType: 'appendtext'
};
this.showProgress( this.i18n.listingMobile );
this.savePage( page, 'Listing [[' + this.pageName + ']]', 'nextTask' );
},
/**
* Check the users talkpage is not blocked indefinite
*/
verifyUserNotify: function ( user ) {
this.queryAPI( {
prop: 'info',
titles: this.userTalkPrefix + user,
redirects: 1,
inprop: 'protection'
}, 'verifyUserNotifyCB' );
},
verifyUserNotifyCB: function ( result ) {
var page;
this.notifyUser = true; // reset
if ( !result || !result.query || !result.query.pages ) {
mw.log.warn( 'Verify user: result.query.pages is undefined. ', result );
return this.uploaderNotified();
}
result = result.query.pages;
for ( var pg in result ) {
pg = result[ pg ];
page = pg.title;
pg = pg.protection;
if ( pg ) {
for ( var p = 0; p < pg.length; p++ ) {
var pt = pg[ p ];
if ( pt && pt.type === 'edit' && pt.level === 'sysop' ) {
// Disable report for protected userpages
this.disableReport = true;
// Disable notify for indefinite protected
if ( pt.expiry === 'infinity' ) {
this.notifyUser = false;
}
}
}
}
}
if ( this.notifyUser && page ) {
page = {
title: page,
// eslint-disable-next-line no-useless-escape
text: '\n' + this.talk_tag + ' ~~~~\n',
editType: 'appendtext',
redirect: true,
minor: false
};
if ( window.AjaxDeleteWatchUserTalk ) {
page.watchlist = 'watch';
}
this.savePage( page, this.talk_summary, 'uploaderNotified' );
} else {
this.uploaderNotified();
}
},
/**
* Notify any uploaders/creators of this page using {{idw}}.
*/
notifyUploaders: function () {
this.uploadersToNotify = 0;
if ( this.notifyUser ) {
for ( var user in this.uploaders ) {
if ( Object.prototype.hasOwnProperty.call( this.uploaders, user ) ) {
if ( user === conf.wgUserName ) {
// notifying yourself is pointless
continue;
}
this.verifyUserNotify( user );
this.showProgress( this.i18n.notifyingUploader.replace( '%USER%', user ) );
this.uploadersToNotify++;
}
}
}
if ( !this.uploadersToNotify ) {
this.nextTask();
}
},
uploaderNotified: function () {
this.uploadersToNotify--;
if ( !this.uploadersToNotify ) {
this.nextTask();
}
},
/**
* Compile a list of uploaders to notify. Users who have only reverted the file to an
* earlier version will not be notified.
* DONE: notify creator of non-file pages
* DONE: notify fileimporter (2019-09-09)
*/
findCreator: function () {
var q = {
curtimestamp: 1,
meta: 'tokens',
prop: 'revisions',
titles: this.pageName,
rvprop: 'timestamp|user',
rvdir: 'newer',
rvslots: 'main',
rvlimit: 1
};
if ( nsNr === 6 ) {
$.extend( q, {
prop: q.prop + '|imageinfo',
rvprop: q.rvprop + '|content',
iiprop: 'user|comment|sha1',
iilimit: '50',
list: 'logevents',
letype: 'import',
leprop: 'user',
letitle: this.pageName
} );
}
this.showProgress( this.i18n.preparingToEdit );
this.queryAPI( q, 'findCreatorCB' );
},
findCreatorCB: function ( r ) {
this.uploaders = {};
if ( !r || !r.query || !r.query.pages ) {
this.disableReport = true;
throw new Error( this.i18n.noPageFound );
}
var q = r.query,
pg = _firstItem( q.pages ),
rv;
if ( !pg || !pg.revisions ) {
throw new Error( this.i18n.noCreatorFound );
}
// The csrftoken only changes between sessions
this.csrftoken = q.tokens.csrftoken;
rv = pg.revisions[ 0 ];
// First handle non-file pages
if ( nsNr !== 6 || !pg.imageinfo ) {
this.starttimestamp = r.curtimestamp;
this.timestamp = rv.timestamp;
if ( ( this.pageCreator = rv.user ) ) {
this.uploaders[ this.pageCreator ] = true;
}
} else {
var info = pg.imageinfo,
i = info.length,
content = rv.slots.main[ '*' ],
seenHashes = {};
// Iterate in reverse order (sha1 check)
for ( --i; i >= 0; i-- ) {
var iii = info[ i ],
rev = seenHashes[ iii.sha1 ];
// Skip reverts and remove users
if ( iii.sha1 && rev ) {
for ( rev; rev > i; rev-- ) {
var u = info[ rev - 1 ].user;
if ( this.uploaders[ u ] < rev ) {
delete this.uploaders[ u ];
}
}
continue;
}
seenHashes[ iii.sha1 ] = i + 1;
// No need to check again the whole shebang
if ( this.uploaders[ iii.user ] ) {
continue;
}
// Now exclude bots which only reupload a new version:
if ( mw.libs.commons.isSmallChangesBot( iii.user ) ) {
continue;
}
// Outsourced to MediaWiki:Gadget-libCommons.js
iii = mw.libs.commons.getUploadBotUser( iii.user, content, iii.comment, rv.user );
if ( iii ) {
this.uploaders[ iii ] = i + 1;
}
}
// Get fileimporter
if ( ( info = q.logevents ) && ( i = info.length ) ) {
for ( --i; i >= 0; i-- ) {
if ( info[ i ].user ) {
this.uploaders[ info[ i ].user ] = true;
}
}
}
}
this.nextTask();
},
getMoveToken: function () {
this.showProgress( this.i18n.preparingToEdit );
var query = {
curtimestamp: 1,
prop: 'info|revisions',
meta: 'tokens',
rvprop: 'content|timestamp',
inprop: 'watched',
titles: this.pageName || pageName.replace( /_/g, ' ' )
};
if ( !this.declineReason ) {
query.prop += '|imageinfo';
query.iiprop = 'mediatype|mime|timestamp';
}
this.queryAPI( query, 'getMoveTokenCB' );
},
/**
* @brief [callback] Prepare page for saving before
* @param [in] result of query
* @return csrftoken, pageContent, starttimestamp, timestamp, imagetimestamp, mimeFileExtension, pageWasWatched
*/
getMoveTokenCB: function ( result ) {
var q = result.query || {},
pg = _firstItem( q.pages );
if ( !pg || !pg.revisions ) {
this.disableReport = true;
throw new Error( this.i18n.noPageFound );
}
// The csrftoken only changes between sessions
$.extend( this, {
csrftoken: q.tokens.csrftoken,
pageContent: pg.revisions[ 0 ][ '*' ],
starttimestamp: result.curtimestamp,
timestamp: pg.revisions[ 0 ].timestamp
} );
if ( pg.watched !== undefined ) {
this.pageWasWatched = true;
}
var ii = pg.imageinfo;
if ( ii && ii.length && ii[ 0 ].mime ) {
ii = ii[ 0 ];
this.imagetimestamp = ii.timestamp;
this.mimeFileExtension = ii.mime
.toLowerCase()
.replace( 'image/jpeg', 'jpg' )
.replace( /image\/(?:x-|vnd\.)?(png|gif|xcf|djvu|svg|tiff)(?:\+xml)?/, '$1' )
.replace( /application\/(ogg|pdf)/, '$1' )
.replace( /video\/(webm)/, '$1' )
.replace( 'audio/midi', 'mid' )
.replace( /audio\/(?:x-|vnd\.)?wave?/, 'wav' )
.replace( /audio\/(?:x-)?flac/, 'flac' );
if ( this.mimeFileExtension.length > 5 ) {
this.mimeFileExtension = '';
} else if ( this.mimeFileExtension === 'ogg' ) {
switch ( ii.mediatype ) {
case 'AUDIO':
this.mimeFileExtension = 'oga';
break;
case 'VIDEO':
this.mimeFileExtension = 'ogv';
break;
}
}
}
this.nextTask();
},
doesFileExist: function () {
if ( !this.destination ) {
// eslint-disable-next-line no-alert
return alert( this.i18n.moveDestination );
}
this.destination = this.cleanFileName( this.destination );
var query = {
prop: 'info|revisions',
titles: this.destination,
rvprop: 'content',
rvlimit: 2
};
// usually you would use 'redirects': 1, to detect the redirect target but
// in this case you would get the revisions for the target and not the redirect
this.showProgress( this.i18n.checkFileExists );
this.queryAPI( query, 'doesFileExistCB' );
},
/**
*  Return nextTask if the page does not exist
*  or it is a redirect with one revision to the source
*/
doesFileExistCB: function ( result ) {
if ( !result || !result.query || !result.query.pages ) {
throw new Error( 'Checking filename: result.query.pages is undefined. ' + this.destination );
}
var exists = true,
pg = _firstItem( result.query.pages ),
getRedirRegExp = function ( title ) {
title = title.replace( /^(File|Image):/, '' ).replace( /_/g, ' ' );
return new RegExp( '^\\s*#REDIRECT\\s*\\[\\[File\\:[' +
mw.util.escapeRegExp( title[ 0 ].toUpperCase() ) + mw.util.escapeRegExp( title[ 0 ].toLowerCase() ) + ']' +
mw.util.escapeRegExp( title.slice( 1 ) ).replace( / /g, '[ _]' ) +
'\\s*\\]\\]',
'' );
};
if ( pg.missing !== undefined ) {
exists = false;
} else if ( !pg.revisions || pg.revisions.length === 1 && getRedirRegExp( pageName )
.test( pg.revisions[ 0 ][ '*' ].replace( 'Image:', 'File:' ) ) ) {
// There seems to be no way to find out whether a title is a redirect
// and whether the redirect only consists of one revision
exists = false;
}
if ( exists ) {
if ( this.fileNameExistsCB ) {
this[ this.fileNameExistsCB ]( pg.title.replace( /^File:/, '' ) );
}
return;
}
this.nextTask();
},
removeTemplate: function () {
this.replaceWith = ( this.replaceWith || ( this.templateRegExp ? '' : '$1$2' ) );
// Remove the template from the text. In case there is an empty line before, remove this also.
var newText = this.pageContent
.replace(
( this.templateRegExp || /(?:([^=])\n)?\{\{(?:rename|rename media|move)\s*\|.*?\}\}(?:\n([^=]))?/i ),
this.replaceWith
);
if ( newText === this.pageContent ) {
return this.nextTask();
}
this.showProgress( this.i18n.removingTemplate );
newText = this.pageContent = newText.trim();
// We have another save request
if ( this.templateReplace ) {
this.img_summary = this.declineReason;
return this.nextTask();
}
if ( !this.declineReason ) {
this.img_summary = 'Removing template; rename done';
}
// If nothing remains, add the no-license-template (this also to prevent abuse filter blocking this edit because of page blanking)
this.replaceTemplate( newText || '{{subst:nld}}' );
},
replaceUsage: function () {
if ( !this.inUse ) {
return this.nextTask();
}
this.showProgress( this.i18n.replacingUsage );
var reasonShort = '[[COM:Duplicate|Duplicate]]:';
if ( !this.details ) {
AQD.reason = AQD.reason.replace( /\[\[Commons:File[_ ]renaming[^[\]]*\]\]:? ?/i, '' );
reasonShort = '[[COM:FR|File renamed]]:';
}
mw.loader.using( 'ext.gadget.libGlobalReplace', function () {
if ( AQD.replaceUsingCORS ) {
mw.libs.globalReplace( pageName, AQD.destination, reasonShort, AQD.reason )
.fail( function ( err ) {
throw new Error( err );
} )
.done( function () {
AQD.nextTask();
} )
.progress( function ( r ) {
AQD.showProgress( r );
mw.log( r );
} );
} else {
mw.libs.globalReplaceDelinker( pageName, AQD.destination, reasonShort + ' ' + AQD.reason, function () {
AQD.nextTask();
}, function ( err ) {
throw new Error( err );
} );
}
} );
},
redirectPage: function () {
var page = {
title: pageName,
text: '#REDIRECT [[' + this.destination + ']]',
editType: 'text',
watchlist: AQD.pageWasWatched ? 'watch' : 'preferences'
};
this.showProgress( this.i18n.redirectingFile );
this.savePage( page, 'Redirecting to duplicate file', 'nextTask' );
},
saveDescription: function () {
var page = {
title: this.destination,
text: this.newPageText,
editType: 'text',
watchlist: AQD.pageWasWatched ? 'watch' : 'preferences'
};
this.showProgress( this.i18n.savingDescription );
this.savePage( page, 'Merging details from duplicate ([[' + pageName + ']])', 'nextTask' );
},
/**
*  Updates the redirects to the current page
*  when moving or processing dupes immediately
*  to prevent double redirects
*/
queryRedirects: function () {
mw.loader.using( 'mediawiki.api' ).then( function () {
return new mw.Api().loadMessagesIfMissing( [
'Whatlinkshere'
] );
} ).then( function () {
AQD.showProgress( mw.msg( 'Whatlinkshere' ) );
// TODO: Replace also the redirects inclusions!?
AQD.queryAPI( {
generator: 'backlinks',
gblfilterredir: 'redirects',
prop: 'revisions',
rvprop: 'content',
gbltitle: AQD.pageName || pageName.replace( /_/g, ' ' )
}, AQD.queryRedirectsCB ?
AQD.queryRedirectsCB :
'updateRedirects' );
} );
},
updateRedirects: function ( result ) {
AQD.redirectsToUpdate = 0;
if ( result.query && result.query.pages ) {
this.showProgress( this.i18n.updRedir );
$.each( result.query.pages, function ( id, pg ) {
var rv = pg.revisions[ 0 ];
if ( !rv || !rv[ '*' ] ) {
return;
}
// Update only redirects with same mimetype
if ( AQD.checkFileExt( pg.title, AQD.destination, true ) ) {
return mw.log( 'Redirect skipped, not same mimetype.', pg.title );
}
var page = {
title: pg.title,
text: rv[ '*' ].replace( /#\s*REDIRECT\s*\[\[.+/, '#REDIRECT [[' + AQD.destination + ']]' ),
editType: 'text',
watchlist: 'preferences'
};
AQD.savePage( page, 'Updating redirect while processing [[' + pageName.replace( /_/g, ' ' ) + ']]', 'updateRedirectsCB' );
AQD.redirectsToUpdate++;
} );
}
if ( !AQD.redirectsToUpdate ) {
AQD.nextTask();
}
},
updateRedirectsCB: function () {
AQD.redirectsToUpdate--;
if ( !AQD.redirectsToUpdate ) {
AQD.nextTask();
}
},
/**
* Pseudo-Modal JS windows.
*/
prompt: function ( questions, title, width ) {
var o = this,
dlgButtons = {};
dlgButtons[ this.i18n.submitButtonLabel ] = function () {
questions.forEach( function ( v, i ) {
var response = document.getElementById( 'AjaxQuestion' + i );
response = ( v.type === 'checkbox' ) ? response.checked : response.value;
if ( v.cleanUp ) {
if ( v.returnvalue === 'reason' ) {
response = AQD.cleanReason( response );
}
if ( v.returnvalue === 'destination' ) {
response = AQD.cleanFileName( response );
}
}
AQD[ v.returnvalue ] = response;
if ( v.returnvalue === 'reason' && AQD.tag ) {
AQD.tag = AQD.tag.replace( '%PARAMETER%', response );
if ( AQD.talk_tag ) {
AQD.talk_tag = AQD.talk_tag.replace( '%PARAMETER%', response );
}
AQD.img_summary = AQD.img_summary.replace( '%PARAMETER%', response )
.replace( '%PARAMETER-LINKED%', '[[:' + response + ']]' );
}
} );
$( this ).dialog( 'close' );
AQD.nextTask();
};
dlgButtons[ this.i18n.cancelButtonLabel ] = function () {
$( this ).dialog( 'close' );
};
var $submitButton,
$AjaxDeleteContainer = $( '<div>', { id: 'AjaxDeleteContainer' } ),
_parseReason = function () {
var $el = $( this ),
$parserResultNode = $el.data( 'parserResultNode' );
if ( !$parserResultNode ) {
return;
}
$parserResultNode.css( 'color', '#877' );
var _gotParsedText = function ( r ) {
try {
$parserResultNode.html( r );
$parserResultNode.css( 'color', '#000' );
} catch ( ex ) {}
};
mw.loader.using( [ 'ext.gadget.libAPI' ], function () {
mw.libs.commons.api.parse( $el.val(), conf.wgUserLanguage, pageName, _gotParsedText );
} );
},
_validateInput = function ( event ) {
var $el = $( this ),
v = $el.data( 'v' );
if ( v.noEmpty ) {
$submitButton.button( 'option', 'disabled', $el.val().trim().length < ( v.minLength || 8 ) );
}
if (
( $el.prop( 'nodeName' ) !== 'TEXTAREA' ) &&
( event.which === 13 ) &&
( v.enterToSubmit !== false ) &&
!$submitButton.button( 'option', 'disabled' )
) {
$submitButton.trigger( 'click' );
}
},
_convertToTextarea = function () {
var $el = $( this ),
$input = $el.data( 'toConvert' ),
$tarea = $( '<textarea>', {
id: $input.attr( 'id' ),
style: 'height:10em; width:98%; display:none;'
} );
$el.off().fadeOut();
$input.parent().prepend(
$tarea
.data( 'v', $input.data( 'v' ) ).data( 'parserResultNode', $input.data( 'parserResultNode' ) )
.val( $input.val() ).on( 'keyup', _parseReason ).on( 'keyup input', _validateInput ) );
$tarea.slideDown();
$input.remove();
};
questions.forEach( function ( v, i ) {
v.type = ( v.type || 'text' );
if ( v.type === 'textarea' ) {
$AjaxDeleteContainer.append( '<label for="AjaxQuestion' + i + '">' + v.message + '</label>' )
.append( '<textarea rows=20 id="AjaxQuestion' + i + '">' );
} else {
$AjaxDeleteContainer.append( '<label for="AjaxQuestion' + i + '">' + v.message + '</label>' )
.append( '<input type="' + v.type + '" id="AjaxQuestion' + i + '" style="width:97%;">' );
}
var curQuestion = $AjaxDeleteContainer.find( '#AjaxQuestion' + i );
if ( v.parseReason ) {
var $parserResultNode = $( '<div>', {
id: 'AjaxQuestionParse' + i,
html: '&nbsp;'
} );
$AjaxDeleteContainer.append( '<br><label for="AjaxQuestionParse' + i + '">' +
o.i18n.previewLabel + '</label>' ).append( $parserResultNode );
curQuestion.data( 'parserResultNode', $parserResultNode ).keyup( _parseReason );
}
if ( v.type !== 'textarea' ) {
$AjaxDeleteContainer.append( '<br>' );
}
$AjaxDeleteContainer.append( v.appendNode ? v.appendNode : '<br>' );
if ( typeof v.byteLimit === 'number' ) {
mw.loader.using( 'jquery.lengthLimit', function () {
curQuestion.byteLimit( v.byteLimit );
} );
}
curQuestion.data( 'v', v );
curQuestion.on( 'keyup input', _validateInput );
// SECURITY: prefill could contain evil jsCode. Never use it unescaped!
// Use .val() or { value: prefill } or '<input value="' + mw.html.escape() + '" …>
curQuestion.val( v.prefill );
if ( v.type === 'checkbox' ) {
curQuestion.prop( 'checked', v.prefill ).attr( 'style', 'margin-left: 5px' );
}
} );
if ( mw.user.isAnon() ) {
AQD.renderNode( $( '<div>', { id: 'ajaxDeleteAnonwarning' } ), 'MediaWiki:Anoneditwarning' ).appendTo( $AjaxDeleteContainer );
}
$( '<div>' ).append( $AjaxDeleteContainer ).dialog( {
width: ( width || 600 ),
modal: true,
title: title,
dialogClass: 'wikiEditor-toolbar-dialog',
close: function () {
$( this ).dialog( 'destroy' ).remove();
if ( AQD.currentTask === 'formerDRRequestpage' ) {
mw.util.$content.find( '.convert-to-dr' ).show();
}
},
buttons: dlgButtons,
open: function () {
// Look out for http://bugs.jqueryui.com/ticket/6830 / jQuery UI 1.9
var $buttons = $( this ).parent().find( '.ui-dialog-buttonpane button' );
$submitButton = $buttons.eq( 0 ).specialButton( 'proceed' );
$buttons.eq( 1 ).specialButton( 'cancel' );
}
} );
questions.forEach( function ( v, i ) {
var curQuestion = $AjaxDeleteContainer.find( '#AjaxQuestion' + i );
curQuestion.trigger( 'keyup' );
if ( v.type === 'text' ) {
var $q = curQuestion.wrap( '<div style="position:relative;">' ).parent(),
$i = $.createIcon( 'ui-icon-arrow-4-diag' ).attr( 'title', AQD.i18n.expandToTextarea );
$( '<span>', {
// eslint-disable-next-line quote-props
'class': 'ajaxTextareaConverter' } ).append( $i ).appendTo( $q ).data( 'toConvert', curQuestion ).on( 'click', _convertToTextarea );
}
} );
$( '#AjaxQuestion0' ).trigger( 'focus' ).trigger( 'select' );
mw.hook( 'aqd.prompt' ).fire( o );
},
/**
* Open a jQuery dialog with preview-images and some options
* and information to compare the two files
*/
compareDetails: function () {
var d = this.details[ 0 ],
f = this.details[ 1 ],
$swapButton,
$overlayButton;
if ( d.sha1 === f.sha1 ) {
this.exactDupes = true;
this.nextTask();
return;
}
var $imgD = $( '<div>' ).append( $( '<img>', {
src: d.thumburl,
height: d.thumbheight,
width: d.thumbwidth
} ), $( '<div>', {
id: 'AjaxDeleteImgDel',
html: Math.round( d.size / 1000 ) + ' KiB <br>' + d.width + '×' + d.height + '<br>'
} ).append(
$( '<a>', {
href: d.descriptionurl,
text: d.title,
target: '_blank'
} ) ) ),
$imgF = $( '<div>' ).append( $( '<img>', {
src: f.thumburl,
height: f.thumbheight,
width: f.thumbwidth
} ), $( '<div>', {
id: 'AjaxDeleteImgKeep',
html: Math.round( f.size / 1000 ) + ' KiB <br>' + f.width + '×' + f.height + '<br>'
} ).append(
$( '<a>', {
href: f.descriptionurl,
text: f.title,
target: '_blank'
} ) ) ),
dlgButtons = {};
dlgButtons[ this.i18n.submitButtonLabel ] = function () {
$( this ).dialog( 'close' );
AQD.nextTask();
};
dlgButtons[ this.i18n.inverseButtonLabel ] = function () {
$( this ).dialog( 'close' );
AQD.destination = pageName.replace( /_/g, ' ' );
pageName = f.title;
AQD.details.reverse();
AQD.inUse = true;
setTimeout( function () {
AQD.compareDetails();
}, 20 );
};
dlgButtons[ this.i18n.swapImagesButtonLabel ] = function () {
if ( $imgD[ 0 ].nextSibling === $imgF[ 0 ] ) {
$imgD.before( $imgF );
} else {
$imgF.before( $imgD );
}
};
var $fClone;
dlgButtons[ this.i18n.overlayButtonLabel ] = function () {
if ( $fClone ) {
$fClone.remove();
$fClone = 0;
} else {
$fClone = $imgF.clone().appendTo( $imgF.parent() );
$fClone.css( 'position', 'absolute' );
var pos = $imgD.position();
$fClone.css( {
top: pos.top - 1, left: pos.left - 1
} )
.fadeTo( 0, 0.65 );
// These modules should be already loaded for the dialog but let's be sure
mw.loader.using( [ 'jquery.ui'], function () {
// Set width to auto because AjaxQuickDelete.css sets it to a fixed size
$fClone.css( {
background: 'rgba(200, 200, 200, 0.5)',
width: 'auto',
border: '1px solid #0c9'
} ).draggable();
$fClone.find( 'img' ).resizable();
// In IE, opacity is not fully inerhited
$fClone.children( 'div' ).fadeTo( 0, 0.7 );
} );
}
};
this.showProgress();
var $AjaxDupeContainer = $( '<div>', { id: 'AjaxDupeContainer' } ).append( $imgD, $imgF );
$( '<div>' ).append( $AjaxDupeContainer ).dialog( {
width: 800,
modal: true,
title: this.i18n.compareDetails,
draggable: false,
dialogClass: 'wikiEditor-toolbar-dialog',
close: function () {
$( this ).dialog( 'destroy' ).remove();
},
buttons: dlgButtons,
open: function () {
var $buttons = $( this ).parent().find( '.ui-dialog-buttonpane button' );
$buttons.eq( 0 ).specialButton( 'proceed' );
$buttons.eq( 1 ).button( { icons: { primary: 'ui-icon-refresh' } } );
$swapButton = $buttons.eq( 2 ).button( { icons: { primary: 'ui-icon-transfer-e-w' } } );
$overlayButton = $buttons.eq( 3 ).button( { icons: { primary: 'ui-icon-newwin' } } );
$swapButton.css( 'float', ( ( $swapButton.css( 'float' ) === 'left' ) ? 'right' : 'left' ) );
$overlayButton.css( 'float', ( ( $overlayButton.css( 'float' ) === 'left' ) ? 'right' : 'left' ) );
}
} );
mw.loader.load( [ 'ext.gadget.libGlobalReplace', 'ext.gadget.libWikiDOM' ] );
},
mergeDescriptions: function () {
var newPageText = this.details[ 1 ].content;
mw.loader.using( [ 'ext.gadget.libGlobalReplace', 'ext.gadget.libWikiDOM' ], function () {
newPageText = mw.libs.wikiDOM.nowikiEscaper( newPageText ).doCleanUp();
AQD.showProgress();
AQD.prompt( [ {
message: '',
prefill: AQD.details[ 0 ].content,
returnvalue: 'discard',
cleanUp: false,
noEmpty: false,
type: 'textarea',
enterToSubmit: false
}, {
message: '',
prefill: newPageText,
returnvalue: 'newPageText',
cleanUp: false,
noEmpty: false,
type: 'textarea',
enterToSubmit: false
}, {
message: AQD.i18n.useCORSForReplace,
prefill: !window.aqdCORSOptOut,
returnvalue: 'replaceUsingCORS',
// cleanUp: false,
noEmpty: false,
type: 'checkbox'
}
], AQD.i18n.mergeDescription, 800 );
AQD.destination = AQD.details[ 1 ].title;
AQD.reason = 'Exact or scaled-down duplicate: [[:' + AQD.destination + ']]';
} );
},
/**
* Correct the MIME-Type; Accepts only valid filenames (with extension)
* Either a filename is passed or the destination property is used
*/
correctMIME: function ( fn ) {
// If the current mime-type is available to the script, check it;
// MediaWiki sometimes allows uploading mismatching mimetypes but not moving
var f = fn || this.destination;
if ( this.mimeFileExtension ) {
f = f.replace( /\.\w{2,5}$/, '.' + this.mimeFileExtension );
}
if ( !fn ) {
this.destination = f;
return this.nextTask();
} else {
return f;
}
},
cleanFileName: function ( fn, ignoreMIME ) {
// Remove Namespace
fn = fn.replace( /^(?:Image|File):/i, '' )
// Convert extension to lower case
.replace( /(\.\w{2,5})+$/, function ( $e ) {
return $e.toLowerCase();
} )
// jpeg -> jpg
.replace( /\.jpe*g$/, '.jpg' )
// First cleanUp from Flinfo (FlinfoOut.php) by Flominator and Lupo
.replace( /~{3,}/g, '' ) // "signature"
.replace( /[\u00A0\u1680\u180E\u2000-\u200B\u2028\u2029\u202F\u205F\u3000]/, ' ' ) // remove NBSP and other unusual spaces
.replace( /\s+|_/g, ' ' ) // (multiple) whitespace
// eslint-disable-next-line no-control-regex
.replace( /[\x00-\x1f\x7f]/g, '' )
.replace( /%([0-9A-Fa-f]{2})/g, '% $1' ) // URL encoding stuff
.replace( /&(([A-Za-z0-9\x80-\xff]+|#[0-9]+|#x[0-9A-Fa-f]+);)/g, '& $1' ) // URL-params?
.replace( /''/g, '"' )
.replace( /[:/|#]/g, '-' )
.replace( /[\]}>]/g, ')' )
.replace( /[[{<]/g, '(' );
fn = this.checkFileExt( pageName, fn, ignoreMIME ) || fn;
// Capitalize the first letter and prefix the namespace
return 'File:' + $.ucFirst( fn ); // own prototype
},
/**
* @brief Compare mimetype
* @param [in] of old filename
* @param [in] fn new filename
* @param [in] boolean
* @return false if same, otherwise new file with old extension
*/
checkFileExt: function ( of, fn, ignoreMIME ) {
var currentExt = ( !ignoreMIME && this.mimeFileExtension ) ?
this.mimeFileExtension :
of.replace( /.*?\.(\w{2,5})$/, '$1' ).toLowerCase().replace( 'jpeg', 'jpg' ),
reCurrentExt = new RegExp( '\\.' + mw.util.escapeRegExp( currentExt ) + '$', 'i' ),
reDestExt = new RegExp( '\\.' + mw.util.escapeRegExp( fn.replace( /.*?\.(\w{2,5})$/, '$1' ) ) + '$', 'i' );
// If new filename is without (same) extension, add the one from the old name
if ( !reCurrentExt.test( fn ) ) {
// First, try to replace the old extension
fn = fn.replace( reDestExt, '.' + currentExt );
if ( !reCurrentExt.test( fn ) ) {
// If this did not work, then simply append the old extension
fn += '.' + currentExt;
}
} else {
fn = false;
} // is equal
return fn;
},
cleanReason: function ( uncleanReason ) {
return uncleanReason
.trim() // whitespace
.replace( /(?:--|–|—)? ?~{3,5} ?/, '' ) // remove signature
.replace( /\|\s/g, '&#124; ' ); // pipes
},
/**
* For display of progress messages.
*/
showProgress: function ( message ) {
if ( !message ) {
if ( this.progressDialog ) {
this.progressDialog.remove();
}
this.progressDialog = 0;
document.body.style.cursor = 'default';
return;
}
if ( $( '#feedbackContainer' ).length ) {
$( '#feedbackContainer' ).html( message );
} else {
document.body.style.cursor = 'wait';
this.progressDialog = $( '<div>' ).html( '<div id="feedbackContainer">' + ( message || this.i18n.preparingToEdit ) + '</div>' ).dialog( {
width: 450,
height: 'auto',
minHeight: 90,
modal: true,
resizable: false,
draggable: false,
closeOnEscape: false,
dialogClass: 'ajaxDeleteFeedback',
open: function () {
$( this ).parent().find( '.ui-dialog-titlebar' ).hide();
},
close: function () {
$( this ).dialog( 'destroy' ).remove();
}
} );
}
},
/**
* Submit an edited page.
*/
savePage: function ( page, summary, callback ) {
if ( AQD.csrftoken ) {
mw.user.tokens.set( 'csrfToken', AQD.csrftoken );
}
$.extend( true, page, {
cb: function ( r ) {
AQD.secureCall( callback, r );
},
// text, result, query
errCb: function ( t, r ) {
if ( AQD.uploadersToNotify ) {
// If user notify fails don't break next task (e.q. redirect to protected page, very rare)
AQD.secureCall( callback, r );
}
AQD.fail( t, r );
},
summary: summary
} );
mw.loader.using( [ 'ext.gadget.libAPI' ], function () {
mw.libs.commons.api.editPage( page );
} );
},
movePage: function () {
mw.user.tokens.set( 'csrfToken', AQD.csrftoken );
// Some users don't get it: They want to move pages to themselves.
if ( pageName.replace( /_/g, ' ' ) === AQD.destination ) {
return AQD.nextTask();
}
mw.loader.using( [ 'ext.gadget.libAPI' ], function () {
var moveArgs = {
cb: function () {
AQD.nextTask();
},
// text, r-result, query
errCb: function ( t, r ) {
if ( r && r.error && /articleexists/.test( r.error.code ) ) {
AQD.disableReport = true;
}
AQD.fail( t, r );
},
from: pageName,
to: AQD.destination,
reason: AQD.reason,
movetalk: true,
watchlist: AQD.pageWasWatched ? 'watch' : 'preferences'
};
// Option to not leave a redirect behind, MediaWiki default does leave one behind
// Just like movetalk, an empty parameter sets it to true
if ( AQD.wpLeaveRedirect === false ) {
moveArgs.noredirect = true;
}
AQD.showProgress( AQD.i18n.movingFile );
mw.libs.commons.api.movePage( moveArgs );
} );
},
deletePage: function () {
mw.user.tokens.set( 'csrfToken', AQD.csrftoken );
mw.loader.using( [ 'ext.gadget.libAPI' ], function () {
AQD.showProgress( AQD.i18n.deletingFile );
mw.libs.commons.api.deletePage( {
cb: function () {
AQD.nextTask();
},
// text, result, query
errCb: function ( t, r ) {
AQD.fail( t, r );
},
title: pageName,
reason: AQD.reason
} );
} );
},
purge: function () {
// No need for checking success, showing progress, nor for waiting for task to complete
this.nextTask();
$.post( this.apiURL, {
format: 'json',
action: 'purge',
forcelinkupdate: 1,
titles: pageName
} );
},
/**
* Does a MediaWiki API request and passes the result to the supplied callback (method name).
*/
queryAPI: function ( params, callback ) {
mw.loader.using( [ 'ext.gadget.libAPI' ], function () {
params.action = params.action || 'query';
mw.libs.commons.api.query( params, {
method: 'GET',
cache: false,
cb: function ( r ) {
AQD.secureCall( callback, r );
},
// text, result, query
errCb: function ( t, r ) {
AQD.fail( t, r );
}
} );
} );
},
/**
* Method to catch errors and report where they occurred
*/
secureCall: function ( fn, r ) {
var o = AQD;
try {
o.currentTask = arguments[ 0 ];
if ( typeof fn === 'function' ) {
// arguments is not of type array so we can't take .slice
return fn.apply( o, Array.prototype.slice.call( arguments, 1 ) );
} else if ( typeof fn === 'string' ) {
return o[ fn ].apply( o, Array.prototype.slice.call( arguments, 1 ) );
} else {
mw.log.warn( fn, this.tasks );
o.fail( 'This is not a function!' );
}
} catch ( ex ) {
o.fail( ex, r );
}
},
/**
* Simple task queue.  addTask() adds a new task to the queue, nextTask() executes
* the next scheduled task.  Tasks are specified as method names to call.
*/
tasks: [],
// list of pending tasks
currentTask: '',
// current task, for error reporting
addTask: function ( task ) {
this.tasks.push( task );
},
nextTask: function () {
this.secureCall( this.tasks.shift() );
},
retryTask: function () {
this.secureCall( this.currentTask );
},
/**
* Once we're all done, reload the page.
*/
reloadPage: function () {
this.showProgress();
if ( this.pageName && this.pageName.replace( / /g, '_' ) !== pageName ) {
return;
}
location.href = mw.util.getUrl( this.destination || pageName );
},
/**
* Error handler. Throws an alert at the user and give him
* the possibility to retry or autoreport the error-message.
*/
fail: function ( err, r ) {
var o = this,
msg,
dlgButtons = {};
if ( typeof err === 'object' ) {
msg = err.message + ' \n\n ' + err.name;
if ( err.lineNumber ) {
msg += ' @line' + err.lineNumber;
}
err = msg;
}
// Mostly the same as err
if ( typeof r === 'object' ) {
if ( r.error && /tpt-target-page|readonly/.test( r.error.code ) ) {
this.disableReport = true;
}
}
// err += '\n' + JSON.stringify( r );
msg = this.i18n.taskFailure[ this.currentTask ] || this.i18n.genericFailure;
// TODO: Needs cleanup
if ( this.img_summary === 'Nominating for deletion' ) {
msg += ' ' + ( this.templateAdded ? this.i18n.completeRequestByHand : this.i18n.addTemplateByHand );
}
dlgButtons[ this.i18n.retryButtonLabel ] = function () {
$( this ).remove();
o.retryTask();
};
if ( [ 'movePage', 'deletePage', 'notifyUploaders' ].indexOf( o.currentTask ) !== -1 &&
( /code 50\d|missingtitle/.test( err ) ) ) {
dlgButtons[ this.i18n.ignoreButtonLabel ] = function () {
$( this ).remove();
o.nextTask();
};
}
if ( !this.disableReport ) {
dlgButtons[ this.i18n.reportButtonLabel ] = function () {
var randomId = Math.round( Math.random() * 1099511627776 ),
toSend = '\n== Autoreport by AjaxQuickDelete ' + randomId + ' ==\n' + err +
'\nAQD version: ' + o.version +
'\n++++\n:Task: ' + o.currentTask + '\n:NextTask: ' + o.tasks[ 0 ] + '\n:LastTask: ' + o.tasks[ o.tasks.length - 1 ] +
'\n:Page: {{Page|1=' + ( o.pageName || pageName ) + '}}\n:Skin: ' + mw.user.options.get( 'skin' ) +
'\n:[{{fullurl:Special:Contributions|target={{subst:urlencode:{{subst:REVISIONUSER}}}}&offset={{subst:REVISIONTIMESTAMP}}}} Contribs] ' +
'[{{fullurl:Special:Log|user={{subst:urlencode:{{subst:REVISIONUSER}}}}&offset={{subst:REVISIONTIMESTAMP}}}} Log] ' +
'before error [[User:{{subst:REVISIONUSER}}|]] ~~~~~\n\n';
$( '#feedbackContainer' ).contents().remove().end()
.append( $( '<img>', { src: '//upload.wikimedia.org/wikipedia/commons/d/de/Ajax-loader.gif' } ) ).css( 'text-align', 'center' );
$.post( o.apiURL, {
action: 'edit',
format: 'json',
title: 'MediaWiki talk:Gadget-AjaxQuickDelete.js/auto-errors',
summary: '/*Autoreport by AjaxQuickDelete ' + randomId + '*/ error with random id',
appendtext: toSend,
token: ( o.csrftoken || mw.user.tokens.get( 'csrfToken' ) )
}, function () {
o.reloadPage();
} );
};
}
dlgButtons[ this.i18n.abortButtonLabel ] = function () {
$( this ).remove();
};
this.disableReport = false;
this.showProgress();
this.progressDialog = $( '<div>' ).append( $( '<div>', {
id: 'feedbackContainer',
html: ( msg + '<br>' + this.i18n.errorDetails + '<br>' + mw.html.escape( err ) + '<br>' +
( this.tag ? ( this.i18n.tagWas + this.tag ) : '' ) + '<br><a href="' + mw.util.getUrl( 'MediaWiki talk:AjaxQuickDelete.js' ) +
'" >' + this.i18n.errorReport.replace( /%BUTTON%/, '<tt>' + this.i18n.reportButtonLabel + '</tt>' ) + '</a>' )
} ) ).dialog( {
width: 550,
modal: true,
closeOnEscape: false,
title: this.i18n.errorDlgTitle,
dialogClass: 'ajaxDeleteError',
buttons: dlgButtons,
close: function () {
$( this ).dialog( 'destroy' ).remove();
}
} );
if ( mw.log.warn ) {
mw.log.warn( err );
}
},
/**
* Very simple date formatter.  Replaces the substrings "YYYY", "MM" and "DD" in a
* given string with the UTC year, month and day numbers respectively.
* Also replaces "MON" with the English full month name and "DAY" with the unpadded day.
*/
formatDate: function ( fmt, date ) {
return mw.libs.commons.formatDate( fmt, date,
( mw.libs.commons.api && mw.libs.commons.api.getCurrentDate() || new Date() )
);
},
// Constants
// DR subpage prefix
requestPagePrefix: 'Commons:Deletion requests/',
// user talk page prefix
userTalkPrefix: conf.wgFormattedNamespaces[ 3 ] + ':',
// MediaWiki API script URL
apiURL: mw.util.wikiScript( 'api' ),
// Max number of errors that are allowed for silent retry
apiErrorThreshold: 10,
// Translatable strings
i18n: {
toolboxLinkDelete: 'Nominate for deletion',
toolboxLinkDiscuss: 'Nominate category for discussion',
// GUI reason prompt form
reasonForDeletion: 'Why should this file be deleted?',
reasonForDiscussion: 'Why does this category need discussion?',
moreInformation: 'More information',
loading: 'Loading…',
keptAfterDR: 'This page was kept after a deletion request. Please contact the administrator who kept it before re-nominating.',
hasTalkpage: 'There is a talk page. Consider reading it or adding your remarks.',
mentionedInDR: 'Consider reading the deletion debate –%PAGE%– that links to this page.',
mentionedInForum: 'On %PAGE%, this page is part of a discussion.',
// Labels
previewLabel: 'Preview:',
submitButtonLabel: 'Proceed',
cancelButtonLabel: 'Cancel',
abortButtonLabel: 'Abort',
reportButtonLabel: 'Report automatically',
retryButtonLabel: 'Retry',
ignoreButtonLabel: 'Ignore and continue',
inverseButtonLabel: 'Inverse. Keep this delete other',
swapImagesButtonLabel: 'Swap to compare',
overlayButtonLabel: 'Overlay to compare',
expandToTextarea: 'Expand to textarea',
notifyUser: 'Notify users',
// GUI progress messages
preparingToEdit: 'Preparing to edit pages… ',
creatingNomination: 'Creating nomination page… ',
listingNomination: 'Adding nomination page to daily list… ',
addingAnyTemplate: 'Adding template to ' + conf.wgCanonicalNamespace.toLowerCase() + ' page… ',
notifyingUploader: 'Notifying %USER%… ',
listingMobile: 'Listing mobile upload',
updRedir: 'Updating redirects',
// Extended version
toolboxLinkSource: 'No source',
toolboxLinkLicense: 'No license',
toolboxLinkPermission: 'No permission',
toolboxLinkCopyvio: 'Report copyright violation',
reasonForCopyvio: 'Why is this file a copyright violation?',
// For moving files
notAllowed: 'You do not have the neccessary rights to move files',
reasonForMove: 'Why do you want to move this file?',
moveDestination: 'What should be the new filename?',
moveOtherDestination: 'The name you have specified exists. Choose a new name, please.',
checkFileExists: 'Checking whether file exists',
movingFile: 'Moving file',
replacingUsage: 'Ordering CommonsDelinker to replace all usage',
dropdownMove: 'Move & Replace',
leaveRedirect: 'Leave a redirect behind:',
moveAndReplace: 'Move file and replace all usage',
warnRename: 'File renaming was recently declined, be prudent!',
// For declining any request
removingTemplate: 'Removing template',
declineRequest: 'Why do you want to decline the request?',
anyDecline: 'Decline request',
// For Duplicates
useCORSForReplace: 'Try to replace usage immediately using your user account:',
deletingFile: 'Deleting file',
compareDetails: 'Please compare the images before merging the descriptions. The image with the bold text will be deleted.',
mergeDescription: 'Please now merge the file descriptions',
redirectingFile: 'Redirecting file',
savingDescription: 'Saving new details',
processDupes: 'Process Duplicates',
// Errors
errorDlgTitle: 'Error',
genericFailure: 'An error occurred while trying to do the requested action. ',
taskFailure: {
listUploaders: 'An error occurred while determining the ' + ( nsNr === 6 ? ' uploader(s) of this file' : 'creator of this page' ) + '.',
loadPages: 'An error occurred while preparing to nominate this ' + conf.wgCanonicalNamespace.toLowerCase() + ' for deletion.',
prependDeletionTemplate: 'An error occurred while adding the {{delete}} template to this ' + conf.wgCanonicalNamespace.toLowerCase() + '.',
createRequestSubpage: 'An error occurred while creating the request subpage.',
listRequestSubpage: 'An error occurred while adding the deletion request to today’s log.',
notifyUploaders: 'An error occurred while notifying the ' + ( nsNr === 6 ? ' uploader(s) of this file' : 'creator of this page' ) + '.',
movePage: 'Error while moving the page.',
deletePage: 'Error deleting the page.'
},
addTemplateByHand: 'To nominate this ' + conf.wgCanonicalNamespace.toLowerCase() + ' for deletion, please edit the page to add the {{delete}} template and follow the instructions shown on it.',
completeRequestByHand: 'Please follow the instructions on the deletion notice to complete the request.',
errorDetails: 'A detailed description of the error is shown below:',
errorReport: 'Manually report the error here or click on %BUTTON% to send an automatic error-report.',
tagWas: 'The tag to be inserted into this page was ',
// Minor errors/warnings
templateRegExp: 'The template does not expose a valid regular expression for {{X-To-DR}}. Go the the template and fix it there.',
findTemplateAdderErr: 'Unable to find the person who added the template. This can occur if the template was already removed, the page is deleted or a redirect to the template is used. In this case you must add the redirect to the RegExp of the target template.',
dupeParaErr: 'Error in the duplicate-template, check your language version!',
dupeExistErr: 'Retrieving information about %TITLE% failed. It is possible that it is deleted, the last revision is corrupt or the file is a redirect.',
noCreatorFound: 'The page you are attempting to add a tag to was deleted or moved. Unable to retrieve the content.',
noPageFound: 'The page you are attempting to modify or move is corrupted, was deleted or moved: Unable to retrieve history and contents.'
}
};
AQD.preinstall();
if ( conf.wgUserLanguage !== 'en' ) {
$.when( mw.loader.getScript( mw.util.wikiScript() +
'?title=MediaWiki:Gadget-AjaxQuickDelete.js/' +
conf.wgUserLanguage + '.js&action=raw&ctype=text/javascript'
), $.ready ).always( function () { AQD.install(); } );
} else {
$( function () {
AQD.install();
} );
}
}() );
// </nowiki>
// This script aligns dates into one of two formats allowed by [[WP:MOSNUM]].
// This script aligns dates into one of two formats allowed by [[WP:MOSNUM]].
// PLEASE READ THE DOCUMENTATION at [[User:Ohconfucius/script/MOSNUM dates]] (click on the link above) before using.
// PLEASE READ THE DOCUMENTATION at [[User:Ohconfucius/script/MOSNUM dates]] (click on the link above) before using.

১৬:০৮, ২৭ এপ্রিল ২০২২ তারিখে সংশোধিত সংস্করণ

// This script aligns dates into one of two formats allowed by [[WP:MOSNUM]].
// PLEASE READ THE DOCUMENTATION at [[User:Ohconfucius/script/MOSNUM dates]] (click on the link above) before using.

// Feedback and constructive criticism are welcome

/**
 * TemplateScript adds configurable templates and scripts to the sidebar, and adds an example regex editor.
 * @see https://meta.wikimedia.org/wiki/TemplateScript
 */
// <pre>
if ($.inArray(mw.config.get('wgAction'), ['edit', 'submit']) !== -1) {
	$.ajax(
		'//tools-static.wmflabs.org/meta/scripts/pathoschild.templatescript.js',
		{dataType: 'script', cache: true}
	).done(function () {
		$.when(
			mw.loader.using(['mediawiki.util']),
			$.ajax('//en.wikipedia.org/w/index.php?title=User:Ohconfucius/script/MOSNUM_utils.js&action=raw&ctype=text/javascript',
				{dataType: 'script', cache: true}),
			$.ready
		).done(function () {
			var add = function() {
            return mw.util.addPortletLink.apply(mw.util, arguments);
			};

			$(add('p-tb', '#', 'DATES to dmy', 'dmy-unitfixer', 'Align all dates to dmy', '', '')).click(ohc_all_to_dmy_driver);
			$(add('p-tb', '#', 'DATES to mdy', 'mdy-unitfixer', 'Align all dates to mdy', '', '')).click(ohc_all_to_mdy_driver);
//			$(add('p-tb', '#', 'Expand ref dates', 't-expandref', 'Expand month names within refs', '', '')).click(ohc_expand_ref_dates_driver);
//			$(add('p-tb', '#', 'Expand all dates', 't-expandall', 'Expand month names throughout', '', '')).click(ohc_expand_all_dates_driver);
			$( add('p-tb', '#', 'US-slash dates', 't-US', 'US-slash', '', '') ).click(ohc_US_slash_dates_driver);
			$( add('p-tb', '#', 'UK-slash dates', 't-UK', 'UK-slash', '', '') ).click(ohc_UK_slash_dates_driver);
		});
	});
}

function ohc_fix_unambiguous_dates()
{
	// resolvable ambiguous date formats
	// UK style
	ohc_regex(/([^-\w/:\.])@DD\.@MM\.@YYYY(?=[^-–/\w&])/gi, "$1@Day @Month @YYYY", function(d) {
		if (d.d == d.m) return true;
		if (d.d > 12) return true;
		return false;
		});
	ohc_regex(/([^-\w/:\.])@DD\/@MM\/@YYYY(?=[^-–/\w&])/gi, "$1@Day @Month @YYYY", function(d) {
		if (d.d == d.m) return true;
		if (d.d > 12) return true;
		return false;
		});

	// US style
	ohc_regex(/([^-\w/:\.])@MM\.@DD\.@YYYY(?=[^-–/\w&])/gi, "$1@Month @Day, @YYYY", function(d) {
		if (d.d > 12) return true;
		return false;
		});
	ohc_regex(/([^-\w/:\.])@MM\/@DD\/@YYYY(?=[^-–/\w&])/gi, "$1@Month @Day, @YYYY", function(d) {
		if (d.d > 12) return true;
		return false;
		});
}

function ohc_US_slash_dates_to_mdy()
{
//ranges
	ohc_regex(/([^-\d/:\.])@MM\/@DD\/@YYNN(&nbsp;|\s)?(?:(?:[-–—]|&[mn]dash;)(?:&nbsp;|\s)?)@MM\/@DD\/@YYNN(?=[^-–/\w&])/gi, "$1@Mon1 @Day1, @Year1$2 – @Mon2 @Day2, @Year2");
	ohc_regex(/([^-\d/:\.])@MM\.@DD\.@YYNN(&nbsp;|\s)?(?:(?:[-–—]|&[mn]dash;)(?:&nbsp;|\s)?)@MM\.@DD\.@YYNN(?=[^-–/\w&])/gi, "$1@Mon1 @Day1, @Year1$2 – @Mon2 @Day2, @Year2");
	ohc_regex(/(\| ?)@MM\/@DD\/@YYNN(&nbsp;|\s)?(?:(?:[-–—]|&[mn]dash;)(?:&nbsp;|\s)?)@MM\/@DD\/@YYNN(?=\s*\|)/gi, "$1@Mon1 @Day1, @Year1$2 – @Mon2 @Day2, @Year2");
	ohc_regex(/(\| ?)@MM\.@DD\.@YYNN(&nbsp;|\s)?(?:(?:[-–—]|&[mn]dash;)(?:&nbsp;|\s)?)@MM\.@DD\.@YYNN(?=\s*\|)/gi, "$1@Mon1 @Day1, @Year1$2 – @Mon @Day2, @Year2");

// resolvable ambiguous date formats
	ohc_regex(/([^-\d/:\.])@MM\/@DD\/@YYNN(?=[^-–/\w&])/gi, '$1@Month @Day, @YYYY');
	ohc_regex(/([^-\d/:\.])@MM\.@DD\.@YYNN(?=[^-–/\w&])/gi, '$1@Month @Day, @YYYY');
	ohc_regex(/([^-\d/:\.])@MM[-–]@DD[-–]@YYNN(?=[^-–/\w&])/gi, '$1@Month @Day, @YYYY');
	ohc_regex(/(\| ?)@MM\/@DD\/@YYNN(?=\s*\|)/gi, '$1@Month @Day, @YYYY');
	ohc_regex(/(\| ?)@MM\.@DD\.@YYNN(?=\s*\|)/gi, '$1@Month @Day, @YYYY');
//	ohc_regex(/(\| ?)@MM[-–]@DD[-–]@YYNN(?=\s*\|)/gi, '$1@Month @Day, @YYYY');
}
 
function ohc_UK_slash_dates_to_dmy()
{
//ranges
	ohc_regex(/([^-\d/:\.])@DD\/@MM\/@YYNN(&nbsp;|\s)?(?:(?:[-–—]|&[mn]dash;)(?:&nbsp;|\s)?)@DD\/@MM\/@YYNN(?=[^-–/\w&])/gi, "$1@Day1 @Mon1 @Year1$2 – @Day2 @Mon2 @Year2");
	ohc_regex(/([^-\d/:\.])@DD\.@MM\.@YYNN(&nbsp;|\s)?(?:(?:[-–—]|&[mn]dash;)(?:&nbsp;|\s)?)@DD\.@MM\.@YYNN(?=[^-–/\w&])/gi, "$1@Day1 @Mon1 @Year1$2 – @Day2 @Mon2 @Year2");
	ohc_regex(/(\| ?)@DD\/@MM\/@YYNN(&nbsp;|\s)?(?:(?:[-–—]|&[mn]dash;)(?:&nbsp;|\s)?)@DD\/@MM\/@YYNN(?=\s*\|)/gi, "$1@Day1 @Mon1 @Year1$2 – @Day2 @Mon2 @Year2");
	ohc_regex(/(\| ?)@DD\.@MM\.@YYNN(&nbsp;|\s)?(?:(?:[-–—]|&[mn]dash;)(?:&nbsp;|\s)?)@DD\.@MM\.@YYNN(?=\s*\|)/gi, "$1@Day1 @Mon1 @Year1$2 – @Day2 @Mon2 @Year2");

// resolvable ambiguous date formats
	ohc_regex(/([^-\d/:\.])@DD\/@MM\/@YYNN(?=[^-–/\w&])/gi, '$1@Day @Month @YYYY');
	ohc_regex(/([^-\d/:\.])@DD\.@MM\.@YYNN(?=[^-–/\w&])/gi, '$1@Day @Month @YYYY');
	ohc_regex(/([^-\d/:\.])@DD[-–]@MM[-–]@YYNN(?=[^-–/\w&])/gi, '$1@Day @Month @YYYY');
	ohc_regex(/(\| ?)@DD\/@MM\/@YYNN(?=\s*\|)/gi, '$1@Day @Month @YYYY');
	ohc_regex(/(\| ?)@DD\.@MM\.@YYNN(?=\s*\|)/gi, '$1@Day @Month @YYYY');
//	ohc_regex(/(\| ?)@DD[-–]@MM[-–]@YYNN(?=\s*\|)/gi, '$1@Day @Month @YYYY');
}

function ohc_remove_leading_zeroes()
{
	ohc_regex(/(\D[^\w\/])@Month\s@ZD@th?,?\s@YYYY(?=\W\D)/gi, "$1@LMonth @Day, @LYear");
	ohc_regex(/(\D[^\w\/])@Month\s@ZD@th?(?=\W\D)/gi, "$1@LMonth @Day");
	ohc_regex(/(\D[^\w\/])@ZD@th?\s@Month\s@YYYY(?=\W\D)/gi, "$1@Day @LMonth @LYear");
	ohc_regex(/(\D[^\w\/])@ZD@th?\s@Month(?=\W\D)/gi, "$1@Day @LMonth");
}

function ohc_delink_dates()
{
	//add missing space between wikilinks
	regex(/(\]\])(\[\[)/gi, '$1 $2');  //remove (?!file:) to ensure a space between all links
 
	 // rem redundant quote marks and parentheses
	regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)\'\'\'([^|}\[\]]*)\'\'\'(?=\s*[|}])/gi, "$1$2");
	regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)\'\'([^|}\[\]]*)\'\'(?=\s*[|}])/gi, "$1$2");
	regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)\"([^|}\[\]]*)\"(?=\s*[|}])/gi, "$1$2");
	regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)\(([^|}\[\]]*)\)(?=\s*[|}])/gi, "$1$2");

//delink unpiped dates
	//delink full dates
	ohc_regex(/\[\[@Day[\s_](?:of[\s_])?@Month(?:\]\]\s?\[\[\| )@YYYY\]\]/gi, "@Day @LMonth @YYYY");
	ohc_regex(/\[\[@Month (?:the\s)?@Day(?:\]\],? \[\[|, )@YYYY\]\]/gi, "@LMonth @Day, @YYYY");

	//delink yyyy-mm-dd dates
	ohc_regex(/\[\[@YYYY(?:\]\]-\[\[|-)@MM-@DD\]\]/gi, "@YYYY-@MM-@DD");
	ohc_regex(/@YYYY-\[\[@MM-@DD\]\]/gi, "@YYYY-@MM-@DD");

	//underscore and nbsp in linked dates
	ohc_regex(/\[\[@DD@th?(?:\s|_|&nbsp;)@Month\]\]/gi, "@Day @LMonth");
	ohc_regex(/\[\[@Month(?:\s|_|&nbsp;)@DD@th?\]\]@th?/gi, "@LMonth @Day"); //consolidated regex with flexible removal of ordinal simple date
	ohc_regex(/\[\[@Day @Month\]\]/gi, "@Day @LMonth");
	ohc_regex(/\[\[@Month @YYYY\]\]/gi, "@LMonth @YYYY");
	ohc_regex(/\[\[@YYYY\]\]/gi, "@YYYY");

	//remove leading zero and links from linked date
	ohc_regex(/\[\[@Month(?:[ _]|&nbsp;)@ZD@th\]\]/gi, "@LMonth @Day");
	ohc_regex(/\[\[@ZD@th(?:[ _]|&nbsp;)@Month\]\]/gi, "@Day @LMonth");

	// remove nowrap template from dm and md dates
	ohc_regex(/(date[ ]*=[ ]*)\{\{(?:j|no ?(?:break|wrap))\|(?:@DD(?:[ _]|&nbsp;)@Month)( @yyyy|)\}\}/gi, '$1@DD @LMonth$2');
	ohc_regex(/(date[ ]*=[ ]*)\{\{(?:j|no ?(?:break|wrap))\|(?:@Month(?:[ _]|&nbsp;)@DD)( @yyyy|)\}\}/gi, '$1@LMonth @DD$2');
	
	//delink single dm or 'dth the m'
	ohc_regex(/(?:the\s)?\[\[@Day@th?[\s_](?:of[\s_])?@Month\]\]/gi, "@Day @LMonth");
	//delink single md or 'm the dth'
	ohc_regex(/\[\[@Month[\s_](?:the[\s_])?@Day@th?\]\](?=\W)/gi, "@LMonth @Day");

//month+day piped
	ohc_regex(/\[\[(?:@dd@th?[\s_](?:of[\s_])?@month|@month[\s_]@dd@th?)\|((?:@month |)@day)@th?\]\]/gi, "$1");
	ohc_regex(/\[\[(?:@dd@th?[\s_](?:of[\s_])?@month|@month[\s_]@dd@th?)\|@Day@th?[\s_](@month|)\]\]/gi, "@Day $1");

//	ohc_regex(/\[\[@month @dd(?:#[^|]+|)\|([^|\]]+)@th?\]\]/gi, "$1");
//	ohc_regex(/\[\[@dd @month(?:#[^|]+|)\|([^|\]]+)@th?\]\]/gi, "$1");
	ohc_regex(/\[\[@month @yyyy(?:#[^|]+|)\|([^|\]]+)\]\]/gi, "$1");

	//month+day+year pseudo-ISO dates
	ohc_regex(/\[\[@Month @DD\|\d\d-\d\d\]\]-(?:\[\[)?(?:@yyyy[^|]*\|)?@YYYY(?:\]\])/gi, "@Day @LMonth @YYYY");
	ohc_regex(/\[\[@DD\s@Month\|\d\d-\d\d\]\]-(?:\[\[)?(?:@yyyy[^|]*\|)?@YYYY(?:\]\])/gi, "@Day @LMonth @YYYY");

	//'[[month day|xxXxx]]Xyyyy ' to 'month day, year'
	ohc_regex(/\[\[@Month\s@Day\|@dd.@dd\]\].@YYYY/gi, "@LMonth @Day, @YYYY");
	 //'[[day month|xxXxx]]Xyyyy' to 'day month year'
	ohc_regex(/\[\[@Day\s@Month\|@dd.@dd\]\].@YYYY/gi, "@Day @LMonth @YYYY");

// century
	regex(/\[\[((?:first|second|third|(?:four|fif|six|seven|eigh|nin|ten|eleven|twelf|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|twentie)th|twenty[\s\-]first[\s\-])centur(?:y|ies)(?:\s(?:AD|BC|CE|BCE))?)\]\]/gi, '$1');
	regex(/\[\[(?:first|second|third|(?:four|fif|six|seven|eigh|nin|ten|eleven|twelf|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|twentie)th|twenty[\s\-]first)[\s\-_]centur(?:y|ies)(?:\s(?:AD|BC|CE|BCE))?\|([^\]]{1,30})\]\]/gi, '$1');
	regex(/\[\[(\d{1,2}(?:st|[nr]d|th))[\s\-_](centur(?:y|ies))(\s(?:AD|BC|CE|BCE)|)\]\]/gi, '$1 $2$3');
	ohc_regex(/\[\[\d{1,2}@th[\s\-_]centur(?:y|ies)(?:\s(?:AD|BC|CE|BCE)|)\|([^\]]{1,30})\]\]/gi, '$1');

	// months
	ohc_regex(/\[\[@Month\]\]/gi, "@LMonth");
	ohc_regex(/\[\[@FullMonth\|([^\]]{1,30})\]\]/gi, "$1");

	// decades and years
	regex(/(\d{1,3}0)[‘`´’′]?s/g, '$1s');
	regex(/\[\[(\d{1,3}0)\'?s\]\]/g, '$1s');
	regex(/\[\[\d{1,3}0\'?s?\|([^\]]{1,30})\]\]/g, '$1');
	regex(/\[\[(\d{1,3}0)\'?(s)?\s(AD|BC|CE|BCE)\]\]/gi, '$1$2 $3');
	regex(/\[\[(\d{1,4}[\s_]?)(AD|BC|CE|BCE)\]\]/gi, '$1$2');
	regex(/\[\[(AD|BC|CE|BCE)([\s_]?)(\d{1,4})\]\]/gi, '$1$2$3');
	ohc_regex(/([-–])\[\[\s?@yyyy\s?\|\s?(\d{2,4})\s?\]\]/gi, '$1$2'); //piped year
	regex(/\[\[([12]\d{3}|[1-9]\d{0,2})\]\]/gi, '$1');
	regex(/\[\[\d{1,3}0\'?s?\s(?:AD|BC|CE|BCE)\|([^\]]{1,30})\]\]/gi, '$1');
	regex(/\[\[\d{1,3}0\'?s?\s\(decade\)\|([^\]]{1,30})\]\]/gi, '$1');

	//month+year
	//Identify surprise or 'Easter egg' diversions linking month+years to year articles. Turn them into month+year links to be dealt with below
	ohc_regex(/\[\[@yyyy in[^|\]]+\|@Day @Month @YYYY\]\]/gi, "@Day @LMonth @YYYY");
	ohc_regex(/\[\[@yyyy in[^|\]]+\|@Month @Day,? @YYYY\]\]/gi, "@LMonth @Day, @YYYY");
	ohc_regex(/\[\[@yyyy#[^|\]]+\|(@month\s|)(@yyyy)\]\]/gi, "$1$2");
	ohc_regex(/\[\[@yyyy#[^|\]]+\|(@month|@yyyy)\]\]/gi, "$1");
	ohc_regex(/\[\[(@month\s@yyyy)\]\]/gi, "$1");
	ohc_regex(/\[\[@month\s@yyyy\|([^\]]{1,30})\]\]/gi, "$1");
	ohc_regex(/\[\[(?:List of |)Bollywood films of @yyyy\|@YYYY\]\](?= [^\[]{2}^B)/gi, "@YYYY");

	ohc_regex(/(\[\[@yyyy[^|\]]+\|@yyyy)(\]\])( season)/gi, "$1$3$2");

	//removed piped years when in full date (excepting disambiguated parentheses - updated 24/2/2012)
//	ohc_regex(/\[\[[^|\]\(\)]{1,32}\|@YYYY\]\]/gi, '@Year');  // 23/6/2021 – disabled delinking "other" year-in articles

	//Identify surprise or 'Easter egg' diversions linking months to year or "year in" articles.
	ohc_regex(/\[\[\d{1,4}#[^|\]]+\|@Month\]\]/gi, "@LMonth");
	ohc_regex(/\[\[@yyyy \w[^|\]]{3,12}\|@Year\]\]/gi, '@Year');

	// month and day piped
	ohc_regex(/\[\[@month[\s_]@day\|@MM-@DD\]\]/gi, "@MM-@DD");
	ohc_regex(/\[\[@month[\s_]@day\|([^\]]{1,30})\]\]/gi, "$1");
	ohc_regex(/\[\[@day(?:\s|_|@th )(?:of[\s_]|)?@month\|([^\]]{1,30})\]\]/gi, "$1");

	//years piped
	regex(/\[\[\d{1,4}\|([^\]]{1,30})\]\]/gi, '$1');
}

function ohc_fix_common_errors()
{
	ohc_regex(/(\d)<sup>@th<\/sup>/gi, '$1th');
	// remove dashbot comment from dates
	regex(/<!-- ?DASHBot ?-->/gi, '');
	ohc_regex(/(\|\s*(?:date|year)\s*=)\s*c(?:irca|a\.)?\s?((?:@day |)@month @year)(?=[\s\n]*[<|}])/gi, '$1c. $2'); //add space
//common cs1 errors
	regex(/(\|\s*(?:date|year)\s*=)\s*(1[7-9]\d|20[0-1])\?(?=[\s\n]*[<|}])/gi, '$1c. $20'); 
	regex(/(\|\s*(?:date|year)\s*=\s*(1[7-9])\d{2})[-–](\d{2})(?=[\s\n]*[<|}])/gi, '$1–$2$3'); 
//	regex(/(\|\s*(?:date|year)\s*=\s*(20)[0-1]\d)[-–]([0-2]\d)(?=[\s\n]*[<|}])/gi, '$1–$2$3'); 
	regex(/(\|\s*(?:date|year)\s*=\s*)@YYYY\s*[-–/]\s*@YYYY(?=[\s\n]*[<|}])/gi, '$1@YYYY1–@YYYY2'); //common cs1 error
	regex(/(\|\s*(?:date)\s*=)\s*s(pring|ummer),?\s*((?:1[7-9]\d|20[0-1])\d)(?=[\s\n]*[<|}])/gi, '$1S$2 $3'); //common cs1 error
	regex(/(\|\s*(?:date)\s*=)\s*a(utumn),?\s*((?:1[7-9]\d|20[0-1])\d)(?=[\s\n]*[<|}])/gi, '$1A$2 $3'); //common cs1 error
	regex(/(\|\s*(?:date)\s*=)\s*f(all),?\s*((?:1[7-9]\d|20[0-1])\d)(?=[\s\n]*[<|}])/gi, '$1F$2 $3'); //common cs1 error
	regex(/(\|\s*(?:date)\s*=)\s*w(inter),?\s*((?:1[7-9]\d|20[0-1])\d)(?=[\s\n]*[<|}])/gi, '$1W$2 $3'); //common cs1 error
	ohc_regex(/(\|\s*access-?date\s*=)\s*(@month @year)(?=[\s\n]*[<|}])/gi, '$11 $2'); //common cs1 error
//	ohc_regex(/(\|\s*date\s*=\s*)@year\?(?=[\s\n]*[<|}])/gi, '$1@Year'); //common cs1 error
//	ohc_regex(/(\|\s*(?:date|year)\s*=)\s*@year\?(?=[\s\n]*[<|}])/gi, '$1c. @Year'); //common cs1 error
//	ohc_regex(/(\|\s*(?:date|year)\s*=)\s*(@month @year)\?(?=[\s\n]*[<|}])/gi, '$1c. $2'); //common cs1 error
	ohc_regex(/(\|\s*access-?date\s*=)\s*@month @day, (1[7-9]\d{2}|2000)(?=[\s\n]*[<|}])/gi, '$1'); //rem access date before Wikipedia (জানুয়ারি 2001)
	ohc_regex(/(\|\s*access-?date\s*=)\s*@day @month.? (1[7-9]\d{2}|2000)(?=[\s\n]*[<|}])/gi, '$1'); //rem access date before Wikipedia (জানুয়ারি 2001)
	ohc_regex(/(\|\s*access-?date\s*=)\s*31( (?:এপ্রিল|জুন|সেপ্টেম্বর|নভেম্বর) @year)(?=[\s\n]*[<|}])/gi, '$130$2'); //rem nonsense access date (short months)
	ohc_regex(/(\|\s*access-?date\s*=)\s*29( ফেব্রুয়ারি (?:200[1235679]|201[1345789]))(?=[\s\n]*[<|}])/gi, '$128$2'); //rem nonsense access date 29 ফেব্রুয়ারি (non-leap year)
	ohc_regex(/(\|\s*access-?date\s*=)\s*(?:3[01])( ফেব্রুয়ারি @yyyy)(?=[\s\n]*[<|}])/gi, '$128$2'); //rem nonsense access dates ফেব্রুয়ারি
	regex(/(\|\s*access-?date\s*=)\s*(\d{4})(?=[\s\n]*[<|}])/gi, ''); //common cs1 error
	
	//month+day+year pseudo-ISO dates
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*@dd)-@Mon-@YYYY/gi, "$1 @FullMonth @YYYY");
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)@YYYY-@DD-@Mon/gi, "$1 @DD @FullMonth @YYYY");

	regex(/(\|\s*(?:date|year)\s*=)\s*(?:(?:date |)unknown|(?:not? |non-|un)date[ds])(?=[\s\n]*[<|}])/gi, '$1n.d.'); //common cs1 error
	regex(/(\|\s*(?:date|year)\s*=)\s*n\.?d(?=[\s\n]*[<|}])/gi, '$1n.d.'); //common cs1 error
	regex(/(\|\s*)year(\s*=\s*)(?=n\.?d\.)(?=[\s\n]*[<|}])/gi, '$1date$2'); //common cs1 error

   // remove parasitic metadata -  days of the week/descriptives
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)(?:[^|}\d]*|)@Day\s+@Month\s+@YYYY((?:[a-z]\b|)\s?)[^|<}]*(?=[\s\n]*[<|}])/gi, "$1@Day @Month @YYYY$2"); //rem negate "<", "hyphens" "dashes" 26/6/2020
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)[^|}]*@Month\s+@Day,\s+@YYYY((?:[a-z]\b|)\s?)[^|<}]*(?=[\s\n]*[<|}])/gi, "$1@Month @Day, @YYYY$2"); //rem negate "<", "hyphens" "dashes" 26/6/2020
//	ohc_regex(/(\|\s*date\s*=\s*)(?:[^|}–<]*\D|)@Day\s+@Month\s+@YYYY ?– ?@Day\s+@Month\s+@YYYY[^|}–<]*(?=[\s\n]*[<|}])/gi, "$1@Day1 @Mon1 @Year1 – @Day2 @Mon2 @Year2");
//	ohc_regex(/(\|\s*date\s*=\s*)[^|}–<]*@Month\s+@Day,\s+@YYYY ?– ?@Month @Day, @YYYY[^|}–<]*(?=[\s\n]*[<|}])/gi, "$1@Mon1 @Day1, @Year1 – @@Mon2 Day2, @Year2");
//	regex(/(\|\s*author\s*=\s*)(?:posted|published)(?: by\b| on\b|)[\s:](?=\w)/gi, "$1");
//	regex(/(\|\s*(?:date|archive-?date|access-?date|author|year)\s*=\s*)(?:accessed|retrieved|entered|posted|published|(?:last |)updated?|©)(?: by\b| on\b|)[\s:]*(?=\w)/gi, "$1");
	regex(/(\|\s*(?:author|first|last)\s*=\s*)(?:by\b|on\b)[\s:]*(?=\w)/gi, "$1");
	regex(/(\|\s*(?:date|archive-?date|access-?date|author|first|last)\s*=\s*)(?:(?:Mon|Tues|Wednes|Thurs|Fri|Satur|Sun)day,?)\s/gi, "$1");
	regex(/(\|\s*(?:date|archive-?date|access-?date|author|first|last)\s*=\s*)(?:Mon|Tues?|Wed|Thur?|Fri|Sat)[\.,]?\s/gi, "$1"); //<!-- rem "Sun" - false positives -->

   // remove deprecated parameters (|day= and |month)
 	ohc_regex(/(\|\s*)day(?:\s*=\s*)@DD ?\| ?month(?:\s*=\s*)@Month ?\| ?year(?:\s*=\s*)@YYYY(?=[|}\s])/gi, '$1date=@Day @Month @Year'); 
 	ohc_regex(/(\|\s*)year(?:\s*=\s*)@YYYY ?\| ?month(?:\s*=\s*)@Month ?\| ?day(?:\s*=\s*)@DD(?=[|}\s])/gi, '$1date=@Month @Day, @Year'); 
 	
// typos
	ohc_regex(/(date *= *)@Day @Month ?@th/gi, '$1@Day @Month'); 
	ohc_regex(/(date *= *)@Day @Month\w(?= \d{3,4})/gi, '$1@Day @Month'); 

	ohc_regex(/(date *= *(?:[12]?\d|30|31) )(জানুয়ারি|Febr)[\w ]?[aur]{3,4}\w{0,2}(?= (?:1[6-9]\d|20[01])\d\b)/gi, '$1$2uary'); 
	ohc_regex(/(date *= *(?:[12]?\d|30|31) )J[anu]{3,5}r\w{0,2}(?= (?:1[6-9]\d|20[01])\d\b)/gi, '$1জানুয়ারি');
	ohc_regex(/(date *= *(?:[12]?\d) )Febua?r\w{0,2}(?= (?:1[6-9]\d|20[01])\d\b)/gi, '$1ফেব্রুয়ারি');
	ohc_regex(/(date *= *(?:[12]?\d|30|31) )M\w{2,3}ch(?= (?:1[6-9]\d|20[01])\d\b)/gi, '$1মার্চ'); 
	ohc_regex(/(date *= *(?:[12]?\d|30) )A[bpv\[]\w{2,3}l\w?(?= (?:1[6-9]\d|20[01])\d\b)/gi, '$1এপ্রিল');
	ohc_regex(/(date *= *(?:[12]?\d|30|31) )Ma[tui](?= (?:1[6-9]\d|20[01])\d\b)/gi, '$1মে'); 
	ohc_regex(/(date *= *(?:[12]?\d|30) )J\wn\w(?= (?:1[6-9]\d|20[01])\d\b)/gi, '$1জুন'); 
	ohc_regex(/(date *= *(?:[12]?\d|30) )J\w{1,2}e(?= (?:1[6-9]\d|20[01])\d\b)/gi, '$1জুন'); 
	ohc_regex(/(date *= *(?:[12]?\d|30|31) )জুলাই\w{1,2}(?= (?:1[6-9]\d|20[01])\d\b)/gi, '$1জুলাই'); 
	ohc_regex(/(date *= *(?:[12]?\d|30|31) )A[oug]{2,3}\w{1,4}t(?:\w|us)?(?= (?:1[6-9]\d|20[01])\d\b)/gi, '$1আগষ্ট'); 
	ohc_regex(/(date *= *(?:[12]?\d|30|31) )(সেপ্টেম্বর|নভেম্বর|ডিসেম্বর)\w{2,4}b[er]{1,2}\w?(?= (?:1[6-9]\d|20[01])\d\b)/gi, '$1$2ember'); 
	ohc_regex(/(date *= *(?:[12]?\d|30) )S\w{0,2}p[ \[]?\w{2,5}[er]{2,3}\w?(?= (?:1[6-9]\d|20[01])\d\b)/gi, '$1সেপ্টেম্বর'); 
	ohc_regex(/(date *= *(?:[12]?\d|30|31) )O\w{0,2}t\w{1,3}[er]{2,3}\w?(?= (?:1[6-9]\d|20[01])\d\b)/gi, '$1অক্টোবর'); 
	ohc_regex(/(date *= *(?:[12]?\d|30) )[MN]\w{1,2}[bv] ?\w{1,3}b[er]{1,2}\w?(?= (?:1[6-9]\d|20[01])\d\b)/gi, '$1নভেম্বর'); 
	ohc_regex(/(date *= *(?:[12]?\d|30|31) )D[ie]?[cs] ?\w{1,4}b[er]{1,2}\w?(?= (?:1[6-9]\d|20[01])\d\b)/gi, '$1ডিসেম্বর'); 

	ohc_regex(/(date *= *)@Month\w(?=(?: (?:[12]?\d|30|31),?|) (?:1[6-9]\d|20[01])\d\b)/gi, '$1@Month'); //rem stray digit at the end of year string
 
	ohc_regex(/(date *= *)(জানুয়ারি|Febr)[\w ]?[aur]{3,4}\w{0,2}(?=(?: (?:[12]?\d|30|31),?|) (?:1[6-9]\d|20[01])\d\b)/gi, '$1$2uary'); 
	ohc_regex(/(date *= *)J[anu]{3,5}r\w{0,2}(?=(?: (?:[12]?\d|30|31),?|) (?:1[6-9]\d|20[01])\d\b)/gi, '$1জানুয়ারি');
	ohc_regex(/(date *= *)Febua?r\w{0,2}(?=(?: (?:[12]?\d),?|) (?:1[6-9]\d|20[01])\d\b)/gi, '$1ফেব্রুয়ারি');
	ohc_regex(/(date *= *)M\w{2,3}ch(?=(?: (?:[12]?\d|30|31),?|) (?:1[6-9]\d|20[01])\d\b)/gi, '$1মার্চ'); 
	ohc_regex(/(date *= *)A[bpv\[]\w{2,3}l\w?(?=(?: (?:[12]?\d|30),?|) (?:1[6-9]\d|20[01])\d\b)/gi, '$1এপ্রিল');
	ohc_regex(/(date *= *)Ma[tui](?=(?: (?:[12]?\d|30|31),?|) (?:1[6-9]\d|20[01])\d\b)/gi, '$1মে'); 
	ohc_regex(/(date *= *)J\wn\w(?=(?: (?:[12]?\d|30),?|) (?:1[6-9]\d|20[01])\d\b)/gi, '$1জুন'); 
	ohc_regex(/(date *= *)J\w{1,2}e(?=(?: (?:[12]?\d|30),?|) (?:1[6-9]\d|20[01])\d\b)/gi, '$1জুন'); 
	ohc_regex(/(date *= *)জুলাই\w{1,2}(?=(?: (?:[12]?\d|30|31),?|) (?:1[6-9]\d|20[01])\d\b)/gi, '$1জুলাই'); 
	ohc_regex(/(date *= *)A[oug]{2,3}\w{1,4}t(?:\w|us)?(?=(?: (?:[12]?\d|30|31),?|) (?:1[6-9]\d|20[01])\d\b)/gi, '$1আগষ্ট'); 
	ohc_regex(/(date *= *)(সেপ্টেম্বর|নভেম্বর|ডিসেম্বর)\w{2,4}b[er]{1,2}\w?(?=(?: (?:[12]?\d|30|31),?|) (?:1[6-9]\d|20[01])\d\b)/gi, '$1$2ember'); 
	ohc_regex(/(date *= *)S\w{0,2}p[ \[]?\w{2,5}[er]{2,3}\w?(?=(?: (?:[12]?\d|30),?|) (?:1[6-9]\d|20[01])\d\b)/gi, '$1সেপ্টেম্বর'); 
	ohc_regex(/(date *= *)O\w{0,2}t\w{1,3}[er]{2,3}\w?(?=(?: (?:[12]?\d|30|31),?|) (?:1[6-9]\d|20[01])\d\b)/gi, '$1অক্টোবর'); 
	ohc_regex(/(date *= *)[MN]\w{1,2}[bv] ?\w{1,3}b[er]{1,2}\w?(?=(?: (?:[12]?\d|30),?|) (?:1[6-9]\d|20[01])\d\b)/gi, '$1নভেম্বর'); 
	ohc_regex(/(date *= *)D[ie]?[cs] ?\w{1,4}b[er]{1,2}\w?(?=(?: (?:[12]?\d|30|31),?|) (?:1[6-9]\d|20[01])\d\b)/gi, '$1ডিসেম্বর'); 

//insert comma to separate date from army unit
	ohc_regex(/@FullMonth ((?:the |)\d\d*@th (?:Air(?:borne|)|Arm(?:ou?red|y)|Artillery|Battalion|Brigade|Co(?:mpan|)y|Division|Fleet|Group|Infantry|Land|Panzer|Regiment|Squadron|Sqn)\b)/g, "@Month, $1");

	// remove parasitic metadata - time
	ohc_regex(/(\|\s*\w*date\s*=\s*@yyyy-@mm-@dd)\s?(?:T[0-2]\d:[0-5]\d:[0-5]\d(?:\s*|&nbsp;|)(?:GMT\s*|UTC\s*|[A-Z]{1,2}[DS]T\s*|Z))(?=\s*[|}])/g, "$1");
	ohc_regex(/(\|\s*\w*date\s*=\s*@month @day,? @yyyy)\s?(?:,? [0-2]?\d[\.:][0-5]\d(?:\s*|&nbsp;)(?:[apAP][mM]\s*|)(?:GMT\s*|UTC\s*|[A-Z]{1,2}[DS]T\s*|))(?=\|)/g, "$1");
	ohc_regex(/(\|\s*\w*date\s*=\s*@day @month,? @yyyy)\s?(?:,? [0-2]?\d[\.:][0-5]\d(?:\s*|&nbsp;)(?:[apAP][mM]\s*|)(?:GMT\s*|UTC\s*|[A-Z]{1,2}[DS]T\s*|))(?=\|)/g, "$1");
	ohc_regex(/(\|\s*\w*date\s*=\s*\w[\w\s]+@month @day,? @yyyy)\s?(?:,? [0-2]?\d[\.:][0-5]\d(?:\s*|&nbsp;)(?:[apAP][mM]\s*|)(?:GMT\s*|UTC\s*|[A-Z]{1,2}[DS]T\s*|))(?=\|)/g, "$1");
	ohc_regex(/(\|\s*\w*date\s*=\s*\w[\w\s]+@day @month,? @yyyy)\s?(?:,? [0-2]?\d[\.:][0-5]\d(?:\s*|&nbsp;)(?:[apAP][mM]\s*|)(?:GMT\s*|UTC\s*|[A-Z]{1,2}[DS]T\s*|))(?=\|)/g, "$1");
	ohc_regex(/(\|\s*\w*date\s*=[^:|}]*)\s?(?:T?[0-2]\d:[0-5]\d:[0-5]\d(?:\s*|&nbsp;|)(?:GMT\s*|UTC\s*|[A-Z]{1,2}[DS]T\s*|Z))/g, "$1");

//  add back spaces or comma or remove other single artefact after date string	
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)(?:on |)@Day\s{,2}@Month\s{,2}@YYYY[^a-z{}]?(?=\s*[|}\n])/gi, "$1@Day @Month @YYYY$2");
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)(?:on |)@Month\s{,2}@Day,?\s{,2}@YYYY[^a-z{}]?(?=\s*[|}\n])/gi, "$1@Month @Day, @YYYY$2");
	//long-hand palliative for observed failure to insert spaces
	ohc_regex(/(\|\s*(?:archive|access|air)-?date\s*=\s*)(?:on |)([0-2]?\d|30|31)\s*(জানুয়ারি|ফেব্রুয়ারি|মার্চ|এপ্রিল|মে|জুন|জুলাই|আগষ্ট|সেপ্টেম্বর|অক্টোবর|নভেম্বর|ডিসেম্বর)\s*((?:19\d|20[0-1])\d\s?)[^|{}\s<>]*(?=\s*[|}])/gi, "$1$2 $3 $4");
//	ohc_regex(/(\|\s*(?:publication|)-?date\s*=\s*)(?:on |)@Day\s*@Month\s*@YYYY([a-z]\s?|\s?)\w*[^|{}<>]*(?=[|}])/gi, "$1@Day @Month @YYYY$2");
//	ohc_regex(/(\|\s*(?:publication|)-?date\s*=\s*)(?:on |)@Month\s*@Day,\s*@YYYY([a-z]\s?|\s?)\w*[^|{}<>]*(?=[|}])/gi, "$1@Month @Day, @YYYY$2");

//remove extraneous bracket //from Batty
	ohc_regex(/{{(\s*[Cc]it(?:e|ation))([^}]+)(\s*\|\s*(?:archive-?|access-?|publication-?)?date\s*=\s*)([\w\s-]+)\](?=\s*[\|}<])/gi, '{{$1$2$3$4');  

	//fix bda template redirect
//	regex(/\{\{bda\|([^}]+)\}\}/gi, '{{birth date and age|$1}}');
//	regex(/\{\{dda\|([^}]+)\}\}/gi, '{{death date and age|$1}}');

	//zap redundant {{date}}, {{accessdate}} {{retrieved}}, {{monthname}} and {{#dateformat}}
//	regex(/({{(?:end|start)[-–]date)\|df=y(?:es|)/gi, "$1"); //rem deprecated parameter - disabled: doesn't work here, so ejected to the formatting script
	ohc_regex(/{{#formatdate:@YYYY-@MM-@DD(?:[^\}]*)}}/gi, "@Day @Month @YYYY");
	regex(/{{#formatdate:([^}]+)}}/gi, "$1");
	regex(/\{\{#dateformat:([^}\|]+)(?:\|dmy|\|mdy)?\}\}/gi, '$1');
//	ohc_regex(/(date[ ]*=[ ]*)\{\{(?:Start|End) ?date(?:\|df=y(?:es|)|)\|@YYYY\|@MM\|@DD(?:\|df=y(?:es|)|)\}\}/gi, '$1@Month @DD, @YYYY');  //stripping start/end template notes inside "|date=" parameter (line 72)
	ohc_regex(/{{#formatdate:@YYYY-@MM-@DD(?:\|(?:[dmy]{3}|iso)|)}}/gi, "@Day @Month @YYYY");
	ohc_regex(/\{\{date\|@YYYY-@MM-@DD\}\}/gi, "@Day @Month @YYYY");
	ohc_regex(/\{\{date\|(@DD[\-\s]@Mon|@Mon[\-\s]@DD)\}\}/gi, "@Day @Month");
	regex(/\{\{date\|([^}\|]+)(?:\|l?(?:[dmy]{3}|iso|none|link))?\}\}/gi, '$1');
	ohc_regex(/[ ]*\{\{accessdate\|@YYYY-@MM-@DD[ ]*\}\}/gi, " Retrieved @YYYY-@MM-@DD");
	ohc_regex(/[ ]*\{\{retrieved[ ]*\|[ ]accessdate=([\-\w, ]*)\}\}/gi, " Retrieved $1");
//	ohc_regex(/(date[ ]*=[ ]*|\w{2,}[ ]*)\{\{(?:start|end).date[^|}]*(?:\|df=y(?:es|)|)\|@YYYY(?:\|df=y(?:es|)|)\}\}/gi, '$1@YYYY');  //stripping start/end template (disabling to placate Pigsonthewing)
//	ohc_regex(/\{\{(?:Start|End) date(?:\|df=y(?:es|)|)\|@YYYY\|@MM\}\}/gi, '@Month @YYYY')  //stripping start/end template notes
//	ohc_regex(/<!--(?:Use)? \{\{(?:Start|End) date\|@YYYY\|@MM\|@DD\}\} -->/gi, '');  //stripping start/end template notes
	ohc_regex(/(\{\{MONTHNAME\|@MM\}\})/gi, "@Month")

//expand one and two-digit years in ranges
	regex(/(\()@Month @YYYY[-–]@Month @YYNN(\))/gi, '$1@Month1 @YYYY1 – @Month2 @YYYY2$2');
	regex(/(\(1[789])(\d)(1)[-–]([2-9]\))/gi, '$1$2$3–$2$4');
	regex(/(\(1[789])(\d)(2)[-–]([3-9]\))/gi, '$1$2$3–$2$4');
	regex(/(\(1[789])(\d)(3)[-–]([4-9]\))/gi, '$1$2$3–$2$4');
	regex(/(\(1[789])(\d)(4)[-–]([5-9]\))/gi, '$1$2$3–$2$4');
	regex(/(\(1[789])(\d)(5)[-–]([6-9]\))/gi, '$1$2$3–$2$4');
	regex(/(\(1[789])(\d)(6)[-–]([7-9]\))/gi, '$1$2$3–$2$4');
	regex(/(\(1[789])(\d)(7)[-–]([8-9]\))/gi, '$1$2$3–$2$4');
	regex(/(\(1[789])(\d)(8)[-–](9\))/gi, '$1$2$3–$2$4');
	regex(/(\(20)([01])(1)[-–]([2-9]\))/gi, '$1$2$3–$2$4');
	regex(/(\(20)([01])(2)[-–]([3-9]\))/gi, '$1$2$3–$2$4');
	regex(/(\(20)([01])(3)[-–]([4-9]\))/gi, '$1$2$3–$2$4');
	regex(/(\(20)([01])(4)[-–]([5-9]\))/gi, '$1$2$3–$2$4');
	regex(/(\(20)([01])(5)[-–]([6-9]\))/gi, '$1$2$3–$2$4');
	regex(/(\(20)([01])(6)[-–]([7-9]\))/gi, '$1$2$3–$2$4');
	regex(/(\(20)([01])(7)[-–]([8-9]\))/gi, '$1$2$3–$2$4');
	regex(/(\(20)([01])(8)[-–](9\))/gi, '$1$2$3–$2$4');

	ohc_regex(/(\W)@DD@th?, @DD@th?((?:[ ]|&nbsp;)(?:and|&|to|or)(?:[ ]|&nbsp;))@DD@th?(?:\sof\s?)?([ ]|&nbsp;)@Month(?=\W)/gi, '$1@Day1, @Day2$2@Day3$3@LMonth');
	ohc_regex(/(\W)@DD@th?((?:[ ]|&nbsp;)(?:and|&|to|or)(?:[ ]|&nbsp;))@DD@th?(?:\sof\s?|)([ ]|&nbsp;)@Month(?=\W)/gi, '$1@Day1$2@Day2$3@LMonth');
	ohc_regex(/(\W)the @DD@th(?:\sof|)\s@Month,? @YYYY(?=\W\D)/g, '$1@Day @LMonth @YYYY');
	ohc_regex(/(\W)the @DD@th(?:\sof|)\s@Month(?=\W\D)/g, '$1@Day @LMonth');
	ohc_regex(/(\W)@Day@th?(?:\sof|)([ _]|&nbsp;|{{(?:break|nbsp)}})@Month(?=[^|\]\w])/gi, '$1@Day$2@LMonth');
	ohc_regex(/(\W)@Month\s(?:the\s)?@DD@th?,(?:\sthe\s)?(?: |&nbsp;)@DD@th?(\s(?:and|&|to|or)(?:[ _]|&nbsp;))(?:the\s)?@DD@th?(?=[^|\]\w])/gi, '$1@LMonth @Day1, @Day2$2@Day3');
	ohc_regex(/(\W)(@month)\s(@day)((?:,\s@day){0,6}),?(\/|\s?[-–]\s?|\s(?:and|&|to|or)\s+?)@Day@th?(?:,?(?:[ _]|&nbsp;)|\sof\s)?(\d{3,4}\W\D)/gi, '$1$2 $3$4$5@Day, $6');
	ohc_regex(/(\W)(@month)\s(@day)((?:,\s@day){0,6}),?(\/|\s?[-–]\s?|\s(?:and|&|to|or)\s+?)@Day@th?(?=\W\D)/gi, '$1$2 $3$4$5@Day');
	ohc_regex(/(\W)@Month([ _]|&nbsp;|{{(?:break|nbsp)}})(?:the\s)?@DD@th?,? @Year/gi, '$1@LMonth$2@Day, @Year');
	ohc_regex(/(\W)@Month @Day(?:\sof|,|)([ _]|&nbsp;|{{(?:break|nbsp)}})@Year(?=[^|\]\w])/gi, '$1@Month @Day,$2@Year');

	// consolidating/amalgamating date fields
	ohc_regex(/(\|[ ]*date[ ]*=[ ]*@day)\s*\|[ ]*month=[ ]*(@month)\s*\|[ ]*year=[ ]*(@yyyy[ ]*)(?=[|}\s])/gi, "$1 $2 $3");
	ohc_regex(/(\|[ ]*date[ ]*=[ ]*@day.?@month)\s*\|[ ]*year=[ ]*(@yyyy[ ]*)(?=[|}\s])/gi, "$1 $2");
	ohc_regex(/(\|[ ]*date[ ]*=[ ]*@month.?@day)\s*\|[ ]*year=[ ]*(@yyyy[ ]*)(?=[|}\s])/gi, "$1 $2");

	// eliminating dates and time placed in author parameter
	//removing artefacts from Indian news sites (TNN আগষ্ট 30, 2012, 05.46AM)
	ohc_regex(/(\|\s*author\s*=\s*(?:[A-Z]{2,3}\b))(?:[^|}]*)\d{4}, [\d\.:]{4,5}(&nbsp;|)[AP]M IST(?=[ ]*\|)/g, '$1$2');
//	ohc_regex(/(\|\s*author=(?:[^\[\]|{}]*))(TNN|PTI) @day @month @yyyy, [\d\.:]{4,5}(&nbsp;|)[AP]M IST(?=[ ]*\|)/g, '$1$2');

	ohc_regex(/(\|\s*author\s*=\s*)@month @day,? @yyyy\s?(?:,? [0-2]?\d[\.:][0-5]\d(?:\s*|&nbsp;)(?:[apAP][mM]\s*|)(?:GMT\s*|UTC\s*|[A-Z]{1,2}[DS]T\s*|)|)(?=\|)/g, "$1");
	ohc_regex(/(\|\s*author\s*=\s*)@day @month,? @yyyy\s?(?:,? [0-2]?\d[\.:][0-5]\d(?:\s*|&nbsp;)(?:[apAP][mM]\s*|)(?:GMT\s*|UTC\s*|[A-Z]{1,2}[DS]T\s*|)|)(?=\|)/g, "$1");
	ohc_regex(/(\|\s*author\s*=\s*\w[\w\s]+)@month @day,? @yyyy(?:[^\[\]|{}]*)(?=[|}])/g, "$1");
	ohc_regex(/(\|\s*author\s*=\s*\w[\w\s]+)@day @month,? @yyyy(?:[^\[\]|{}]*)(?=[|}])/g, "$1");
	ohc_regex(/(\|\s*author\s*=\s*(?:\w[\w\s]+)?)@dd-@mm-@yyyy/gi, "$1");
	ohc_regex(/(\|\s*author\s*=\s*(?:\w[\w\s]+)?)@YYYY-@MM-@DD ?/gi, "$1");
	regex(/(\|\s*(?:date|archive-?date|access-?date|author)\s*=\s*(?:\w[\w\s]+)?)[0-2]\d:[0-5]\d(?:[ ]|&nbsp;)?(?:[ap]m|[ap]\.m\.|)(?: ?(?:[A-Z]{1,2}T|UTC)[\.,]?|)/gi, "$1");
//	ohc_regex(/(\|\s*author\s*=\s*(?:\w[\w\s]+)?)\s*[0-2]\d[\.:][0-5]\d(?:[\.:][0-5]\d|)/gi, "$1"); //let's see later if we need this

	// eliminating mm-dd-yyyy dates
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)@MM[-–\/\.=\s](1[3-9]|2\d|3[01])[-–\/\.=\s]@YYYY/gi, "$1@Month $2, @YYYY");
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)@Mon[-–\/\.=\s](1[3-9]|2\d|3[01])[-–\/\.=\s]@YYYY/gi, "$1@Month $2, @YYYY");
	ohc_regex(/[ ](?:Accessed|Retrieved)(?:(?: online|) on|:?)[ ]@MM[-–\/\.=\s](1[3-9]|2\d|3[01])[-–\/\.=\s]@YYYY(?=\D)/gi, " Retrieved @Month $1, @YYYY");
//	ohc_regex(/[ ](?:Accessed|Retrieved)(?:(?: online|) on|:?)[ ]@YYYY,? @Month @DD(?=\D)/gi, " Retrieved @Day @Month @YYYY");

	ohc_regex(/([ =|])@Mon[-–](1[3-9]|2\d|3[01])[-–]@YYYY(?=[^-–\d/])/gi, "$1@Mon $2, @YYYY"); 
	ohc_regex(/([ =|])@Mon\/(1[3-9]|2\d|3[01])\/@YYYY(?=[^-–\d/])/gi, "$1@Mon $2, @YYYY"); 
	ohc_regex(/([ =|])@Mon\.(1[3-9]|2\d|3[01])\.@YYYY(?=[^-–\d/])/gi, "$1@Mon $2, @YYYY"); 
	ohc_regex(/([ =|])@Mon (1[3-9]|2\d|3[01]) @YYYY(?=[^-–\d/])/gi, "$1@Mon $2, @YYYY"); 
	ohc_regex(/([ =|])@MM[-–](1[3-9]|2\d|3[01])[-–]@YYYY(?=[^-–\d/])/gi, "$1@Mon $2, @YYYY"); 
	ohc_regex(/([ =|])@MM\/(1[3-9]|2\d|3[01])\/@YYYY(?=[^-–\d/])/gi, "$1@Mon $2, @YYYY"); 
	ohc_regex(/([ =|])@MM\.(1[3-9]|2\d|3[01])\.@YYYY(?=[^-–\d/])/gi, "$1@Mon $2, @YYYY"); 
	ohc_regex(/([ =|])@MM (1[3-9]|2\d|3[01]) @YYYY(?=[^-–\d/])/gi, "$1@Mon $2, @YYYY"); 

	// eliminating dd-mm-yyyy dates (assumed default)
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)@DD[-–\/\.=\s]@MM[-–\/\.=\s]@YYYY/gi, "$1@Day @Month @YYYY");
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)@DD[-–\/\.=\s]@Mon[-–\/\.=\s]@YYYY/gi, "$1@Day @Month @YYYY");
	ohc_regex(/[ ](?:Accessed|Retrieved)(?:(?: online|) on|:?)[ ]@DD[-–\/\.=\s]@MM[-–\/\.=\s]@YYYY(?=\D)/gi, " Retrieved @Day @Month @YYYY");
	ohc_regex(/[ ](?:Accessed|Retrieved)(?:(?: online|) on|:?)[ ]@YYYY,? @Month @DD(?=\D)/gi, " Retrieved @Day @Month @YYYY");
	ohc_regex(/([ =|])@DD[-–]@Mon[-–]@YYYY(?=[^-–\d/])/gi, "$1@Day @Month @YYYY"); 
	ohc_regex(/([ =|])@DD\/@Mon\/@YYYY(?=[^-–\d/])/gi, "$1@Day @Month @YYYY"); 
	ohc_regex(/([ =|])@DD\.@Mon\.@YYYY(?=[^-–\d/])/gi, "$1@Day @Month @YYYY");
	ohc_regex(/([ =|])@DD @Mon @YYYY(?=[^-–\d/])/gi, "$1@Day @Month @YYYY"); 
	ohc_regex(/([ =|])@DD[-–]@MM[-–]@YYYY(?=[^-–\d/])/gi, "$1@Day @Month @YYYY"); 
	ohc_regex(/([ =|])@DD\/@MM\/@YYYY(?=[^-–\d/])/gi, "$1@Day @Month @YYYY"); 
	ohc_regex(/([ =|])@DD\.@MM\.@YYYY(?=[^-–\d/])/gi, "$1@Day @Month @YYYY");
	ohc_regex(/([ =|])@DD @MM @YYYY(?=[^-–\d/])/gi, "$1@Day @Month @YYYY"); 
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)@DD[-–\/\.=\s]@Month[-–\/\.=\s]@YYNN(?=\s*[|}\n])/gi, '$1@Day @Month @YYYY');

//convert yyyy-dd-mm to yyyy-mm-dd
	ohc_regex(/{{(\s*[Cc]it(?:e|ation))([^}]+)(\s*\|\s*(?:publication|archive|access|air|)-?date\s*=\s*(?:1[0-9]|20)\d{2})[-/\.=\s](1[3-9]|2\d|3[01])[-/\.=\s](0?\d|1[0-2])(\s*[\|}<])/gi, '{{$1$2$3-$5-$4$6'); //from Batty

// eliminating other errant formats
	ohc_regex(/(\|(?:[\w ]*)date\s*=\s*)([0-2]?\d|30|31) @Month \2,? @YYYY(?=\s*[|}])/gi, "$1$2 @Month @YYYY"); //repeated digits
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)@Day ?@Month ?200([01]\d)[^\s|}]?(?=\s*[|}])/gi, "$1@Day @Month 20$2");
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)@Month ?@Day,? ?200([01]\d)[^\s|}]?(?=\s*[|}])/gi, "$1@Month @Day, 20$2");

	ohc_regex(/([ ]\()@DD-@MM-@YYYY(\)\W)/gi, '$1@Day @Month @YYYY$2');
	ohc_regex(/([ ]\()@DD-@Month-@YYYY(\)\W)/gi, '$1@Day @Month @YYYY$2');
	ohc_regex(/(\|(?:[\w ]*)date\s*=\s*)@Month, @DD, @YYYY(?=\s*[|}])/gi, "$1@Day @Month @YYYY");
	ohc_regex(/(\|(?:[\w ]*)date\s*=\s*)@DD[\.,] @Month,? @YYYY(?=\s*[|}])/gi, "$1@Day @Month @YYYY");
	ohc_regex(/(\|(?:[\w ]*)date\s*=\s*)@YYYY,? @Month @DD(?=\s*[|}])/gi, "$1@Day @Month @YYYY");
	ohc_regex(/(\|(?:[\w ]*)date\s*=\s*)@YYYY,? @DD @Month(?=\s*[|}])/gi, "$1@Day @Month @YYYY");
	ohc_regex(/[ ]\(@YYYY,? @Month @DD\)/gi, " (@Day @Month @YYYY)");
	ohc_regex(/[ ]\(@YYYY @MM @DD\)/gi, " (@Day @Month @YYYY)");
	ohc_regex(/[ ]\(@YYYY, @DD @Month\)/gi, " (@Day @Month @YYYY)");
	ohc_regex(/(\|(?:[\w ]*)date\s*=\s*)@YYYY,? @Month(?=\s*[|}])/gi, "$1@Month @YYYY");
	ohc_regex(/[ ]\(@YYYY, @Month\)/gi, " (@Month @YYYY)");
	ohc_regex(/[ ]\(@Mon@YYYY\)/gi, " (@Mon @YYYY)");

	//CS1 errors ISO-like dates (too few or too many digits)
	ohc_regex(/(date\s*=\s*)(?:\[\[)?@YYYY(?:\]\][–—‐]\[\[|[–—‐])@MM[\-–—‐]@DD(?:\]\])?(?=\s*[|}])/gi, "$1@YYYY-@ZM-@ZD"); //ndashes and emdashes
	ohc_regex(/(\|\s*access-?date\s*=)\s*@YYYY-0[–—]@DD(?=\s*[|}])/gi, ""); //rem nonsense access date
	ohc_regex(/(\|(?:[\w ]*)date\s*=\s*)@YYYY[-–—]@MM[-–—]@DD(?=\s*[|}])/gi, "$1@YYYY-@ZM-@ZD"); //ndashes and emdashes
//	ohc_regex(/(\|(?:[\w ]*)date\s*=\s*)@YYYY[\-–—‐]@MM(?=\s*[|}])/gi, "$1@Month @YYYY"); //transform "yyyy-mm" to "month year"
	ohc_regex(/(<ref[^>]*>[^<]+?)([\s\(])@YYYY[–—]@MM[–—]@DD([^-\w\/%,<][^<]*?<\/ref>)/gi, "$1$2@Day @Month @YYYY$3");
	ohc_regex(/(<ref[^>]*>[^<]+?)([\s\(])@YYYY[-]@MM[-]([1-9])([^-\w\/%,<][^<]*?<\/ref>)/gi, "$1$2$3 @Month @YYYY$4");  

	// spaces and commas between month and year
	ohc_regex(/@Month(?:,?|\s+of|)(\s|&nbsp;)@YYYY(?=\D)/gi, "@LMonth$1@YYYY");

// fix month names (capitalize, remove dots)
	ohc_regex(/(\W)@DD\s@FullMonth(\s+|\s*,)/gi, "$1@Day @FullMonth$2");
	ohc_regex(/(\W)@DD\s@Mon(\s+|\s*,)/gi, "$1@Day @Mon$2");
	ohc_regex(/(\W)@FullMonth\s@DD(\s+|\s*,)/gi, "$1@FullMonth @Day$2");
	ohc_regex(/(\W)@Mon\s@DD(\s+|\s*,)/gi, "$1@Mon @Day$2");
	regex(/(\d(?:st|nd|rd|th) )C(entur(?:ies|y))(?=[ ]*(=|BC|AD|CE))/g, '$1c$2');
//	regex(/(\d(?:st|nd|rd|th) )C(entur(?:ies|y))(?![ \-][A-Z]\w*|''|")/g, '$1c$2');

	//spaces and commas - in date formats
	ohc_regex(/(\D\W\[?\[?@dd)[ ]+(@month)(\]\])?[ ]*,[ ]*(\[?\[?@yyyy(\sAD|\sBC|\sCE|\sBCE|)\]?\]?\W\D)/gi, "$1 $2$3 $4");
	ohc_regex(/(\D\W\[?\[?)(@month)[ ]+(@dd)(\]?\]?)(?:[ ]*,[ ]*)(\[?\[?@yyyy(\sAD|\sBC|\sCE|\sBCE|)\]?\]?\W\D)/gi, "$1$2 $3$4, $5");
	ohc_regex(/(\D\W\[?\[?)(@month)[ ]+(@dd)(\]?\]?)[ ]+(\[?\[?@yyyy(\sAD|\sBC|\sCE|\sBCE|)\]?\]?\W\D)/gi, "$1$2 $3$4, $5");

	ohc_regex(/(@month)(?:, | of )(@yyyy\w)/gi, "$1 $2"); //repeat after delinking

	// spaces and commas - md-md and dm-dm date ranges
	ohc_regex(/(\D\W)@Month\s@DD(&nbsp;|\s)(?:[-–—]|&[mn]dash;)(?:&nbsp;|\s)?@Month\s@DD(?=\W\D)/gi, "$1@LMonth1 @Day1$2– @LMonth2 @Day2");
	ohc_regex(/(\D\W)@Month\s@DD(?:[-–—]|&[mn]dash;)(?:&nbsp;|\s)?@Month\s@DD(?=\W\D)/gi, "$1@LMonth1 @Day1 – @LMonth2 @Day2");
	ohc_regex(/(\D\W)@DD\s@Month(&nbsp;|\s)(?:[-–—]|&[mn]dash;)(?:&nbsp;|\s)?@DD\s@Month(?=\W\D)/gi, "$1@Day1 @LMonth1$2– @Day2 @LMonth2");
	ohc_regex(/(\D\W)@DD\s@Month(?:[-–—]|&[mn]dash;)(?:&nbsp;|\s)?@DD\s@Month(?=\W\D)/gi, "$1@Day1 @LMonth1 – @Day2 @LMonth2");

	// spaces and commas - d-dm and md-d date ranges
	ohc_regex(/(\D\W)@Month(\s|&nbsp;)@DD@th?(?:(?:\s*|&nbsp;|)[-–](?:\s*|&nbsp;|))@DD@th?(?=\W\D)/gi, "$1@LMonth1$2@Day1–@Day2");
	ohc_regex(/(\D\W)@DD@th?(?:(?:\s*|&nbsp;|)[-–](?:\s*|&nbsp;|))@DD@th?(\s|&nbsp;)@Month(?=\W\D)/gi, "$1@Day1–@Day2$2@LMonth1");

	// spaces and commas between month and year (again)
	ohc_regex(/@Month(?:,\s+|\s+of\s+)@YYYY(\w)/gi, "@LMonth @YYYY$1");
}

/** ------------------------------------------------------------------------- */
/// ISO to long format

function ohc_ISO_to_dmy_in_citations()
{
	//ISO dates within single citation
	ohc_regex(/(\|\s*(?:publication|archive|access|air|designation\d?_|)-?date\s*=\s*)@YYYY[-–]@MM[-–]@DD(?=\W\D)/gi, "$1@Day @Month @YYYY");
}

function ohc_ISO_to_mdy_in_citations()
{
	//ISO dates within single citation
	ohc_regex(/(\|\s*(?:publication|archive|access|air|designation\d?_|)-?date\s*=\s*)@YYYY[-–]@MM[-–]@DD(?=\W\D)/gi,  "$1@Month @Day, @YYYY");
}

function ohc_ISO_to_dmy_in_references()
{
	//multiple calls for multiple dates within single citation
	ohc_regex(/(<ref[^>]*>[^<]+?)([\s\(])@YYYY[-–]@MM[-–]@DD([^-\w\/%,<][^<]*?<\/ref>)/gi, "$1$2@Day @Month @YYYY$3");
	ohc_regex(/(<ref[^>]*>[^<]+?)([\s\(])@YYYY[-–]@MM[-–]@DD(<\/ref>)/gi, "$1$2@Day @Month @YYYY$3");
}

function ohc_ISO_to_mdy_in_references()
{
	//multiple calls for multiple dates within single citation
	ohc_regex(/(<ref[^>]*>[^<]+?)([\s\(])@YYYY[-–]@MM[-–]@DD([^-\w\/%,<][^<]*?<\/ref>)/gi, "$1$2@Month @Day, @YYYY$3");
	ohc_regex(/(<ref[^>]*>[^<]+?)([\s\(])@YYYY[-–]@MM[-–]@DD(<\/ref>)/gi, "$1$2@Month @Day, @YYYY$3");
}

// currently unused
function ohc_ISO_to_dmy_anywhere()
{
	//multiple calls for multiple dates within single citation
	ohc_regex(/([^-\w/])@YYYY[-–]@MM[-–]@DD([^-\w/])/gi, '$1@Day @Month @YYYY$2');
	ohc_regex(/([^-\w/])@YYYY[-–]@MM[-–]@DD([^-\w/])/gi, '$1@Day @Month @YYYY$2');
	ohc_regex(/([^-\w/])@YYYY[-–]@MM[-–]@DD([^-\w/])/gi, '$1@Day @Month @YYYY$2');
}

// currently unused
function ohc_ISO_to_mdy_anywhere()
{
	//multiple calls for multiple dates within single citation
	ohc_regex(/([^-\w/])@YYYY[-–]@MM[-–]@DD([^-\w/])/gi, '$1@Month @Day, @YYYY$2');
	ohc_regex(/([^-\w/])@YYYY[-–]@MM[-–]@DD([^-\w/])/gi, '$1@Month @Day, @YYYY$2');
	ohc_regex(/([^-\w/])@YYYY[-–]@MM[-–]@DD([^-\w/])/gi, '$1@Month @Day, @YYYY$2');
}

function ohc_delink_ISO_to_dmy()
{
	ohc_ISO_to_dmy_in_citations();
	ohc_ISO_to_dmy_in_references();
	regex(/([^\w\/\-%,])@YYYY-@MM-@DD(<\s?\/ref.*?>)/g, '$1@Day @Month @Year$2');
	ohc_regex(/(\|\|[ ]*)@YYYY[-–]@MM[-–]@DD([ ]*\|\|)/gi, '$1{{dts|format=dmy|@YYYY|@MM|@DD}}$2');  //dts template for sortable tables
	ohc_regex(/(\{\{dts\|format=)mdy\|/gi, '$1dmy|');  //flip dts template formats
}

function ohc_delink_ISO_to_mdy()
{
	ohc_ISO_to_mdy_in_citations();
	ohc_ISO_to_mdy_in_references();
	regex(/([^\w\/\-%,])@YYYY-@MM-@DD(<\s?\/ref.*?>)/g, '$1@Month @Day, @Year$2');
	ohc_regex(/(\|\|[ ]*)@YYYY[-–]@MM[-–]@DD([ ]*\|\|)/gi, '$1{{dts|@YYYY|@MM|@DD}}$2');  //dts template for sortable tables (mdy is default)
	ohc_regex(/(\{\{dts\|)format=(?:mdy|dmy|) ?\|/gi, '$1');  //flip dts template formats
}

function ohc_delink_year_in_X()
{
//	ohc_regex(/\{\{(?:avyear|by|baseball\syear|fy|ly|mlby|mlb\syear|scy|sdy)\|(@year)\}\}/gi, "$1"); //disabled 3/5/21 discussion at https://en.wikipedia.org/w/index.php?title=Wikipedia_talk:WikiProject_Baseball&oldid=1021203365#Links_to_baseball_year_articles_in_infobox?
//	ohc_regex(/\{\{(?:avyear|by|baseball\syear|fy|ly|mlby|mlb\syear|scy|sdy)\|@year\|(@year)\}\}/gi, "$1");
	ohc_regex(/\[\[@yyyy\sin\s[^|\]]+\|((?:(?:@day |)@month |)@yyyy)\]\]/gi, '$1');
	regex(/\[\[(?:\d{4}[-–]\d{2} in English football)\|((?:(?:@Day |)@Month |)@YYYY)\]\]/gi, '$1'); 

	regex(/\[\[\d{4} Major League Baseball season\|(\d{4})(\sseason)?\]\]/gi, '$1$2');
}


// format parameter must be 'dmy' or 'mdy'
function ohc_fix_dts_template(format)
{
	// dts - format=dmy in this case (per D12000)
	// per {{dts}} doc, remove the obsolete link=off param
	regex(/(\{\{dts[^}]*)(?:\|link=off)/gi, '$1');
	ohc_regex(/(\{\{dts\s*\|\s*@year\s*\|\s*@month\s*\|\s*@day\s*\|\s*format=)(?:dmy|mdy)(\}\})/gi, '$1'+format+'$2');
	ohc_regex(/(\{\{dts\s*\|\s*format=)(?:dmy|mdy)(\s*\|\s*@year\s*\|\s*@month\s*\|\s*@day\s*\}\})/gi, '$1'+format+'$2');
	ohc_regex(/(\{\{dts\s*\|\s*@year\s*\|\s*@month\s*\|\s*@day\s*)(\}\})/gi, '$1|format='+format+'$2');

   // stripping – {{dts}} serves no purpose inside date parameters
	ohc_regex(/(\|(?:[\w ]*)date\s*=\s*)\{\{dts\s*\|\s*format=(?:dmy|mdy)\s*\|\s*([|}]*)\}\}(?=\s*[|}])/gi, "$1$2");
	ohc_regex(/(\|(?:[\w ]*)date\s*=\s*)\{\{dts\s*\|\s*([|}]*)(?:\|\s*format=(?:dmy|mdy)\s*|)\}\}(?=\s*[|}])/gi, "$1$2");
	ohc_regex(/(\|(?:[\w ]*)date\s*=\s*)\{\{dts\s*\|\s*format=(?:dmy|mdy)\s*\|\s*@YYYY(\s*\|\s*|-)@MM(\s*\|\s*|-)@DD\s*\}\}(?=\s*[|}])/gi, "$1@YYYY-@MM-@DD ");
	ohc_regex(/(\|(?:[\w ]*)date\s*=\s*)\{\{dts\s*\|\s*@YYYY(\s*\|\s*|-)@MM(\s*\|\s*|-)@DD\s*\|\s*format=(?:dmy|mdy)\s*\}\}(?=\s*[|}])/gi, "$1@YYYY-@MM-@DD ");
}

// format parameter must be 'dmy' or 'mdy'
function ohc_fix_gr_template(format)
{
	// GR - date formatting parameter
	// per {GR} doc, insert date formatting param
	regex(/(\{\{GR\|\d\d?)(?!\|date)/gi, '$1|dateform=' + format);
}

function ohc_dates_to_dmy()
{
	regex(/\|df=[mdy]{3}(?:-all|)(?=\s*[|}])/gi, '');
	regex(/\|format=mdy/gi, '|format=dmy');
	//change start and end templates; vgrelease new v=2 or mdy is default
	regex(/(\{\{(?:start date|end date)[^|}]*\|)df=ye?s?\|([^}]*df=ye?s?)/gi, '$1$2');
	regex(/(\{\{vgrelease new[^|}]*\|)(?:v=1\||)([A-Z]{2,3}\|)/g, '$1v=2|$2');
	ohc_regex(/(\|\s*(?:begin|end|first|last)\s*=\s*)@YYYY[-–]@MM[-–]@DD(?=\W\D)/gi, "$1@Day @Month @YYYY"); //spotted at [[Template:Infobox recurring event]]
 
	//change birth and death templates
	regex(/(\{\{(?:(?:Birth|Death) date(?: and age|)|launch|release|start)[^}]*\|)m(f=ye?s?)/gi, '$1d$2'); // substitute df for mf 
	regex(/(\{\{(?:(?:Birth|Death) date(?: and age|)|launch|release|start|film ?date|Wayback)[\|\d]+)(\}\})/gi, '$1|df=y$2'); //insert df parameter
	regex(/(\{\{(?:(?:Birth|Death) date(?: and age|)|launch|release|start|film ?date|Wayback)[\|\d]+\|)df=ye?s?\|([^}]*df=ye?s?)/gi, '$1$2'); //put date format parameter at the end
	regex(/(\{\{(?:start date|end date)\|)df=ye?s?\|((?:1[789]|20)\d{2}\}\})/gi, '$1$2');  //date format parameter not needed – year only

	//convert date ranges (md,d,d-dy to d,d,d-dmy; md,d,d-d to d,d,d-dm; md,d,d to d,d,dm)
	ohc_regex(/(\D\W)@Month((?:\s@day?,?){1,6}),?(\/|\s?(?:[-–]|&ndash;)\s?|(?:[ _]|&nbsp;)(?:and|&|to|or)(?:[ _]|&nbsp;)+?)@Day,?\s(?:of\s)?(@yyyy\W\D)/gi, "$1$2$3@Day @LMonth $4");
	ohc_regex(/(\D\W)@Month((?:\s@day?,?){1,6}),?(\/|\s?(?:[-–]|&ndash;)\s?|(?:[ _]|&nbsp;)(?:and|&|to|or)(?:[ _]|&nbsp;)+?)@Day(?=\W\D)/gi, "$1$2$3@Day @LMonth");

//	ohc_regex(/(\D\W)@Month((?:\s@day?,?){1,6}) @Day(?=\W\D)/gi, "$1$2 @Day @LMonth"); //disabling as unlikely and ungrammatical constructions causing false positives

	//'md, md,' to 'dm, dm,'
	ohc_regex(/(\D\W)@Month @Day, @Month @Day(?=[,\.]\W\D)/gi, "$1@Day1 @LMonth1, @Day2 @LMonth2");

	//convert simple mdy dates to dmy
	ohc_regex(/(p(?:g?\.?|age) ?\d+|p(?:p\.?|ages) ?\d+[-–]\d+), @Month((?:\s@day?,?){1,6}) @Day(?=\W\D)/gi, "$1. $2 @Day @LMonth");
	ohc_regex(/(\D\W)@Month\s@Day,?\s@Year(\s?(?:AD|BC|CE|BCE)\W\D)/gi, "$1@Day @LMonth @Year$2");
	ohc_regex(/(\|\s*term_(?:end|start)\d\s*=\s*|\D\W)@Month\s@Day,?\s@YYYY(?=\W\D)/gi, "$1@Day @LMonth @Year");
	ohc_regex(/(\|\s*term_(?:end|start)\d\s*=\s*|\D\W)@Month\s@Day(?=\W\D)/gi, "$1@Day @LMonth");

	//Month+day_number " 7th মার্চ" -> "7 মার্চ"
	ohc_regex(/(\D\W)@Day\s@Month\s@YYYY(?=\W\D)/gi, "$1@Day @LMonth @Year");
	ohc_regex(/(\D\W)@Day\s@Month(?=\W\D)/gi, "$1@Day @LMonth");
	ohc_regex(/(\D\W)@Month\s@Day,?\s@Year(?=\W\D)/gi, "$1@Day @LMonth @Year");

	//dates with embedded nbsp
	ohc_regex(/(\D\W)@Month([ _]|&nbsp;)(\d{1,2},(?: |&nbsp;)\d{1,2}(?:\s(?:and|&|to|or)(?:[ _]|&nbsp;))\d{1,2})(?=[^|\]\w])/gi, '$1$3$2@LMonth ');
	ohc_regex(/(\D\W)@Month([ _]|&nbsp;|{{(?:break|nbsp)}})@Day,([ _]|&nbsp;|{{(?:break|nbsp)}})@YYYY(?=[^|\]\w])/gi, '$1@Day$2@Month$3@Year');

	//remove comma
	ohc_regex(/(\D\W)@Day\s@Month,\s?@Year(?=\W\D)/gi, "$1@Day @LMonth @Year");

	//	remove "the" from "on the dd month"
	ohc_regex(/(on |by )the @Day\s@Month(?=[ ,\)\.])/gi, "$1@Day @LMonth");

	//remove space from date range conversion
	ohc_regex(/(\D ) @Day(\/|\s?(?:[-–]|&ndash;)\s?|(?:[ _]|&nbsp;)(?:and|&|to|or)(?:[ _]|&nbsp;)+?)/gi, "$1@Day$2");
}

function ohc_dates_to_mdy()
{
	//change birth and death templates – mf=y is the default; vgrelease new v=2 or mdy is default
	regex(/\|df=[mdy]{3}(?:-all|)(?=\s*[|}])/gi, '');
	regex(/\|df=y(?:es|)(?=[|}\s])/gi, '');
	regex(/(mf=y(?:es|)\|[^}]*\|)(?:mf=y(?:es|)\|)/gi, '$1');
	regex(/(\{\{vgrelease new[^|}]*\|)(?:v=2\||)([A-Z]{2,3}\|)/g, '$1$2');
	ohc_regex(/(\|\s*(?:begin|end|first|last)\s*=\s*)@YYYY[-–]@MM[-–]@DD(?=\W\D)/gi, "$1@Month @Day, @YYYY");

	//convert date ranges (d,d,d-dmy to md,d,d-dy; d,d,d-dm to md,d,d-d; dm,d,d to md,d,d)
	ohc_regex(/(\D\W)@Day((?:, @day){0,5})(\/|\s?(?:[-–]|&ndash;)\s?|\s(?:and|&|to|or)\s+?)@Day\s@Month,? @YYYY(?=\W\D)/gi, "$1@LMonth @Day1$2$3@Day2, @YYYY");
	ohc_regex(/(\D\W)@Day((?:, @day){0,5})(\/|\s?(?:[-–]|&ndash;)\s?|\s(?:and|&|to|or)\s+?)@Day\s@Month(?=\W\D)/gi, "$1@LMonth @Day1$2$3@Day2");
//	ohc_regex(/(\D\W)@Day((?:, @day){0,5})\s@Month,? @YYYY(?=\W\D)/gi, "$1@LMonth @Day1$2, @YYYY"); //disabling as unlikely and ungrammatical constructions causing false positives
//	ohc_regex(/(\D\W)@Day((?:, @day){0,5})\s@Month(?=\W\D)/gi, "$1@LMonth @Day1$2"); //disabling as unlikely and ungrammatical constructions causing false positives

	//'dm, dm,' to 'md, md,'
	ohc_regex(/(\D\W)@Day @Month, @Day @Month(?=[,\.]?\W\D)/gi, "$1@LMonth1 @Day1, @LMonth2 @Day2");

	//convert simple dmy dates to mdy
	ohc_regex(/(p(?:g?\.?|age) ?\d+|p(?:p\.?|ages) ?\d+[-–]\d+), @Month((?:\s@day?,?){1,6}) @Day(?=\W\D)/gi, "$1. @LMonth $2 @Day");
	ohc_regex(/(\D\W)@Day(\s|&nbsp;)@Month,?(\s|&nbsp;)@Year(?=\W\D)/gi, "$1@LMonth$2@Day,$3@Year");
	ohc_regex(/(\|\s*term_(?:end|start)\d\s*=\s*|\D\W)@Day[ ]+@Month,?\s@YYYY(?=\W\D)/gi, "$1@LMonth @Day, @Year");
	ohc_regex(/(\|\s*term_(?:end|start)\d\s*=\s*|\D\W)@Day[ ]+@Month(?=\W\D)/gi, "$1@LMonth @Day");

	//Month+day_number "মার্চ 7th" -> "মার্চ 7"
	ohc_regex(/(\D\W)@Month\s@Day@th?,?\s@YYYY(?=\W\D)/gi, "$1@LMonth @Day, @YYYY");
	ohc_regex(/(\D\W)@Day@th?(\s|&nbsp;)@Month(\s|&nbsp;)@YYYY(?=\W\D)/gi, "$1@LMonth$2@Day,$3@YYYY");
	ohc_regex(/(\D\W)@Month(\s|&nbsp;)@Day(?=\W\D)/gi, "$1@LMonth$2@Day");
	ohc_regex(/(\D\W)@Day@th?(\s|&nbsp;)@Month([,\.])(?=\W\D)/gi, "$1@LMonth$2@Day$3");

	//add comma where missing
	ohc_regex(/(\D\W)@Month\s@Day,?\s@YYYY,?(?=\s\w)/gi, "$1@LMonth @Day, @YYYY,");
	//rem superfluous comma where applicable
	ohc_regex(/(\D[^\w\/])@Month\s@ZD,,(?=\W\D|\b)/gi, "$1@LMonth @Day,");
}

function ohc_fix_dmy_redundancies()
{
	//month-range redundancies (repeating month names)
	ohc_regex(/([\D]@dd)@th? @Month[ ]{1,2}((?:to|and|-|–)[ ]{1,2}@dd)@th? @Month/, "$1 $2 @LMonth", function(d1, d2) {
		if (d1.m == d2.m) return true;
		return false;
	});
}
//not currently used
function ohc_fix_mdy_redundancies()
{
	//month-range redundancies (repeating month names)
	ohc_regex(/(@Month[ ]{1,2}@dd)@th? (to|and|-|–)[ ]{1,2}@Month[ ]{1,2}@DD@th?/, "$1 $2 @LDay", function(d1, d2) {
		if (d1.m == d2.m) return true;
		return false;
	});
}

function ohc_expand_ref_dates()
{
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)@Month @YYYY(?=\s*[|}])/gi, "$1@FullMonth @YYYY");
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)@Day @Month @YYYY(?=\s*[|}])/gi, "$1@Day @FullMonth @YYYY");
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)@Month @Day, @YYYY(?=\s*[|}])/gi, "$1@FullMonth @Day, @YYYY");

	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)((?:[01-2]?\d|30|31) |)@Month @YYYY ?(?:-|–|&ndash;) ?((?:[01-3]?\d|30|31) |)@Month @YYYY(?=\s*[|}])/gi, "$1$2 @FullMonth1 @YYYY1 – $3@FullMonth2 @YYYY2");
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)@Month @Day(, (?:19|20)\d\d) ?(?:-|–|&ndash;) ?@Month @Day, @YYYY(?=\s*[|}])/gi, "$1@FullMonth1 @Day1$2 – @FullMonth2 @Day2, @YYYY");
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)@Day @Month,?( (?:19|20)\d\d) ?(?:-|–|&ndash;) ?@Day @Month @YYYY(?=\s*[|}])/gi, "$1@Day1 @FullMonth1$2 – @Day2 @FullMonth2 @YYYY");
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)@Month,?( (?:19|20)\d\d) ?(?:-|–|&ndash;) ?@Month,? @YYYY(?=\s*[|}])/gi, "$1@FullMonth1$2 – @FullMonth2 @YYYY");
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)((?:19|20)\d\d) ?(?:-|–|&ndash;) ?@Month @YYYY(?=\s*[|}])/gi, "$1@$2 – @FullMonth @YYYY");

	ohc_regex(/(<ref[^>]*>(?:[^<]+?[\s\(]|))((?:[01-2]?\d|30|31) |)@Month @YYYY ?(?:-|–|&ndash;) ?((?:[01-3]?\d|30|31) |)@Month @YYYY(?=(?:[^-\w\/%,<][^<]*?|)<\/ref>)/gi, "$1$2@FullMonth1 @YYYY1 – $3@FullMonth2 @YYYY2");
	ohc_regex(/(<ref[^>]*>(?:[^<]+?[\s\(]|))@Month @Day(, (?:19|20)\d\d) ?(?:-|–|&ndash;) ?@Month @Day, @YYYY(?=(?:[^-\w\/%,<][^<]*?|)<\/ref>)/gi, "$1@FullMonth1 @Day1$2 – @FullMonth2 @Day2, @YYYY");
	ohc_regex(/(<ref[^>]*>(?:[^<]+?[\s\(]|))@Day @Month,?( (?:19|20)\d\d) ?(?:-|–|&ndash;) ?@Day @Month @YYYY(?=(?:[^-\w\/%,<][^<]*?|)<\/ref>)/gi, "$1@Day1 @FullMonth1$2 – @Day2 @FullMonth2 @YYYY");
	ohc_regex(/(<ref[^>]*>(?:[^<]+?[\s\(]|))@Month,?( (?:19|20)\d\d) ?(?:-|–|&ndash;) ?@Month,? @YYYY(?=(?:[^-\w\/%,<][^<]*?|)<\/ref>)/gi, "$1@FullMonth1$2 – @FullMonth2 @YYYY");
	ohc_regex(/(<ref[^>]*>(?:[^<]+?[\s\(]|))((?:19|20)\d\d) ?(?:-|–|&ndash;) ?@Month @YYYY(?=(?:[^-\w\/%,<][^<]*?|)<\/ref>)/gi, "$1$2 – @FullMonth @YYYY");
}

function ohc_expand_all_dates()
{
	ohc_regex(/([^-\w/])@Month @YYYY(?=[^-\w/])/gi, '$1@FullMonth @YYYY');
	ohc_regex(/([^-\w/])@Day @Month @YYYY(?=[^-\w/])/gi, '$1@Day @FullMonth @YYYY');
	ohc_regex(/([^-\w/])@Month @Day, @YYYY(?=[^-\w/])/gi, '$1@FullMonth @Day, @YYYY');

	ohc_regex(/([^-\w/])((?:[01-2]?\d|30|31) |)@Month @YYYY ?(?:-|–|&ndash;) ?((?:[01-3]?\d|30|31) |)@Month @YYYY(?=[^-\w/])/gi, "$1$2@FullMonth1 @YYYY1 – $3@FullMonth2 @YYYY2");
	ohc_regex(/([^-\w/])@Month @Day(, (?:19|20)\d\d) ?(?:-|–|&ndash;) ?@Month @Day, @YYYY(?=[^-\w/])/gi, "$1@FullMonth1 @Day1$2 – @FullMonth2 @Day2, @YYYY");
	ohc_regex(/([^-\w/])@Day @Month,?( (?:19|20)\d\d) ?(?:-|–|&ndash;) ?@Day @Month @YYYY(?=[^-\w/])/gi, "$1@Day1 @FullMonth1$2 – @Day2 @FullMonth2 @YYYY");
	ohc_regex(/([^-\w/])@Month,?( (?:19|20)\d\d) ?(?:-|–|&ndash;) ?@Month,? @YYYY(?=[^-\w/])/gi, "$1@FullMonth1$2 – @FullMonth2 @YYYY");
	ohc_regex(/([^-\w/])((?:19|20)\d\d) ?(?:-|–|&ndash;) ?@Month @YYYY(?=[^-\w/])/gi, "$1$2 – @FullMonth @YYYY");

	ohc_regex(/([ ]\(|\|\s*)@Day @Month @YYYY(?=\)\W|\s*[|\n])/gi, "$1@Day @FullMonth @YYYY");
	ohc_regex(/([ ]\(|\|\s*)@Month @Day,? @YYYY(?=\)\W|\s*[|\n])/gi, "$1@FullMonth @Day, @YYYY");
	ohc_regex(/([ ]\((?:c\. |))@Month @YYYY ?(?:-|–|&nbsp;) ?@Day @Month @YYYY(?=\)\W)/gi, "$1@FullMonth1 @YYYY1 – @Day @FullMonth2 @YYYY2");
	ohc_regex(/([ ]\((?:c\. |))@Month @YYYY ?(?:-|–|&nbsp;) ?@Month @YYYY(?=\)\W)/gi, "$1@FullMonth1 @YYYY1 – @FullMonth2 @YYYY2");
	ohc_regex(/([ ]\((?:c\. |))@YYYY ?(?:-|–|&nbsp;) ?@Month @YYYY(?=\)\W)/gi, "$1@YYYY1 – @FullMonth @YYYY2");
	ohc_regex(/([ ]\((?:c\. |))@Month ?(?:-|–|&nbsp;) ?@Month @YYYY(?=\)\W)/gi, "$1@FullMonth1 – @FullMonth2 @YYYY");
	ohc_regex(/([ ]\((?:c\. |))@Month @YYYY(?=\)\W)/gi, "$1@FullMonth @YYYY");
}

function ohc_abbrev_ref_dates()
{
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)@Day @Month @YYYY(?=\s*[|}])/gi, "$1@Day @Mon @YYYY");
	ohc_regex(/(<ref[^>]*>(?:[^<]+?[\s\(]|))([12]?\d|30|31) (জানুয়ারি|ফেব্রুয়ারি|মার্চ|এপ্রিল|মে|জুন|জুলাই|আগষ্ট|অক্টোবর|Oct|নভেম্বর|ডিসেম্বর)(?:r?uary|ch|il|[ey]|ust|(?:t?em|o)ber)( (?:19\d|20[01])\d)(?=(?:[^-\w\/%,<][^<]*?|)<\/ref>)/gi, "$1$2 $3$4");
	ohc_regex(/([ ]\()@Day @Month @YYYY([^-\w\/])/gi, "$1@Day @Mon @YYYY$2");
 
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)@Month @Day, @YYYY(?=\s*[|}])/gi, "$1@Mon @Day, @YYYY");
	ohc_regex(/(<ref[^>]*>(?:[^<]+?[\s\(]|))(জানুয়ারি|ফেব্রুয়ারি|মার্চ|এপ্রিল|মে|জুন|জুলাই|আগষ্ট|অক্টোবর|Oct|নভেম্বর|ডিসেম্বর)(?:r?uary|ch|il|[ey]|ust|(?:t?em|o)ber) ([12]?\d|30|31),( (?:19\d|20[01])\d)(?=(?:[^-\w\/%,<][^<]*?|)<\/ref>)/gi, "$1$2 $3,$4");
	ohc_regex(/([^-\w\/])@Month @Day, @YYYY([^-\w\/])/gi, '$1@Mon @Day, @YYYY$2');
}
 
//not currently used
function ohc_abbrev_all_dates()
{
	ohc_regex(/([^-\w/])@Day @Month @YYYY(?=[^-\w/])/gi, '$1@Day @Mon @YYYY');
	ohc_regex(/([^-\w/])@Month @Day, @YYYY(?=[^-\w/])/gi, '$1@Mon @Day, @YYYY');
}

//not currently used
function ohc_dmy_publication_dates()
{
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)@Month @Day,? @YYYY/gi, "$1@Day @Month @YYYY"); // conversion of dates in references outside of the protection loop (eg for quotations etc.)
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)(?:\[\[)?@YYYY(?:\]\][-–]\[\[|[-–])@MM[-–]@DD(?:\]\])?(?=\s*[|}])/gi, "$1@Day @Month @YYYY");
	//replace ISO dates (within parentheses) only within refs
	ohc_regex(/(<ref[^>]*>[^<]+?)([ ]\()@YYYY-@MM-@DD(\))(\W[^<]*?<\/ref>)/gi, "$1$2@Day @Month @YYYY$3$4");
}

function ohc_mdy_publication_dates()
{
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)@Day @Month @YYYY/gi, "$1@Month @Day, @YYYY"); // conversion of dates in references outside of the protection loop (eg for quotations etc.)
	ohc_regex(/(\|\s*(?:publication|archive|access|air|)-?date\s*=\s*)(?:\[\[)?@YYYY(?:\]\][-–]\[\[|[-–])@MM[-–]@DD(?:\]\])?(?=\s*[|}])/gi, "$1@Month @Day, @YYYY"); 
	//replace ISO dates (within parentheses) only within refs
	ohc_regex(/(<ref[^>]*>[^<]+?)([ ]\()@YYYY-@MM-@DD(\))(\W[^<]*?<\/ref>)/gi, "$1$2@Month @Day, @YYYY$3$4");
}

function ohc_Bigendian_ref_dates() {
	// Add a tag to the summary box
	regex(/(\{\{use (?:mdy|dmy) dates)(?:\|cs1-dates=\w{1,2}|)(\|[^\}\|]+\}\})/gi, '$1|cs1-dates=y$2');
}

/** ------------------------------------------------------------------------ **/
/// EDIT SUMMARIES & USE DMY TEMPLATE
// this function modified 2019-03-27 from [[Special:Permalink/846525463]]
// format parameter must be 'dmy' or 'mdy'
function ohc_use_dates_template(format) 
{
	var txt = document.editform.wpTextbox1;
	// current month-year
	var currentDate = new Date();
	var currmonth = currentDate.getMonth();
	var curryear = currentDate.getFullYear();
	var myMonths = ["জানুয়ারি", "ফেব্রুয়ারি", "মার্চ", "এপ্রিল", "মে", "জুন", "জুলাই", "আগষ্ট", "সেপ্টেম্বর", "অক্টোবর", "নভেম্বর", "ডিসেম্বর"];
	var curryyyymm = myMonths[currmonth] + ' ' + curryear;

// step 1: normalize redirect template names to canonical template names 'Use dmy dates' or 'Use mdy dates' according to 'format' argument 
// rename redirects 'dmy', 'mdy', 'usedmydates', 'usemdydates' ('usedmydates' and 'usemdydates' are not currently listed as redirects but might be encountered?)
	regex(/\{\{ *(?:use(?:dmy|mdy)dates|dmy|mdy) *([\|\}])/gi, '{{Use ' + format + ' dates$1');
// rename redirects 'usedmy', 'usemdy', 'use dmy', 'use mdy' to canonical form
	regex(/\{\{ *use *(?:dmy|mdy) *([\|\}])/gi, '{{Use ' + format + ' dates$1');
// strip leading / trailing whitespace from 'use xxx dates'
	regex(/\{\{ *use (?:dmy|mdy) dates *([\|\}])/gi, '{{Use ' + format + ' dates$1');

// step 2: look for a canonical template name (the above might not have had anthing to work on) ; if found continue, write new template else
	var rxpdd = new RegExp("{{Use " + format + " dates", "gi");	// here we search for canonical form {{use xxx dates}} that has current date
	var dflagfound = txt.value.search(rxpdd);
	if (dflagfound === -1) {
		txt.value = '{{Use ' + format + ' dates|date=' + curryyyymm + '}}\r\n' + txt.value;	// not found so insert new template at top of wikitext
		return;																	// and done
	}

// step 3: rewrite existing canonical templates; add or refresh |date= to current month year; preserve |cs1-dates= as is
	regex(/(\{\{use (?:dmy|mdy) dates)\| *date *=[^\|]*\| *cs1\-dates *= *([^\|\}]*?) *\}\}/gi, '$1|date=' + curryyyymm + '|cs1-dates=$2}}');	// with |date= followed by |cs1-dates=
	regex(/(\{\{use (?:dmy|mdy) dates)\| *cs1\-dates *= *([^\|\}]*?) *\| *date *=[^\}]*\}\}/gi, '$1|date=' + curryyyymm + '|cs1-dates=$2}}');	// with |cs1-dates= followed by |date=
	regex(/(\{\{use (?:dmy|mdy) dates)\| *date *=[^\|\}]*\}\}/gi, '$1|date=' + curryyyymm + '}}');												// with |date=
	regex(/(\{\{use (?:dmy|mdy) dates)\| *cs1\-dates *= *([^\|\}]*?) \}\}/gi, '$1|date=' + curryyyymm + '|cs1-dates=$2}}');						// with |cs1-dates
	regex(/(\{\{use (?:dmy|mdy) dates)\}\}/gi, '$1|date=' + curryyyymm + '}}');																	// no parameters so add |date=curryyyymm 
	regex(/(\{\{[\t_ ]*use[\t_ ]+(?:dmy|mdy)[\t_ ]+dates[^{}]*\}\})([\r\n\t ]*)(\{\{[\t ]*short description[^{}]*\}\})/gi, '$3$2$1');			// repositioning "short description" template at the top
}



/** ------------------------------------------------------------------------ **/
/// DATE PROTECTION

var linkmap = [];

function ohc_protect_dates()
{
	// protects dates within links, quotes, etc
	// the sensitive part is stored and replaced with a unique identifier,
	// which is later replaced with the stored part.
 
	var protect_function = function(s, begin, replace, end) {
		linkmap.push(replace);
		return begin + "⍌"+(linkmap.length-1)+"⍍" + end;
	};
//\|x=
	regex(/(<timeline>)([\s\S]*?)(<\/timeline>)/gi, protect_function);
	regex(/(<!--)([^<\{\}]*?)(-->)/gi, protect_function);
	regex(/(<math>)([\s\S]*?)(<\/math>)/gi, protect_function);
	regex(/((?:{(?:Wikimedia |)Commons ?|C ?))(Cat(?:egory|))\|[^{}*](})/gi, protect_function);
	regex(/(<ref)([^>]+)(>)/gi, protect_function);
	regex(/((?:Category|Image|File):)([^|\]]*)([|\]])/gi, protect_function);
	regex(/(\{(?:See ?also|Main))(\|[^}]*)(\})/gi, protect_function);
	regex(/(\{\{(?:double ?|external ?|wide ?)image\s?\|)([^}]+)(\})/gi, protect_function);
	regex(/(\{\{(?:harvnb|r|wikisource)\|)([^}]+)(\})/gi, protect_function);
	regex(/(\{\{(?:Canadian federal by-election))([^}]+)(\}\})/gi, protect_function);
	
	regex(/(\[(?:https?:|ftp:))([^\]]*)(\])/gi, protect_function);
	regex(/(>[ ]*(?:https?:|ftp:))([^< >\]]*)([ ]*<)/gi, protect_function);
//	regex(/(https?:|ftp:)([^\s\]]*)([\s\]])/gi, protect_function);
	regex(/(<blockquote>)([\s\S]*?)(<\/blockquote>)/gi, protect_function);
	regex(/(<noinclude>)([\s\S]*?)(<\/noinclude>)/gi, protect_function);
	regex(/(<gallery)([\s\S]*?)(<\/gallery>)/gi, protect_function);
	regex(/(<poem>)([\s\S]*?)(<\/poem>)/gi, protect_function);
	regex(/(\{[^\{]{0,6}(?:quot[^|]{1,7}\s?|sic)\|)([^}]+)(\})/gi, protect_function);
	regex(/((?:image\d?|image_skyline|image[ _]location\d?|image[ _]name|image[ _]file|img|map\d|pic)\s*=)([^|}]*)([|}])/gi, protect_function);
	regex(/([\|\{]\s*(?:file(?:name\d?|)|image\d?|image location\d?|img|pic|Cover|(?:trans-?|)title|quote|chapter|journal|url|archiveurl|work|doi|club|at|volume|reporter)\s*=)([^|\}⍍]*)([|}])/gi, protect_function);
	regex(/([\|\{]\s*(?:file(?:name\d?|)|image\d?|image location\d?|img|pic|Cover|(?:trans-?|)title|quote|chapter|journal|url|archiveurl|work|doi|club|at|volume|reporter)\s*=)([^|\}⍍]*)([|}])/gi, protect_function);
	regex(/([\|\{]\s*(?:season)\s*=)(\s*\[\[[^\]]*\]\]\s*)([|}])/gi, protect_function);
	regex(/([\|\{]\s*(?:[xy])\s*=)(\s*[^\|]+\s*)(\|)/gi, protect_function);
	regex(/(\{\{navsource\|)([^}]+)(\})/gi, protect_function);
	regex(/(\{\{(?:singlechart)\|)([^}]+)(\})/gi, protect_function);
	regex(/(\{\{(?:defaultsort|graph):)([^}]+)(\})/gi, protect_function);
	regex(/(["“])([^"”\n]*)(["”])/gi, protect_function);
	regex(/(.)(\(\{\{by\|[12]\d{3}\}\}[-–]\{\{by\|)([12]\d{3}[ ]*\}\}\))/gi, protect_function);
	regex(/(.)(\(\{\{by\|[12]\d{3}\}\}(?:[-–]present|))(\))/gi, protect_function);
	regex(/(\[\[)(4AD)(\]\]|\|)/gi, protect_function);

	//retraining redirects containing a date
	regex(/(\[\[)(?:সেপ্টেম্বর 3 Society)(\]\]|\|)/gi, '$1Jiusan Society$2');
	regex(/(\[\[)(?:জুন 4th incident)(\]\]|\|)/gi, '$1Tiananmen Square protests of 1989$2');
	regex(/(\[\[)(?:5@th? অক্টোবর (?:\(Serbia\)|overthrow))(\]\]|\|)/gi, '$1Overthrow of Slobodan Milošević$2');
	regex(/(\[\[)(?:অক্টোবর 5@th?(?: \(Serbia\)| overthrow|, 2000))(\]\]|\|)/gi, '$1Overthrow of Slobodan Milošević$2');

	//protect alternate meanings of 'মে' and 'মার্চ' (note: not case insensitive)
//	ohc_regex(/([^\w])(@day,?\s{0,3}মে)([^\w][^\d])/g, protect_function);  //disabled 26 মে – not case senstitve: false negatives in converting dates in মে
	ohc_regex(/([^\w])(মার্চ\s@day)(\s(?:mile|kilomet|met))/g, protect_function);

	//protect all links containing a date and some text
	ohc_regex(/(\[\[)(\s*\w[^\]\|\n]+?@day[^\]\|\n]+?@fullmonth[^\]\|\n]*)(\]\]|\|)/gi, protect_function);
	ohc_regex(/(\[\[)([^\]\|\n]*?@day[^\]\|\n]+?@fullmonth(?:,? @year|) \D[^\]\|\n]+\w\s*)(\]\]|\|)/gi, protect_function);
	ohc_regex(/(\[\[)(\s*\w[^\]\|\n]+?@fullmonth[^\]\|\n]+?@day[^\]\|\n]*)(\|)/gi, protect_function);
	ohc_regex(/(\[\[)([^\]\|\n]*?@fullmonth[^\]\|\n]+?@day(?:, @year|) \D[^\]\|\n]+\w\s*)(\]\]|\|)/gi, protect_function);

	//protects certain dates
	regex(/(\[\[)(4AD)([\s\S])/gi, protect_function);
	regex(/([\s\S])(মার্চ (?:8|14) Alliance)([\s\S])/gi, protect_function);
	regex(/([\s\S])(23rd মার্চ 1931: Shaheed)([\s\S])/gi, protect_function);
	regex(/([\s\S])(Long মার্চ [1-7])([\s\S])/gi, protect_function);
	regex(/([\s\S])(National সেপ্টেম্বর 11 Memorial & Museum)([\s\S])/gi, protect_function);
	regex(/([\s\S])(Queen Elizabeth II সেপ্টেম্বর 11th Garden)([\s\S])/gi, protect_function);
	regex(/([\s\S])(Bombay মার্চ 12)([\s\S])/gi, protect_function);
	regex(/([\s\S])(movement 2 জুন)([\s\S])/gi, protect_function);
	regex(/([\s\S])(6th\sof অক্টোবর City)([\s\S])/gi, protect_function);
	regex(/([\s\S])(Party Workers' Liberation Front 30th of মে)([\s\S])/gi, protect_function);
	regex(/([\s\S])(4th\sof আগষ্ট regime)([\s\S])/gi, protect_function);
	regex(/([\s\S])(19th\sof এপ্রিল movement)([\s\S])/gi, protect_function);
	regex(/([\s\S])(জুন 4th (?:incident|museum))([\s\S])/gi, protect_function);
	regex(/([\s\S])(The Battle Of Marston Moor \(জুলাই 2nd,? 1644\))([\s\S])/gi, protect_function);
	regex(/([\s\S])(Night of জানুয়ারি 16th)([\s\S])/gi, protect_function);
	regex(/([\s\S])(Observance of 5th নভেম্বর Act)([\s\S])/gi, protect_function);
	regex(/(\[\[)(13 মে incident)(\|)/gi, protect_function);
	regex(/(\'\'\')(22nd\sof মে)(\'\'\')/gi, protect_function);
	regex(/(\[\[)(22nd\sof মে \(film\))([|\]\'])/gi, protect_function);
	regex(/(\[\[)(জুলাই 12, 2007, Baghdad airstrike)(\|)/gi, protect_function);
	
	regex(/(\[\[)(নভেম্বর 1828)(\]\])/gi, protect_function);
	regex(/(.)(4th\sof জুলাই)(.)/gi, protect_function);
	regex(/(\[\[)((?:2300|2000)\s?AD)(\]\])/gi, protect_function);
	regex(/(\[\[)(29 ফেব্রুয়ারি)(\]\])/gi, protect_function);
	regex(/(\[\[)(ফেব্রুয়ারি 29)(\]\])/gi, protect_function);

	// works names
//	regex(/(.)(protect string)(.)/gi, protect_function);
	regex(/(.)(11\/22\/63)(.)/gi, protect_function);
	regex(/(.)(1\.1\.1994)(.)/gi, protect_function);
	regex(/([\s\S])(2\.13\.61)([\s\S])/gi, protect_function);
//	regex(/(.)(4th of জুলাই, Asbury)(.)/gi, protect_function); //protected above globally
	regex(/(.)(26 অক্টোবর 1993)(.)/gi, protect_function);
	regex(/(\[\[|\'\')(জুন 1, 1974)(.)/gi, protect_function);
	regex(/(\[\[|\'\')(জুলাই 15, 1972)(.)/gi, protect_function);
	regex(/(\[\[|\'\')(আগষ্ট 1914)(.)/gi, protect_function);
	ohc_regex(/(\[\[|\'\')(@fullmonth @dd@th? \((?:@yyyy |)film\)(?:\|@fullmonth @dd@th?|))([\s\S])/gi, protect_function);
	ohc_regex(/(\[\[|\'\')(@dd@th? @fullmonth \((?:@yyyy |)film\)(?:\|@dd@th? @fullmonth|))([\s\S])/gi, protect_function);
//	regex(/(Les Bains Douches 18)( ডিসেম্বর 1979)(.)/gi, protect_function);
	regex(/(আগষ্ট)( 7, 4:15)(.)/gi, protect_function);
	regex(/(In Concert, Zürich, অক্টোবর)( 28, 1979)(.)/gi, protect_function);
	regex(/(CBGB OMFUG Masters: Live জুন)( 29, 2001)(.)/gi, protect_function);
	ohc_regex(/(Live at [\w ]*,? [1-3]\d)( @fullmonth)(.)/gi, protect_function);
	ohc_regex(/(Live at [\w ]*,? @fullmonth)( @dd)(.)/gi, protect_function);
	ohc_regex(/(Bootmoon Series: [\w ]*[-–] @fullmonth)( @day, @YYYY)(.)/gi, protect_function);

// expressions and grammatical strings including modal "মে"
	regex(/(\W)((?:\d{1,3}) মে)((?: have(?: \w+|)|) be)/g, protect_function);
	regex(/(\W)((?:\d{3}|3[2-9]|[4-9]\d)\/\d ডিসেম্বর(?:l\.?|))(\W)/gi, protect_function);
	regex(/(\W)((?:\d{2,3})\/\d ডিসেম্বর(?:l\.?|))( \(\d\d? overs)/gi, protect_function);
}

/** ------------------------------------------------------------------------ **/
/// DATE PROTECTION FOR ALL REF SECTION

var linkmap = [];

function ohc_protect_dates_ref() 
{
	// protects dates within links, quotes, etc
	// the sensitive part is stored and replaced with a unique identifier,
	// which is later replaced with the stored part.

	var protect_function = function (s, begin, replace, end) {
		linkmap.push(replace);
		return begin + "⍌" + (linkmap.length - 1) + "⍍" + end;
	};

	regex(/(<ref\s?(?:>|name=[^>]+))([^<]+)(<\/ref>)/gi, protect_function);
	regex(/(<timeline>)([\s\S]*?)(<\/timeline>)/gi, protect_function);
	regex(/(<math>)([\s\S]*?)(<\/math>)/gi, protect_function);
	regex(/((?:{(?:Wikimedia |)Commons ?|C ?))(Cat(?:egory|))\|[^{}*](})/gi, protect_function);
	regex(/((?:Category|Image|File):)([^|\]]*)([|\]])/gi, protect_function);
	regex(/(\{(?:See ?also|Main))(\|[^}]*)(\})/gi, protect_function);
	regex(/(\{\{(?:double ?|external ?|wide ?)image\s?\|)([^}]+)(\})/gi, protect_function);
	regex(/(\{\{(?:harvnb|wikisource)\|)([^}]+)(\})/gi, protect_function);
	regex(/(\[(?:https?:|ftp:))([^\]]*)(\])/gi, protect_function);
	regex(/(>[ ]*(?:https?:|ftp:))([^< >\]]*)([ ]*<)/gi, protect_function);
	//regex(/(https?:|ftp:)([^\s\]]*)([\s\]])/gi, protect_function);
	regex(/(<blockquote>)([\s\S]*?)(<\/blockquote>)/gi, protect_function);
	regex(/(\{[^\{]{0,6}(?:quot[^|]{1,7}\s?|sic)\|)([^}]+)(\})/gi, protect_function);
	regex(/((?:image\d?|image_skyline|image[ _]location\d?|image[ _]name|image[ _]file|img|pic)\s*=)([^|}]*)([|}])/gi, protect_function);
	regex(/([\|\{]\s*(?:file(?:name\d?|)|image\d?|image location\d?|img|pic|Cover|title|quote|chapter|journal|url|archiveurl|work|doi|club|at|volume|reporter)\s*=)([^|\}⍍]*)([|}])/gi, protect_function);
	regex(/([\|\{]\s*(?:file(?:name\d?|)|image\d?|image location\d?|img|pic|Cover|title|quote|chapter|journal|url|archiveurl|work|doi|club|at|volume|reporter)\s*=)([^|\}⍍]*)([|}])/gi, protect_function);
	regex(/([\|\{]\s*(?:season)\s*=)(\s*\[\[[^\]]*\]\]\s*)([|}])/gi, protect_function);
	regex(/(\{\{navsource\|)([^}]+)(\})/gi, protect_function);
	regex(/(\{\{singlechart\|)([^}]+)(\})/gi, protect_function);
	regex(/(\{\{defaultsort:)([^}]+)(\})/gi, protect_function);
	regex(/([\s\(>]")([^"\n]*)(")/gi, protect_function);
	regex(/([\s\(>]“)([^”\n]*)(”)/gi, protect_function);
	regex(/(.)(\(\{\{by\|[12]\d{3}\}\}[-–]\{\{by\|)([12]\d{3}[ ]*\}\}\))/gi, protect_function);
	regex(/(.)(\(\{\{by\|[12]\d{3}\}\}(?:[-–]present|))(\))/gi, protect_function);

	//retraining redirects containing a date
	regex(/(\[\[)(?:সেপ্টেম্বর 3 Society)(\]\]|\|)/gi, '$1Jiusan Society$2');
	regex(/(\[\[)(?:জুন 4th incident)(\]\]|\|)/gi, '$1Tiananmen Square protests of 1989$2');
	ohc_regex(/(\[\[)(?:5@th? অক্টোবর (?:\(Serbia\)|overthrow))(\]\]|\|)/gi, '$1Overthrow of Slobodan Milošević$2');
	ohc_regex(/(\[\[)(?:অক্টোবর 5@th?(?: \(Serbia\)| overthrow|, 2000))(\]\]|\|)/gi, '$1Overthrow of Slobodan Milošević$2');

	//protect alternate meanings of 'মে' and 'মার্চ' (note: not case insensitive)
	ohc_regex(/([^\w])(@day,?\s{0,3}মে)([^\w][^\d])/g, protect_function);
	ohc_regex(/([^\w])(মার্চ\s@day)(\s(?:mile|kilomet|met))/g, protect_function);

	//protect all links containing a date and some text
	ohc_regex(/(\[\[)(\s*\w[^\]\|\n]+?@day[^\]\|\n]+?@fullmonth[^\]\|\n]*)(\]\]|\|)/gi, protect_function);
	ohc_regex(/(\[\[)([^\]\|\n]*?@day[^\]\|\n]+?@fullmonth(?:,? @year|) \D[^\]\|\n]+\w\s*)(\]\]|\|)/gi, protect_function);
	ohc_regex(/(\[\[)(\s*\w[^\]\|\n]+?@fullmonth[^\]\|\n]+?@day[^\]\|\n]*)(\|)/gi, protect_function);
	ohc_regex(/(\[\[)([^\]\|\n]*?@fullmonth[^\]\|\n]+?@day(?:, @year|) \D[^\]\|\n]+\w\s*)(\]\]|\|)/gi, protect_function);

	//protects certain dates
	regex(/(\[\[)(4AD)([\s\S])/gi, protect_function);
	regex(/([\s\S])(মার্চ (?:8|14) Alliance)([\s\S])/gi, protect_function);
	regex(/([\s\S])(23rd মার্চ 1931: Shaheed)([\s\S])/gi, protect_function);
	regex(/([\s\S])(Long মার্চ [1-7])([\s\S])/gi, protect_function);
	regex(/([\s\S])(Bombay মার্চ 12)([\s\S])/gi, protect_function);
	regex(/([\s\S])(movement 2 জুন)([\s\S])/gi, protect_function);
	regex(/([\s\S])(6th\sof অক্টোবর City)([\s\S])/gi, protect_function);
	regex(/([\s\S])(Party Workers' Liberation Front 30th of মে)([\s\S])/gi, protect_function);
	regex(/([\s\S])(4th\sof আগষ্ট regime)([\s\S])/gi, protect_function);
	regex(/([\s\S])(19th\sof এপ্রিল movement)([\s\S])/gi, protect_function);
	regex(/([\s\S])(জুন 4th incident)([\s\S])/gi, protect_function);
	regex(/([\s\S])(The Battle Of Marston Moor \(জুলাই 2nd,? 1644\))([\s\S])/gi, protect_function);
	regex(/([\s\S])(Night of জানুয়ারি 16th)([\s\S])/gi, protect_function);
	regex(/([\s\S])(Observance of 5th নভেম্বর Act)([\s\S])/gi, protect_function);
	regex(/(\[\[)(13 মে incident)(\|)/gi, protect_function);
	regex(/(\'\'\')(22nd\sof মে)(\'\'\')/gi, protect_function);
	regex(/(\[\[)(22nd\sof মে \(film\))([|\]\'])/gi, protect_function);
	regex(/(\[\[)(জুলাই 12, 2007, Baghdad airstrike)(\|)/gi, protect_function);
	
	regex(/(\[\[)(নভেম্বর 1828)(\]\])/gi, protect_function);
	regex(/(.)(4th\sof জুলাই)(.)/gi, protect_function);
	regex(/(\[\[)((?:2300|2000)\s?AD)(\]\])/gi, protect_function);
	regex(/(\[\[)(29 ফেব্রুয়ারি)(\]\])/gi, protect_function);
	regex(/(\[\[)(ফেব্রুয়ারি 29)(\]\])/gi, protect_function);

	// works names
	//regex(/(.)(protect string)(.)/gi, protect_function);
	regex(/(.)(11\/22\/63)(.)/gi, protect_function);
	regex(/(.)(1\.1\.1994)(.)/gi, protect_function);
	regex(/([\s\S])(2\.13\.61)([\s\S])/gi, protect_function);
	//regex(/(.)(4th of জুলাই, Asbury)(.)/gi, protect_function); //protected above globally
	regex(/(.)(26 অক্টোবর 1993)(.)/gi, protect_function);
	regex(/(\[\[|\'\')(জুন 1, 1974)(.)/gi, protect_function);
	regex(/(\[\[|\'\')(জুলাই 15, 1972)(.)/gi, protect_function);
	regex(/(\[\[|\'\')(আগষ্ট 1914)(.)/gi, protect_function);
	ohc_regex(/(\[\[|\'\')(@fullmonth @dd@th? \((?:@yyyy |)film\)(?:\|@fullmonth @dd@th?|))([\s\S])/gi, protect_function);
	ohc_regex(/(\[\[|\'\')(@dd@th? @fullmonth \((?:@yyyy |)film\)(?:\|@dd@th? @fullmonth|))([\s\S])/gi, protect_function);
	//regex(/(Les Bains Douches 18)( ডিসেম্বর 1979)(.)/gi, protect_function);
	regex(/(আগষ্ট)( 7, 4:15)(.)/gi, protect_function);
	regex(/(In Concert, Zürich, অক্টোবর)( 28, 1979)(.)/gi, protect_function);
	regex(/(CBGB OMFUG Masters: Live জুন)( 29, 2001)(.)/gi, protect_function);
	ohc_regex(/(Live at [\w ]*,? [1-3]\d)( @fullmonth)(.)/gi, protect_function);
	ohc_regex(/(Live at [\w ]*,? @fullmonth)( @dd)(.)/gi, protect_function);
	ohc_regex(/(Bootmoon Series: [\w ]*[-–] @fullmonth)( @day, @YYYY)(.)/gi, protect_function);

	regex(/(\W)((?:\d{3}|3[2-9]|[4-9]\d)\/\d ডিসেম্বর(?:l\.?|))(\W)/gi, protect_function);
	regex(/(\W)((?:\d{2,3})\/\d ডিসেম্বর(?:l\.?|))( \(\d\d? overs)/gi, protect_function);
}


/** ------------------------------------------------------------------------ **/
/// DATE PROTECTION FOR SLASH modules

var linkmap = [];

function ohc_protect_dates_slash() 
{
	// protects dates within links, quotes, etc
	// the sensitive part is stored and replaced with a unique identifier,
	// which is later replaced with the stored part.

	var protect_function = function (s, begin, replace, end) {
		linkmap.push(replace);
		return begin + "⍌" + (linkmap.length - 1) + "⍍" + end;
	};

	regex(/(<ref\s?(?:>|name=[^>]+))([^<]+)(<\/ref>)/gi, protect_function);
	regex(/(<timeline>)([\s\S]*?)(<\/timeline>)/gi, protect_function);
	regex(/(<math>)([\s\S]*?)(<\/math>)/gi, protect_function);
	regex(/((?:{(?:Wikimedia |)Commons ?|C ?))(Cat(?:egory|))\|[^{}*](})/gi, protect_function);
	regex(/((?:Category|Image|File):)([^|\]]*)([|\]])/gi, protect_function);
	regex(/(\{(?:See ?also|Main))(\|[^}]*)(\})/gi, protect_function);
	regex(/(\{\{(?:double ?|external ?|wide ?)image\s?\|)([^}]+)(\})/gi, protect_function);
	regex(/(\{\{(?:harvnb|wikisource)\|)([^}]+)(\})/gi, protect_function);
	regex(/(\[(?:https?:|ftp:))([^\]]*)(\])/gi, protect_function);
	regex(/(>[ ]*(?:https?:|ftp:))([^< >\]]*)([ ]*<)/gi, protect_function);
	//regex(/(https?:|ftp:)([^\s\]]*)([\s\]])/gi, protect_function);
	regex(/(<blockquote>)([\s\S]*?)(<\/blockquote>)/gi, protect_function);
	regex(/(\{[^\{]{0,6}(?:quot[^|]{1,7}\s?|sic)\|)([^}]+)(\})/gi, protect_function);
	regex(/((?:image\d?|image_skyline|image[ _]location\d?|image[ _]name|image[ _]file|img|pic)\s*=)([^|}]*)([|}])/gi, protect_function);
	regex(/([\|\{]\s*(?:file(?:name\d?|)|image\d?|image location\d?|img|pic|Cover|title|quote|chapter|journal|url|archiveurl|work|doi|club|at|volume|reporter)\s*=)([^|\}⍍]*)([|}])/gi, protect_function);
	regex(/([\|\{]\s*(?:file(?:name\d?|)|image\d?|image location\d?|img|pic|Cover|title|quote|chapter|journal|url|archiveurl|work|doi|club|at|volume|reporter)\s*=)([^|\}⍍]*)([|}])/gi, protect_function);
	regex(/([\|\{]\s*(?:season)\s*=)(\s*\[\[[^\]]*\]\]\s*)([|}])/gi, protect_function);
	regex(/(\{\{navsource\|)([^}]+)(\})/gi, protect_function);
	regex(/(\{\{singlechart\|)([^}]+)(\})/gi, protect_function);
	regex(/(\{\{defaultsort:)([^}]+)(\})/gi, protect_function);
	regex(/([\s\(>]")([^"\n]*)(")/gi, protect_function);
	regex(/([\s\(>]“)([^”\n]*)(”)/gi, protect_function);
	regex(/(.)(\(\{\{by\|[12]\d{3}\}\}[-–]\{\{by\|)([12]\d{3}[ ]*\}\}\))/gi, protect_function);
	regex(/(.)(\(\{\{by\|[12]\d{3}\}\}(?:[-–]present|))(\))/gi, protect_function);

}

function ohc_unprotect_dates() 
{
	//unprotect all dates
	regex(/[♫]/g, '');
	regex(/⍌([0-9]+)⍍/g, function (x, n) {
		var res = linkmap[n];
		res = res.replace(/⍌([0-9]+)⍍/g, function (x, n) {
			var res = linkmap[n];
			res = res.replace(/⍌([0-9]+)⍍/g, function (x, n) {
				var res = linkmap[n];
				res = res.replace(/⍌([0-9]+)⍍/g, function (x, n) {
					return linkmap[n];
				});
				return res;
			});
			return res;
		});
		return res;
	});
}

function ohc_MOSNUM_edit_summary() 
{
	//Add a tag to the summary box
	setoptions(minor = 'true');
	setreason('date formats per [[MOS:DATEFORMAT]] by [[WP:MOSNUMscript|script]]', 'append');
	doaction('diff');
}

function ohc_bigendien_edit_summary() 
{
	//Add a tag to the summary box
	setoptions(minor = 'true');
	setreason('ymd ref dates', 'append');
	doaction('diff');
}

function ohc_expand_edit_summary() 
{
	//Add a tag to the summary box
	setoptions(minor = 'true');
	setreason('expand month names', 'append');
	doaction('diff');
}

function ohc_slash_edit_summary() 
{
	//Add a tag to the summary box
	setoptions(minor = 'true');
	setreason('resolved slash dates', 'append');
	doaction('diff');
}

function ohc_abbrev_edit_summary() 
{
	//Add a tag to the summary box
	setoptions(minor = 'true');
	setreason('abbrev month names', 'append');
	doaction('diff');
}

/** ------------------------------------------------------------------------ **/
/// CUSTOMIZATION POINTS
function ohc_customize_all_to_dmy() {
}

function ohc_customize_all_to_mdy() {
}

function ohc_customize_body_to_dmy() {
}

function ohc_customize_body_to_mdy() {
}

function ohc_customize_ISO_to_dmy() {
}

function ohc_customize_ISO_to_mdy() {
}

/** ------------------------------------------------------------------------ **/
function ohc_body_dates_to_dmy() 
{
	ohc_use_dates_template('dmy');

	ohc_fix_common_errors();
	ohc_fix_dts_template('dmy');
	ohc_fix_gr_template('dmy');
	ohc_dates_to_dmy();
	ohc_remove_leading_zeroes();
	ohc_fix_dmy_redundancies();
}

function ohc_body_dates_to_mdy() 
{
	ohc_use_dates_template('mdy');
	ohc_fix_common_errors();
	ohc_fix_dts_template('mdy');
	ohc_fix_gr_template('mdy');
	ohc_dates_to_mdy();
	ohc_remove_leading_zeroes();
	ohc_fix_mdy_redundancies();
}

/** ------------------------------------------------------------------------ **/
function ohc_all_to_dmy_driver(e) 
{
	e.preventDefault();
	ohc_delink_dates();
	ohc_protect_dates();
	ohc_fix_unambiguous_dates();
	ohc_body_dates_to_dmy();
	ohc_delink_ISO_to_dmy();
	ohc_delink_year_in_X();
	ohc_customize_all_to_dmy();
	ohc_ISO_to_dmy_in_citations();
	ohc_unprotect_dates();

	ohc_MOSNUM_edit_summary();
}

function ohc_all_to_mdy_driver(e) 
{
	e.preventDefault();
	ohc_delink_dates();
	ohc_protect_dates();
	ohc_fix_unambiguous_dates();
	ohc_body_dates_to_mdy();
	ohc_delink_ISO_to_mdy();
	ohc_delink_year_in_X();
	ohc_customize_all_to_mdy();
	ohc_ISO_to_mdy_in_citations();
	ohc_unprotect_dates();

	ohc_MOSNUM_edit_summary();
}

function ohc_dmy_publication_dates_driver(e) 
{
	e.preventDefault();
//	ohc_delink_dates();
	ohc_protect_dates();
	ohc_body_dates_to_dmy();
	ohc_customize_body_to_dmy();
	ohc_dmy_publication_dates();
	ohc_unprotect_dates();

	ohc_MOSNUM_edit_summary();
}

function ohc_mdy_publication_dates_driver(e) 
{
	e.preventDefault();
//	ohc_delink_dates();
	ohc_protect_dates();
	ohc_body_dates_to_mdy();
	ohc_customize_body_to_mdy();
	ohc_mdy_publication_dates();
	ohc_unprotect_dates();

	ohc_MOSNUM_edit_summary();

}

function ohc_body_to_dmy_driver(e) 
{
	e.preventDefault();
//	ohc_delink_dates();
	ohc_protect_dates_ref();
	ohc_body_dates_to_dmy();
	ohc_customize_body_to_dmy();
	ohc_unprotect_dates();

	ohc_MOSNUM_edit_summary();
}

function ohc_body_to_mdy_driver(e) 
{
	e.preventDefault();
//	ohc_delink_dates();
	ohc_protect_dates_ref();
	ohc_body_dates_to_mdy();
	ohc_customize_body_to_mdy();
	ohc_unprotect_dates();

	ohc_MOSNUM_edit_summary();
}

function ohc_ISO_to_dmy_driver(e) 
{
	e.preventDefault();
	ohc_protect_dates();
	ohc_delink_ISO_to_dmy();
	ohc_customize_ISO_to_dmy();
	ohc_unprotect_dates();

//	ohc_MOSNUM_edit_summary();
}

function ohc_ISO_to_mdy_driver(e) {
	e.preventDefault();
	ohc_protect_dates();
	ohc_delink_ISO_to_mdy();
	ohc_customize_ISO_to_mdy();
	ohc_unprotect_dates();

//	ohc_MOSNUM_edit_summary();
}

function ohc_delink_year_in_X_driver(e) 
{
	e.preventDefault();
	ohc_delink_year_in_X();
}

function ohc_expand_ref_dates_driver(e) {
	e.preventDefault();
	ohc_expand_ref_dates();
	ohc_protect_dates();
	ohc_unprotect_dates();
	ohc_expand_edit_summary();
}

function ohc_expand_all_dates_driver(e) 
{
	e.preventDefault();
	ohc_expand_ref_dates();
	ohc_protect_dates();
	ohc_expand_all_dates();
	ohc_unprotect_dates();
	ohc_expand_edit_summary();
}

function ohc_abbrev_ref_dates_driver(e) 
{
	e.preventDefault();
	ohc_protect_dates();
	ohc_abbrev_ref_dates();
	ohc_unprotect_dates();
	ohc_slash_edit_summary();
}

function ohc_UK_slash_dates_driver(e) 
{
	e.preventDefault();
	ohc_expand_ref_dates();
	ohc_protect_dates_slash();
		ohc_UK_slash_dates_to_dmy();
	ohc_unprotect_dates();
	ohc_slash_edit_summary();
}

function ohc_US_slash_dates_driver(e) 
{
	e.preventDefault();
	ohc_expand_ref_dates();
	ohc_protect_dates_slash();
		ohc_US_slash_dates_to_mdy();
	ohc_unprotect_dates();
	ohc_expand_edit_summary();
}

// </pre>

//সংশ্লিষ্ট পাতা ত্যাগ না করেই অন্য পাতা থেকে পুনর্নির্দেশ করা যাবে।
//<nowiki>
( function () {
	var redir = $(mw.util.addPortletLink('p-tb','#','পুনর্নির্দেশক','পুনর্নির্দেশ তৈরিকারী','পুনর্নির্দেশ তৈরিকারী','','#pt-mytalk'));
	$( redir ).click( function() {
			var redirec = prompt("যে পাতা থেকে এই পাতায় পুনর্নির্দেশ করতে চান তার নাম লিখুন:", "");
		  if (redirec === null || redirec === "") {
				alert( 'আপনি কোনও নাম প্রবেশ করান নি। দয়া করে আবার চেষ্টা করুন।' );	  
		  } else  {
			   var params = {
					action: 'edit',
					title: redirec ,
					createonly: 1,
					prependtext: '#পুনর্নির্দেশ [[' + mw.config.get("wgPageName") + ']]',
					appendtext: " \n" + '{{একটি পুনর্নির্দেশ}}',
					summary: '[[' + mw.config.get("wgPageName") + ']] পাতায় পুনর্নির্দেশ করা হল' ,
					format: 'json'
				};
				api = new mw.Api();
			api.postWithToken( 'csrf', params ).done( function ( data ) {
				alert( 'সফলভাবে ' + redirec + ' পাতা থেকে একটি পুনর্নির্দেশ তৈরি করা হয়েছে!' );
			});
		  }
			}
	);
}() );
//</nowiki>

//<nowiki>
( function () {
	var talkp = $(mw.util.addPortletLink('p-tb','#','স্বাগত জানান','স্বাগত জানান','স্বাগত জানান','','#pt-mytalk'));
	$( talkp ).click( function() {
			var talk = prompt("কোন ধরনের স্বাগত বার্তা যুক্ত করতে চান এমন টেমপ্লেটটি লিখুন {{Subst:}} সাথে, অন্যথায় পূর্বনির্ধারিত {{Subst:স্বাগতম}} যুক্ত হবে:", "");
		  if (talk === null || talk === "") {
		    var params1 = {
					action: 'edit',
					title: 'User talk:' + mw.config.get("wgRelevantUserName"),
					prependtext: '{{Subst:স্বাগতম}}'
					,
					summary: 'ভারতপিডিয়ায় স্বাগতম!',
					format: 'json'
				};
				api = new mw.Api();
			
			api.postWithToken( 'csrf', params1 ).done( function ( data ) {
				alert( 'সফলভাবে স্বাগত জানানো হয়েছে!' );
			} );
		  
		  } else {
			   var params = {
					action: 'edit',
					title: 'User talk:' + mw.config.get("wgRelevantUserName"),
					prependtext: talk
					,
					summary: 'ভারতপিডিয়ায় স্বাগত!',
					format: 'json'
				};
				api = new mw.Api();
			
			api.postWithToken( 'csrf', params ).done( function ( data ) {
				alert( 'সফলভাবে স্বাগত জানানো হয়েছে!' );
			} );
		  }
			}
	);
}() );
//</nowiki>
//<nowiki>
console.time('mobileUndo');
$.when(mw.loader.using(['mediawiki.util', 'mediawiki.api', 'oojs-ui-windows', 'oojs-ui-core', 'oojs-ui.styles.icons-editing-core'])).then(function() {
    return new mw.Api().getMessages(['editundo', 'Undo-nochange']);
}).then(function(globalmessages) {
    var mobileUndo, i18n_lang = mw.config.get('wgUserLanguage');
    var i18n = {
        "en": {
            "mu-success": "Successful",
            "mu-fail": "Failed",
            "mu-loading": "Loading...",
            "editsummary-ad": "",
            "mu-undo-successful": "Revert successful.... Reloading in a sec",
            "mu-empty-reponse-from-server": "An empty response was received from the server",
            "mu-edit-summary-prompt": "Add a reason to your edit summary !",
            "mu-edit-summary-prompt-placeholder": "Reason...",
            "mu-thank-success": "Thanked",
            "mu-thank-confirm": "Send public thanks ?",
            "mu-thank-loading": "Thanking...",
            "mu-thank-successful": "You thanked $1.",
            "mu-thank-failed": "Failed to thank $1.",
            "mu-http-error":"HTTP error: "
        },
        "bn": {
            "mu-success": "সফল",
            "mu-fail": "ব্যর্থ হয়েছে",
            "mu-loading": "লোড করা হচ্ছে...",
            "editsummary-ad": "",
            "mu-undo-successful": "পূর্বাবস্থায় ফেরত যাওয়া সফল হয়েছে.... পুনঃলোড করা হচ্ছে",
            "mu-empty-reponse-from-server": "সার্ভার থেকে একটি খালি প্রতিক্রিয়া পাওয়া গেছে।",
            "mu-edit-summary-prompt": "সম্পাদনা সারাংশে কারণ উল্লেখ করুন!",
            "mu-edit-summary-prompt-placeholder": "কারণ...",
            "mu-thank-success": "ধন্যবাদ দিয়েছেন",
            "mu-thank-confirm": "প্রকাশ্য ধন্যবাদ জানাবেন?",
            "mu-thank-loading": "ধন্যবাদ জানানো হচ্ছে...",
            "mu-thank-successful": "আপনি $1 কে ধন্যবাদ জানিয়েছেন।",
            "mu-thank-failed": "$1 কে ধন্যবাদ জানানো ব্যর্থ হয়েছে।",
            "mu-http-error":"HTTP ত্রুটি: "
        }
    };
	if(undefined === i18n[i18n_lang]){
		i18n_lang = 'en';
	}
    if (mw.config.get('wgCanonicalSpecialPageName') === 'MobileDiff') {
        mw.util.addCSS('#mw-mf-userinfo .mobileUndo-ui .mw-ui-icon.mw-ui-icon-before:before{display:none;}\n#mobileUndo > a > span.oo-ui-iconElement-icon.oo-ui-icon-editUndo.oo-ui-image-invert{display:inline-block; position:initial;}\n#mobileUndo > a{padding:0.57142857em 0.9375em;}'+
        '#mw-mf-userinfo > div > div.mobileUndo-ui > a > div{line-height:normal;}');
        if (mw.config.get('wgVisualEditor').pageLanguageDir === 'ltr') {
            $('#mw-mf-userinfo .post-content').append($('<div>').attr('class', 'mobileUndo-ui').css({
                'display': 'inline-block',
                'float': 'right'
            }));
        } else {
            $('#mw-mf-userinfo .post-content').append($('<div>').attr('class', 'mobileUndo-ui').css({
                'display': 'inline-block',
                'float': 'left'
            }));
        }
        $('.mobileUndo-ui').append($('.mw-mf-action-button').remove().css({
            'clear': 'none'
        }));
        if (!$('.warningbox').length && mw.config.get('wgRelevantPageIsProbablyEditable')) {
            mobileUndo = new OO.ui.ButtonWidget({
                label: (globalmessages.editundo).charAt(0).toUpperCase() + (globalmessages.editundo).slice(1),
                icon: 'editUndo',
                title: 'mobileUndo',
                flags: ['destructive', 'primary'],
                id: 'mobileUndo'
            });
            $('.mobileUndo-ui').append(mobileUndo.$element);
            if (mw.config.get('wgVisualEditor').pageLanguageDir === 'ltr') {
                $('#mobileUndo').css('margin-right', '0.3em');
            } else {
                $('#mobileUndo').css('margin-left', '0.3em');
            }
        }
        window.wgRelevantUser = function() {
            var user;
            if ($('.mw-mf-user-link').text() !== '') {
                user = $('.mw-mf-user-link').text();
            } else {
                user = $('#mw-mf-userinfo .post-content div:nth-child(2)').text();
            }
            return user;
        };
        window.wgRevId = ($('#mw-mf-diffarea > div.mw-mf-diff-info > h3 > a').attr('href')).split('&oldid=')[1];
        var revId = wgRevId;
        console.log(revId);
        var username = wgRelevantUser();
        $('#mw-mf-userinfo .post-content .mobileUndo-ui .mw-mf-action-button').click(function(e) {
            e.preventDefault();
            OO.ui.confirm(i18n[i18n_lang]['mu-thank-confirm']).done(function(confirmed) {
                if (confirmed) {
                    $('.mw-mf-action-button').css('pointer-events', 'none').text(i18n[i18n_lang]['mu-thank-loading']);
                    var api = new mw.Api();
                    api.postWithToken('csrf', {
                        action: "thank",
                        rev: revId,
                    }).done(function(result) {
                        mw.notify((i18n[i18n_lang]['mu-thank-successful']).replace(/\$1/g, username));
                        $('.mw-mf-action-button').text(i18n[i18n_lang]['mu-thank-success']);
                    }).fail(function() {
                        mw.notify((i18n[i18n_lang]['mu-thank-failed']).replace(/\$1/g, username));
                        $('.mw-mf-action-button').text(i18n[i18n_lang]['mu-failed']);
                    });
                }
            });
        });
        console.timeEnd('mobileUndo');
        mobileUndo.on('click', function() {
            OO.ui.prompt(i18n[i18n_lang]['mu-edit-summary-prompt'], {
                textInput: {
                    placeholder: i18n[i18n_lang]['mu-edit-summary-prompt-placeholder'] 
                }
            }).done(function(customEditSummary) {
                $.when(mw.loader.using('mediawiki.api')).then(function() {
                    return new mw.Api().getMessages(['undo-summary'], {
                        amlang: mw.config.get('wgServerName').split('.wik')[0]
                    });
                }).then(function(message) {
                    var editSummaryMessage = message['undo-summary'];
                    var editSummary = editSummaryMessage.replace(/\$1/g, revId);
                    editSummary = editSummary.replace(/\$2/g, username);
                    if (customEditSummary !== null) {
                        mobileUndo.setDisabled(true);
                        editSummary = editSummary + ' ' + customEditSummary + (i18n[i18n_lang]['editsummary-ad']);
                        //call the API
                        var api = new mw.Api({
                            ajax: {
                                headers: {
                                    'Api-User-Agent': 'mobileUndo/2.0.2(https://en.wikipedia.org/wiki/User:FR30799386/undo.js)'
                                }
                            }
                        });
                        //Feedback UI
                        mobileUndo.setLabel(i18n[i18n_lang]['mu-loading']);
                        api.postWithToken('csrf', {
                            action: "edit",
                            title: mw.config.get('wgRelevantPageName'),
                            summary: editSummary,
                            undo: revId,
                        }).done(function(result) {
                            if (result.edit.code === 'abusefilter-warning' || result.edit.code === 'abusefilter-disallowed') {
                                mobileUndo.setLabel(i18n[i18n_lang]['mu-fail']);
                                OO.ui.alert($('<p>').html(result.edit.warning), {
                                    title: result.edit.info
                                }).done(function() {});
                                return;
                            } else if (typeof result.edit.nochange !== 'undefined') {
                                mobileUndo.setLabel(i18n[i18n_lang]['mu-fail']);
                                OO.ui.alert($('<p>').html(globalmessages['Undo-nochange'])).done(function() {});
                                return;
                            }
                            console.log(result);
                            mobileUndo.setLabel(i18n[i18n_lang]['mu-success']);
                            mw.notify(i18n[i18n_lang]['mu-undo-successful']);
                            setTimeout(function() {
                                location.href = mw.util.getUrl('Special:MobileDiff/' + result.edit.newrevid);
                            }, 1500);
                        }).fail(function(code, jqxhr) {
                            mobileUndo.setLabel(i18n[i18n_lang]['mu-fail']);
                            var details;
                            if (code === 'http' && jqxhr.textStatus === 'error') {
                                details = i18n[i18n_lang]['mu-http-error'] + jqxhr.xhr.status;
                            } else if (code === 'http') {
                                details = i18n[i18n_lang]['mu-http-error'] + jqxhr.textStatus;
                            } else if (code === 'ok-but-empty') {
                                details = i18n[i18n_lang]['mu-empty response-from-server'];
                            } else {
                                details = jqxhr.error.info;
                            }
                            OO.ui.alert($('<p>').html(details)).done(function() {});
                        });
                    }
                });
            });
        });
    }
});
//End of code
//</nowiki>
window.wgRelevantUser = function() {
    var user;
    	if ($('.mw-mf-user-link').text() !== '') {
        	user = $('.mw-mf-user-link').text();
    	} else {
        	user = $('#mw-mf-userinfo .post-content div:nth-child(2)').text();
    	}
    return user;
    };
var href = ($('#mw-mf-diffarea > div.mw-mf-diff-info > h3 > a').attr('href')) || '';
window.wgRevId = href.split('&oldid=')[1];
if( $('#mw-mf-diffarea > ul > li.revision-history-next').length ) {
	$('#mw-mf-diffarea > div.mw-mf-diff-info > h3').append(
		$('<a>').attr('id','mobileRestore').attr('href','javascript:void(0)').append(
			$('<b>').text('(পুনরুদ্ধার)')
		)
	);
}
$('#mobileRestore').click(function(e){
	e.preventDefault();
	$('#mobileRestore b').text('(লোড হচ্ছে....)');
	$('#mobileRestore').css('pointer-events','none');
	var customEditSummary = prompt('পুনরুদ্ধারের কারণ (ঐচ্ছিক)');
	if(customEditSummary === null) {
		$('#mobileRestore b').text('(পুনরুদ্ধার)');
		$('#mobileRestore').css('pointer-events','auto');
		return;
	}
	var username =wgRelevantUser();
	var editSummary = '[[Special:Contributions/'+username+'|'+username+']] ([[User talk:'+username+'|আলাপ]])-এর করা ' +wgRevId+ 'নং সংস্করণ পুনরুদ্ধার করা হয়েছে';
	editSummary = editSummary + customEditSummary + ' (পুনরুদ্ধারায়ন)';
	$.when(mw.loader.load('mediawiki.api')).then(function(){
		var api = new mw.Api();
		api.get({
			'action':'query',
			'prop':'revisions',
			'titles':mw.config.get('wgRelevantPageName'),
			'rvprop':'ids'
		}).done(function(result){
			if(result.query.pages) {
				var StartRevId = result.query.pages[mw.config.get('wgRelevantArticleId')].revisions[0].revid;
				console.log(StartRevId);
				api.postWithToken('csrf', {
                    action: "edit",
                    title: mw.config.get('wgRelevantPageName'),
                    summary: editSummary,
                    undo:StartRevId,
					undoafter:wgRevId,
                }).done(function(result) {
                    if (typeof result.edit.nochange !== 'undefined') {
                    	$('#mobileRestore b').text('(Failed)');
						alert( 'No change occured');
                        return;
                    }
					console.log(result);
					$('#mobileRestore b').text('(সফলভাবে হয়েছে)')
                    mw.notify('সংস্করণ পুনরুদ্ধার সফল হয়েছে.... পুনঃলোড করা হচ্ছে');
					setTimeout(function() {
                      location.href = mw.util.getUrl('Special:MobileDiff/' + result.edit.newrevid);
                    }, 1500);
                }).fail(function(code, jqxhr) {
                	$('#mobileRestore b').text('(পুনরুদ্ধার কার্য বাতিল করা হয়েছে)');
                    var details;
                    if (code === 'http' && jqxhr.textStatus === 'error') {
                        details = 'HTTP error: ' + jqxhr.xhr.status;
                    } else if (code === 'http') {
                        details = 'HTTP error: ' + jqxhr.textStatus;
                    } else if (code === 'ok-but-empty') {
                        details = 'An empty response was given the server';
                    } else {
                        details = jqxhr.error.info;
                    }
                    alert( details );
                });
			} else {
				alert('Failed to retrieve page details');
			}
		});
	});
});
if(mw.config.get('wgCanonicalSpecialPageName') === 'MobileDiff') {
	mw.loader.using('mediawiki.util', function() {
		var ele_a = document.createElement('a');
		ele_a.setAttribute('href', mw.util.getUrl(mw.config.get('wgRelevantPageName'), {action: 'history'}));
		ele_a.innerHTML = '(ইতিহাস)';
		document.getElementsByTagName('h2')[0].appendChild(ele_a);
	});
}

//my common.js
$.when(mw.loader.using(['mediawiki.util'], $.ready)).done( function() {
	mw.util.addPortletLink("p-tb", mw.config.get('wgArticlePath').replace('$1', "ব্যবহারকারী:রবি/common.js"), "common.js", "tb-awbscript", "Personal common.js");
});

if (mw.config.get('wgCanonicalNamespace')+':'+mw.config.get('wgTitle') === 'ব্যবহারকারী:রবি/common.js' && mw.config.get('wgAction') == 'view');

//শীর্ষক
(function($, mw) {
	var scrollDownButtonId = 'scrollDownButton',
		scrollUpButtonId = 'scrollUpButton';
	if (mw.config.get('wgServerName').match(/wikimirror\.org$/)) {
		scrollDownButtonId += '-zhwiki';
		scrollUpButtonId += '-zhwiki'
	}

	var scrollButtonIcon = '//upload.wikimedia.org/wikipedia/commons/7/7f/Font_Awesome_5_regular_arrow-circle-up_green.svg';
	if (!document.implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#Image', '1.1'))
		scrollButtonIcon = '//upload.wikimedia.org/wikipedia/commons/thumb/7/7f/Font_Awesome_5_regular_arrow-circle-up_green.svg/32px-Font_Awesome_5_regular_arrow-circle-up_green.svg.png';

	$scrollDownButton = $('<img>', {
		src: scrollButtonIcon,
		id: scrollDownButtonId
	}).css({
		cursor: 'pointer',
		opacity: 0.7,
		position: 'fixed',
		display: 'none',
		right: '18px',
		transform: 'rotate(180deg)',
		'-webkit-transform': 'rotate(180deg)',
		'-moz-transform': 'rotate(180deg)',
		'-o-transform': 'rotate(180deg)',
		'-ms-transform': 'rotate(180deg)'
	}).on('click', function() {
		$('html, body').animate({
			scrollTop: $(document).height() - $(window).height()
		}, 660)
	}).on('mouseenter mouseleave', function(e) {
		this.style.opacity = e.type === 'mouseenter' ? 1 : 0.7
	}).appendTo('body');

	$scrollUpButton = $('<img>', {
		src: scrollButtonIcon,
		id: scrollUpButtonId
	}).css({
		cursor: 'pointer',
		opacity: 0.7,
		position: 'fixed',
		display: 'none',
		right: '18px'
	}).on('click', function() {
		$('html, body').animate({
			scrollTop: 0
		}, 660)
	}).on('mouseenter mouseleave', function(e) {
		this.style.opacity = e.type === 'mouseenter' ? 1 : 0.7
	}).appendTo('body');

	var scrollButtonTimer;
	$(window).on('scroll', function() {
		var dingHeight = $('#bluedeck_ding>div').height() ? $('#bluedeck_ding>div').height() : 0;
		$('#mw-ge-help-panel-cta-button').length > 0 ? $scrollDownButton.css('bottom', dingHeight + 75 + 'px') && $scrollUpButton.css('bottom', dingHeight + 116 + 'px') : $scrollDownButton.css('bottom', dingHeight + 24 + 'px') && $scrollUpButton.css('bottom', dingHeight + 65 + 'px');
		$('#cat_a_lot').length > 0 || $('#proveit').length > 0 || $('.wordcount').length > 0 ? $scrollDownButton.css('left', '10px') && $scrollUpButton.css('left', '10px') : $scrollDownButton.css('left', 'unset') && $scrollUpButton.css('left', 'unset');
		$(this).scrollTop() > 60 ? $scrollDownButton.fadeIn('slow') && $scrollUpButton.fadeIn('slow') : $scrollDownButton.fadeOut('slow') && $scrollUpButton.fadeOut('slow');
		this.clearTimeout(scrollButtonTimer);
		scrollButtonTimer = this.setTimeout(function() {
			$scrollDownButton.fadeOut('slow');
			$scrollUpButton.fadeOut('slow')
		}, 2000)
	});
	$scrollDownButton.on('mouseenter', function() {
		window.clearTimeout(scrollButtonTimer)
	});
	$scrollUpButton.on('mouseenter', function() {
		window.clearTimeout(scrollButtonTimer)
	})
})(jQuery, mw);

/**
 * Add "Purge" content action link.
 *
 * Dependencies: mediawiki.util, mediawiki.api
 *
 * @source https://www.mediawiki.org/wiki/Snippets/Purge_action
 * @revision 2016-05-22
 */
$( function () {
	if ( $( '#ca-purge' ).length || !mw.config.get( 'wgIsArticle' ) ) return;
	var node = mw.util.addPortletLink(
		'p-cactions',
		mw.util.getUrl( null, { action: 'purge' } ),
		mw.config.get( 'skin' ) === 'vector' ? 'শোধন' : 'শোধন',
		'ca-purge',
		'এই পাতার সার্ভার ক্যাশে পরিস্কার করুন',
		'শোধন'
	);
	$(node).on( 'click', function (e) {
		new mw.Api().post( { action: 'purge', titles: mw.config.get( 'wgPageName' ) } ).then(function () {
			location.reload();
		}, function () {
			mw.notify( 'শোধন ব্যর্থ হয়েছে', { type: 'error' } );
		});
		e.preventDefault();
	});
});

//rollback confirmation
//<nowiki>
(function() {
	if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
		$(".mw-rollback-link").on('click', function(e) {
			var linkText = $(e.target).text(),
				count = linkText.match(/\d/) ? linkText.match(/\d+/)[0] : null,
				message = 'রোলব্যাক ' + 'করছেন ' + mw.util.getParamValue('from',e.target.href) + ' কতৃক সম্পাদিত ' + (count ? count + ' edits' : 'সম্পাদনা') + '?';
			if(!confirm(message)) return e.preventDefault();
		});
	}
}());
//</nowiki>

/** Quick Edit **/

// Edit sections of a page without leaving the article
// [[en:w:User:BrandonXLF/QuickEdit]]
// By [[en:w:User:BrandonXLF]]

(function() {
	var mobile = mw.config.get('skin') === 'minerva',
		apiSingleton,
		titleRegexp = new RegExp(
			mw.config.get('wgArticlePath').replace(/[.*+?^${}()|[\]\\]/g, '\\$&').replace(/\\\$1/, '([^?]+)') +
			'|[?&]title=([^&#]*)'
		);

	function api(func, params) {
		if (!apiSingleton) apiSingleton = new mw.Api();

		$.extend(params, {
			errorformat: 'html',
			errorlang: mw.config.get('wgUserLanguage'),
			errorsuselocal: true
		});

		return apiSingleton[func](params).fail(function(_, data) {
			mw.notify(apiSingleton.getErrorMessage(data), {
				type: 'error',
				tag: 'quickedit'
			});
		});
	}

	function getPageInfo(title, sectionID) {
		return api('get', {
			action: 'query',
			curtimestamp: 1,
			prop: 'revisions',
			indexpageids: 1,
			titles: title,
			rvprop: ['timestamp', 'content'],
			rvslots: 'main',
			rvsection: sectionID
		}).then(function(res) {
			var rev = res.query.pages[res.query.pageids[0]].revisions[0];

			return {
				start: res.curtimestamp,
				base: rev.timestamp,
				full: rev.slots.main['*']
			};
		});
	}

	function getPreviewCallback(editor) {
		editor.children('.preview').remove();

		new OO.ui.ProgressBarWidget().$element.css({
			maxWidth: '100%',
			borderRadius: '0',
			boxShadow: 'none',
			margin: '8px 0'
		}).addClass('preview').appendTo(editor);

		return function(html) {
			editor.children('.preview').remove();

			$('<div>').html(html).css({
				margin: '8px 0',
				border: '1px solid #a2a9b1',
				padding: '8px',
				overflowX: 'hidden'
			}).addClass('preview').appendTo(editor);
		};
	}

	function showCompare(editor, title, from, to) {
		mw.loader.load('mediawiki.diff.styles');

		api('post', {
			action: 'compare',
			fromslots: 'main',
			'fromtext-main': from,
			fromtitle: title,
			frompst: 'true',
			toslots: 'main',
			'totext-main': to,
			totitle: title,
			topst: 'true'
		}).then(function(r) {
			return r.compare['*'] ? $('<table>').addClass('diff').append(
				$('<colgroup>').append(
					$('<col>').addClass('diff-marker'),
					$('<col>').addClass('diff-content'),
					$('<col>').addClass('diff-marker'),
					$('<col>').addClass('diff-content')
				)
			).append(r.compare['*']) : 'কোন পার্থক্য নেই';
		}).then(getPreviewCallback(editor));
	}

	// Parts taken from EditPage::extractSectionTitle and Parser::stripSectionName
	function getSectionSummary(text) {
		var match = text.match(/^(=+)(.+)\1\s*(\n|$)/);

		return !match ? '' : '/* ' + match[2].trim()
			// Strip internal link markup
			.replace(/\[\[:?([^[|]+)\|([^[]+)\]\]/g, '$2')
			.replace(/\[\[:?([^[]+)\|?\]\]/g, '$1')
			// Strip external link markup
			.replace(new RegExp('\\[(?:' + mw.config.get('wgUrlProtocols') + ')([^ ]+?) ([^\\[]+)\\]', 'ig'), '$2')
			// Remove wikitext quotes
			.replace(/(''|'''|''''')(?!')/g, '')
			// Strip HTML tags
			.replace(/<[^>]+?>/g, '') + ' */ ';
	}

	function showEditor(el) {
		var progress = new OO.ui.ProgressBarWidget(),
			heading = el.closest(':header'),
			matcher = heading.nextUntil.bind(heading),
			inserter = heading.after.bind(heading),
			targetEl = el.siblings('.quickedit-target').last(),
			titleMatch = targetEl.attr('href').match(titleRegexp),
			title = decodeURIComponent(titleMatch[1] || titleMatch[2]),
			sectionID = /[?&]v?e?section=T?-?(\d*)/.exec(targetEl.attr('href'))[1];

		if (!heading.closest('.mw-parser-output').length) {
			var articleContent = $('#mw-content-text .mw-parser-output');

			matcher = function(selector) {
				var child = articleContent.children(selector).first();

				if (child.length) return child.prevAll();
				return articleContent.children();
			};
			inserter = articleContent.prepend.bind(articleContent);
		}

		inserter(progress.$element.css({
			maxWidth: '100%',
			borderRadius: '0',
			boxShadow: 'none'
		}));

		el.addClass('quickedit-loading');
		$('.quickedit-hide').removeClass('quickedit-hide');
		$('.quickedit-heading').removeClass('quickedit-heading');
		$('#quickedit-editor').remove();

		getPageInfo(title, sectionID).then(function(r) {
			var start = r.start,
				base = r.base,
				full = r.full,
				saving = false,
				expanded = false,
				remainderStart = full.match(/\n=+.+=+(?:\n|$)/),
				part =  remainderStart ? full.substring(0, remainderStart.index) : full,
				remainder = remainderStart ? full.substring(remainderStart.index) : '',
				level = 0,
				editor;

			full.replace(/^(=+).+?(=+)(?:\n|$)/, function(m, a, b) {
				level = Math.min(a.length, b.length);
				return m;
			});

			var levelMatch = 'h1';
			for (var i = 2; i <= level; i++) levelMatch += ',h' + i + ':has(*)';

			var partSection = matcher(':header:has(*)'),
				fullSection = matcher(levelMatch),
				textarea = new OO.ui.MultilineTextInputWidget({
					rows: 1,
					maxRows: 20,
					autosize: true,
					value: part
				}),
				summary = new OO.ui.TextInputWidget({
					value: getSectionSummary(part)
				}),
				minor = new OO.ui.CheckboxInputWidget(),
				save = new OO.ui.ButtonInputWidget({
					label: 'পরিবর্তন প্রকাশ করুন',
					title: 'Save your changes',
					flags: ['primary', 'progressive']
				}),
				preview = new OO.ui.ButtonInputWidget({
					label: 'প্রাকদর্শন',
					title: 'Preview the new wikitext'
				}),
				compare = new OO.ui.ButtonInputWidget({
					label: 'পরিবর্তনসমূহ',
					title: 'View the difference between the current revision and your revision'
				}),
				cancel = new OO.ui.ButtonInputWidget({
					useInputTag: true,
					label: 'বাতিল',
					title: 'Close the edit form and discard changes',
					flags: ['secondary', 'destructive']
				}),
				more = new OO.ui.ButtonInputWidget({
					label: '+',
					title: 'Edit the entire section (including subsections)'
				}),
				buttons = new OO.ui.HorizontalLayout({
					items: [save, preview, compare, cancel]
				});

			if (part != full) {
				buttons.addItems([more], 3);
			}

			partSection.addClass('quickedit-hide');
			heading.addClass('quickedit-heading');
			el.removeClass('quickedit-loading');
			progress.$element.remove();
			textarea.$input.css({
				borderRadius: '0'
			});

			summary.on('enter', function() {
				save.emit('click');
			});

			save.on('click', function() {
				if (saving) return;

				var fullText = textarea.getValue() + (expanded ? '' : remainder);
				saving = true;
				save.setLabel('সংরক্ষণ করা হচ্ছে...');
				compare.setDisabled(true);
				preview.setDisabled(true);
				cancel.setDisabled(true);
				more.setDisabled(true);

				api('postWithEditToken', {
					action: 'edit',
					title: title,
					section: sectionID,
					summary: summary.getValue(),
					text: fullText,
					minor: minor.isSelected() ? true : undefined,
					notminor: minor.isSelected() ? undefined : true,
					starttimestamp: start,
					basetimestamp: base
				}).then(function() {
					api('get', {
						action: 'parse',
						page: mw.config.get('wgPageName'),
						prop: ['text', 'categorieshtml']
					}).then(function(r) {
						var contentText = $('#mw-content-text'),
							catLinks = $('#catlinks');

						contentText.find('.mw-parser-output').replaceWith(r.parse.text['*']);
						mw.hook('wikipage.content').fire(contentText);

						catLinks.replaceWith(r.parse.categorieshtml['*']);
						mw.hook('wikipage.categories').fire(catLinks);

						saving = false;
					});
				}, function(code) {
					if (code == 'editconflict') {
						showEditConflict(editor, title, sectionID, fullText).then(function(r) {
							start = r.start;
							base = r.base;
							textarea = r.textarea;
							expanded = true;
						});
					}

					compare.setDisabled(false);
					preview.setDisabled(false);
					cancel.setDisabled(false);
					more.setDisabled(expanded);
					saving = false;
					save.setLabel('Save');
				});
			});

			preview.on('click', function() {
				api('post', {
					action: 'parse',
					title: title,
					prop: 'text',
					pst: 'true',
					disablelimitreport: 'true',
					disableeditsection: 'true',
					sectionpreview: 'true',
					disabletoc: 'true',
					text: textarea.getValue()
				}).then(function(r) {
					return r.parse.text['*'] + '<div style="clear:both;"></div>';
				}).then(getPreviewCallback(editor));
			});

			compare.on('click', function() {
				showCompare(editor, title, part + (expanded ? remainder : ''), textarea.getValue());
			});

			cancel.on('click', function() {
				editor.remove();
				heading.removeClass('quickedit-heading');
				fullSection.removeClass('quickedit-hide');
			});

			more.on('click', function() {
				expanded = true;
				textarea.setValue(textarea.getValue() + remainder);
				fullSection.addClass('quickedit-hide');
				more.setDisabled(true);
			});

			editor = $('<div id="quickedit-editor">').css({
				overflowX: 'hidden'
			}).append(
				$('<div>').css({
					backgroundColor: '#eaecf0',
					borderBottom: '1px solid #a2a9b1',
					marginBottom: '8px'
				}).append(
					textarea.$element.css({
						width: '100%',
						maxWidth: '100%',
						fontFamily: 'monospace, monospace'
					}).addClass('quickedit-textarea'),
					$('<div>').css({
						border: '1px solid #a2a9b1',
						borderWidth: '0 1px'
					}).append(
						$('<div>').css({
							padding: '8px 4px 8px 8px',
							display: 'table-cell',
							verticalAlign: 'middle'
						}).html('সারাংশ:'),
						summary.$element.css({
							width: '100%',
							maxWidth: '100%',
							padding: '8px 0px',
							display: 'table-cell',
							verticalAlign: 'middle'
						}),
						new OO.ui.FieldLayout(minor, {
							label: new OO.ui.HtmlSnippet('🤏?'),
							align: 'inline'
						}).$element.css({
							padding: '8px 8px 8px 4px',
							display: 'table-cell',
							verticalAlign: 'middle'
						})
					),
					buttons.$element.css({
						border: '1px solid #a2a9b1',
						borderWidth: '0 1px',
						padding: '0px 8px 0'
					}),
					title !== mw.config.get('wgPageName') ? $('<div>').css({
						border: '1px solid #a2a9b1',
						borderWidth: '0 1px',
						padding: '0px 8px 8px'
					}).append(
						'Editing page: ',
						$('<a>').attr('href', mw.config.get('wgArticlePath').replace('$1', title)).css({
							fontWeight: 'bold'
						}).text(title.replace(/_/g, ' '))
					) : undefined
				)
			);

			inserter(editor);
		}, function() {
			el.removeClass('quickedit-loading');
			progress.$element.remove();
		});
	}

	function showEditConflict(editor, title, sectionID, text) {
		return getPageInfo(title, sectionID).then(function(r) {
			var textarea = new OO.ui.MultilineTextInputWidget({
					rows: 1,
					maxRows: 20,
					autosize: true,
					value: r.full
				}),
				textarea2 = new OO.ui.MultilineTextInputWidget({
					rows: 1,
					maxRows: 20,
					autosize: true,
					value: text,
				});

			function syncSize() {
				textarea.styleHeight = -1;
				textarea.adjustSize(true);

				textarea2.styleHeight = -1;
				textarea2.adjustSize(true);

				var height = Math.max(textarea.$input.height(), textarea2.$input.height());
				textarea.$input.height(height);
				textarea2.$input.height(height);
			}

			textarea.$input.css({
				borderRadius: '0'
			});
			editor.find('> :first-child > :first-child').remove();

			$('<table>').css({
				width: '100%',
				border: '1px solid #a2a9b1',
				borderBottom: 'none',
				borderSpacing: '0',
				margin: '0 !important'
			}).append(
				$('<tr>').append(
					$('<th>').css({
						width: '50%',
						paddingTop: '4px'
					}).text('Their version (to be saved)'),
					$('<th>').css({
						width: '50%',
						paddingTop: '4px'
					}).text('Your version')
				),
				$('<tr>').append(
					$('<td>').css({
						width: '50%',
						padding: '4px 4px 0 8px'
					}).append(
						textarea.$element.css({
							width: '100%',
							maxWidth: '100%',
							fontFamily: 'monospace, monospace'
						})
					),
					$('<td>').css({
						width: '50%',
						padding: '4px 8px 0 4px'
					}).append(
						textarea2.$element.css({
							width: '100%',
							maxWidth: '100%',
							fontFamily: 'monospace, monospace'
						})
					)
				)
			).prependTo(editor.find('> :first-child'));

			textarea.on('change', syncSize);
			textarea2.on('change', syncSize);
			syncSize();
			showCompare(editor, title, text, r.full);

			r.textarea = textarea;
			return r;
		});
	}

	function clickHandler(e) {
		var el = $(e.target);

		if (!el.hasClass('quickedit-editlink') || el.hasClass('quickedit-loading')) return;

		e.preventDefault();

		showEditor(el);
	}

	function addLinksToChildren(element) {
		element.find('#quickedit-editor, .quickedit-section').remove();
		element.find('.mw-editsection').each(function() {
			$('[href*="section="]', this).last().after(
				mobile ? '' : '<span class="quickedit-section"> | </span>',
				$('<a>').html(mobile ? '&nbsp;💨' : 'দ্রুত সম্পাদনা').addClass('quickedit-section quickedit-editlink')
			).addClass('quickedit-target');
		});
	}

	$.when(mw.loader.using('oojs-ui-core'), $.ready).done(function() {
		var body = $(document.body);

		body.on('click', clickHandler);
		addLinksToChildren(body);
		mw.hook('wikipage.content').add(addLinksToChildren);
	});

	mw.loader.addStyleTag(
		'.skin-minerva .mw-editsection { white-space: nowrap; }' +
		'.skin-minerva .content .collapsible-heading .quickedit-section { visibility: hidden; }' +
		'.skin-minerva .content .collapsible-heading.open-block .quickedit-section { visibility: visible; }' +
		'.quickedit-hide { display: none !important; }' +
		'.quickedit-loading, .quickedit-heading { color: #777; }'
	);
})();

//খেলাঘর
$( document ).ready( function() {
  mw.util.addPortletLink(
    'p-personal',
    mw.util.getUrl( 'Special:MyPage/খেলাঘর' ), //No need for a variable.
    'খেলাঘর',
    'pt-sandbox2',
    'খেলাঘর',
    null,
    '#pt-sandbox'
  );
});

//article creation


(function() {
	$(document).ready(function() {
		mw.loader.using( ['mediawiki.util'], function() {
			{
				var L=mw.util.addPortletLink("p-navigation", "#", "নতুন পাতা তৈরি");L.addEventListener("click", create);
				
				return;
			}
		});
	});
}());
function create() {
	var art = prompt ("যে নিবন্ধটি তৈরি করতে চান তার নাম লিখুন:");
	switch (art) {
		case null:
		case undefined:
		case '':
		//Do nothing
		break;
		default:
		{
			window.open('/index.php?preload=Special:New_page&editintro=&title=' + art + '&create=Create+page#/editor/all', '_blank');
		}
	}


}