Binding of Isaac: Rebirth Wiki
m (Erreurs)
m (Erreur de mot clé)
Ligne 107 : Ligne 107 :
 
if ( !row.source || !row.target ) {
 
if ( !row.source || !row.target ) {
 
$statusTd.css( 'color', 'darkred' ).html( '☒' );
 
$statusTd.css( 'color', 'darkred' ).html( '☒' );
return;
+
break;
 
}
 
}
   
Ligne 114 : Ligne 114 :
 
$tr.addClass( 'translation-list-uptodate' );
 
$tr.addClass( 'translation-list-uptodate' );
 
$statusTd.css( 'color', 'green' ).html( '☑' );
 
$statusTd.css( 'color', 'green' ).html( '☑' );
return;
+
break;
 
}
 
}
   

Version du 5 octobre 2020 à 15:32

$.when(
	mw.loader.using( [ 'mediawiki.api', 'mediawiki.ForeignApi' ] ),
	$.ready
).then( function () {
    var sourceWikiRoot = 'https://bindingofisaacrebirth.gamepedia.com',
        targetWikiRoot = 'https://bindingofisaacrebirth-fr.gamepedia.com',
        sourceApi      = new mw.ForeignApi( sourceWikiRoot + '/api.php' ),
		targetApi      = new mw.Api();

    /**
    * @typedef {{ pageid: string, title: string }} PageQueryResult
    * @typedef {{ page: string, revision: string }} CargoQueryResult
    * @typedef {{ source: PageQueryResult?, target: PageQueryResult?, oldRevision: number, newRevision: number }} RowData
    */

    $( '.translation-list' ).each( function () {
        new TranslationList( $( this ) );
    } );

    /**
     * @constructor
     * @param {JQuery} $table
     */
    function TranslationList( $table ) {
        var self      = this,
            namespace = $table.attr( 'data-translation-list-ns' );

        this.$table      = $table;
        this.namespace   = namespace ? +namespace : 0;
        /** @type {PageQueryResult[]} */
        this.sourcePages = [];
        /** @type {PageQueryResult[]} */
        this.targetPages = [];
        /** @type {RowData[]} */
        this.rows        = [];

        Promise.all( [
            apiQueryAllPages( sourceApi, this.namespace ),
            apiQueryAllPages( targetApi, this.namespace ),
            apiCargoQueryAll( targetApi )
        ] ).then( function ( data ) {
            self.onDataFetch( data );
        } );
    }

    /**
     * @param {[ PageQueryResult[], PageQueryResult[], CargoQueryResult[] ]} data
     */
    TranslationList.prototype.onDataFetch = function ( data ) {
        var self = this;

        this.sourcePages = data[ 0 ];
        this.targetPages = data[ 1 ];

        Promise.all( data[ 2 ].map( this.linkCargoTuple, this ) ).then( function ( rows ) {
            rows = self.sourcePages.reduce( accUnlinkedSourcePage, rows );
            rows = self.targetPages.reduce( accUnlinkedTargetPage, rows );
            self.rows = rows;
            self.fillTable();
        } );
    };

    TranslationList.prototype.fillTable = function () {
        var $table = this.$table,
            $tbody = $table.children( 'tbody' ).empty(),
            rows   = this.rows;

        for ( var i in rows ) {
            var row       = rows[ i ],
                $tr       = $( '<tr>' ).appendTo( $tbody ),
                $targetTd = $( '<td>' ).appendTo( $tr ),
                $lArrowTd = $( '<td>' ).appendTo( $tr ),
                $statusTd = $( '<td>' ).appendTo( $tr ),
                $rArrowTd = $( '<td>' ).appendTo( $tr ),
                $sourceTd = $( '<td>' ).appendTo( $tr );

            // TODO: Check if an existing function can be used instead.
            if ( $table.hasClass( 'mw-collapsed' ) ) {
                $tr.css( 'display', 'none' );
            }

            // Fills the source page cells
            if ( row.source ) {
                $rArrowTd.html( '←' );
                $sourceTd.html(
                    '<a href="' + sourceWikiRoot + '/index.php?curid=' + row.source.pageid + '">' +
                    row.source.title + '</a>'
                );
            } else {
                $tr.addClass( 'translation-list-nosource' );
                $rArrowTd.css( 'color', 'grey' ).html( '⬾' );
            }

            // Fills the target page cells
            if ( row.target ) {
                $targetTd.html(
                    '<a href="' + targetWikiRoot + '/index.php?curid=' + row.target.pageid + '">' +
                    row.target.title + '</a>'
                );
                $lArrowTd.html( '→' );
            } else {
                $tr.addClass( 'translation-list-notarget' );
                $lArrowTd.css( 'color', 'grey' ).html( '⥇' );
            }

            // If the source or target page is unlinked.
            if ( !row.source || !row.target ) {
                $statusTd.css( 'color', 'darkred' ).html( '☒' );
                break;
            }

            // If the translation is up-to-date.
            if ( row.oldRevision === row.newRevision ) {
                $tr.addClass( 'translation-list-uptodate' );
                $statusTd.css( 'color', 'green' ).html( '☑' );
                break;
            }

            // If the translation is outdated.
            $tr.addClass( 'translation-list-outdated' );
            $targetTd.html(
                '<a href="' + targetWikiRoot + '/index.php?curid=' + row.target.pageid +
                '&action=edit">' + row.target.title + '</a>'
            );
            $statusTd.html(
                '<a href="' + sourceWikiRoot + '/index.php?type=revision&diff=' + row.newRevision +
                '&oldid=' + row.oldRevision + '" style="color: red">☒</a>'
            );
        }
    };

    /**
     * @param {CargoQueryResult} cargoTuple
     */
    TranslationList.prototype.linkCargoTuple = function ( cargoTuple ) {
        /** @type {RowData} */
        var row = {
            source: null,
            target: null,
            oldRevision: +cargoTuple.revision,
            newRevision: 0
        };

        var targetPageTitle = cargoTuple.page;
        var targetPage      = this.targetPages.find( function ( targetPage ) {
            return targetPage.title === targetPageTitle;
        } );

        if ( !targetPage ) {
            mw.log.warn( 'Missing page ("' + row.oldRevision + '") with translation template.' );
            return row;
        }

        row.target = {
            pageid: targetPage.pageid,
            title: targetPage.title
        };

        return sourceApi.get( {
            action: 'query',
            prop: 'info',
            revids: row.oldRevision
        } ).then( function ( data ) {
            /** @type {?{ [ key: string ]: PageQueryResult & { lastrevid: string } }} */
            var pages = data.query.pages;

            if ( !pages || pages[ '-1' ] ) {
                mw.log.warn(
                    'Invalid revision ID ("' + row.oldRevision + '") from translation template ' +
                    'on page "' + row.target.title + '".'
                );
                return row;
            }

            for ( var i in pages ) {
                var sourcePage = pages[ i ];
                row.source = {
                    pageid: i,
                    title: sourcePage.title
                };
                row.newRevision = +sourcePage.lastrevid;
            }

            return row;
        } );
    };

    /**
     * @param {RowData[]} rows
     * @param {PageQueryResult} sourcePage
     */
    function accUnlinkedSourcePage( rows, sourcePage ) {
        var pageid = sourcePage.pageid;

        if ( rows.find( function ( row ) {
            return row.source && row.source.pageid === pageid;
        } ) ) {
            rows.push( {
                source: {
                    pageid: pageid,
                    title: sourcePage.title
                },
                target: null,
                oldRevision: 0,
                newRevision: 0
            } );
        }

        return rows;
    }

    /**
     * @param {RowData[]} rows
     * @param {PageQueryResult} targetPage
     */
    function accUnlinkedTargetPage( rows, targetPage ) {
        var pageid = targetPage.pageid;

        if ( rows.find( function ( row ) {
            return row.target && row.target.pageid === pageid;
        } ) ) {
            rows.push( {
                source: null,
                target: {
                    pageid: pageid,
                    title: targetPage.title
                },
                oldRevision: 0,
                newRevision: 0
            } );
        }

        return rows;
    }

    /**
     * Queries all pages from a specific namespace.
     * @param {mwApi} api MediaWiki API.
     * @param {number} namespace Namespace title.
     * @returns The page array promise.
     */
    function apiQueryAllPages( api, namespace ) {
        var args = {
            action: 'query',
            list: 'allpages',
            rawcontinue: true,
            aplimit: 500,
            apnamespace: namespace
        };
        return _apiQueryAllPages( api, args, [] );
    }
    /**
     * @param {mwApi} api
     * @param {*} args
     * @param {PageQueryResult[]} storage
     * @returns {PageQueryResult[] | JQuery.Promise<PageQueryResult[]>}
     */
    function _apiQueryAllPages( api, args, storage ) {
        return api.get( args ).then( function ( data ) {
            storage = storage ? storage.concat( data.query.allpages ) : data.query.allpages;
            if ( !data[ 'query-continue' ] ) {
                return storage;
            }
            for ( var i in data[ 'query-continue' ] ) {
                for ( var arg in data[ 'query-continue' ][ i ] ) {
                    args[ arg ] = data[ 'query-continue' ][ i ][ arg ];
                }
            }
            return _apiQueryAllPages( api, args, storage );
        } );
    }

    /**
     * Queries all tuples from the maintenance Cargo table.
     * @param {mwApi} api MediaWiki API.
     * @returns The tuple array promise.
     */
    function apiCargoQueryAll( api ) {
        return api.get( {
            action: 'cargoquery',
            tables: 'maintenance',
            fields: '_pageName=page,revision',
            limit: 500
        } ).then( getCargoDataTitles );
    }

    /**
     * Gets the title objects from a Cargo query result.
     * @param {{ cargoquery: { title: CargoQueryResult }[] }} data 
     */
    function getCargoDataTitles( data ) {
        return data.cargoquery.map( getTitle );
    }

    /**
     * Gets the title property of an object.
     * @template T
     * @param {{ title: T }} obj Object.
     * @returns The title property of the given object.
     */
    function getTitle( obj ) {
        return obj.title;
    }
} );