Hinweis: Leere nach dem Veröffentlichen den Browser-Cache, um die Änderungen sehen zu können.

  • Firefox/Safari: Umschalttaste drücken und gleichzeitig Aktualisieren anklicken oder entweder Strg+F5 oder Strg+R (⌘+R auf dem Mac) drücken
  • Google Chrome: Umschalttaste+Strg+R (⌘+Umschalttaste+R auf dem Mac) drücken
  • Edge: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
// <nowiki> /* eslint-disable max-len */ /******************************************************************************  * SisterWeblinks  * Kopiert Links auf einige ausgewählte Schwesterprojekte in den Abschnitt „Weblinks“  *  * License: CC0  * Maintainer: nw520  ******************************************************************************/  ( () => { 	const strings = { 		'voy-sisterweblinks-sisterdescription-commons': { 			de: 'Sammlung von Bildern, Videos und Audiodateien' 		}, 		'voy-sisterweblinks-sisterdescription-wikinews': { 			de: 'Nachrichten' 		}, 		'voy-sisterweblinks-sisterdescription-wikipedia': { 			de: 'Enzyklopädie' 		} 	};  	function main() { 		mw.hook( 'wikipage.content' ).add( ( $el ) => { 			const parserOutput = $el[ 0 ].querySelector( '.mw-parser-output' );  			if ( parserOutput === null ) { 				return; 			}  			let insertPoint = findWeblinksInsertPoint( parserOutput ); 			if ( insertPoint.insertPoint === null ) { 				mw.log.warn( '[SisterWeblinks] Failed to find insert point.' ); 				return; 			}  			// Create list after insert point, if needed 			if ( !insertPoint.isList ) { 				const list = document.createElement( 'ul' ); 				insertPoint.insertPoint.insertAdjacentElement( 'afterend', list ); 				insertPoint.insertPoint = list; 				insertPoint.location = 'beforeend'; 			}  			const sitelinks = getSitelinks(); 			if ( sitelinks === null ) { 				throw new Error( '[SisterWeblinks] Failed to get insert point.' ); 			}  			setupStrings(); 			insertSitelinks( sitelinks, insertPoint.insertPoint, insertPoint.location ); 		} ); 	}  	/** 	 * Creates a list item for a sitelink. 	 * 	 * @param  {Object} sitelink 	 * @return {HTMLElement} 	 */ 	function createItem( sitelink ) { 		let projectMeta = getProjectMeta( sitelink.project ); 		if ( projectMeta === null ) { 			return null; 		}  		const li = document.createElement( 'li' ); 		const a = document.createElement( 'a' ); 		a.href = sitelink.url;  		if ( ( projectMeta.logo ?? null ) !== null ) { 			const logo = document.createElement( 'img' ); 			logo.height = 16; 			logo.width = 16; 			logo.src = projectMeta.logo; 			a.appendChild( logo ); 			a.appendChild( document.createTextNode( ' ' ) ); 		}  		a.appendChild( document.createTextNode( projectMeta.name ) );  		li.appendChild( a );  		if ( ( projectMeta.description ?? null ) !== null ) { 			li.appendChild( document.createTextNode( ` – ${projectMeta.description}` ) ); 		}  		return li; 	}  	/** 	 * Scans an article for the #Weblinks-section. 	 * 	 * @param  {HTMLElement} parserOutput 	 * @return {Object} 	 */ 	function findWeblinksInsertPoint( parserOutput ) { 		let weblinksSectionElement = null; 		let weblinksLastListElement = null; 		let weblinksLastElement = null;  		for ( const el of [ ...parserOutput.querySelectorAll( '.mw-parser-output > *' ) ] ) { 			if ( el.matches( 'h2' ) ) { 				if ( weblinksSectionElement !== null ) { 					// We already found #Weblinks. 					// Since this section is on the same hierarchical level, #Weblinks has just concluded. 					// Therefore, we can terminate. 					break; 				}  				if ( el.querySelector( '.mw-headline' ) !== null && el.querySelector( '.mw-headline' ).textContent === 'Weblinks' ) { 					// We found #Weblinks. 					weblinksSectionElement = el; 				} else { 					// This section is not #Weblinks. 					continue; 				} 			}  			if ( weblinksSectionElement === null ) { 				// #Weblinks was not found yet 				continue; 			}  			if ( el.matches( 'ul' ) ) { 				weblinksLastListElement = el; 			} 			 			if ( el.matches( 'div' ) || el.matches( 'table' ) ) { 				// We don't want to insert below divs or tables, therefore terminate 				break; 			}  			weblinksLastElement = el; 		}  		return { 			insertPoint: weblinksLastListElement?.lastChild ?? weblinksLastElement, 			isList: weblinksLastListElement !== null, 			location: 'afterend', 			sectionElement: weblinksSectionElement, 			lastListElement: weblinksLastListElement, 			lastElement: weblinksLastElement 		}; 	}  	/** 	 * Returns meta data for sister projects. 	 * 	 * @param  {string} project 	 * @return {Object} 	 */ 	function getProjectMeta( project ) { 		switch ( project ) { 			case 'commons': 				return { 					description: mw.msg( 'voy-sisterweblinks-sisterdescription-commons' ), 					logo: 'https://commons.wikimedia.org/wiki/Special:FilePath/File:Commons-logo.svg', 					name: 'Commons' 				}; 			case 'wikinews': 				return { 					description: mw.msg( 'voy-sisterweblinks-sisterdescription-wikinews' ), 					logo: 'https://commons.wikimedia.org/wiki/Special:FilePath/File:Wikinews-logo.svg', 					name: 'Wikinews' 				}; 			case 'wikipedia': 				return { 					description: mw.msg( 'voy-sisterweblinks-sisterdescription-wikipedia' ), 					logo: 'https://commons.wikimedia.org/wiki/Special:FilePath/File:Wikipedia-logo-v2.svg', 					name: 'Wikipedia' 				}; 			default: 				mw.log.error( `[SisterWeblinks] Unknown sister project ${sitelink.project}` ); 				return null; 		} 	}  	/** 	 * Extracts the sister project's name from a portlet. 	 * @param  {HTMLElement} el 	 * @return {string} 	 */ 	function getProjectName( el ) { 		if ( el.matches( '.wb-otherproject-commons' ) ) { 			return 'commons'; 		} else if ( el.matches( '.wb-otherproject-wikinews' ) ) { 			return 'wikinews'; 		} else if ( el.matches( '.wb-otherproject-wikipedia' ) ) { 			return 'wikipedia'; 		} else if ( el.matches( '.wb-otherproject-wikiquote' ) ) { 			return 'wikiquote'; 		} else if ( el.matches( '.wb-otherproject-wikisource' ) ) { 			return 'wikisource'; 		} else { 			return null; 		} 	}  	/** 	 * Returns a list of sitelinks. 	 * 	 * Tested for monobook, timeless, vector-{2020,legacy}. 	 * Does not work for Minerva. 	 * 	 * @return {Object} 	 */ 	function getSitelinks() { 		const links = document.querySelectorAll( '.wb-otherproject-link' );  		return [ ...links ].map( ( el ) => { 			return { 				project: getProjectName( el ), 				url: el.querySelector( 'a' ).href 			}; 		} ); 	}  	/** 	 * Generates and inserts a sister project's sitelink. 	 * 	 * @param  {Object[]} sitelinks 	 * @param  {HTMLElement} insertPoint 	 * @param  {string} location 	 */ 	function insertSitelinks( sitelinks, insertPoint, location ) { 		let insertAfter = insertPoint; 		let insertLocation = location; 		const sitelinksOrder = { 			commons: 1, 			wikinews: 2, 			wikipedia: 0 		};  		// Filter and sort 		const orderedSitelinks = sitelinks.filter( ( sitelink ) => { 			return sitelinksOrder[ sitelink.project ] !== undefined; 		} ).sort( ( left, right ) => { 			const l = sitelinksOrder[ left.project ]; 			const r = sitelinksOrder[ right.project ];  			if ( l < r ) { 				return -1; 			} else if ( l > r ) { 				return 1; 			} else { 				return 0; 			} 		} );  		for ( const sitelink of orderedSitelinks ) { 			const li = createItem( sitelink );  			if ( li === null ) { 				continue; 			}  			insertAfter.insertAdjacentElement( location, li ); 			insertAfter = li; 			location = 'afterend'; 		} 	}  	function setupStrings() { 		const lang = mw.config.get( 'wgUserLanguage' ); 		mw.messages.set( Object.fromEntries( Object.keys( strings ).map( ( stringKey ) => { 			return [ stringKey, strings[ stringKey ][ lang ] ?? strings[ stringKey ].en ]; 		} ) ) ); 	}  	main(); } )(); // </nowiki>