MediaWiki:Gadget-verifEbauche.js

Note : après avoir enregistré la page, vous devrez forcer le rechargement complet du cache de votre navigateur pour voir les changements.

Mozilla / Firefox / Konqueror / Safari : maintenez la touche Majuscule (Shift) en cliquant sur le bouton Actualiser (Reload) ou pressez Maj-Ctrl-R (Cmd-R sur Apple Mac) ;

Chrome / Internet Explorer / Opera : maintenez la touche Ctrl en cliquant sur le bouton Actualiser ou pressez Ctrl-F5.
// {{Projet:JavaScript/Script|VerifEbauche}}
/* globals mw, OO, $ */

$.when( mw.loader.using( 'mediawiki.util' ), $.ready ).done( function () {
    'use strict';

    //internationalization messages
    var messages = {
        'fr': {
            'verifebauche-portlet-text': 'Vérif. ébauches',
            'verifebauche-portlet-tooltip': 'Vérifier les liens de cette page menant vers des pages d\'ébauche',
            'verifebauche-popup-confirm': 'liens vont être analysés.',
            'verifebauche-popup-msg-no-link': 'Aucun lien vers une page d’ébauche n’a été trouvé.',
            'verifebauche-popup-msg-one-link': '1 lien vers une page d’ébauche a été trouvé.',
            'verifebauche-popup-msg-link-found': 'liens vers des pages d’ébauche ont été trouvés.'
        },

        'en': {
            'verifebauche-portlet-text': 'Check stubs',
            'verifebauche-portlet-tooltip': 'Check links on this page that lead to stub pages',
            'verifebauche-popup-confirm': 'links will be analyzed.',
            'verifebauche-popup-msg-no-link': 'No links found.',
            'verifebauche-popup-msg-one-link': '1 link to a stub found.',
            'verifebauche-popup-msg-link-found': 'links to stubs found.'
        }
    };

    //setting the fallback language
    mw.messages.set( messages.en );

    var lang = mw.config.get( 'wgUserLanguage' );
    if ( lang !== 'en' && lang in messages ) {
        mw.messages.set( messages[ lang ] );
    }

    var portlet = mw.util.addPortletLink( 'p-tb', '#', mw.msg( 'verifebauche-portlet-text' ), 't-ebauche', mw.msg( 'verifebauche-portlet-tooltip' ) );
    $( portlet ).click( function ( event ) {
        event.preventDefault();
        mw.loader.using( [ 'mediawiki.api', 'oojs-ui-windows' ], function () {
            process();
        } );
    } );

    function process() {
        var nbLinks = 0;
        var titlesToLinks = {};
        var compteurEbauches = 0;

        var server = mw.config.get( 'wgServer' );
        if ( server.indexOf( '//' ) === 0 ) {
            server = 'https:' + server;
        }
        var hrefSelf = server + '/wiki/' + encodeURI( mw.config.get( 'wgPageName' ) );

        $( '#mw-content-text' ).find( 'a' ).each( function ( i, link ) {
            /* jshint laxbreak: true, scripturl: true */
            if ( ! (
                ! link.href
                || link.href.indexOf( 'javascript:' ) === 0
                || link.href === hrefSelf
                || link.href.indexOf( hrefSelf + '#' ) === 0
                || link.classList.contains( 'external' )
                || link.classList.contains( 'extiw' )
                || link.classList.contains( 'new' )
                || link.classList.contains( 'image' )
                || link.classList.contains( 'mw-file-description' ) // see [[mw:Parsoid/Parser Unification/Media structure/FAQ]]
                || link.classList.contains( 'noprint' )
                || link.closest( '.toc, .mw-editsection, .noprint, .bandeau-article, .bandeau-portail, .wd_identifiers, .cachelinks' )
            ) ) {
                nbLinks++;

                var title = link.title || link.textContent;

                if ( !titlesToLinks[ title ] ) {
                    titlesToLinks[ title ] = [ link ];
                } else {
                    titlesToLinks[ title ].push( link );
                }
            }
        } );

        OO.ui.confirm( nbLinks + ' ' + mw.msg( 'verifebauche-popup-confirm' ) ).done( function ( confirmed ) {
            if ( confirmed ) {
                verifEbauche();
            }
        } );

        function verifEbauche() {
            var titles = Object.keys( titlesToLinks );

            var userGroups = mw.config.get( 'wgUserGroups' );
            var titlesLimit = ( userGroups.indexOf( 'sysop' ) > -1 || userGroups.indexOf( 'bot' ) > -1 ) ? 500 : 50;

            var chunks = makeChunks( titles, titlesLimit );

            var api = new mw.Api();

            function request( chunkIndex ) {
                var chunk = chunks[ chunkIndex ];
                if ( !chunk ) {
                    resultMessage();
                    return;
                }

                // requêtes POST, car avec des requêtes GET on peut avoir des erreurs "414 URI Too Long"
                api.post( {
                    action: 'query',
                    prop: 'templates',
                    tltemplates: 'Modèle:Ébauche',
                    titles: chunk,
                    redirects: true,
                    formatversion: 2
                } )
                .then( function ( data ) {
                    // protection : si la requête ne retourne aucune page, le résultat ne contient pas d'array "pages"
                    // (par exemple, si une page est en fait un interwiki, qui n'a pas été détecté et exclu en amont,
                    // elle n'est pas ajoutée dans l'array "pages", mais dans un autre array "interwiki")
                    if ( !data.query.pages ) {
                        return;
                    }

                    // avec les redirects, l'API retourne les résultats pour les pages de destination,
                    // et il retourne aussi la liste des redirects, il faut donc modifier titlesToLinks
                    // pour que les liens soient rangés dans les pages de destination
                    if ( data.query.redirects ) {
                        data.query.redirects.forEach( function ( redirect ) {
                            var redirFrom = redirect.from;
                            var redirTo = redirect.to;

                            if ( !titlesToLinks[ redirTo ] ) {
                                titlesToLinks[ redirTo ] = titlesToLinks[ redirFrom ];
                            } else {
                                titlesToLinks[ redirTo ] = titlesToLinks[ redirTo ].concat( titlesToLinks[ redirFrom ] );
                            }

                            delete titlesToLinks[ redirFrom ]; // pas indispensable, c'est seulement pour nettoyer
                        } );
                    }

                    data.query.pages.forEach( function ( page ) {
                        var links = titlesToLinks[ page.title ];

                        // simple sécurité, même si normalement l'API ne devrait jamais
                        // retourner d'autres pages que celles qui ont été demandées
                        // (à l'exception des redirects, cf. traitement juste au-dessus)
                        if ( !links ) {
                            return;
                        }

                        // si des templates sont retournés, il y en a un seul et c'est celui d'ébauche
                        if ( page.templates ) {
                            links.forEach( function ( link ) {
                                link.style.backgroundColor = '#FFCCCC';
                                compteurEbauches++;
                            } );
                        } else {
                            links.forEach( function ( link ) {
                                link.style.backgroundColor = '#C8FFC8';
                            } );
                        }
                    } );

                    request( chunkIndex + 1 );
                } );
            }

            request( 0 );
        }

        function resultMessage() {
            var msg;
            if ( compteurEbauches === 0 ) {
                msg = mw.msg( 'verifebauche-popup-msg-no-link' );
            } else if ( compteurEbauches === 1 ) {
                msg = mw.msg( 'verifebauche-popup-msg-one-link' );
            } else {
                msg = compteurEbauches + ' ' + mw.msg( 'verifebauche-popup-msg-link-found' );
            }

            OO.ui.alert( msg );
        }
    }

    // Utilities

    function makeChunks( arr, size ) {
        var chunks = [];
        for ( var i = 0; i < arr.length; i += size ) {
            chunks.push( arr.slice( i, i + size ) );
        }
        return chunks;
    }

} );