MediaWiki:Gadget-section-links.js

Uwaga: aby zobaczyć zmiany po opublikowaniu, może zajść potrzeba wyczyszczenia pamięci podręcznej przeglądarki.

  • Firefox / Safari: Przytrzymaj Shift podczas klikania Odśwież bieżącą stronę, lub naciśnij klawisze Ctrl+F5, lub Ctrl+R (⌘-R na komputerze Mac)
  • Google Chrome: Naciśnij Ctrl-Shift-R (⌘-Shift-R na komputerze Mac)
  • Internet Explorer / Edge: Przytrzymaj Ctrl, jednocześnie klikając Odśwież, lub naciśnij klawisze Ctrl+F5
  • Opera: Naciśnij klawisze Ctrl+F5.
// Kod przeniesiony z Common.js: [[Specjalna:Niezmienny link/4475173]]

/*
Funkcje skryptu:
 * obsługa szablonu {{język linków}}
 * dodanie kodów języka do linków w artykułach i w kategoriach
 * czarne self-linki tylko jeśli prowadzą do tej samej sekcji językowej
 * klasy CSS dla sekcji językowych i pól
Przetestowane pod IE 7, IE 8, FF 3.6, Opera 10.50, Google Chrome 4.1.249.1036, Opera Mini, Nokia OSS
Autor: [[user:Olaf]]. Zmierzony narzut czasowy: 0.1-0.3 s
*/

//podział sekcji
var om$START = 0; //początek sekcji językowej
var om$KEEP = 1; //nie zmieniamy linków
var om$PL = 2; //linkujemy do języka polskiego
var om$EXAMPL = 3; //linkujemy do języka obcego przed strzałką i polskiego po strzałce
var om$FOREIGN = 4; //linkujemy do języka obcego
var om$TRANSL = 5; //linkujemy w zależności od nazwy języka
var om$SET = 6; //ustawione za pomocą szablonu {{język linków}}
var om$TABLE = 7; //linkujemy w zależności od kolumny
var om$ESPERANTO = 8; //linkujemy do sekcji esperanto

var om$CurLanguageId = '';
var om$CurSectionName = '';
var om$CurField = '';
var om$Field = om$KEEP;
var om$FieldsBeforeSet = [];
var om$LangIdBeforeSet = [];
var om$ArrowPassed = 0;
var om$ExpliciteBlock = 0;
var om$TransSection = 'other';
var om$LastNodeName = '';
var om$NewClasses = null;
var om$LocationUrl = null;
var om$LangOfColumn = null;
var om$Column = 0;
var om$Row = 0;
var om$DefHeader = 0;

var config = mw.config.get( [
	'wgNamespaceNumber',
	'wgServer',
	'wgPageName',
	'wgArticlePath',
	'wgNamespaceIds'
] );

// http://stackoverflow.com/questions/14947307
var om$reNumber = /^\d+$/;

