MediaWiki:Common.js: Difference between revisions
From Criminal Defense Wiki
Jump to navigationJump to search
No edit summary |
No edit summary |
||
| Line 331: | Line 331: | ||
} ); | } ); | ||
} ); | } ); | ||
}() ); | |||
/* Mark logged-in users so highlights can be shown only to them. */ | |||
( function () { | |||
if ( mw.config.get( 'wgUserName' ) ) { | |||
document.documentElement.classList.add( 'flagger-user' ); | |||
} | |||
}() ); | }() ); | ||
Revision as of 01:46, 30 August 2026
/* Any JavaScript here will be loaded for all users on every page load. */
/* For wikiDefense Flagger. For more information consult documentation or contact Brandyn Lu */
/* Claim-flag popover: click a highlight to see the model's reasoning. */
( function () {
var POPOVER_ID = 'claim-flag-popover';
function closePopover() {
var existing = document.getElementById( POPOVER_ID );
if ( existing ) {
existing.remove();
}
document.querySelectorAll( '.review-highlight.is-open' ).forEach( function ( el ) {
el.classList.remove( 'is-open' );
} );
}
function escapeRegExp( str ) {
return str.replace( /[.*+?^${}()|[\]\\]/g, '\\$&' );
}
function dismissFlag( span ) {
var sentence = span.childNodes[ 0 ] ? span.childNodes[ 0 ].textContent : '';
if ( !sentence ) {
mw.notify( 'Could not identify the flagged text.', { type: 'error' } );
return;
}
var title = mw.config.get( 'wgPageName' );
var api = new mw.Api();
api.get( {
action: 'query',
prop: 'revisions',
rvprop: 'content',
rvslots: 'main',
titles: title,
formatversion: 2
} ).done( function ( data ) {
var page = data.query.pages[ 0 ];
if ( !page || page.missing ) {
mw.notify( 'Could not load page content.', { type: 'error' } );
return;
}
var wikitext = page.revisions[ 0 ].slots.main.content;
// Find the {{Highlight|...}} call whose first parameter is this sentence.
var pattern = new RegExp(
'\\{\\{Highlight\\|' + escapeRegExp( sentence ) + '(?:\\|[^}]*)?\\}\\}'
);
if ( !pattern.test( wikitext ) ) {
mw.notify( 'Could not find this flag in the page source.', { type: 'error' } );
return;
}
var cleaned = wikitext.replace( pattern, sentence );
api.postWithToken( 'csrf', {
action: 'edit',
title: title,
text: cleaned,
summary: 'Dismissed one claim flag',
formatversion: 2
} ).done( function () {
mw.notify( 'Flag dismissed. Reloading…' );
window.location.reload();
} ).fail( function ( code, result ) {
mw.notify( 'Could not save: ' + code, { type: 'error' } );
console.error( 'Dismiss failed:', code, result );
} );
} ).fail( function ( code ) {
mw.notify( 'Could not fetch page: ' + code, { type: 'error' } );
} );
}
function openPopover( span ) {
closePopover();
var reason = span.getAttribute( 'data-reason' ) || 'No explanation available.';
var popover = document.createElement( 'div' );
popover.id = POPOVER_ID;
popover.className = 'claim-flag-popover';
var close = document.createElement( 'button' );
close.className = 'claim-flag-close';
close.textContent = '×';
close.title = 'Close';
close.addEventListener( 'click', function ( e ) {
e.stopPropagation();
closePopover();
} );
var body = document.createElement( 'div' );
body.className = 'claim-flag-body';
body.textContent = reason;
var dismiss = document.createElement( 'button' );
dismiss.className = 'claim-flag-dismiss';
dismiss.textContent = 'Dismiss this flag';
dismiss.addEventListener( 'click', function ( e ) {
e.stopPropagation();
dismissFlag( span );
} );
popover.appendChild( close );
popover.appendChild( body );
popover.appendChild( dismiss );
span.classList.add( 'is-open' );
span.appendChild( popover );
}
document.addEventListener( 'click', function ( e ) {
if ( e.target.closest( '.claim-flag-popover' ) ) {
return; // clicks inside the popover do nothing
}
var span = e.target.closest( '.review-highlight' );
if ( span ) {
if ( span.classList.contains( 'is-open' ) ) {
closePopover();
} else {
openPopover( span );
}
} else {
closePopover();
}
} );
document.addEventListener( 'keydown', function ( e ) {
if ( e.key === 'Escape' ) {
closePopover();
}
} );
}() );
/* Sidebar tool: remove all claim flags from the current page. */
( function () {
// Matches {{Highlight|<text>}} or {{Highlight|<text>|<reason>}},
// capturing only the first parameter (the original sentence).
var HIGHLIGHT_RE = /\{\{Highlight\|([\s\S]*?)(?:\|[^}]*)?\}\}/g;
function resetHighlights() {
var title = mw.config.get( 'wgPageName' );
var api = new mw.Api();
api.get( {
action: 'query',
prop: 'revisions',
rvprop: 'content',
rvslots: 'main',
titles: title,
formatversion: 2
} ).done( function ( data ) {
var page = data.query.pages[ 0 ];
if ( !page || page.missing ) {
mw.notify( 'Could not load page content.', { type: 'error' } );
return;
}
var wikitext = page.revisions[ 0 ].slots.main.content;
var matches = wikitext.match( HIGHLIGHT_RE );
var count = matches ? matches.length : 0;
if ( count === 0 ) {
mw.notify( 'No highlights found on this page.' );
return;
}
if ( !window.confirm(
'Remove all ' + count + ' claim flag(s) from this page?\n\n' +
'This edits the page. It can be undone from the page history.'
) ) {
return;
}
var cleaned = wikitext.replace( HIGHLIGHT_RE, '$1' );
api.postWithToken( 'csrf', {
action: 'edit',
title: title,
text: cleaned,
summary: 'Removed ' + count + ' claim-flag highlight(s) via sidebar tool',
formatversion: 2
} ).done( function () {
mw.notify( 'Removed ' + count + ' highlight(s). Reloading…' );
window.location.reload();
} ).fail( function ( code, result ) {
mw.notify( 'Edit failed: ' + code, { type: 'error' } );
console.error( 'Reset highlights failed:', code, result );
} );
} ).fail( function ( code ) {
mw.notify( 'Could not fetch page: ' + code, { type: 'error' } );
} );
}
mw.loader.using( [ 'mediawiki.api', 'mediawiki.util' ] ).then( function () {
if ( mw.config.get( 'wgNamespaceNumber' ) !== 0 ) {
return; // article namespace only
}
if ( !mw.config.get( 'wgUserName' ) ) {
return; // logged-in users only
}
var portletIds = [ 'p-cactions', 'p-tb', 'p-views' ];
var link = null;
for ( var i = 0; i < portletIds.length && !link; i++ ) {
link = mw.util.addPortletLink(
portletIds[ i ],
'#',
'Reset all highlights',
'ca-reset-highlights',
'Remove all claim flags from this page'
);
}
if ( link ) {
link.addEventListener( 'click', function ( e ) {
e.preventDefault();
resetHighlights();
} );
} else {
console.warn( 'Reset highlights: no suitable portlet found.' );
}
} );
}() );
/* Sysop-only global toggle for claim-flag highlighting. */
( function () {
var TEMPLATE_PAGE = 'Template:Highlight';
var TEMPLATE_ON = '<includeonly><span class="review-highlight" ' +
'data-reason="{{{2|}}}">{{{1}}}</span></includeonly>' +
'<noinclude>Usage: {{Highlight|text|reason}} — highlighting is ON.</noinclude>';
var TEMPLATE_OFF = '<includeonly>{{{1}}}</includeonly>' +
'<noinclude>Usage: {{Highlight|text|reason}} — highlighting is OFF.</noinclude>';
function purgeTransclusions( api ) {
return api.post( {
action: 'purge',
generator: 'transcludedin',
titles: TEMPLATE_PAGE,
gtilimit: 500,
gtinamespace: 0,
forcelinkupdate: 1,
formatversion: 2
} );
}
function setState( enable ) {
var verb = enable ? 'enable' : 'disable';
if ( !window.confirm(
'This will ' + verb + ' claim-flag highlighting for the entire wiki.\n\nContinue?'
) ) {
return;
}
var api = new mw.Api();
api.postWithToken( 'csrf', {
action: 'edit',
title: TEMPLATE_PAGE,
text: enable ? TEMPLATE_ON : TEMPLATE_OFF,
summary: 'Claim-flag highlighting ' + ( enable ? 'enabled' : 'disabled' ),
formatversion: 2
} ).done( function () {
mw.notify( 'Template updated. Refreshing affected pages…' );
purgeTransclusions( api ).always( function () {
window.location.reload();
} );
} ).fail( function ( code, result ) {
mw.notify( 'Could not update template: ' + code, { type: 'error' } );
console.error( 'Toggle failed:', code, result );
} );
}
function insertToggle( isOn ) {
var portletIds = [ 'p-cactions', 'p-tb', 'p-views' ];
var link = null;
for ( var i = 0; i < portletIds.length && !link; i++ ) {
link = mw.util.addPortletLink(
portletIds[ i ],
'#',
isOn ? 'Flags: ON' : 'Flags: OFF',
'ca-flagger-toggle',
'Claim-flag highlighting is ' + ( isOn ? 'ON' : 'OFF' ) +
' wiki-wide. Click to ' + ( isOn ? 'disable' : 'enable' ) + '.'
);
}
if ( !link ) {
console.warn( 'Flagger toggle: no suitable portlet found.' );
return;
}
link.addEventListener( 'click', function ( e ) {
e.preventDefault();
setState( !isOn );
} );
}
mw.loader.using( [ 'mediawiki.api', 'mediawiki.util' ] ).then( function () {
if ( mw.config.get( 'wgUserGroups' ).indexOf( 'sysop' ) === -1 ) {
return; // admins only
}
new mw.Api().get( {
action: 'query',
prop: 'revisions',
rvprop: 'content',
rvslots: 'main',
titles: TEMPLATE_PAGE,
formatversion: 2
} ).done( function ( data ) {
var page = data.query.pages[ 0 ];
if ( !page || page.missing ) {
console.warn( 'Flagger toggle: template page not found.' );
return;
}
var content = page.revisions[ 0 ].slots.main.content;
var isOn = content.indexOf( 'review-highlight' ) !== -1;
insertToggle( isOn );
} ).fail( function () {
console.warn( 'Flagger toggle: could not read template.' );
} );
} );
}() );
/* Mark logged-in users so highlights can be shown only to them. */
( function () {
if ( mw.config.get( 'wgUserName' ) ) {
document.documentElement.classList.add( 'flagger-user' );
}
}() );