User:Inductiveload/maintain-ws-tools.js

From Wikisource
Jump to navigation Jump to search
Note: After saving, changes may not occur immediately. Click here to learn how to bypass your browser's cache.
  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (Cmd-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (Cmd-Shift-R on a Mac)
  • Internet Explorer: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Clear the cache in Tools → Preferences

For details and instructions about other browsers, see Wikipedia:Bypass your cache.

/**
 * Simple maintenance tools - Wikisource Tools Initialisation
 */

/* eslint-disable no-useless-concat */

'use strict';

// IIFE used when including as a user script (to allow debug or config)
// Default gadget use will get an IIFE wrapper as well
( function ( $, mw ) {

	var getMaintainCfg = function ( maintain, cfg ) {
		var transforms = maintain.transforms;

		// function make_linkify_tool

		function getTools() {

			var tools = [],
				cns = mw.config.get( 'wgCanonicalNamespace' ),
				sandbox = mw.config.get( 'wgTitle' ).indexOf( 'Sandbox' ) !== -1;

			if ( sandbox || [ '', 'Translation' ].indexOf( cns ) !== -1 ) {
				tools.push( {
					label: '{{' + 'incomplete}}',
					id: 'ws.incomplete',
					transform: function () {
						return transforms.add_template( false, 'incomplete' );
					}
				} );
				tools.push( {
					label: '{{' + 'no source}}',
					id: 'ws.no-source',
					transform: function () {
						return transforms.add_template( false, 'no source' );
					}
				} );
				tools.push( {
					label: '{' + '{migrate to}}',
					id: 'ws.migrate-to',
					help: 'Use when an Index: for a matching edition exists and has an Index: page.',
					needs: [ {
						type: 'page',
						namespaces: [ 106 ],
						label: 'Index',
						help: 'The Index: page for a matching edition of this work'
					} ],
					transform: function ( params ) {
						return transforms.chain( [
							transforms.delete_templates( [ 'no source', 'scans available', 'migrate to' ] ),
							transforms.add_template( false, 'migrate to',
								[ '[[' + params[ 0 ] + ']]' ] )
						] );
					}
				} );
				tools.push( {
					label: '{' + '{move to subpage}}',
					id: 'ws.move-to-subpage',
					help: 'Use when a top-level page should be moved to a subpage of another mainspace page',
					needs: [ {
						type: 'page',
						namespaces: [ 0 ],
						label: 'Top-level page',
						help: 'The top level page for this subpage.'
					} ],
					transform: function ( params ) {

						var tparams = [];

						if ( params[ 0 ] ) {
							tparams.push( 'target=[[' + params[ 0 ] + ']]' );
						}

						return transforms.add_template( false, 'move to subpage', tparams );
					}
				} );
				tools.push( {
					label: '{' + '{scans available}}',
					id: 'ws.scans-available',
					help: 'Use when scans are available elsewhere, or an Index: exists for a different edition.',
					needs: [ {
						type: 'text',
						label: 'Scans location',
						help: 'For example a link to the scans at the Internet Archive.' +
									' If an Index: page exists for this edition, use {{' + 'migrate to}}.' } ],
					transform: function ( params ) {
						return transforms.chain( [
							transforms.delete_templates( [ 'no source', 'scans available', 'migrate to' ] ),
							transforms.add_template( false, 'scans available', [ params[ 0 ] ] )
						] );
					}
				} );
				tools.push( {
					label: '{' + '{similar}}',
					id: 'ws.similar',
					help: 'Link a work to a disambiguation page',
					needs: [ {
						type: 'page',
						namespaces: [ 0 ],
						label: 'Disambiguation page',
						help: 'Title of a  disambiguation page holding a list of similar works'
					} ],
					transform: function ( params ) {
						return transforms.chain( [
							transforms.delete_templates( [ 'similar', 'other versions' ] ),
							transforms.add_template( false, 'similar', [ params[ 0 ] ] )
						] );
					}
				} );
				tools.push( {
					label: '{' + '{other version}}',
					id: 'ws.other-versions',
					help: 'Link a work to a version page',
					needs: [ {
						type: 'page',
						namespaces: [ 0 ],
						label: 'Versions page',
						help: 'Title of a versions page holding a list of other versions of this works'
					} ],
					transform: function ( params ) {
						return transforms.chain( [
							transforms.delete_templates( [ 'similar', 'other versions' ] ),
							transforms.add_template( false, 'other versions', [ params[ 0 ] ] )
						] );
					}
				} );
				tools.push( {
					label: 'Ready for export',
					id: 'ws.ready-for-export',
					help: "Mark a page as 'ready for export', meaning the formatting and layout is compatible with e-book generation.",
					transform: function () {
						return transforms.add_category( 'Ready for export' );
					}
				} );
				tools.push( {
					label: 'Add {{ac}}',
					id: 'ws.authority-control',
					help: 'Add {{authority control}} template',
					transform: function () {
						var ac = 'authority control';

						return function ( old ) {

							var text = maintain.utils.append_text(
								old, maintain.utils.make_template_str( ac ),
								[ /^\s*$/, /^\[\[Category:/ ], true, false
							);

							return {
								text: text,
								summary: 'Added ' + maintain.utils.linkify_template( ac )
							};
						};
					}
				} );

				tools.push( {
					label: 'Page break after 1st',
					id: 'ws.split-after-1st',
					help: 'Split the first page from the <pages/> tag and add a page break',
					transform: function () {
						return transforms.regex( [
							[ /< *pages +index="(.*?)" +from="?(\S+)"? +(.*?)\/>/, function ( m, p1, p2, p3 ) {
								var n = parseInt( p2 ),
									s = '<pages index="' + p1 + '" include="' + n + '" />\n';
								s += '{{padded page break}}\n';
								s += '<pages index="' + p1 + '" from="' + ( n + 1 ) + '" ' + p3 + ' />\n';
								return s;
							} ]
						], 'Add page break after title page: this means the following content starts on a new page on export (see [[H:PAGEBREAK]])' );
					}
				} );
			}

			// These tools always work
			{
				tools.push( {
					label: 'Make link',
					id: 'make-link',
					help: 'Convert the given text into a link',
					needs: [ {
						type: 'page',
						namespaces: [ 0, 102 ],
						label: 'Target page',
						help: 'The page that the link should point to'
					},
					{
						type: 'bool',
						label: 'All instances',
						value: false,
						help: 'Convert all instances of the selected text, or just the first'
					} ],
					transform: function ( params ) {

						function escapeRegExp( string ) {
							return string.replace( /[.*+?^${}()|[\]\\]/g, '\\$&' ); // $& means the whole matched string
						}

						var transform = function ( old, selection ) {
							var selText = selection.selection.toString();
							var regex = new RegExp( escapeRegExp( selText ), params[ 1 ] ? 'g' : '' );

							var link = '[[' + params[ 0 ] + '|' + selText + ']]';
							var newText = old.replace( regex, link );

							return {
								text: newText,
								summary: 'Converted "' + selText + '" to link: ' + link
							};
						};

						return transform;
					}
				} );
			}

			if ( cns === 'Index' ) {
				tools.push( {
					label: 'Change status',
					id: 'ws.index-change-status',
					help: "Choose this scan's new status",
					needs: [ {
						type: 'radio-button',
						label: 'Index status',
						options: [
							{ label: 'To be proofread (C)', data: 'C' },
							{ label: 'To be validated (V)', data: 'V' },
							{ label: 'Scan to check (X)', data: 'X' },
							{ label: 'Match & Split (MS)', data: 'MS' },
							{ label: 'Needs OCR (OCR)', data: 'OCR' },
							{ label: 'Source file incorrect (L)', data: 'L' },
							{ label: 'Done (T)', data: 'T' }
						]
					} ],
					transform: function ( params ) {

						var newStat = {
							C: 'to be proofread',
							V: 'to be validated',
							X: 'scan to check',
							MS: 'ready for Match & Split',
							OCR: 'needs OCR',
							L: 'source file incorrect',
							T: 'done'
						}[ params[ 0 ] ];

						return transforms.regex( [
							[ /\|Progress=.*/, '|Progress=' + params[ 0 ] ]
						], 'Change status to "' + newStat + '"' );
					}
				} );
				tools.push( {
					label: 'Volume template',
					id: 'ws.index-add-vol-template',
					help: 'Add a volume list template',
					needs: [ {
						type: 'page',
						namespaces: [ 10 ],
						label: 'Volume list template'
					} ],
					transform: function ( params ) {
						var tmpl = params[ 0 ].split( ':', 2 )[ 1 ];
						return transforms.regex( [
							[ /\|Volumes=.*/, '|Volumes={{' + tmpl + '}}' ]
						], 'Add volume list template: {{' + '[[Template:' + tmpl + '|' + tmpl + ']]}}' );
					}
				} );
			} else if ( cns === 'User_talk' ) {
				tools.push( {
					label: '{' + '{warning}}',
					id: 'ws.user-warn',
					help: 'Warn this user',
					needs: [ {
						type: 'contrib',
						label: 'Example contribution',
						user: mw.config.get( 'wgRelevantUserName' )
					} ],
					transform: function ( params ) {

						var summary = 'Warn user for edit',
							tparams = [];

						if ( params[ 0 ] ) {
							tparams.push( 'example=' + params[ 0 ] );
							summary += ': [[Special:Diff/' + params[ 0 ] + ']]';
						}

						return transforms.add_template( true, 'warning', tparams, {
							sign: true,
							separation: '\n\n',
							summary: summary
						} );
					}
				} );
				tools.push( {
					label: '{{' + 'welcome}}',
					id: 'ws.user-welcome',
					help: 'Welcome this user',
					transform: function () {

						var summary = 'Welcome to Wikisource! :-)';

						return transforms.add_template( true, 'welcome', [], {
							sign: true,
							summary: summary
						} );
					}
				} );
			} else if ( cns === 'Page' ) {
				tools.push( {
					label: 'Change status',
					id: 'ws.page-change-status',
					help: "Change the page's proofread status",
					needs: [ {
						type: 'radio-button',
						label: 'Page status',
						options: [
							{ label: 'Without text', data: 0 },
							{ label: 'Not proofread', data: 1 },
							{ label: 'Problematic', data: 2 },
							{ label: 'Proofread', data: 3 },
							{ label: 'Validated', data: 4 }
						],
						submit: true
					} ],
					transform: function ( params ) {
						var status = {
							0: 'Without text',
							1: 'Not proofread',
							2: 'Problematic',
							3: 'Proofread',
							4: 'Validated'
						}[ params[ 0 ] ];
						return transforms.regex( [
							[ /<pagequality\s+level="\d" user="(.*?)"/,
								'<pagequality level="' + params[ 0 ] + '" ' +
								'user="' + mw.config.get( 'wgUserName' ) + '"' ]
						], '/* ' + status + ' */' );
					}
				} );
				tools.push( {
					label: 'Add {{nop}}',
					id: 'ws.page-add-nop',
					help: 'Add a {{nop}} to this page',
					transform: function () {
						return transforms.regex( [
							[ /\s*(?=<noinclude>.*?<\/noinclude>$)/, '{{nop}}' ]
						], 'Insert {{nop}} at end of page' );
					}
				} );
			}

			tools.push( {
				label: 'Obsolete tags',
				id: 'ws.obsolete-tags',
				help: 'Try to fix obsolete HTML tags like <center>',
				transform: function () {
					return transforms.regex( [
						[ /< *center *> */gi, '{{center|' ],
						[ /< *big *> */gi, '{{larger|' ],
						[ /<font size="+1">/gi, '{{larger|' ],
						[ /<font size="+2">/gi, '{{x-larger|' ],
						[ / *< *\/ *(?:center|big|font) *>/gi, '}}' ]
					], 'Replace obsolete HTML tags (e.g. <center> → {{[[Template:center|center]]}})' );
				}
			} );

			if ( cns === 'Author' || cns === 'Portal' ) {

				/*
				* Cleans links and templates from a work entry line ready for a fresh link template
				*/
				var cleanWorkEntryLine = function ( l ) {
					return l
						.replace( /\(?\[ *http.*?\]\)?/, '' )
						.replace( /\{\{ *(small scan link|ssl|ext scan link|esl|commons file).*?\}\}/i, '' )
						.trim();
				};

				/* A need for a line that looks like a work entry on an author/portal page */
				var workEntryLineNeed = {
					type: 'wikitext-line',
					label: 'Item to add link for',
					filters: [
						/^\*/
					]
				};

				tools.push( {
					label: 'Add index link',
					id: 'author-add-index-link',
					help: 'Add index link to a item on this page',
					needs: [
						workEntryLineNeed,
						{
							type: 'page',
							namespaces: [ 106 ],
							label: 'Index page',
							help: 'Index page to add'
						}
					],
					transform: function ( params ) {
						var newLine = cleanWorkEntryLine( params[ 0 ] );
						var index = params[ 1 ].replace( /^.*:/, '' );
						var summary = 'Adding index link: [[Index:' + index + ']]';
						var link = '{' + '{small scan link|' + index + '}}';

						return transforms.replace(
							[
								[ params[ 0 ], newLine + ' ' + link ]
							],
							summary
						);
					}
				} );

				tools.push( {
					label: 'Add ext link',
					id: 'author-add-ext-link',
					help: 'Add index link to a item on this page',
					needs: [
						workEntryLineNeed,
						{
							type: 'text',
							label: 'URL',
							help: 'URL of external scan'
						}
					],
					transform: function ( params ) {
						var newLine = cleanWorkEntryLine( params[ 0 ] );
						var url = params[ 1 ];
						var summary = 'Adding external scan link: ' + url;
						var link = '{' + '{ext scan link|1=' + url + '}}';

						return transforms.replace(
							[
								[ params[ 0 ], newLine + ' ' + link ]
							],
							summary
						);
					}
				} );
			}

			return tools;
		}
		// add our new tools
		[].push.apply( cfg.tools, getTools() );
	};

	$( function () {
		mw.hook( 'maintain_replace.config' ).add( getMaintainCfg );
	} );

// eslint-disable-next-line no-undef
}( jQuery, mediaWiki ) );