function om$ChangeLinks( node ) {
	for( var j = 0; j < node.childNodes.length; j++) {
		var subNode = node.childNodes[ j ];
		var nodeName = subNode.nodeName.toLowerCase();
		var $subNode = $( subNode );
		
		if (
			subNode.nodeType === 1 &&
			!$subNode.hasClass( 'mw-editTools' ) &&
			!$subNode.hasClass( 'portlet' ) &&
			nodeName !== 'textarea'
		) {
			//rozpoznanie końca artykułu
			if ( subNode.id === 'toolbar' ) {
				om$Field = om$START;
				om$ExpliciteBlock = 0;
				om$CurSectionName = '';
				om$CurField = '';
				om$CurLanguageId = '';
				om$NewClasses = null;
			}

			if ( nodeName === 'span' ) {
				//znacznik szablonu {{język linków}}
				if ( subNode.id === 'linkLanguage' ) {
					var title = subNode.getAttribute( 'title' );
						
					if ( title === '' ) {
						om$Field = om$FieldsBeforeSet.pop() || om$START;
						om$CurLanguageId = om$LangIdBeforeSet.pop() || '';
					} else {
						var iso;
						if ( ( title + ' ' ).substring( 0, 1 ) === '#' ) {
							iso = title.substring( 1 );
						} else {
							iso = mw.libs.langData.lang2code[ title ];
						}

						om$FieldsBeforeSet.push(om$Field);
						om$LangIdBeforeSet.push(om$CurLanguageId);
						
						om$Field = om$SET;
						if ( iso ) {
							om$CurLanguageId = iso;
						}
					}
				}

				//rozpoznanie sekcji językowej
				if (
					$subNode.hasClass( 'mw-headline' ) &&
					//!$( om$LastNodeName ).hasClass( 'mw-headline' ) &&
					om$Field !== om$SET
				) {
					om$Field = om$START;
					om$ExpliciteBlock = 0;
					om$CurSectionName = subNode.id;
					om$CurField = 'header';
					om$CurLanguageId = '';
					om$NewClasses = null;
					om$ArrowPassed = 0;
					
					for ( var k = 0; k < subNode.childNodes.length; k++ ) {
						var subSubNode = subNode.childNodes[ k ];
						var $subSubNode = $( subSubNode );
						
						if ( $subSubNode.hasClass( 'primary-lang-code' ) ) {
							om$CurLanguageId = subSubNode.id.replace( '-foreign', '' );
							om$NewClasses = 'lang-' + om$CurLanguageId + ' fldt-header';
							
							if ( !$subSubNode.hasClass( 'no-headline-links' ) ) {
								om$Field = om$FOREIGN;
							}
							
							break;
						}
					}
				}

				if (
					$subNode.hasClass( 'field' ) &&
					!$( om$LastNodeName ).hasClass( 'field' ) &&
					om$Field !== om$SET
				) {
					var start = ( ' ' + subNode.className ).indexOf( ' fld-' );
					
					if ( start >= 0 ) {
						var end = ( subNode.className + ' ' ).indexOf( ' ', start );
						om$CurField = subNode.className.substring( start + 4, end );
					}
					
					om$NewClasses = 'lang-' + ( om$CurLanguageId || 'other' ) +
						( om$CurField  ? ' fldt-' + om$CurField : '' );
					
					if ( $subNode.hasClass( 'field-keep' ) ) {
						om$Field = om$KEEP;
					} else if ( $subNode.hasClass( 'field-pl' ) ) {
						om$Field = om$PL;
					} else if ( $subNode.hasClass( 'field-foreign' ) ) {
						om$Field = om$FOREIGN;
					} else if ( $subNode.hasClass( 'field-exampl' ) ) {
						om$Field = om$EXAMPL;
					} else if ( $subNode.hasClass( 'field-transl' ) ) {
						om$Field = om$TRANSL;
					} else if ( $subNode.hasClass( 'field-esperanto' ) ) {
						om$Field = om$ESPERANTO;
					}
				}
			}

			var newLang = null;
			if (
				(
					om$Field === om$PL &&
					//nie jest to rozwinięcie skrótu
					om$ExpliciteBlock == 0
				) ||
				//przykłady za strzałką
				om$ArrowPassed == 1
			) {
				newLang = 'pl';
			}

			if ( om$Field === om$ESPERANTO ) {
				newLang = 'eo';
			}

			if (
				(
					om$Field == om$FOREIGN ||
					om$Field == om$EXAMPL ||
					om$Field == om$SET ||
					om$ExpliciteBlock > 0
				) &&
				om$ArrowPassed == 0
			) {
				newLang = om$CurLanguageId;
			}
			
			// wyjątek: rozwinięcie skrótów w użyciu międzynarodowym,
			// pole znaczeń (np. [[BWA#inter]])
			if (
				om$Field == om$PL &&
				om$ExpliciteBlock > 0 &&
				om$CurLanguageId === 'inter'
			) {
				newLang = 'pl';
			}

			if ( om$Field === om$TRANSL ) {
				newLang = om$TransSection;
			}

			if ( om$Field === om$TABLE ) {
				newLang = om$LangOfColumn[ om$Column ];
			}
			
			if (newLang) {
				$subNode.addClass("text-" + newLang)
			}
			
			if ( om$Field == om$PL && om$DefHeader ) {
				newLang = om$CurLanguageId; // naglowek w polu znaczen
			}
			
			if ( nodeName === 'a' ) {
				var href, isSelfLink;
				
				if (
					config.wgNamespaceNumber === 0 &&
					$subNode.hasClass( 'mw-selflink' )
				) {
					isSelfLink = true;
					href = om$LocationUrl;
					
					try {
						subNode.setAttribute( 'href', om$LocationUrl );
					} catch ( err ) {
						var hrefAttr = document.createAttribute( 'href' );
						subNode.setAttribute( hrefAttr, om$LocationUrl );
					}
				} else if (
					config.wgNamespaceNumber === 0 &&
					$subNode.hasClass( 'mw-selflink-fragment' )
				) {
					isSelfLink = true;
					href = om$LocationUrl + subNode.getAttribute( 'href' );
					
					try {
						subNode.setAttribute( 'href', href );
					} catch ( err ) {
						var hrefAttr = document.createAttribute( 'href' );
						subNode.setAttribute( hrefAttr, href );
					}
				} else {
					isSelfLink = false;
					href = subNode.getAttribute( 'href' );
				}

				if ( href ) {
					var startTitle = href.lastIndexOf( '/' ) + 1;
					//var firstChar=href.charAt(startTitle).toLowerCase();
					
					if (
						newLang != null &&
						// wykluczenie innych przestrzeni nazw oraz linków zewnętrznych
						// TODO: ignoruje linki do haseł z dwukropkiem w nazwie
						// przykład: [[daj kurze grzędę, a ona: wyżej siędę]]
						( href.indexOf( ':' ) < 0 ||
							href.substring( 0, config.wgServer.length ) === config.wgServer &&
							href.substring( config.wgServer.length ).indexOf( ':' ) < 0
						) &&
						// wykluczenie linków do siostrzanych projektów
						subNode.className.indexOf( 'extiw' ) === -1 &&
						href.indexOf( '/S%C5%82ownik_' ) < 0 && //nie jest to link np. do Słownika języka pol.
						href.indexOf( '#' ) < 0 && //sekcja nie jest podana w linku
						//!$subNode.hasClass( 'new' ) && //nie jest to czerwony link
						( href.indexOf( '?' ) < 0 || href.indexOf( '&action=edit' ) >= 0 ) && //np. link pod polem edycji
						// nie jest to liczba, ale może być np. "1."
						!om$reNumber.test( href.substring( startTitle ) ) &&
						( om$Field == om$SET || om$Field == om$TABLE ||
							om$CurField != '' && om$CurLanguageId != '')
					) {
						href += '#' + newLang;
						subNode.setAttribute( 'href', href );
					}
					
					var i = href.indexOf( '#' );

					//wyłączenie boldów w self-linkach
					if ( isSelfLink && (
						i === -1 ||
						href === '#' ||
						!(
							href.substring( i + 1 ) === om$CurLanguageId ||
							href.substring( i + 1 ) === om$CurSectionName
						) ||
						( om$LocationUrl + '#' ).indexOf( href.substring( 0, i + 1 ) ) === -1 ||
						href.endsWith( '#zh' ) ||
						href.endsWith( '#zh-char' ) ||
						href.endsWith( '#zh-min-nan' ) ||
						href.endsWith( '#ja' ) ||
						href.endsWith( '#gan' ) ||
						href.endsWith( '#hak' ) ||
						href.endsWith( '#cdo' ) ||
						href.endsWith( '#chi' ) ||
						href.endsWith( '#djk' ) ||
						href.endsWith( '#wuu' ) ||
						href.endsWith( '#akk' ) ||
						href.endsWith( '#hit' ) ||
						href.endsWith( '#peo' ) ||
						href.endsWith( '#sux' )
					) ) {
						$subNode.addClass( 'mw-selflink-suppressed' );
					}
				}
			}
			
			// pusty <dd> w każdym polu: [[Dyskusja szablonu:pole#Dwukropek]]
			if ( nodeName === 'dd' && subNode.textContent === '' ) {
				subNode.parentNode.removeChild( subNode );
				j--;
				continue;
			}

			if ( nodeName === 'dd' || nodeName === 'li') {
				om$ExpliciteBlock = 0;
				om$ArrowPassed = 0;
				om$TransSection = 'other';
			}

			if ( nodeName === 'tr' ) {
				om$Column = 0;
				om$Row++;
			}
			
			if ( nodeName === 'th' || nodeName === 'td' ) {
				om$Column++;
			}

			if ( nodeName === 'p' && om$CurField === 'znaczenia' ) {
				om$DefHeader = 1;
			}
			
			if ( om$Field === om$TABLE && om$Row == 1 && !om$LangOfColumn[ om$Column ] ) {
				var text = subNode.innerHTML;
				
				if ( text == null ) {
					text = subNode.innerText;
				}
					
				if ( text != null ) {
					var i = text.indexOf( ' ' );
					
					if ( i >= 0 ) {
						text = text.substring( 0, i );
					}
						
					var iso = mw.libs.langData.lang2code[ text.toLowerCase() ];
					
					if ( iso ) {
						om$LangOfColumn[ om$Column ] = iso;
					}
				}
			}

			om$LastNodeName = nodeName;

			if ( nodeName === 'table' && om$Field !== om$SET ) {
				var field = om$Field;
				var column = om$Column;
				var row = om$Row;
				var lang = om$LangOfColumn;

				om$Field = om$TABLE;
				om$Column = 0;
				om$Row = 0;
				om$LangOfColumn = {};

				om$ChangeLinks( subNode );

				om$Field = field;
				om$Column = column;
				om$Row = row;
				om$LangOfColumn = lang;
			} else if ( nodeName === 'span' && $subNode.hasClass( 'set-foreign' ) ) {
				//obsługa linków z szablonów zobacz
				var field = om$Field;
				var arrow = om$ArrowPassed;
				var expl = om$ExpliciteBlock;
				
				om$Field = om$FOREIGN;
				om$ArrowPassed = 0;
				om$ExpliciteBlock = 0;

				//rekurencyjne przeszukanie podwęzłów
				om$ChangeLinks( subNode );

				om$Field = field;
				om$ArrowPassed = arrow;
				om$ExpliciteBlock = expl;
			} else if ( nodeName === 'span' && $subNode.hasClass( 'colLanguage' ) ) {
				//obsługa szablonu {{język kolumny}}
				var text = subNode.getAttribute( 'title' );
				
				if ( ( text + ' ' ).substring( 0, 1 ) === '#' ) {
					om$LangOfColumn[ om$Column ] = text.substring( 1 );
				} else if ( text != null ) {
					var i = text.indexOf( ' ' );
					
					if ( i >= 0 ) {
						text = text.substring( 0, i );
					}
					var iso = mw.libs.langData.lang2code[ text.toLowerCase() ];
					
					if ( iso ) {
						om$LangOfColumn[ om$Column ] = iso;
					}
				}

				//rekurencyjne przeszukanie podwęzłów
				om$ChangeLinks( subNode );
			} else {
				//rekurencyjne przeszukanie podwęzłów
				om$ChangeLinks( subNode );
			}

			if (
				om$NewClasses &&
				nodeName !== 'div' &&
				nodeName !== 'dl' &&
				!$subNode.hasClass( 'editsection' )
			) {
				$subNode.addClass( om$NewClasses );
			}
			
			if ( nodeName === 'p' && om$CurField === 'znaczenia' ) {
				om$DefHeader = 0;
			}
		}

		var cont = subNode.nodeValue;
		
		if ( cont != null && nodeName !== 'textarea' ) {
			var pos = cont.lastIndexOf( '(=' );
			
			if ( om$ExpliciteBlock == 0 && pos >= 0 && cont.indexOf( ')', pos ) < 0 ) {
				om$ExpliciteBlock = 1;
			} else if ( om$ExpliciteBlock == 1 && cont.indexOf( ')' ) >= 0 ) {
				om$ExpliciteBlock = 0;
			}
			
			if ( pos < 0 && om$ExpliciteBlock == 0 && cont.indexOf( '=' ) >= 0 ) {
				om$ExpliciteBlock = 2;
			}
			
			if ( subNode.nodeType === 1 ) {
				if ( subNode.getAttribute( 'title' ) == 'zobacz' ) {
					om$ExpliciteBlock = 2;
				}
			}
			
			if ( om$Field !== om$EXAMPL && cont.indexOf( '•' ) >= 0 ) {
				if (
					cont.indexOf( '→' ) >= 0 &&
					cont.indexOf( '•' ) < cont.indexOf( '→' )
				) {
					om$ArrowPassed = 1;
				} else {
					om$ArrowPassed = 0;
				}
			} else if ( cont.indexOf( '→' ) >= 0 ) {
				om$ArrowPassed = 1;
			}

			if ( om$Field === om$TRANSL ) {
				var i = cont.indexOf( ':' );
				
				if ( i > 0 ) {
					var lang = mw.libs.langData.lang2code[ cont.substring(
							cont.charAt( 0 ) === ' ' ? 1 : 0,
							i
						) ];
					
					if ( lang ) {
						om$TransSection = lang;
					}
				}
			}
		}
	}
};

if (
	!mw.util.getParamValue( 'nosectionlinks' ) &&
	config.wgNamespaceNumber >= 0 &&
	!config.wgPageName.endsWith( '.js' ) &&
	config.wgNamespaceNumber !== config.wgNamespaceIds.mediawiki
) {
	mw.libs.langData = require( 'ext.gadget.langdata' );
	
	om$LocationUrl = mw.format(
			config.wgArticlePath,
			encodeURIComponent( config.wgPageName )
				.replace( /%20/ig, ' ' )
				.replace( /%2F/ig, '/' )
				.replace( /%3A/ig, ':' )
		);

	mw.hook( 'wikipage.content' ).add( function ( $content ) {
		om$ChangeLinks( $content[ 0 ] );
	} );
}