Differenze tra le versioni di "MediaWiki:Gadget-minipedia.js"
Jump to navigation
Jump to search
m (now the $.when( $.ready ) is not useful) |
(introduce stats box) |
||
Riga 8: | Riga 8: | ||
* @revision 2020-06-27 |
* @revision 2020-06-27 |
||
*/ |
*/ |
||
− | + | ( function ( $, mw ) { |
|
/* |
/* |
||
Riga 37: | Riga 37: | ||
createMinipediaPageTitle: "Accesso Minipedia", |
createMinipediaPageTitle: "Accesso Minipedia", |
||
createMinipediaPageBody: "Sii il primo a creare una versione più ridotta e più accessibile di questa voce, in Minipedia!", |
createMinipediaPageBody: "Sii il primo a creare una versione più ridotta e più accessibile di questa voce, in Minipedia!", |
||
+ | statsTitle: "Mini Report", |
||
+ | statsWords: "Parole", |
||
+ | statsLines: "Paragrafi", |
||
+ | statsComplexWords: "Parole complesse", |
||
}; |
}; |
||
Riga 51: | Riga 55: | ||
// default edit intro page title |
// default edit intro page title |
||
mp.editIntro = mp.editIntro || 'Progetto:Minipedia/Creazione voce'; |
mp.editIntro = mp.editIntro || 'Progetto:Minipedia/Creazione voce'; |
||
+ | |||
+ | // how much characters should have a word to be considered too much lon |
||
+ | // this somehow help people with dyslexia |
||
+ | mp.longWordLen = 13; |
||
// localization stuff |
// localization stuff |
||
Riga 86: | Riga 94: | ||
// no page no party |
// no page no party |
||
return false; |
return false; |
||
+ | }; |
||
+ | |||
+ | /** |
||
+ | * Get a fresh MediaWiki API object |
||
+ | * |
||
+ | * @return mw.Api |
||
+ | */ |
||
+ | function mwApi() { |
||
+ | return mw.loader.using( 'mediawiki.api' ).then( function() { |
||
+ | return new mw.Api(); |
||
+ | } ); |
||
}; |
}; |
||
Riga 96: | Riga 115: | ||
function pageExists( title ) { |
function pageExists( title ) { |
||
− | // |
+ | // prepare the API request |
+ | var request = { |
||
− | // TODO: check if it's called everytime and eventually put dependency in ResourceLoader |
||
+ | action: 'query', |
||
− | // this returns the Promise created downstream (false or existing page) |
||
+ | prop: 'info', |
||
− | return mw.loader.using( 'mediawiki.api' ).then( function() { |
||
+ | titles: title, |
||
+ | }; |
||
− | + | // eventually load API stuff |
|
+ | return mwApi().then( function( api ) { |
||
− | var request = { |
||
− | action: 'query', |
||
− | prop: 'info', |
||
− | titles: title |
||
− | }; |
||
− | // make the API request |
+ | // make the API request |
+ | return api.get( request ).then( function ( response ) { |
||
− | // resolve the parent Promise with another Promise giving the existing page or false |
||
− | return ( new mw.Api() ).get( request ).then( function ( response ) { |
||
// check if it exists |
// check if it exists |
||
Riga 120: | Riga 136: | ||
return false; |
return false; |
||
} ); |
} ); |
||
+ | } ); |
||
+ | }; |
||
+ | |||
+ | /** |
||
+ | * Query the current page plain text |
||
+ | * |
||
+ | * @return Promise |
||
+ | */ |
||
+ | function queryPlainText() { |
||
+ | |||
+ | // complete page title with namespace |
||
+ | var pageName = mw.config.get( 'wgPageName' ); |
||
+ | |||
+ | // prepare the API request |
||
+ | // See https://phabricator.wikimedia.org/T259332 |
||
+ | var request = { |
||
+ | action: 'query', |
||
+ | prop: 'extracts', |
||
+ | titles: pageName, |
||
+ | explaintext: 1, |
||
+ | exlimit: 1, |
||
+ | exsectionformat: 'plain', |
||
+ | }; |
||
+ | |||
+ | // this will return a Promise resolving the page plain text, returned upstream |
||
+ | return mwApi().then( function( api ) { |
||
+ | |||
+ | // make the API request and return a Promise |
||
+ | return api.get( request ).then( function( response ) { |
||
+ | // resolve the Promise with the page content |
||
+ | var page = justFirstQueryPage( response ); |
||
+ | if( page && page.pageid && page.pageid > 0 && page.extract ) { |
||
+ | return page.extract; |
||
+ | } |
||
+ | |||
+ | // no content |
||
+ | return false; |
||
+ | |||
+ | } ); |
||
} ); |
} ); |
||
}; |
}; |
||
Riga 214: | Riga 269: | ||
// check if you accepted the page creation |
// check if you accepted the page creation |
||
windowInstance.closed.then( function ( data ) { |
windowInstance.closed.then( function ( data ) { |
||
+ | |||
+ | // user is confirming action |
||
if( data.action === 'accept' ) { |
if( data.action === 'accept' ) { |
||
Riga 235: | Riga 292: | ||
}; |
}; |
||
// end prepareNormalWiki() |
// end prepareNormalWiki() |
||
+ | |||
+ | /** |
||
+ | * Calculate some stats over a text |
||
+ | */ |
||
+ | function textStats( text ) { |
||
+ | |||
+ | var stats = {}; |
||
+ | |||
+ | text = text.trim(); |
||
+ | |||
+ | // count long words |
||
+ | var totalLongWords = 0; |
||
+ | var word, words = text.split( /\s+/ ); |
||
+ | for( var i = 0; i < words.length; i++ ) { |
||
+ | word = words[i]; |
||
+ | if( word.length > mp.longWordLen ) { |
||
+ | totalLongWords++; |
||
+ | } |
||
+ | } |
||
+ | |||
+ | // how much lines? |
||
+ | stats.totalLines = text.split( "\n+" ).length; |
||
+ | |||
+ | // how much words? |
||
+ | stats.totalWords = words.length; |
||
+ | |||
+ | // how much of these words are so much long? |
||
+ | // See 'longWordLen' |
||
+ | stats.totalLongWords = totalLongWords; |
||
+ | |||
+ | return stats; |
||
+ | }; |
||
+ | |||
+ | /** |
||
+ | * Query content stats of the current page |
||
+ | * |
||
+ | * @return Promise |
||
+ | */ |
||
+ | function queryContentStats() { |
||
+ | return queryPlainText().then( textStats ); |
||
+ | }; |
||
+ | |||
+ | /** |
||
+ | * Prepare the Minipedia stats box |
||
+ | */ |
||
+ | function prepareMinipediaStatsBox() { |
||
+ | |||
+ | // body container |
||
+ | var $contentText = $( '#mw-content-text' ); |
||
+ | |||
+ | // prepare the DOM tree |
||
+ | var $container = $( '<div>' ); |
||
+ | var $table = $( '<table>' ); |
||
+ | var $thead = $( '<tbody>' ); |
||
+ | |||
+ | // prepare the stats container |
||
+ | $container.addClass( 'minipedia-stats' ); |
||
+ | |||
+ | // put a title |
||
+ | $container.append( $( '<h2>' ).text( mp.L10N.statsTitle ) ); |
||
+ | |||
+ | // put the table |
||
+ | $container.append( $table ); |
||
+ | |||
+ | // prepare the table |
||
+ | $table.addClass( 'wikitable' ) |
||
+ | .append( $thead ); |
||
+ | |||
+ | /** |
||
+ | * Append a row (with a label and a value) into a table |
||
+ | * |
||
+ | * @param {Object} jQuery table |
||
+ | * @param {String} className |
||
+ | * @param {String} label |
||
+ | * @param {String} value |
||
+ | */ |
||
+ | function appendTableStatsRow( $table, className, label, value ) { |
||
+ | var $tr = $( '<tr>' ); |
||
+ | $tr.addClass( 'minipedia-stats-row-' + className ); |
||
+ | $tr.append( $( '<td>' ).text( label ) ); |
||
+ | $tr.append( $( '<td>' ).text( value ) ); |
||
+ | $table.append( $tr ); |
||
+ | }; |
||
+ | |||
+ | // query the page plain text |
||
+ | queryContentStats().then( function( stats ) { |
||
+ | |||
+ | // show the number of words, lines and complex words (actually just long words) |
||
+ | appendTableStatsRow( $table, 'long-words', mp.L10N.statsComplexWords, stats.totalLongWords ); |
||
+ | appendTableStatsRow( $table, 'words', mp.L10N.statsWords, stats.totalWords ); |
||
+ | appendTableStatsRow( $table, 'lines', mp.L10N.statsLines, stats.totalLines ); |
||
+ | } ); |
||
+ | |||
+ | // show the stats container at the bottom of the page |
||
+ | $contentText.append( $container ); |
||
+ | }; |
||
/** |
/** |
||
Riga 240: | Riga 393: | ||
*/ |
*/ |
||
function prepareMinipedia() { |
function prepareMinipedia() { |
||
+ | |||
+ | // action of the page (edit, view etc.) |
||
+ | var action = mw.config.get( 'wgAction' ); |
||
// normal page title and mini version |
// normal page title and mini version |
||
Riga 261: | Riga 417: | ||
L10N.openNormalpedia |
L10N.openNormalpedia |
||
); |
); |
||
+ | |||
+ | // check if we are in view mode |
||
+ | if( action === 'view' ) { |
||
+ | |||
+ | // in view mode we can fetch the stats |
||
+ | prepareMinipediaStatsBox(); |
||
+ | } |
||
}; |
}; |
||
// end prepareMinipedia() |
// end prepareMinipedia() |
||
Riga 273: | Riga 436: | ||
// end namespace zero check |
// end namespace zero check |
||
− | } ); |
+ | } )( $, mw ); |
Versione delle 17:21, 31 lug 2020
/** * Make Minipedia magics * * Dependencies: mediawiki.util * * See https://phabricator.wikimedia.org/tag/minipedia/ * * @revision 2020-06-27 */ ( function ( $, mw ) { /* * CONFIGURATION/LOCALIZATION INSTRUCTIONS * * Declare somewhere something like this: * * // assure that you do not overwrite other-people customizations * window.MiniPedia = window.MiniPedia || {}; * window.MiniPedia.L10N = window.MiniPedia.L10N || {}; * * // then customize something * window.MiniPedia.editIntro = 'Project:How to create'; * window.MiniPedia.L10N.minipedia = 'Otherpedia'; * * For all the strings available in the 'MiniPedia.L10N' object * see the L10N_DEFAULTS variable below. */ // load localization defaults var L10N_DEFAULTS = { minipedia: "Minipedia", minipediaShort: "Mini", normalpedia: "Wikipedia Test", normalpediaShort: "WikipediaTest", openMinipedia: "Apri Minipedia", openNormalpedia: "Apri Wikipedia Test", createMinipediaPageTitle: "Accesso Minipedia", createMinipediaPageBody: "Sii il primo a creare una versione più ridotta e più accessibile di questa voce, in Minipedia!", statsTitle: "Mini Report", statsWords: "Parole", statsLines: "Paragrafi", statsComplexWords: "Parole complesse", }; // global configuration file window.MiniPedia = window.MiniPedia || {}; // shortcut for the global configuration file (mp = mini-pedia) var mp = window.MiniPedia; // default namespace informations mp.namespace = mp.namespace || 'Mini'; mp.namespaceNum = mp.namespaceNum || 3002; // default edit intro page title mp.editIntro = mp.editIntro || 'Progetto:Minipedia/Creazione voce'; // how much characters should have a word to be considered too much lon // this somehow help people with dyslexia mp.longWordLen = 13; // localization stuff mp.L10N = mp.L10N || {}; // shortcut var L10N = mp.L10N; // load the defaults for( var key in L10N_DEFAULTS ) { if( !L10N[ key ] ) { L10N[ key ] = L10N_DEFAULTS[ key ]; } } /** * Lazy shortcut to obtain just the first API result * * @param {Object} response API Response * @return {Object} page object */ function justFirstQueryPage( response ) { // no response no party if( !response.query || !response.query.pages ) { throw 'no valid API response'; } // the list should contain just one page var pages = response.query.pages; for( var id in pages ) { return pages[ id ]; } // no page no party return false; }; /** * Get a fresh MediaWiki API object * * @return mw.Api */ function mwApi() { return mw.loader.using( 'mediawiki.api' ).then( function() { return new mw.Api(); } ); }; /** * Check if a page title already exists * * @param title Page title * @return Promise */ function pageExists( title ) { // prepare the API request var request = { action: 'query', prop: 'info', titles: title, }; // eventually load API stuff return mwApi().then( function( api ) { // make the API request return api.get( request ).then( function ( response ) { // check if it exists var page = justFirstQueryPage( response ); if( page && page.pageid && page.pageid > 0 ) { return page; } return false; } ); } ); }; /** * Query the current page plain text * * @return Promise */ function queryPlainText() { // complete page title with namespace var pageName = mw.config.get( 'wgPageName' ); // prepare the API request // See https://phabricator.wikimedia.org/T259332 var request = { action: 'query', prop: 'extracts', titles: pageName, explaintext: 1, exlimit: 1, exsectionformat: 'plain', }; // this will return a Promise resolving the page plain text, returned upstream return mwApi().then( function( api ) { // make the API request and return a Promise return api.get( request ).then( function( response ) { // resolve the Promise with the page content var page = justFirstQueryPage( response ); if( page && page.pageid && page.pageid > 0 && page.extract ) { return page.extract; } // no content return false; } ); } ); }; /** * Prepare the wiki */ function prepareNormalpedia() { // normal page title and mini version var pageName = mw.config.get( 'wgPageName' ); // prepare the Minipedia title object var miniTitleObject = new mw.Title( pageName, mp.namespaceNum ); // minipedia page title with prefix var miniPageName = miniTitleObject.getPrefixedText(); // minipedia page URL var miniPageUrl = miniTitleObject.getUrl(); /** * Go to the Minipedia page in edit mode * * The page in the main namespace will be preloaded. */ function goToMinipediaEditPage() { /** * Build the query string to edit a page * * TODO: eventually add VisualEditor support */ var editPageQueryString = { action: 'edit', title: miniPageName, preload: pageName, editintro: mp.editIntro, }; // '/index.php' var wgScript = mw.config.get( 'wgScript' ); // go to the edit page URL window.location = wgScript + '?' + $.param( editPageQueryString ); }; // add a "Minipedia" var miniVersionPortletLink = mw.util.addPortletLink( 'p-namespaces', miniPageUrl, L10N.minipediaShort, 'ca-minipedia', L10N.openMinipedia, 'n' ); // on the mini toolback click, check if a mini version exists $( miniVersionPortletLink ).click( function( e ) { // wait for some information $.when( // check if the page really exists pageExists( miniPageName ), // allow to open OO UI windows mw.loader.using( 'oojs-ui-windows' ) ).done( function( miniPageExists, loader ) { // check if the page already exist if( miniPageExists ) { // just redirect to the Minipedia version window.location = miniPageUrl; } else { // ask if you want to create the page // create message dialog window var messageDialog = new OO.ui.MessageDialog(); var windowManager = new OO.ui.WindowManager(); $( 'body' ).append( windowManager.$element ); windowManager.addWindows( [ messageDialog ] ); // configure and open dialog var windowInstance = windowManager.openWindow( messageDialog, { title: L10N.createMinipediaPageTitle, message: L10N.createMinipediaPageBody, } ); // check if you accepted the page creation windowInstance.closed.then( function ( data ) { // user is confirming action if( data.action === 'accept' ) { // go go go! goToMinipediaEditPage(); } } ); } // end if page exists } ); // end $.when() // avoid scrolling to the top e.preventDefault(); } ); // end $( miniVersionPortletLink ).click }; // end prepareNormalWiki() /** * Calculate some stats over a text */ function textStats( text ) { var stats = {}; text = text.trim(); // count long words var totalLongWords = 0; var word, words = text.split( /\s+/ ); for( var i = 0; i < words.length; i++ ) { word = words[i]; if( word.length > mp.longWordLen ) { totalLongWords++; } } // how much lines? stats.totalLines = text.split( "\n+" ).length; // how much words? stats.totalWords = words.length; // how much of these words are so much long? // See 'longWordLen' stats.totalLongWords = totalLongWords; return stats; }; /** * Query content stats of the current page * * @return Promise */ function queryContentStats() { return queryPlainText().then( textStats ); }; /** * Prepare the Minipedia stats box */ function prepareMinipediaStatsBox() { // body container var $contentText = $( '#mw-content-text' ); // prepare the DOM tree var $container = $( '<div>' ); var $table = $( '<table>' ); var $thead = $( '<tbody>' ); // prepare the stats container $container.addClass( 'minipedia-stats' ); // put a title $container.append( $( '<h2>' ).text( mp.L10N.statsTitle ) ); // put the table $container.append( $table ); // prepare the table $table.addClass( 'wikitable' ) .append( $thead ); /** * Append a row (with a label and a value) into a table * * @param {Object} jQuery table * @param {String} className * @param {String} label * @param {String} value */ function appendTableStatsRow( $table, className, label, value ) { var $tr = $( '<tr>' ); $tr.addClass( 'minipedia-stats-row-' + className ); $tr.append( $( '<td>' ).text( label ) ); $tr.append( $( '<td>' ).text( value ) ); $table.append( $tr ); }; // query the page plain text queryContentStats().then( function( stats ) { // show the number of words, lines and complex words (actually just long words) appendTableStatsRow( $table, 'long-words', mp.L10N.statsComplexWords, stats.totalLongWords ); appendTableStatsRow( $table, 'words', mp.L10N.statsWords, stats.totalWords ); appendTableStatsRow( $table, 'lines', mp.L10N.statsLines, stats.totalLines ); } ); // show the stats container at the bottom of the page $contentText.append( $container ); }; /** * Prepare the Minipedia namespace */ function prepareMinipedia() { // action of the page (edit, view etc.) var action = mw.config.get( 'wgAction' ); // normal page title and mini version var pageName = mw.config.get( 'wgTitle' ); // prepare the Normalpedia title object var normalTitleObject = new mw.Title( pageName ); // minipedia page title with prefix var normalPageName = normalTitleObject.getPrefixedText(); // minipedia page URL var normalPageUrl = normalTitleObject.getUrl(); // add a "Minipedia" var normalVersionPortletLink = mw.util.addPortletLink( 'p-namespaces', normalPageUrl, L10N.normalpediaShort, 'ca-normalpedia', L10N.openNormalpedia ); // check if we are in view mode if( action === 'view' ) { // in view mode we can fetch the stats prepareMinipediaStatsBox(); } }; // end prepareMinipedia() // work only in the main namespace var ns = mw.config.get( 'wgNamespaceNumber' ); if( ns === 0 ) { prepareNormalpedia(); } else if( ns == mp.namespaceNum ) { prepareMinipedia(); } // end namespace zero check } )( $, mw );