User:SoledadKabocha/badAnchorWarning.js

Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
// <nowiki>
function defaultPref( cfig, dflt ) {
  return ( typeof cfig == typeof dflt ? cfig : dflt );
}

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 = 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 : 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           = /\{\{.+\}\}/g;
    var exclPipeTemplateRegex   = /\{\{!\}\}/g; //MW now implements this as a magic word; still needed?
    var equalsTemplateRegex     = /\{\{=\}\}/g;
    var anchorTemplateRegex     = /\{\{[Aa]nchor\|.+\}\}/g;
    var apostropheTemplateRegex = /\{\{(?:\.27|[Aa]postrophe)\}\}/g;
    var tlTemplateRegex         = /\{\{[Tt](?:l[pux]?)?\|(.+)\}\}/g;
    var noRedirectTemplateRegex = /\{\{(?:[Nn]o_redirect|-r)\|(.+)\}\}/g;
    if ( templateRegex.test( myAnchor ) ) {
      warningText += 'if you edited a ';
      var fixedAnchor =    myAnchor.replace( exclPipeTemplateRegex, '|' ).replace( equalsTemplateRegex, '=' );
          fixedAnchor = fixedAnchor.replace( anchorTemplateRegex, '' ).replace( apostropheTemplateRegex, '\'' ).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, '{{' + tlParam + '}}' );

      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';
      }
      /* // probably obsolete?
      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>';
        }
      }*/
      /* // ditto (needs testing)
      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.notify( warningText.replace( / id="badanchorwarn-/g, ' id="badanchorwarn-jsmsg-' ) ); }
  }
}

if ( !window.BAWarnManual ) $( showBadAnchorWarning );
// </nowiki>