// __NOINDEX__{{DEFAULTSORT:badAnchorWarning.js}}
function defaultPref( cfig, dflt ) {
return ( typeof cfig == typeof dflt ? cfig : dflt );
}
function unencodeAnchor( anAnchor ) {
var fixedAnchor = anAnchor.replace(
/_/g, ' '
).replace(
/\.([2-7][0-9A-F])/g, function(x,n){ return String.fromCharCode(parseInt(n,16)); }
).replace(
/\u007F/g, '.7F'
);
//2 UTF-8 bytes
var regex2b = /\.([CD][0-9A-F])\.([89AB][0-9A-F])/, result2b = regex2b.exec( fixedAnchor );
var safetyCounter = 0;
while ( result2b !== null && safetyCounter < 255 ) {
var byte1 = parseInt( result2b[ 1 ], 16 );
var byte2 = parseInt( result2b[ 2 ], 16 );
var fixedCode = ( ( byte1 & 0x1F ) << 6 ) | ( byte2 & 0x3F );
fixedAnchor = fixedAnchor.replace( regex2b, String.fromCharCode( fixedCode ) );
result2b = regex2b.exec( fixedAnchor );
safetyCounter++;
}
//3 UTF-8 bytes
var regex3b = /\.E([0-9A-F])\.([89AB][0-9A-F])\.([89AB][0-9A-F])/, result3b = regex3b.exec( fixedAnchor );
/* _*/ safetyCounter = 0;
while ( result3b !== null && safetyCounter < 255 ) {
var nibb1 = parseInt( result3b[ 1 ], 16 );
var byte2 = parseInt( result3b[ 2 ], 16 );
var byte3 = parseInt( result3b[ 3 ], 16 );
var fixedCode = ( nibb1 << 12 ) | ( ( byte2 & 0x3F ) << 6 ) | ( byte3 & 0x3F );
fixedAnchor = fixedAnchor.replace( regex3b, String.fromCharCode( fixedCode ) );
result3b = regex3b.exec( fixedAnchor );
safetyCounter++;
}
return fixedAnchor;
}
function showBadAnchorWarning( ) {
var zzAction = mw.config.get( 'wgAction' );
var zzNamespaceNumber = mw.config.get( 'wgNamespaceNumber' );
// not useful when editing nor on special pages
if ( !window.location.hash || zzAction != 'view' || zzNamespaceNumber < 0 ) return;
// strip the pound sign
var myAnchor = window.location.hash.substr( 1 );
if ( !myAnchor || document.getElementById( myAnchor ) ) return;
var warningLink = 'searchInput';
if ( document.getElementById( 'searchbox' ) ) {
warningLink = 'searchbox';
}
else if ( document.getElementById( 'toc' ) ) {
warningLink = 'toc';
}
if ( window.BAAutofillSearch === true ) {
if ( typeof document.getElementById( warningLink ).value == 'string' ) {
document.getElementById( warningLink ).value = unencodeAnchor( myAnchor );
}
else {
var jqWarningLink = $( '#' + warningLink );
var myInput = jqWarningLink.find( 'input' );
if ( myInput ) {
// avoid overwriting existing values because doing so would change button labels
myInput.val( function( index, oldValue ) { return oldValue ? oldValue : unencodeAnchor( myAnchor ) } );
}
}
}
window.BAWarnInSiteSub = defaultPref( window.BAWarnInSiteSub, true );
window.BAWarnAsJsMessage = defaultPref( window.BAWarnAsJsMessage, true );
if ( window.BAWarnInSiteSub || window.BAWarnAsJsMessage ) {
// ensure valid HTML syntax even if bad characters got into the anchor somehow (not a serious security measure)
if ( myAnchor.indexOf( '<' ) != -1 || myAnchor.indexOf( '>' ) != -1 || myAnchor.indexOf( '"' ) != -1 )
myAnchor = 'Invalid_anchor_redacted';
var warningText = ' <span id="badanchorwarn-outer-' + myAnchor + '" class="badanchorwarn-outer">';
warningText += '(The anchor <span id="badanchorwarn-inner-' + myAnchor + '" class="badanchorwarn-inner">' + myAnchor + '</span> was not found; ';
var templateRegex = /\.7B\.7B.+\.7D\.7D/g;
var exclPipeTemplateRegex = /\.7B\.7B\.21\.7D\.7D/g; //MW now implements this as a magic word; still needed?
var equalsTemplateRegex = /\.7B\.7B\.3D\.7D\.7D/g;
var anchorTemplateRegex = /\.7B\.7B[Aa]nchor\.7C.+\.7D\.7D/g;
var apostropheTemplateRegex = /\.7B\.7B(?:\.27|[Aa]postrophe)\.7D\.7D/g;
var tlTemplateRegex = /\.7B\.7B[Tt](?:l[pux]?)?\.7C(.+)\.7D\.7D/g;
var noRedirectTemplateRegex = /\.7B\.7B(?:[Nn]o_redirect|-r)\.7C(.+)\.7D\.7D/g;
if ( templateRegex.test( myAnchor ) ) {
warningText += 'if you edited a ';
var fixedAnchor = myAnchor.replace( exclPipeTemplateRegex, '.7C' ).replace( equalsTemplateRegex, '.3D' );
fixedAnchor = fixedAnchor.replace( anchorTemplateRegex, '' ).replace( apostropheTemplateRegex, '.27' ).replace( /^_+|_+$/g, '' );
//Now extract template parameters where needed - XXX this won't work correctly with multiple transclusions of any such template...
var tlCall = tlTemplateRegex.exec( fixedAnchor );
var tlParam = '';
if ( tlCall ) tlParam = tlCall[1];
if ( tlParam ) fixedAnchor = fixedAnchor.replace( tlTemplateRegex, '.7B.7B' + tlParam + '.7D.7D' );
var nrCall = noRedirectTemplateRegex.exec( fixedAnchor );
var nrParam = '';
if ( nrCall ) nrParam = nrCall[1];
if ( nrParam ) fixedAnchor = fixedAnchor.replace( noRedirectTemplateRegex, nrParam );
if ( fixedAnchor && ( fixedAnchor != myAnchor ) && document.getElementById( fixedAnchor ) ) {
warningText += '<a href="#' + fixedAnchor + '">section</a>';
}
else { // don't attempt to fix the anchor if there are templates we don't recognize
warningText += 'section';
}
warningText += ', you have encountered a MediaWiki software issue';
}
else {
if ( myAnchor.indexOf( '/media/' ) == 0 ) {
warningText += 'if you just closed Media Viewer, there is no problem';
}
else if ( myAnchor.indexOf( '.5B.5B' ) != -1 && myAnchor.indexOf( '.5D.5D' ) != -1 ) {
// Echo (Notifications) fails to strip wikilink markup and unnecessarily percent-encodes some characters.
// XXX: This doesn't handle piped links
// XXX: There are probably more such characters to deal with...
fixedAnchor = myAnchor.replace( /(\.5[BD]){2}/g, '' ).replace( /%3A/g, ':' );
warningText += 'if you clicked on a notification, you have encountered a MediaWiki software issue';
if ( fixedAnchor && ( fixedAnchor != myAnchor ) && document.getElementById( fixedAnchor ) ) {
warningText += '. You were probably looking for ';
warningText += '<a href="#' + fixedAnchor + '" title="#' + fixedAnchor + '">';
warningText += 'this section';
warningText += '</a>';
}
}
else if ( /\.7C(_|$)/.test( myAnchor ) && document.getElementById( 'ca-addsection' ) ) {
warningText += 'if you used a pipe trick in the title of a ';
var lastHeadline = $( 'h2:last-of-type > .mw-headline' );
var lastHeadlineID = '';
if ( lastHeadline && lastHeadline.length > 0 ) lastHeadlineID = lastHeadline.attr( 'id' );
if ( lastHeadlineID ) {
warningText += '<a href="#' + lastHeadlineID + '" title="#' + lastHeadlineID + '">';
warningText += 'new section';
warningText += '</a>';
}
else {
warningText += 'new section';
}
warningText += ', you have encountered a MediaWiki software issue';
}
else {
if ( warningLink == 'searchbox' ) {
warningText += 'try <a href="#searchbox" title="Go to archive search box">searching this page\'s archives</a>';
}
else {
// TODO: descriptive titles here too, once I rethink whether searchInput is a good default for warningLink
warningText += 'please <a href="#' + warningLink + '" title="#' + warningLink + '">check its spelling and capitalization</a>';
if ( zzNamespaceNumber != 0 ) {
warningText += ', or search this page\'s archives if any';
}
}
}
}
warningText += '.)';
warningText += '</span>';
if ( window.BAWarnInSiteSub === true ) {
// non-WMF wikis hide siteSub by default
if ( typeof mw.util.addCSS == 'function' ) { mw.util.addCSS( '#siteSub { display:inline; }' ); }
$( '#siteSub' ).append( warningText );
}
if ( window.BAWarnAsJsMessage === true ) { mw.util.jsMessage( warningText.replace( / id="badanchorwarn-/g, ' id="badanchorwarn-jsmsg-' ) ); }
}
}
if ( !window.BAWarnManual ) $( showBadAnchorWarning );
Categories: Noindexed pages