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>