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.
This code will be executed when previewing this page.
This user script seems to have a documentation page at User:Rusalkii/previewRedirectContext.
// @ts-check
//Shows the paragraph containing the redirect term in the target article
//Also searches Wikipedia for other articles containing the redirect term
( function () {
'use strict';
// Only run on redirect pages
if ( !mw.config.get( 'wgIsRedirect' ) ) {
return;
}
mw.loader.using( [ 'mediawiki.api', 'mediawiki.util' ] ).then( function () {
let autoRun = true; //user-defined pref, defaults to true
if (typeof(autoRunRedirectContext) != "undefined" && autoRunRedirectContext == false) {
autoRun = false;
}
if ( autoRun ) {
runContextFinder();
} else {
addButton();
}
function addButton() {
// Create button
const button = document.createElement( 'button' );
button.textContent = 'Find in target';
button.style.cssText = 'margin-left: 10px; padding: 6px 12px; background-color: #3366cc; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 13px; vertical-align: middle;';
button.onmouseover = function() { this.style.backgroundColor = '#2952a3'; };
button.onmouseout = function() { this.style.backgroundColor = '#3366cc'; };
button.addEventListener( 'click', function() {
button.disabled = true;
runContextFinder();
} );
// Insert after redirect message (inline)
const redirectMsg = document.querySelector( '.redirectMsg' );
if ( redirectMsg ) {
redirectMsg.appendChild( button );
}
}
function runContextFinder() {
const api = new mw.Api( {
ajax: {
headers: {
'Api-User-Agent': 'RedirectContextFinder/1.0'
}
}
} );
// Get redirect target
api.get( {
action: 'query',
prop: 'info',
titles: mw.config.get( 'wgPageName' ),
redirects: 1
} ).then( function ( data ) {
const pages = data.query.pages;
const redirects = data.query.redirects;
if ( !redirects || redirects.length === 0 ) {
return;
}
const targetTitle = redirects[ 0 ].to;
const redirectTitle = mw.config.get( 'wgTitle' );
// Fetch target page content
api.get( {
action: 'query',
prop: 'revisions',
titles: targetTitle,
rvprop: 'content',
rvslots: 'main',
formatversion: 2
} ).then( function ( data ) {
// Create container for results
const container = document.createElement( 'div' );
container.className = 'redirect-context-finder';
container.style.cssText = 'margin: 20px 0; padding: 15px; border: 2px solid #3366cc; background-color: #f0f8ff; border-radius: 5px;';
// Insert after redirect message
const redirectMsg = document.querySelector( '.redirectMsg' );
redirectMsg.parentNode.insertBefore( container, redirectMsg.nextSibling );
if ( !data.query.pages[ 0 ].revisions ) {
container.innerHTML = '<strong style="color: #cc0000;">Error: Could not load target page</strong>';
return;
}
const wikitext = data.query.pages[ 0 ].revisions[ 0 ].slots.main.content;
const result = findRedirectContext( redirectTitle, wikitext );
if ( result ) {
container.innerHTML = '<div style="background: white; padding: 10px; margin-top: 10px;">' +
result.paragraph +
'</div>';
} else {
container.innerHTML = '<div style="margin-top: 10px; color: #666;">' +
'<strong style="color: #cc0000;">✗</strong> "<strong>' + mw.html.escape( redirectTitle ) + '</strong>" does not appear in the target. ' +
'</div>';
}
// Add search results section
const searchContainer = document.createElement( 'div' );
searchContainer.style.cssText = 'margin-top: 15px; padding-top: 15px; border-top: 1px solid #3366cc;';
container.appendChild( searchContainer );
// Perform Wikipedia search
searchWikipedia( api, redirectTitle, targetTitle, searchContainer );
} ).catch( function () {
const container = document.createElement( 'div' );
container.innerHTML = '<strong style="color: #cc0000;">Error loading target page</strong>';
const redirectMsg = document.querySelector( '.redirectMsg' );
if ( redirectMsg ) {
redirectMsg.parentNode.insertBefore( container, redirectMsg.nextSibling );
}
} );
} ).catch( function () {
// Silently fail if we can't get redirect info
} );
}
function searchWikipedia( api, searchTerm, targetTitle, container ) {
api.get( {
action: 'query',
list: 'search',
srsearch: '"' + searchTerm + '"',
srnamespace: 0,
srlimit: 5,
srwhat: 'text',
srprop: 'snippet|titlesnippet'
} ).then( function ( data ) {
const results = data.query.search;
// Filter out the target article itself
const otherArticles = results.filter( function( result ) {
return result.title !== targetTitle;
} );
const totalResults = data.query.searchinfo.totalhits;
const otherCount = Math.max(0, totalResults - 1); // Exclude target article
let html = '<div class="mw-search-results-container">';
html += '<strong>Search Results:</strong> ';
if ( otherCount === 0 ) {
html += '"<strong>' + mw.html.escape( searchTerm ) + '</strong>" was not found in any other articles.';
html += '</div>';
} else {
html += 'Found in <strong>' + otherCount + '</strong> other article' + (otherCount !== 1 ? 's' : '');
html += '</div>';
html += '<ul class="mw-search-results">';
for ( let i = 0; i < otherArticles.length; i++ ) {
const article = otherArticles[i];
const articleUrl = mw.util.getUrl( article.title );
html += '<li class="mw-search-result">';
html += '<a href="' + articleUrl + '" title="' + mw.html.escape( article.title ) + '">';
html += mw.html.escape( article.title );
html += '</a>';
html += '</div>';
// Highlight the search term in snippets
if ( article.snippet ) {
let highlightedSnippet = article.snippet.replace(
/<span class="searchmatch">(.*?)<\/span>/gi,
'<mark style="background-color: #ffffcc; font-weight: normal;">$1</mark>'
);
html += '<div class="searchresult">' + highlightedSnippet + '</div>';
}
html += '</li>';
}
html += '</ul>';
if ( otherCount > 5 ) {
const searchUrl = mw.util.getUrl( 'Special:Search', { search: searchTerm } ) + '&fulltext=1&ns0=1';
html += '<div style="margin-top: 10px;"><a href="' + searchUrl + '">View all ' +
otherCount + ' results →</a></div>';
}
html += '</div>';
}
container.innerHTML = html;
} ).catch( function () {
container.innerHTML = '<div style="margin-top: 10px; color: #cc0000;">Error performing search</div>';
} );
}
function createRegex( term ) {
// Create a version without parenthetical content
const termWithoutParens = term.replace(/\s*\([^)]*\)\s*/g, '').trim();
function createPattern(str) {
// Escape special regex characters except spaces and hyphens
let pattern = str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
// Replace spaces with flexible whitespace/punctuation pattern
pattern = pattern.replace(/\s+/g, '[\\s\\-–—]*');
// Replace hyphens/dashes with flexible dash pattern (matches -, –, —, or absence)
pattern = pattern.replace(/[\-–—]/g, '[\\s\\-–—]*');
// Replace punctuation with optional pattern
pattern = pattern.replace(/\./g, '\\.?');
pattern = pattern.replace(/!/g, '!?');
pattern = pattern.replace(/,/g, ',?');
pattern = pattern.replace(/'/g, '[\']?');
pattern = pattern.replace(/"/g, '[""]?');
return pattern;
}
const patterns = [createPattern(term)];
// Only add the version without parens if it's different
if (termWithoutParens !== term && termWithoutParens.length > 0) {
patterns.push(createPattern(termWithoutParens));
}
return new RegExp('(' + patterns.join('|') + ')', 'gi');
}
function findRedirectContext( searchTerm, wikitext ) {
let regex = createRegex(searchTerm);
const paragraphs = wikitext.split( /\n\n+/ );
console.log(regex);
for ( let i = 0; i < paragraphs.length; i++ ) {
const para = paragraphs[ i ];
// Check if paragraph contains the search term
if ( para.match(regex) ) {
let cleaned = para
.replace( /<ref[^>]*>.*?<\/ref>/gi, '' ) // Remove refs
.replace( /<ref[^>]*\/>/gi, '' ) // Remove self-closing refs
.trim();
// Highlight the search term
cleaned = cleaned.replace( regex, '<mark style="background-color: #ffff00; font-weight: bold;">$1</mark>' );
return {
paragraph: cleaned,
};
}
}
return null;
}
} );
}() );