User:SunAfterRain/js/MOSNUM dates.js

注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google ChromeFirefoxMicrosoft EdgeSafari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
/**
 * Base on https://zh.wikipedia.org/w/index.php?oldid=73381030
 * Partial Reference: https://en.wikipedia.org/w/index.php?oldid=1093730518
 */
// <nowiki>
$.when(
	$.ready,
	mw.loader.using( [ 'ext.gadget.HanAssist' ] )
).then( function ( _$, require ) {
	if ( mw.config.get( 'wgAction' ) !== 'edit' || !mw.config.get( 'wgIsProbablyEditable' ) ) {
		return;
	}
	
	const HanAssist = require( 'ext.gadget.HanAssist' );
	const summaryPrefix = '[[User:SunAfterRain/js/MOSNUM_dates.js]]:';
	const dateRegExp = {
		YYYY: /([1-2]\d{3})/,
		MM: /(0?[1-9]|1[012])/,
		DD: /(0?[1-9]|[12]\d|3[01])/,
		Month: /(January|February|March|April|May|June|July|August|September|October|November|December|(?:Jan|Feb|Mar|Apr|Jun|Jul|Aug|Sept?|Oct|Nov|Dec)\.?)/,
		Day: /((?:0?[1-9]|[12]?\d|3[01]))(?:st|nd|rd|th|)?/
	};
	
	const monthNames = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ];
	const monthNamesShort = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ];
	
	function makeDateRegExp( rawRegExp ) {
		let raw = rawRegExp.source;
		for ( const key of Object.keys( dateRegExp ) ) {
			raw = raw.replace( new RegExp( '@' + key + '\\b', 'g' ), dateRegExp[ key ].source );
		}
		return new RegExp( raw, rawRegExp.flags );
	}
	
	function upperFirst( str ) {
		return str.slice( 0, 1 ).toUpperCase() + str.slice( 1 );
	}
	
	function covertMonth( $m ) {
		if ( $m.endsWith( '.' ) ) {
			$m = $m.slice( 0, -1 );
		}
		$m = $m.toLowerCase();
		$m = $m.slice( 0, 1 ).toUpperCase() + $m.slice( 1 );
		return ( monthNames.includes( $m ) ? monthNames.indexOf( $m ) : monthNamesShort.indexOf( $m ) ) + 1;
	}
	
	function padZero( str ) {
		return String( str ).padStart( 2, '0' );
	}
	
	function checkPortlet() {
		if ( !document.getElementById( 'p-mosnum' ) ) {
			const $mosnum = $( '#p-tb' ).clone().attr( {
				id: 'p-mosnum',
				'aria-labelledby': 'p-mosnum-label'
			} );
			$mosnum.find( '#p-tb-label, h1, h2, h3, h4, h5, h6' ).first().attr( {
				id: 'p-mosnum-label'
			} ).text( HanAssist.conv( {
				hans: '参考资料日期修正',
				hant: '參考資料日期修正'
			} ) );
			$mosnum.find( 'ul' ).empty();
			$mosnum.insertAfter( '#p-tb' );
		}
	}
	
	class MOSNum {
		constructor( id, name, tooltip, summary ) {
			this.id = id;
			this.name = name;
			this.tooltip = tooltip;
			this.summary = summary;
			this.replaceMap = [];
		}
		
		doReplace( pattern, replacement ) {
			this.replaceMap.push( { pattern, replacement } );
			return this;
		}
		
		doDateReplace( pattern, replacement ) {
			if ( typeof replacement === 'function' ) {
				const oldReplacement = replacement;
				replacement = ( ...args ) => {
					const result = oldReplacement( ...args );
					console.log( {
						pattern,
						replaceArgs: args,
						result
					} );
					return result;
				};
			}
			this.replaceMap.push( { pattern: makeDateRegExp( pattern ), replacement } );
			return this;
		}
		
		register() {
			checkPortlet();
			return $( mw.util.addPortletLink( 'p-mosnum', '#', this.name, 't-mosnum-' + this.id, this.tooltip ) )
				.on( 'click', this.onClick );
		}
		
		get onClick() {
			return ( event ) => {
				event.preventDefault();
				let wikitext = $( '#wpTextbox1' ).val();
				for ( const { pattern, replacement } of this.replaceMap ) {
					wikitext = wikitext.replace( pattern, replacement );
				}
				$( '#wpTextbox1' ).val( wikitext );
				const oldSummary = $( '#wpSummary' ).val();
				if ( !oldSummary ) {
					$( '#wpSummary' ).val( summaryPrefix + this.summary );
				} else {
					$( '#wpSummary' ).val( summaryPrefix + this.summary + ';' + oldSummary );
				}
				if ( !window.wgMOSNumNoAutoShowDiff ) {
					$( '#wpDiff' ).click();
				}
			};
		}
	}
	
	const formats = [
		{
			id: 'en2iso',
			name: '英文日期->ISO',
			tooltip: '英文日期格式修正至ISO格式',
			summary: '參考資料英文日期格式轉ISO',
			replace: [
				[ 'DateReplace', /(\|\s*(?:(?:(?:access|archive|)-?)date)\s*)=(\s*)@Day @Month,? @YYYY(?=[\s]*[|}])/gi, ( _orig, $1, $d, $m, $y, $2 ) => {
					return `${ $1 }=${ $2 }${ $y }-${ padZero( covertMonth( $m ) ) }-${ padZero( $d ) }`;
				} ],
				[ 'DateReplace', /(\|\s*(?:(?:(?:access|archive|)-?)date)\s*)=(\s*)@Month @Day,? @YYYY(?=[\s]*[|}])/gi, ( _orig, $1, $m, $d, $y, $2 ) => {
					return `${ $1 }=${ $2 }${ $y }-${ padZero( covertMonth( $m ) ) }-${ padZero( $d ) }`;
				} ],
				[ 'DateReplace', /(?:Retrieved |Accessed)[ ]*(?:on |)@Day @Month,? @YYYY(?=[\s]*[|}])/gi, ( _orig, $d, $m, $y ) => {
					return `Retrieved ${ $y }-${ padZero( covertMonth( $m ) ) }-${ padZero( $d ) }`;
				} ],
				[ 'DateReplace', /(?:Retrieved |Accessed)[ ]*(?:on |)@Month @Day,? @YYYY(?=[\s]*[|}])/gi, ( _orig, $m, $d, $y ) => {
					return `Retrieved ${ $y }-${ padZero( covertMonth( $m ) ) }-${ padZero( $d ) }`;
				} ],
				[ 'Replace', /\|\s*df\s*=\s*[\w-]*(?=[\s]*[|}])/gi, '' ],
				[ 'Replace', /{{\s*use (dmy|mdy) dates\s*\|[^}]*}}(\n)?/gi, '' ]
			]
		},
		{
			id: 'zh2iso',
			name: '中文日期->ISO',
			tooltip: '中文日期格式修正至ISO格式',
			summary: '參考資料中文日期格式轉ISO',
			replace: [
				[ 'Replace', /(\|\s*(?:access|archive|)-?date\s*=\s*)(\d+)年(\d+)月(\d+)日(?=[\s]*[|}])/gi, ( _orig, $1, $y, $m, $d ) => {
					return `${ $1 }${ $y }-${ padZero( $m ) }-${ padZero( $d ) }`;
				} ]
			]
		},
		{
			id: 'dmy2ymd',
			name: 'ISO日月年->ISO年月日',
			tooltip: HanAssist.conv( {
				hans: 'ISO格式的日月年日期修正,包括ISO年月日标准格式修正',
				hant: 'ISO格式的日月年日期修正,包括ISO年月日標準格式修正'
			} ),
			summary: '參考資料ISO日月年格式修正',
			replace: [
				// ISO style
				[ 'DateReplace', /(\|\s*(?:(?:(?:access|archive|)-?)date)\s*=\s*)@YYYY[.\/-]@MM[.\/-]@DD(?=[\s]*[|}])/gi, ( _orig, $1, $y, $m, $d ) => {
					return `${ $1 }${ $y }-${ padZero( $m ) }-${ padZero( $d ) }`;
				} ],
				// UK style
				[ 'DateReplace', /(\|\s*(?:(?:(?:access|archive|)-?)date)\s*=\s*)@DD[.\/-]@MM[.\/-]@YYYY(?=[\s]*[|}])/gi, ( orig, $1, $d, $m, $y ) => {
					if ( Number.parseInt( $y, 10 ) !== Number.parseInt( $m, 10 ) && Number.parseInt( $y, 10 ) <= 12 ) {
						return orig;
					}
					return `${ $1 }${ $y }-${ padZero( $m ) }-${ padZero( $d ) }`;
				} ]
			]
		},
		{
			id: 'mdy2ymd',
			name: 'ISO月日年->ISO年月日',
			tooltip: HanAssist.conv( {
				hans: 'ISO格式的月日年日期修正,包括ISO年月日标准格式修正',
				hant: 'ISO格式的月日年日期修正,包括ISO年月日標準格式修正'
			} ),
			summary: '參考資料ISO月日年格式修正',
			replace: [
				// ISO style
				[ 'DateReplace', /(\|\s*(?:(?:(?:access|archive|)-?)date)\s*=\s*)@YYYY[.\/-]@MM[.\/-]@DD(?=[\s]*[|}])/gi, ( _orig, $1, $y, $m, $d ) => {
					return `${ $1 }${ $y }-${ padZero( $m ) }-${ padZero( $d ) }`;
				} ],
				// US style
				[ 'DateReplace', /(\|\s*(?:(?:(?:access|archive|)-?)date)\s*=\s*)@MM[.\/-]@DD[.\/-]@YYYY(?=[\s]*[|}])/gi, ( orig, $1, $m, $d, $y ) => {
					if ( Number.parseInt( $y, 10 ) <= 12 ) {
						return orig;
					}
					return `${ $1 }${ $y }-${ padZero( $m ) }-${ padZero( $d ) }`;
				} ]
			]
		},
		{
			id: 'del-language',
			name: HanAssist.conv(  {
				hans: '删除语言参数',
				hant: '刪除語言參數'
			} ),
			tooltip: HanAssist.conv(  {
				hans: '删除参考资料语言标签',
				hant: '刪除參考資料語言標籤'
			} ),
			summary: '刪除所有語言參數',
			replace: [
				[ 'Replace', /(\|\s*language\s*=\s*)([\w-]*)(?=[\s]*[|}])/gi, '$1' ]
			]
		}
	];
	
	for ( const format of formats ) {
		const instance = new MOSNum( format.id, format.name, format.tooltip, format.summary );
		for ( const [ type, pattern, replacement ] of format.replace ) {
			if ( type === 'DateReplace' ) {
				instance.doDateReplace( pattern, replacement );
			} else {
				instance.doReplace( pattern, replacement );
			}
		}
		instance.register();
	}
} );
// </nowiki>