לדלג לתוכן

משתמש:איסתרק/diffedit.js

מתוך המכלול, האנציקלופדיה היהודית

לתשומת ליבך: לאחר הפרסום, ייתכן שיהיה צורך לנקות את זיכרון המטמון (cache) של הדפדפן כדי להבחין בשינויים.

  • פיירפוקס / ספארי: להחזיק את המקש Shift בעת לחיצה על טעינה מחדש (Reload) או ללחוץ על צירוף המקשים Ctrl-F5 או Ctrl-R (במחשב מק: ⌘-R).
  • גוגל כרום: ללחוץ על צירוף המקשים Ctrl-Shift-R (במחשב מק: ⌘-Shift-R).
  • אדג': להחזיק את המקש Ctrl בעת לחיצה על רענן (Refresh) או ללחוץ על צירוף המקשים Ctrl-F5.
//מועתק מכאן
//https://meta.wikimedia.org/w/index.php?title=User:Jon_Harald_S%C3%B8by/diffedit.js&action=raw&ctype=text/javascript
//רק בלי התוספת המעצבנת לתקציר

/*!
 * diffedit.js – script that lets you edit pages directly from the diff view
 * @authors User:Jon Harald Søby
 * @licence CC-by-SA 4.0
 *
 * For documentation, see [[User:Jon Harald Søby/diffedit]]
 */
