User:Novem Linguae/Scripts/MarkFreeUseRationale.js
Appearance
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
![]() | Documentation for this user script can be added at User:Novem Linguae/Scripts/MarkFreeUseRationale. |
// <nowiki>
/*
- Requested by https://en.wikipedia.org/wiki/User:Elli on 2024-04-22
- When it runs (all 3 conditions must be met):
1) In the file namespace,
2) on pages that have one of these 100-ish templates that follow the format {{Non-free X}}: https://en.wikipedia.org/wiki/Category:Wikipedia_non-free_file_copyright_templates,
3) and the template does not have a parameter image_has_rationale=yes,
- What it does:
- shows a button that allows adding this parameter in one click
- Motivation:
- Useful for patrolling the category https://en.wikipedia.org/wiki/Category:Wikipedia_non-free_files_for_NFUR_review, because many of these files marked as not having a rationale already have a rationale and just need this one parameter added
*/
class MarkFreeUseRationale {
constructor( mw, $ ) {
this.mw = mw;
// eslint-disable-next-line no-jquery/variable-pattern
this.$ = $;
}
async execute() {
if ( !this.shouldRunOnThisPage() ) {
return;
}
// Only run if there is a {{Non-free X}} template (https://en.wikipedia.org/wiki/Category:Wikipedia_non-free_file_copyright_templates) that isnt a rationale template ( {{Non-free use rationale X}} )
const pageName = this.mw.config.get( 'wgPageName' );
const wikicode = await this.getWikicode( pageName );
const hasCopyrightTemplate = wikicode.match( /\{\{Non-free (?!use)/gi );
if ( !hasCopyrightTemplate ) {
return;
}
// only run if image_has_rationale=yes is not present
const hasRationale = wikicode.match( /image[_ ]has[_ ]rationale\s*=\s*yes/i );
if ( hasRationale ) {
return;
}
// add button
const $button = $( '<button>' )
.attr( 'id', 'MarkFreeUseRationale' )
.html( 'Set image_has_rationale=yes' );
const $div = $( '<div>' )
.html( $button )
.css( 'margin', '0.5em 0' );
this.$( '.licensetpl .imbox-notice .mbox-text' ).prepend( $div );
// add listener
$button.on( 'click', async () => {
$button.remove();
await this.addRationale();
} );
}
async addRationale() {
// get fresh wikicode, to reduce likelihood of edit conflict
const pageName = this.mw.config.get( 'wgPageName' );
const wikicode = await this.getWikicode( pageName );
// insert image_has_rationale=yes into wikicode somewhere (look at Elli's example diff)
const newWikicode = this.insertImageHasRationaleYes( wikicode );
if ( newWikicode === wikicode ) {
this.mw.notify( this.wrapErrorText( 'ERROR: Unable to find a place to insert |image_has_rationale=yes' ) );
return;
}
// API query to edit the page
try {
const editSummary = 'add template parameter image_has_rationale=yes ([[User:Novem Linguae/Scripts/MarkFreeUseRationale.js|MarkFreeUseRationale]])';
await this.editPage( pageName, newWikicode, editSummary, 'nochange' );
} catch {
this.mw.notify( this.wrapErrorText( 'ERROR: Unable to save the edit.' ) );
return;
}
this.mw.notify( 'Edit successful. Refresh to see changes.' );
}
insertImageHasRationaleYes( wikicode ) {
return wikicode.replace( /({{Non-free (?!use)[^|}]+)([|}])/i, '$1|image_has_rationale=yes$2' );
}
/**
* mw.notify likes to receive HTML as a jQuery object. If you pass it a string, it will escape and print the string.
*/
wrapErrorText( text ) {
return this.$( '<span>' )
.css( 'color', 'red' )
.css( 'font-weight', 'bold' )
.html( text );
}
/**
* @param pageName
* @param wikicode
* @param editSummary
* @param {string} addToWatchlist nochange, preferences, unwatch, watch. Default is preferences.
*/
async editPage( pageName, wikicode, editSummary, addToWatchlist = 'preferences' ) {
const api = new this.mw.Api();
await api.postWithEditToken( {
action: 'edit',
title: pageName,
text: wikicode,
summary: editSummary,
formatversion: 2,
watchlist: addToWatchlist
} );
}
async getWikicode( pageName ) {
const pageIsDeleted = !this.mw.config.get( 'wgCurRevisionId' );
if ( pageIsDeleted ) {
return '';
}
const api = new this.mw.Api();
const response = await api.get( {
action: 'parse',
page: pageName,
prop: 'wikitext',
formatversion: '2',
format: 'json'
} );
return response.parse.wikitext;
}
shouldRunOnThisPage() {
const isViewing = this.mw.config.get( 'wgAction' ) === 'view';
if ( !isViewing ) {
return false;
}
const isDiff = this.mw.config.get( 'wgDiffNewId' );
if ( isDiff ) {
return false;
}
const isDeletedPage = ( !this.mw.config.get( 'wgCurRevisionId' ) );
if ( isDeletedPage ) {
return false;
}
const isFileNamespace = this.mw.config.get( 'wgNamespaceNumber' ) === 6;
if ( !isFileNamespace ) {
return false;
}
return true;
}
}
$( async () => {
await mw.loader.using( [ 'mediawiki.api' ], async () => {
await ( new MarkFreeUseRationale( mw, $ ) ).execute();
} );
} );
// </nowiki>