function initDiffedit( $, mw, OO ) {
	"use strict";
	var messages,
		linetopCache = "",
		tabIndex = 1,
		pageId = mw.config.get( 'wgArticleId' ),
		oldRevisionId = mw.config.get( 'wgDiffOldId' ),
		newRevisionId = mw.config.get( 'wgDiffNewId' ),
		currentRevisionId = mw.config.get( 'wgCurRevisionId' ),
		contentModel = mw.config.get( 'wgPageContentModel' ),
		allowedContentModels = [ 'wikitext', 'text', 'sanitized-css', 'json', 'javascript', 'css', 'Scribunto' ],
		api = new mw.Api();
		
	/* The 'messages' function is from [[d:MediaWiki:Gadget-Merge.js]],
	 * see that page's history for credits
	 */
	messages = function() {
		var translations = {
			he: {
				editTitle: 'עריכת ההשוואה הזאת',
				editTitleNewerRevs: 'ההשוואה הזאת לא ניתנת לעריכה, מכיוון שקיימות גרסאות חדשות יותר של הדף.',
				noPermission: 'אין לך הרשאות לעריכת הדף הזה',
				refresh: 'להראות את המאוחר ביותר',
				refreshTitle: 'ללחוץ לקבלת ההשוואה עם הגרסה האחרונה של הדף'
		
		}},
			chain = mw.language.getFallbackLanguageChain(),
			len = chain.length,
			ret = {},
			i = len - 1;
	    while ( i >= 0 ) {
			if ( translations.hasOwnProperty( chain[ i ] ) ) {
	        	$.extend( ret, translations[ chain[ i ] ] );
	    	}
	    	i = i - 1;
	    	}
			return ret;
	}();

	
	function enumerateLines() {
		var currentLine = 0,
			numberRegex = "0-9",
			localNumbers = mw.language.getDigitTransformTable();
		if ( ( localNumbers instanceof Array && localNumbers.length ) || Object.keys( localNumbers ).length ) {
			for ( const i of Array( 10 ).keys() ) {
				numberRegex = numberRegex.concat( localNumbers[ i ] );
			}
		}
		$( 'table.diff tbody tr td:last-of-type' ).each( function() {
			if ( $( this ).hasClass( 'diff-lineno' ) ) {
				var lineNo = $( this ).text();
				lineNo = mw.language.convertNumber( lineNo.replace( new RegExp( '[^' + numberRegex + ']', 'g' ), "" ), true );
				currentLine = lineNo;
			} else if ( $( this ).hasClass( 'diff-addedline' ) || $( this ).hasClass( 'diff-context' ) ) {
				$( this ).addClass( 'diff-editable' ).attr( 'data-mw-diff-line', currentLine );
				$( this ).attr( 'data-mw-diff-tabindex', tabIndex );
				currentLine++;
				tabIndex++;
			}
		});
	}
	
	function addEditButton( titleText ) {
		var editTitle = titleText ? titleText : messages.editTitle,
			editIcon = titleText ? 'editLock' : 'edit';
		var editButton = new OO.ui.ButtonWidget( {
				label: mw.message( 'edit' ).text(),
				icon: editIcon,
				title: editTitle,
				flags: [ 'primary', 'progressive' ],
				disabled: !!titleText
			});
		linetopCache = $( '.diff-linetop' ).html();
		$( '.diffedit-editbutton' ).append( editButton.$element );
		if ( !titleText ) {
			editButton.on( 'click', function() {
				toggleEditMode( 'enable' );
				addEditLine();
			});
		}
	}
	
	function addRefreshButton() {
		var refreshButton = new OO.ui.ButtonWidget( {
				label: messages.refresh,
				icon: 'reload',
				title: messages.refreshTitle,
				flags: [ 'progressive' ],
				invisibleLabel: true,
				framed: false
			});
		$( '.diffedit-editbutton' ).prepend( refreshButton.$element );
		refreshButton.on( 'click', function() {
			window.location.href = mw.config.get( 'wgServer' ) + mw.util.getUrl( mw.config.get( 'wgPageName' ), { 'diff': 'cur', 'oldid': oldRevisionId } );
		});
	}
	
	function addEditLine() {
		var editSummary = new OO.ui.TextInputWidget( {
				icon: 'textSummary',
				accessKey: mw.message( 'accesskey-summary' ).text(),
				name: 'wpSummary',
				tabIndex: tabIndex + 1,
				placeholder: mw.message( 'revisionslider-label-comment' ).text(),
				title: mw.message( 'tooltip-summary' ).text(),
				classes: [ 'diffedit-editsummary' ]
			}),
			publishButton = new OO.ui.ButtonWidget( {
				label: mw.message( 'publishchanges' ).text(),
				title: mw.message( 'tooltip-publish' ).text(),
				accessKey: mw.message( 'accesskey-publish' ).text(),
				tabIndex: tabIndex + 2,
				flags: [ 'primary', 'progressive' ],
				classes: [ 'diffedit-publishbutton' ]
			}),
			cancelButton = new OO.ui.ButtonWidget( {
				label: mw.message( 'cancel' ).text(),
				icon: 'cancel',
				invisibleLabel: true,
				tabIndex: tabIndex + 3,
				flags: [ 'destructive' ],
				framed: false
			}),
			editLine = new OO.ui.FieldLayout( new OO.ui.Widget( {
				content: [
					new OO.ui.HorizontalLayout( {
						items: [ editSummary, publishButton, cancelButton ]
					})]
				}));
		publishButton.on( 'click', function() {
			processEdit();
		});
		publishButton.$element.hover( function() {
			if ( $( 'input[name=wpSummary]' ).val().length === 0 ) {
				$( 'input[name=wpSummary]' ).css( { 'outline': '5px solid gold', 'transition': 'outline 500ms cubic-bezier(.5,2,.5,-1)' } );
			} else {
				$( 'input[name=wpSummary] ').css( { 'outline': '5px solid transparent' } );
			}
		});
		editSummary.$element.keyup( function( e ) {
			if ( e.key === 'Enter' ) {
				processEdit();
			}
		});
		cancelButton.on( 'click', function() {
			toggleEditMode( 'disable' );
		});
		editLine.$field.css( 'float', 'none' );
		$( '.diff-linetop' ).html( editLine.$element );
		$( 'input[name=wpSummary]' ).on( 'keyup keydown change', function() {
			$( this ).css( { 'outline': '5px solid transparent', 'transition': 'outline 500ms ease-out' } );
		});
	}
	
	function toggleEditMode( state ) {
		if ( state === 'enable' ) {
			$( 'table.diff' ).addClass( 'diff-editmode' );
			$( '.diff-editable' ).each( function() {
				$( this ).attr( { 'contenteditable': 'true', 'tabindex': $( this ).attr( 'data-mw-diff-tabindex' ) } ).css( { 'word-wrap': 'break-word', 'white-space': 'pre-wrap' } );
			});
			$( '.diff-editable div' ).text();
			$( '.diff-editable' ).first().attr( 'accesskey', ',' ).focus();
		} else {
			$( 'table.diff' ).removeClass( 'diff-editmode' );
			$( '.diff-linetop' ).html( linetopCache );
			addEditButton();
			$( '.diff-editable' ).each( function() {
				$( this ).attr( 'contenteditable', 'false').removeAttr( 'tabindex' ).css( { 'word-wrap': 'break-word', 'white-space': 'pre-wrap' } );
			});
		}
	}
	
	function processEdit() {
		$( '.diffedit-publishbutton' ).addClass( 'oo-ui-pendingElement-pending' ).removeClass( 'oo-ui-flaggedElement-primary' );
		var currentContent = "",
			contentFromApi = api.get( {
				action: 'query',
				prop: 'revisions',
				rvprop: 'content',
				rvslots: 'main',
				pageids: pageId,
				rvstartid: currentRevisionId,
				rvendid: currentRevisionId
			} );
		contentFromApi.done( function( data ) {
			var mainSlot = data.query.pages[pageId].revisions[0].slots.main,
				contentModel = mainSlot.contentmodel;
			currentContent = mainSlot["*"];
			currentContent = currentContent.split( "\n" );
			var newContent = currentContent;
			$( '.diff-editable' ).each( function() {
				var thisline = [],
					lineNo = $( this ).attr( 'data-mw-diff-line' );
				if ( $( this ).contents().length === 0 ) {
					thisline.push( "" );
				} else if ( $( this ).contents()[0].nodeName === "#text" ) {
					thisline.push( $( this ).contents()[0].textContent );
				} else {
					$( this ).contents().each( function() {
						thisline.push( this.textContent );
					});
				}
				newContent[lineNo-1] = thisline.join( "\n" );
			});
			api.postWithEditToken( {
				action: 'edit',
				pageid: pageId,
				baserevid: newRevisionId,
				nocreate: true,
				text: newContent.join( "\n" ),
				minor: true,
				summary: $( 'input[name=wpSummary]' ).val()
			} ).done( function( data ) {
				window.location.href = mw.config.get( 'wgServer' ) + mw.util.getUrl( mw.config.get( 'wgPageName' ), { 'diff': 'cur' } );
			}).fail( function( err ) {
				console.log(err);
				alert( "Error: " + err );
			});
		}).fail( function( err ) {
			alert( "Failed: " + err );
			return;
		});
	}
	
	$( '.diff-lineno:first' ).next().addClass( 'diff-linetop' ).append( $( '<div />' ).addClass( 'diffedit-editbutton' ) );
	if ( !mw.config.get( 'wgIsProbablyEditable' ) ) {
		addEditButton( messages.noPermission );
	} else if ( $( ".mw-diff-slot-header" ).length ) {
		addEditButton( mw.message( 'editpage-invalidcontentmodel-text', 'mixed content' ).text() );
	} else if ( !allowedContentModels.includes( contentModel ) ) {
		addEditButton( mw.message( 'editpage-invalidcontentmodel-text', contentModel ).text() );
	} else if ( newRevisionId !== currentRevisionId ) {
		addEditButton( messages.editTitleNewerRevs );
		addRefreshButton();
	} else {
		enumerateLines();
		addEditButton();
		$( '.diff-linetop, .diff-editable' ).keyup( function( e ) {
			if ( e.key === 'Escape' ) {
				toggleEditMode( 'disable' );
			} else if ( e.ctrlKey && e.key === 'Enter' ) {
				processEdit();
			}
		});
	}
}

mw.loader.using( [ 'oojs-ui-core', 'oojs-ui.styles.icons-editing-core', 'oojs-ui.styles.icons-interactions', 'oojs-ui.styles.icons-layout' ] ).then( function() {
	if ( !( mw.config.get( 'wgDiffNewId' ) ) ) {
		return;
	} else {
		mw.loader.load( 'https://meta.wikimedia.org/w/index.php?title=User:Jon_Harald_Søby/diffedit.css&action=raw&ctype=text/css', 'text/css' );
		new mw.Api().loadMessagesIfMissing( [
			'edit', // Edit
			'publishchanges', // Publish
			'tooltip-publish', // Publish these changes
			'cancel', // Cancel
			'accesskey-publish', // s
			'accesskey-summary', // b
			'editpage-invalidcontentmodel-text', // Invalid content model $1
			'revisionslider-label-comment', // Edit summary
			'tooltip-summary', // Summary tooltip
			'parentheses' // ($1)
		] ).done( function( data ) {
			initDiffedit( jQuery, mediaWiki, OO );
		} ).fail( function( err ) {
			mw.notify( err, { title: "diffedit error", type: "error" } );
		} );
	}
});