MediaWiki:Gadget-LintHint.js

Nga Wikipedia, enciklopedia e lirë

Shënim: Pas ruajtjes së parapëlqimeve ose kryerjes së ndryshimet, për t'ju shfaqur dallimet duhet të pastroni ruajtësin (cache) e shfletuesit. Pastrimi i ruajtësit të shfletuesve bëhet duke shtypur në të njëjten kohë Ctrl+Shift+Reload për Mozilla/Safari/Konqueror ose ctrl+shift+r për IE ose Ctrl+f5 për Opera: F5.

/// User:PerfektesChaos/js/lintHint/d.js
/// 2021-06-03 PerfektesChaos@de.wikipedia
//  Show LintErrors analysis live
//  ResourceLoader:  compatible;
//    dependencies: user, mw.API, mediawiki.storage, mediawiki.util
/// Fingerprint: #0#0#
/// License: CC-by-sa/4.0
/// <nowiki>
/* global window: false                                                */
/* jshint forin: false,
          bitwise:true, curly:true, eqeqeq:true, latedef:true,
          laxbreak:true,
          nocomma:true, strict:true, undef:true, unused:true           */



( function ( mw, $ ) {
   "use strict";
   var Version   = -4.7,
       Signature = "lintHint",
       HINT      = { cmodels:   { "wikitext":        true,
                                  "proofread-index": true,
                                  "proofread-page":  true },
                     doc:       "en:User:PerfektesChaos/js/" + Signature,
                     errors:    [ "bogus-image-options",
                                  "deletable-table-tag",
                                  "fostered",
                                  "html5-misnesting",
                                  "ignored-table-attr",
                                  "misc-tidy-replacement-issues",
                                  "misnested-tag",
                                  "missing-end-tag",
                                  "missing-start-tag",
                                  "mixed-content",
                                  "multi-colon-escape",
                                  "multiline-html-table-in-list",
                                  "multiple-unclosed-formatting-tags",
                                  "obsolete-tag",
                                  "pwrap-bug-workaround",
                                  "self-closed-tag",
                                  "stripped-tag",
                                  "tidy-font-bug",
                                  "tidy-whitespace-bug",
                                  "unclosed-quotes-in-heading",
                                  "wikilink-in-extlink" ],
                     idRev:     0,
                     indicators:".mw-indicators",
                     last:      true,
                     later:     false,
                     launch:    false,
                     launched:  false,
                     layer:     null,
                     lazy:      false,
                     live:      false,
                     ltr:       true,
                     selMain:   "[role='main']",
                     source:    false,
                     using:     [ "mediawiki.api",
                                  "mediawiki.storage",
                                  "mediawiki.util",
                                  "user.options" ],
                     $body:     false,
                     $content:  false,
                     $main:     false,
                     $textarea: false,
                     $widget:   false },
       API       = { Api:     false,
                     errors:  false,
                     scream:  false,
                     server:  "api/rest_v1/",
                     scanner: "transform/wikitext/to/lint",
                     swift:   "page/lint" },
       BOX       = { bgc:        "FFFF00",
                     bgcErr:     "FFE4E1",
                     bgcOk:      "ADFF2F",
                     bgcRun:     "C0C0C0",
                     boc:        "808080",
                     fgc:        "000000",
                     fgcRun:     "A0A0A0",
                     swift:      false,
                     $box:       false,
                     $collapsed: false,
                     $failure:   false,
                     $null:      false,
                     $other:     false,
                     $pagename:  false,
                     $swift:     false,
                     $tbody:     false,
                     $table:     false,
                     $top:       false },
       CODMIRROR = { cm: false },
       EDIT      = { layer:      false,
                     listen:     false,
                     live:       false,
                     selTextbox: "div[role='textbox']",
                     selVEsrc:   ".ve-init-mw-desktopArticleTarget-"
                                                   + "uneditableContent",
                     source:     false,
                     sourceVE:   "&veaction=editsource",
                     $source:    false },
       GUIDER    = { last:     false,
                     live:     false,
                     reTrim:   false,
                     suitable: String.fromCharCode( 0x2714 ),
                     using:    [ "jquery.textSelection",
                                 "mediawiki.ui.button",
                                 "mediawiki.ui.input" ],
                     $pagename: false },
       LINTER    = { live: false },
       PREGO     = { app:       false,
                     live:      false,
                     maxage:    604813,
                     pars:      [ [ "last",   "boolean" ],
                                  [ "later",  "boolean" ],
                                  [ "launch", "boolean" ],
                               // [ "layer",  "boolean" ],
                                  [ "lazy",   "boolean" ],
                                  [ "spaces", "string" ] ],
                     signature: "preferencesGadgetOptions",
                     site:      "w:en",
                     store:     "User:PerfektesChaos/js/",
                     sub:       "/r.js" },
       REPOS     = { },
       TMPLXPAND = { live: false },
       UPDATE    = { },
       WIKED     = { };



   HINT.texts = {
      // 2019-01-19 PerfektesChaos@de.wikipedia
      "desc":    {"en": "Show LintErrors analysis live.",
                  "de": "Zeige LintErrors-Analyse live.",
                  "it": "Mostra analisi degli errori di Lint"
                        + " in diretta."},
      "domain":  {"en": "en.wikipedia.org",
                  "de": "de.wikipedia.org"},
      "howTo":   {"en": "Fill balanced wikitext into first input area"
                        + " and press adjacent submit button,"
                        + " or enter page name into second input field"
                        + " (might be followed by revision ID).",
                  "de": "Füge ausgeglichenen Wikitext"
                        + " in das obere Eingabefeld ein,"
                        + " oder einen Seitennamen in das untere"
                        + " (ggf. gefolgt von einer Versionsnummer),"
                        + " und betätige die jeweilige Schaltfläche.",
                  "it": "Inserisci il wikitesto"
                        + " nella prima area di input e premi"
                        + " il tasto di invio adiacente,"
                        + " oppure scrivi il titolo della pagina"
                        + " nel secondo campo"
                        + " (potrebbe essere seguito"
                        + " dall’ID della revisione)."},
      "mark":    {"en": "select problem in source text",
                  "de": "Problem im Quelltext selektieren",
                  "it": "Seleziona un problema nel testo sorgente"},
      "noPage":  {"en": "Wikitext page not found",
                  "de": "Wikitext-Seite nicht gefunden",
                  "it": "Pagina di wikitesto non trovata"},
      "other":   {"en": "Future problems detected.",
                  "de": "Zukünftige Probleme detektiert.",
                  "it": "Futuri problemi individuati."},
      "^suffix": {"en": "&#8211; linter error analysis support",
                  "de": "&#8211; Unterstützung"
                        + " der Analyse von Linter-Fehlern",
                  "it": "&#8211; Supporto"
                        + " per l’analisi degli errori di Lint"},
      "^^last":  {"en": "Analyze previous revisions, too.",
                  "de": "Analysiere auch frühere Seitenversionen.",
                  "it": "Analizza anche le revisioni precedenti."},
/*
      "^^later"  {"en": "",
                  "de": "Zeige auch zukünftige Fehlertypen,"
                        + " zu denen noch keine"
                        + " Linter-Kategorien existieren."},
*/
      "^^launch":{"en": "Run analysis automatically in namespaces"
                        + " on visit"
                        + " rather than manually triggered by button.",
                  "de": "Löse die Analyse automatisch"
                        + " beim Seitenbesuch in den Namensräumen aus,"
                        + " statt sie manuell"
                        + " über den angebotenen Knopf zu starten.",
                  "it": "Esegui automaticamente l’analisi"
                        + " nei namespace all’accesso, "
                        + " piuttosto che avviandola manualmente "
                        + " tramite bottone."},
/*
      "^^layer": {"en": "Convert all source edit links on"
                        + " LintErrors special page"
                        + " into ParserMigration tool edit.",
                  "de": "Wandle auf der LintErrors-Spezialseite"
                        + " alle Verlinkungen zur Quelltextbearbeitung"
                        + " in das Migrationswerkzeug um.",
                  "it": "Converti tutti i link di modifica sorgente"
                        + " presenti"
                        + " sulla pagina speciale Errori di Lint"
                        + " nello"
                        + " strumento di modifica ParserMigration."},
*/
      "^^lazy":  {"en": "Suppress small label if no error detected.",
                  "de": "Unterdrücke das kleine grüne Feld,"
                        + " falls bei einer Seitendarstellung"
                        + " kein Problem gefunden wurde.",
                  "it": "Nascondi l’etichetta"
                        + " in assenza di errori rilevati."},
      "^^spaces":{"en": "Space separated list of namespace numbers,"
                        + " for automatized analysis"
                        + " or - for none or * for all",
                  "de": "Namensraum-Nummern für automatische Analyse,"
                        + " durch Leerzeichen getrennt,"
                        + " oder - für keine oder * für alle",
                  "it": "Lista di namespace,"
                        + " in formato numerico separati da spazi,"
                        + " dove effettuare l’analisi."
                        + " Usare - per la lista vuota"
                        + " e * per indicarli tutti."}
   };   // HINT.texts



   function face() {
      // Page orientation
      // Precondition:
      //    DOM ready
      // Uses:
      //    >< HINT.$body
      //     < HINT.ltr
      // 2017-08-19 PerfektesChaos@de.wikipedia
      if ( ! HINT.$body ) {
         HINT.$body = $( "body" );
         HINT.ltr   = ( $( "html" ).attr( "dir" )  !==  "rtl" );
      }
   }   // face()



   function fair( action ) {
      // Adapt to special conditions (mobile)
      // Precondition:
      //    action  -- function to be executed, or not
      // Uses:
      //    >< HINT.using
      //    mw.config.get()
      //    mw.loader.using()
      // 2017-08-07 PerfektesChaos@de.wikipedia
      if ( mw.config.get( "skin" ) !== "minerva" ) {   // T49858
         if ( action ) {
            mw.loader.using( "jquery.tablesorter",
                             action );
         } else {
            HINT.using.push( "jquery.tablesorter" );
         }
      }
   }   // fair()



   function features( apply ) {
      // Config hook has been fired
      // Precondition:
      //    apply  -- hook payload
      // Uses:
      //    >  HINT.nsn
      //    >  HINT.last
      //    >  HINT.launched
      //    >  HINT.using
      //    >< HINT.launch
      //    >< HINT.layer
      //    >< HINT.live
      //     < HINT.later
      //     < HINT.lazy
      //    mw.loader.using()
      //    BOX.flat()
      //    (API.full)
      //    (BOX.feed)
      // 2019-01-19 PerfektesChaos@de.wikipedia
      var i, live;
      if ( typeof apply  ===  "object"
           &&     apply ) {
         if ( typeof apply.rooms  ===  "object"
              &&     apply.rooms   &&
              typeof apply.rooms.length  ===  "number" ) {
            live = false;
            if ( HINT.nsn >= 0 ) {
               for ( i = 0;  i < apply.rooms.length;  i++ ) {
                  if ( apply.rooms[ i ] === HINT.nsn ) {
                     live = true;
                     break;   // for i
                  }
               }   // for i
            }
         } else if ( typeof apply.rooms  ===  "string"
                     &&     apply.rooms === "*" ) {
            live = ( HINT.nsn >= 0 );
         } else {
            live = false;
         }
         if ( typeof apply.later  ===  "boolean" ) {
            HINT.later = apply.later;
         }
         if ( typeof apply.launch  ===  "boolean" ) {
            HINT.launch = apply.launch;
         }
/*
         if ( typeof apply.layer  ===  "boolean" ) {
            HINT.layer = apply.layer;
         }
*/
         if ( typeof apply.lazy  ===  "boolean" ) {
            HINT.lazy = apply.lazy;
            if ( HINT.lazy ) {
               BOX.flat();
            }
         }
         if ( live  &&  ! HINT.last ) {
            live = false;
            if ( typeof apply.oldid  ===  "boolean"
                 &&     apply.oldid ) {
               live = true;
            }
         }
         if ( live  &&  ! HINT.live ) {
            HINT.live = true;
            if ( HINT.launch  &&  ! HINT.launched ) {
               mw.loader.using( HINT.using, API.full );
            } else {
               mw.loader.using( HINT.using, BOX.feed );
            }
         } else if ( HINT.live  &&  ! live ) {
            BOX.flat();
         }
      }
   }   // features()



   function first() {
      // Autorun on loading
      // Uses:
      //    >  Signature
      //    >  PREGO.signature
      //    >  LINTER.first
      //    >  HINT.cmodels
      //    >  EDIT.sourceVE
      //    >  EDIT.selTextbox
      //    >  HINT.doc
      //    >  Version
      //    >< HINT.using
      //     < HINT.signature
      //     < HINT.selector
      //     < HINT.nsn
      //     < PREGO.live
      //     < LINTER.live
      //     < HINT.source
      //     < HINT.idRev
      //     < HINT.last
      //     < HINT.live
      //     < HINT.launch
      //     < EDIT.live
      //     < EDIT.layer
      //     < EDIT.selector
      //     < HINT.pub
      //    mw.loader.getState()
      //    mw.loader.state()
      //    mw.config.get()
      //    GUIDER.first()
      //    PREGO.fire()
      //    fair()
      //    mw.loader.using()
      //    mw.hook()
      //    (TMPLXPAND.first)
      //    (LINTER.first)
      //    (features)
      // 2021-06-03 PerfektesChaos@de.wikipedia
      var i, later, listen, live, re, rls, s;
      HINT.signature = "ext.gadget." + Signature;
      if ( mw.loader.getState( HINT.signature )  !==  "ready" ) {
         rls = { };
         rls[ HINT.signature ] = "ready";
         mw.loader.state( rls );
         HINT.selector = Signature.toLowerCase();
         switch ( mw.config.get( "wgAction" ) ) {
            case "view":
               HINT.nsn = mw.config.get( "wgNamespaceNumber" );
               switch ( HINT.nsn ) {
                  case -1:
                     s = mw.config.get( "wgCanonicalSpecialPageName" );
                     switch ( s ) {
                        case "Blankpage":
                           s = mw.config.get( "wgTitle" );
                           i = s.indexOf( "/" );
                           if ( i > 1 ) {
                              switch ( s.substr( i + 1 ) ) {
                                 case Signature:
                                    GUIDER.first();
                                    listen = true;
                                    break;
                                 case PREGO.signature:
                                    PREGO.live = true;
                                    PREGO.fire();
                                    break;
                              }   // switch subPage
                           }
                           break;
                        case "ExpandTemplates":
                           PREGO.fire();
                           fair( TMPLXPAND.first );
                           break;
                        case "LintErrors":
                           LINTER.live = true;
                           PREGO.fire();
                           fair( LINTER.first );
                           break;
                     }   // switch wgCanonicalSpecialPageName
                     break;
                  case 102:
                  case 104:
                  case 106:
                  case 108:
                  case 110:
                  case 112:
                     // might be Wikisource
                     s = mw.config.get( "wgPageContentModel" );
                     if ( typeof HINT.cmodels[ s ]  ===  "boolean" ) {
                        HINT.source = s;
                     }   // fall through
                  default:
                     HINT.idRev = mw.config.get( "wgRevisionId" );
                     s          = window.location.search;
                     if ( HINT.idRev <= 0 ) {
                        live = false;
                     } else if ( s ) {
                        re     = "\\b(diff|history|printable)=";
                        re     = new RegExp( re );
                        live = ! re.test( s );
                        if ( live ) {
                           if ( s.indexOf( "&oldid=" )  >  0 ) {
                              if ( mw.config.get( "wgCurRevisionId" ) !==
                                                           HINT.idRev ) {
                                 HINT.last = false;
                                 HINT.live = false;
                              }
                           } else if ( s.indexOf( "&lintid=" )  >  0 ) {
                              HINT.launch = true;
                           }
                           if ( s.indexOf( EDIT.sourceVE )  >  0 ) {
                              later         = true;
                              EDIT.layer    = true;
                              EDIT.live     = true;
                              EDIT.selector = HINT.selTextbox;
                           }
                        }
                     } else {
                        live = true;
                     }
               }   // switch wgNamespaceNumber
               break;
            case "edit":
            case "submit":
//          case "parsermigration-edit":
               EDIT.live = true;
               HINT.nsn  = mw.config.get( "wgNamespaceNumber" );
               HINT.using.push( "jquery.textSelection" );
               live = true;
               if ( HINT.nsn >= 100 ) {
                  s = mw.config.get( "wgPageContentModel" );
                  if ( s === "proofread-page" ) {
                     HINT.source = s;
                  }
               }
               // mw.hook( "CodeMirror.enabled" ).add( CODMIRROR.fire );
               break;
         }   // switch wgAction
         if ( live ) {
            if ( ! HINT.source ) {
               HINT.source = mw.config.get( "wgPageContentModel" );
               live        = ( HINT.source === "wikitext" );
            }
            listen = live;
         }
         if ( listen ) {
            mw.hook( Signature + ".config" ).add( features );
         }
         if ( live ) {
            if ( later ) {
               mw.loader.using( HINT.using, EDIT.fading );
            } else {
               fair();
               PREGO.fire();
            }
         }
         HINT.pub = { doc:  "[[" + HINT.doc + "]]",
                      type: Signature,
                      vsn:  Version };
         mw.hook( Signature + ".ready" ).fire( HINT.pub );
      }
   }   // first()



   API.fault = function ( jqXHR, textStatus, errorThrown ) {
      // API failure
      // Precondition:
      //    Common failure call
      // Uses:
      //    >  Signature
      //     < API.scream
      //     < API.errors
      //    (BOX.fault)
      // 2017-08-03 PerfektesChaos@de.wikipedia
      if ( textStatus ) {
         switch ( typeof textStatus ) {
            case "object":
               if ( typeof textStatus.textStatus  ===  "string" ) {
                  API.scream = textStatus.textStatus;
               } else {
                  API.scream = "";
               }
               if ( typeof textStatus.exception  ===  "string"
                    &&     textStatus.exception ) {
                  API.scream = API.scream + " ("
                               + textStatus.exception + ")";
               }
               break;
            case "string":
               API.scream = textStatus;
               break;
         }   // switch typeof textStatus
      }
      if ( errorThrown ) {
         if ( API.scream ) {
            API.scream = API.scream + "  -- Error: ";
         }
         API.scream = API.scream + errorThrown;
      }
      if ( ! API.scream ) {
         API.scream = "???";
      }
      if ( typeof window.console  ===  "object"   &&
           typeof window.console.log  ===  "function" ) {
         window.console.log( Signature + " * " + API.scream );
         if ( typeof textStatus  ===  "object"
              &&     textStatus   &&
              typeof window.console.dir  ===  "function" ) {
            window.console.dir( textStatus );
         }
      }
      API.errors = false;
      mw.hook( "wikipage.content" ).add( BOX.fault );
   };   // API.fault()



   API.fine = function ( arrived ) {
      // Answer on LINT arrived
      // Precondition:
      //    arrived  -- JSON result of ajax lint query
      // Uses:
      //     < API.errors
      //     < API.scream
      //    (BOX.fill)
      //    (BOX.flat)
      // 2017-08-01 PerfektesChaos@de.wikipedia
      var start;
      if ( typeof arrived  ===  "object"
           &&     arrived   &&
           typeof arrived.length  ===  "number"
           &&     arrived.length ) {
         API.errors = arrived;
         start      = "fill";
      } else {
         API.errors = false;
         start      = "flat";
      }
      API.scream = false;
      mw.hook( "wikipage.content" ).add( BOX[ start ] );
   };   // API.fine()



   API.fire = function ( ask ) {
      // Request POST
      // Precondition:
      //    ask  -- wikitext string, or not (current wikitext page)
      //    mediawiki.api available
      // Uses:
      //    >  API.site
      //    >  API.server
      //    >  API.scanner
      //    >< API.query
      //    API.first()
      //    (API.fine)
      //    (API.fault)
      // 2018-05-02 PerfektesChaos@de.wikipedia
      var local = ( typeof ask  ===  "string" );
               /* , f; */
      if ( typeof API.query  !==  "object" ) {
         /*
         f = function ( jqXHR ) {
                            jqXHR.setRequestHeader( "Content-Type",
                                                    "application/json" );
             };
         */
         API.query = { //beforeSend: f,
                       dataType:   "json"   // No "Intelligent Guess"
                     };
         if ( local ) {
            API.first();
            API.query.type = "POST";
            API.query.url  = API.site + API.server + API.scanner;
            //               API.site + "v3/" + API.scanner;
         }
      }
      if ( local ) {
         API.query.data = { wikitext: ask };
      }
      $.ajax( API.query ).done( API.fine )
                         .fail( API.fault );
   };   // API.fire()



   API.first = function () {
      // Initialize API
      // Uses:
      //    >< API.Api
      //    >< API.site
      // 2017-08-01 PerfektesChaos@de.wikipedia
      if ( ! API.Api ) {
         API.Api = new mw.Api();
      }
      if ( typeof API.site  !==  "string" ) {
         API.site  = window.location.protocol + "//" +
                     window.location.hostname + "/";
      }
   };   // API.first()



   API.full = function ( access, actual ) {
      // Analyse wikitext per page name
      // Precondition:
      //    access  -- string, with title of particular page, or current
      //    actual  -- number, of revID, or not
      //    mediawiki.api available
      // Uses:
      //    >  API.server
      //    >< API.single
      //    >< HINT.idRev
      //    >< API.page
      //    >< API.solver
      //    >< API.reSpace
      //     < HINT.launched
      //    API.first()
      //    (API.fine)
      //    (API.fault)
      // 2020-01-04 PerfektesChaos@de.wikipedia
      var idRev   = actual,
          subject = access   /* ,
          f */;
      HINT.launched = true;
      if ( typeof subject  ===  "string" ) {
         subject = subject.trim();
      } else {
         if ( ! API.single ) {
            API.single = mw.config.get( "wgPageName" );
         }
         subject = API.single;
         if ( ! HINT.idRev ) {
            HINT.idRev = mw.config.get( "wgRevisionId" );
         }
         idRev = HINT.idRev;
      }
      if ( typeof API.page  !==  "object" ) {
         API.first();
         /*
         f = function ( jqXHR ) {
                            jqXHR.setRequestHeader( "Content-Type",
                                                    "application/json" );
             }; */
         API.page = { /* beforeSend: f,   */
                      dataType:   "json"   // No "Intelligent Guess"
                    };
         API.solver = API.site + API.server + API.swift + "/";
      }
      if ( subject.indexOf( " " )  >  0 ) {
         if ( typeof API.reSpace  !==  "object" ) {
            API.reSpace = new RegExp( " +", "g" );
         }
         subject = subject.replace( API.reSpace, "_" );
      }
      API.page.url = API.solver + encodeURIComponent( subject );
      if ( idRev ) {
         API.page.url = API.page.url + "/" + idRev;
      }
      $.ajax( API.page ).done( API.fine )
                        .fail( API.fault );
   };   // API.full()



   BOX.facet = function ( $activate ) {
      // Button for PREGO options arrived
      // Precondition:
      //    $activate  -- jQuery object of PREGO special page button
      // Uses:
      //    >  HINT.ltr
      //    >
      // 2018-09-25 PerfektesChaos@de.wikipedia
      if ( $activate ) {
         $activate.css( { "display": "block",
                          "float":   ( HINT.ltr ? "right": "left" ) } );
         BOX.$box.append( $activate );
      }
   };   // BOX.facet()



   BOX.factory = function ( $area ) {
      // Create and equip large box, if necessary
      // Precondition:
      //    $area  -- mw-content-text
      // Uses:
      //    >  HINT.live
      //    >  HINT.ltr
      //    >  BOX.bgc
      //    >  BOX.boc
      //    >  BOX.fgc
      //    >  GUIDER.live
      //    >  PREGO.signature
      //    >  HINT.selector
      //    >  Signature
      //    >  Version
      //    >< BOX.$box
      //    BOX.first()
      //    face()
      //    BOX.focus()
      //    BOX.flat()
      //    BOX.firing()
      //    (BOX.flip)
      //    (BOX.facet)
      // 2021-06-03 PerfektesChaos@de.wikipedia
      var $a, $e;
      if ( HINT.live ) {
         BOX.first( $area );
         if ( BOX.$box ) {
            if ( BOX.$failure ) {
               BOX.$failure.hide();
            }
            BOX.$box.show();
         } else {
            face();
            BOX.$box = $( "<div>" );
            $e = $( "<div>" );
            if ( HINT.nsn < 0 ) {
               $a = $( "<span>" );
            } else {
               $a = $( "<a>" );
               $a.attr( { href:   "/wiki/Special:Blankpage/" + Signature,
                          target: Signature } );
            }
            $a.css( { "font-weight": "bold",
                      "font-size":  "larger" } )
              .text( Signature + "@PerfektesChaos" );
            $e.append( $a )
              .css( { "float": ( HINT.ltr ? "left": "right" ) } );
            BOX.$box.append( $e )
                    .addClass( HINT.selector + "-box" )
                    .attr( { id:   HINT.selector,
                             role: "alert" } )
                    .css( { "background-color":  "#" + BOX.bgc,
                            "border-color":      "#" + BOX.boc,
                            "border-style":      "solid",
                            "border-width":      "1px",
                            "color":             "#" + BOX.fgc,
                            "margin-bottom":     "1em",
                            "padding":           "0.5em",
                            "pointer-events":    "all" } );
            $e = $( "<button>" );
            $e.click( BOX.flip )
              .css( { "color":          "#FF0000",
                      "cursor":         "pointer",
                      "display":        "block",
                      "float":          ( HINT.ltr ? "right": "left" ),
                      "font-weight":    "bolder",
                      "pointer-events": "all" } )
              .css( "margin-" + ( HINT.ltr ? "right": "left" ),
                    "6px" )
              .text( "X" );
            BOX.$box.append( $e );
            BOX.focus( BOX.$box );
            if ( ! GUIDER.live ) {
               mw.hook( PREGO.signature + ".$button" ).fire( BOX.facet,
                                                             Signature );
            }
         }
      } else {
         BOX.flat();
      }
      BOX.firing( Version, false );
   };   // BOX.factory()



   BOX.fault = function ( $area ) {
      // API error arrived
      // Precondition:
      //    $area  -- mw-content-text
      //    DOM ready
      // Uses:
      //    >  BOX.$box
      //    >  BOX.$table
      //    >< BOX.$failure
      //     < API.scream
      //    BOX.flat()
      //    BOX.factory()
      //    GUIDER.fine()
      // 2021-06-03 PerfektesChaos@de.wikipedia
      BOX.flat();
      BOX.factory( $area );
      if ( API.scream && BOX.$box ) {
         if ( BOX.$table ) {
            BOX.$table.hide();
         }
         if ( ! BOX.$failure ) {
            BOX.$failure = $( "<div>" );
            BOX.$failure.css( { "clear":       "both",
                                "color":       "#FF0000",
                                "font-weight": "bold" } );
            BOX.$box.append( BOX.$failure );
         }
         BOX.$failure.text( API.scream )
                     .show();
      }
      GUIDER.fine( false );
   };   // BOX.fault()



   BOX.feed = function () {
      // Shrink box initiated
      // Uses:
      //    >  HINT.launch
      //    >  HINT.launched
      //    >  EDIT.live
      //     < API.errors
      //    UPDATE.fetch()
      //    API.full()
      //    mw.hook()
      //    (BOX.flip)
      // 2021-06-03 PerfektesChaos@de.wikipedia
      UPDATE.fetch();
      if ( HINT.launch  &&  ! HINT.launched  &&  ! EDIT.live ) {
         API.full();
      } else {
         API.errors = true;
         mw.hook( "wikipage.content" ).add( BOX.flip );
      }
   };   // BOX.feed()



   BOX.fill = function ( $area ) {
      // Table content arrived
      // Precondition:
      //    $area  -- mw-content-text
      //    mediawiki.api.messages available
      // Uses:
      //    >  BOX.$collapsed
      //    >  HINT.$widget
      //    >  BOX.$box
      //    >  HINT.$textarea
      //    >  GUIDER.last
      //    >  HINT.errors
      //    >  HINT.nsn
      //    >  PREGO.signature
      //    >  HINT.selector
      //    >< BOX.$table
      //    >< BOX.$tbody
      //    >< BOX.swift
      //    >< API.Api
      //    >< BOX.$pagename
      //    BOX.factory()
      //    mw.hook()
      //    BOX.filler()
      //    mw.Api.loadMessagesIfMissing()
      //    GUIDER.fine()
      //    (BOX.flag)
      //    (BOX.filler)
      //    (API.fault)
      // 2021-06-03 PerfektesChaos@de.wikipedia
      var i, req, $th, $thead, $tr;
      BOX.factory( $area );
      if ( BOX.$collapsed  &&  ! HINT.$widget ) {
         BOX.$collapsed.hide();
      }
      if ( BOX.$box ) {
         if ( BOX.$table ) {
            if ( HINT.$textarea ) {
               if ( GUIDER.last ) {
                  BOX.$swift.hide();
               } else {
                  BOX.$swift.show();
               }
            }
            BOX.$tbody.empty();
            BOX.filler();
         } else {
            BOX.$table = $( "<table>" );
            $thead = $( "<thead>" );
            if ( HINT.nsn < 0 ) {
               BOX.$pagename = $( "<caption>" );
               BOX.$pagename.css( { "font-weight": "normal",
                                    "white-space": "nowrap" } );
               BOX.$table.append( BOX.$pagename );
            }
            $tr = $( "<tr>" );
            $th = $( "<th>" );
            $th.text( "lint" );
            $tr.append( $th );
            $th = $( "<th>" );
            $th.text( "+" );
            $tr.append( $th );
            if ( HINT.$textarea ) {
               BOX.$swift = $( "<th>" );
               BOX.$swift.data( "sort-type", "number" )
                         .text( String.fromCharCode( 8659 ) );
               mw.hook( PREGO.signature + ".ready" ).add( BOX.flag );
               if ( GUIDER.last ) {
                  BOX.$swift.hide();
               }
               $tr.append( BOX.$swift );
            }
            $thead.append( $tr );
            BOX.$tbody = $( "<tbody>" );
            BOX.$table.addClass( "wikitable "
                                 + HINT.selector + "-table" )
                      .attr( { id:  HINT.selector + "-table" } )
                      .append( $thead, BOX.$tbody )
                      .css( { "clear":    "both",
                              "overflow": "scroll" } );
            if ( HINT.errors.length > 1  ||  HINT.nsn < 0 ) {
               BOX.$table.addClass( "sortable" );
            }
            BOX.$box.append( BOX.$table );
            req = [ ];
            for ( i = 0;  i < HINT.errors.length;  i++ ) {
               req.push( "linter-category-" + HINT.errors[ i ] );
            }   // for i
            if ( ! API.Api ) {
               API.Api = new mw.Api();
            }
            API.Api.loadMessagesIfMissing( req ).done( BOX.filler )
                                                .fail( API.fault );
         }
         GUIDER.fine( false );
      }
   };   // BOX.fill()



   BOX.filler = function () {
      // Table body rows
      // Precondition:
      //    api.messages available
      // Uses:
      //    >  API.errors
      //    >  mw.messages
      //    >  HINT.later
      //    >  HINT.selector
      //    >  BOX.bgcErr
      //    >  HINT.$textarea
      //    >  GUIDER.last
      //    >  BOX.swift
      //    >  BOX.$tbody
      //    >  BOX.$table
      //    >  BOX.boc
      //    >  PREGO.app
      //    >  PREGO.signature
      //    >< BOX.$other
      //    mw.message()
      //    UPDATE.feed()
      //    BOX.future()
      //    (BOX.find)
      //    (BOX.future)
      // 2021-06-03 PerfektesChaos@de.wikipedia
      var n = 0,
          e, i, k, par, s, $e, $e2, $e3, $td, $tr;
      for ( i = 0;  i < API.errors.length;  i++ ) {
         e = API.errors[ i ];
         s = "linter-category-" + e.type;
         if ( mw.messages.exists( s ) ) {
            s = mw.message( s ).text();
         } else {
            UPDATE.feed( e.type );
            if ( HINT.later ) {
               s = e.type;
            } else {
               s = false;
            }
         }
         if ( s ) {
            $tr = $( "<tr>" );
            $tr.addClass( HINT.selector + "-" + e.type );
            $td = $( "<td>" );
            $td.css( { "background-color":  "#" + BOX.bgcErr } );
            $td.text( s );
            $tr.append( $td );
            $td = $( "<td>" );
            $td.css( { "background-color":  "#FFFFFF" } );
            if ( typeof e.params  ===  "object" ) {
               par = e.params;
/*
if ( Version < 0 ) {
   for ( s in par ) {
      if ( s !== "child"  &&
           s !== "items"  &&
           s !== "name"  &&
           s !== "root" ) {
         console.log(s,par)
      }
   }   // for s in par
}
*/
               if ( typeof par.name  ===  "string" ) {
                  $td.text( par.name );
               } else if ( typeof par.subtype  ===  "string" ) {
                  $td.text( par.subtype );
               } else if ( typeof par.root  ===  "string"   &&
                           typeof par.child  ===  "string" ) {
                  $e = $( "<code>" );
                  $e.text( par.root );
                  $e2 = $( "<span>" );
                  $e2.css( { "padding-left":   "1em",
                             "padding-right":  "1em" } )
                     .html( "&gt;" );
                  $e3 = $( "<code>" );
                  $e3.text( par.child );
                  $td.append( $e, $e2, $e3 )
                     .css( { "white-space":  "nowrap" } );
               } else if ( typeof par.items  ===  "object"  &&
                           typeof par.items.length  ===  "number" ) {
                  for ( k = 0;  k < par.items.length;  k++ ) {
                     s = par.items[ k ];
                     if ( s.length > 50 ) {
                        $e = $( "<span>" );
                     } else {
                        $e = $( "<code>" );
                        $e.css( { "margin-right": "6px",
                               "white-space":  "nowrap" } );
                     }
                     $e.text( s );
                     $td.append( $e );
                  }   // for k
               }
            }
            $tr.append( $td );
            if ( HINT.$textarea   &&
                 ! GUIDER.last   &&
                 typeof e.dsr  ===  "object"
                 &&     e.dsr   &&
                 typeof e.dsr[ 0 ]  ===  "number"   &&
                 typeof e.dsr[ 1 ]  ===  "number" ) {
               $td = $( "<td>" );
               $td.click( BOX.find )
                  .css( { "background-color":  "#FFFFFF" } )
                  .data( "range", e.dsr )
                  .data( "sort-value", i )
                  .text( String.fromCharCode( 160, 8595, 160 ) );
               if ( typeof BOX.swift  ===  "string" ) {
                  $td.attr( { title: BOX.swift } );
               }
               $tr.append( $td );
            }
            BOX.$tbody.append( $tr );
            n++;
         }
      }   // for i
      if ( n ) {
         if ( BOX.$other ) {
            BOX.$other.hide();
         }
         if ( n > 1   &&
              typeof BOX.$table.tablesorter  ===  "function" ) {
            BOX.$table.tablesorter();
         }
         BOX.$table.show();
      } else {
         BOX.$table.hide();
         if ( BOX.$other ) {
            BOX.$other.show();
         } else {
            if ( PREGO.app ) {
               BOX.future();
            } else {
               mw.hook( PREGO.signature + ".ready" ).add( BOX.future );
            }
         }
      }
   };   // BOX.filler()



   BOX.find = function ( event ) {
      // Marker link has been clicked
      // Precondition:
      //    event  -- object, with event
      // Uses:
      //    >  HINT.$textarea
      // 2017-10-06 PerfektesChaos@de.wikipedia
      var $item = $( event.target ),
          range = $item.data( "range" );
      HINT.$textarea.focus()
                    .textSelection( "setSelection",
                                    { start: range[ 0 ],
                                      end:   range[ 1 ] } );
   };   // BOX.find()



   BOX.fine = function () {
      // Analysis without errors
      // Uses:
      //    >  BOX.$collapsed
      //    >  API.errors
      //    >  HINT.selector
      //    >  BOX.bgcOk
      //    BOX.firing()
      // 2021-06-03 PerfektesChaos@de.wikipedia
      if ( BOX.$collapsed  &&  ! API.errors ) {
         BOX.firing( "+" );
         BOX.$collapsed.addClass( HINT.selector + "-fine" )
                       .css( { "background-color":  "#" + BOX.bgcOk } );
      }
   };   // BOX.fine()



   BOX.firing = function ( about, active, attach ) {
      // Manage pivot button
      // Precondition:
      //    about   -- tooltip text
      //    active  -- true, if enabled after call
      //    attach  -- cursor style, or not
      // Uses:
      //    >  BOX.$collapsed
      //    >  BOX.bgcRun
      //    >  BOX.fgcRun
      //    >  BOX.fgc
      //    >  HINT.selector
      //    (BOX.full)
      // 2021-06-03 PerfektesChaos@de.wikipedia
      var signal;
      if ( BOX.$collapsed ) {
         if ( active ) {
            BOX.$collapsed.click( BOX.full )
                          .css( { "color":  "#" + BOX.fgc } );
            signal = "pointer";
         } else {
            BOX.$collapsed.css( { "background-color":  "#" + BOX.bgcRun,
                                  "color":             "#" + BOX.fgcRun
                                } )
                          .off( "click", BOX.full );
            signal = "default";
         }
         BOX.$collapsed.attr( { "aria-disabled":  ! active,
                                "title":          about } )
                       .css( { "cursor":  attach || signal } )
                       .removeClass( [ HINT.selector + "-fine",
                                       HINT.selector + "-progress" ] )
                       .show();
      }
   };   // BOX.firing()



   BOX.first = function ( $area ) {
      // Detect main section of page
      // Precondition:
      //    $area  -- mw-content-text, or nil
      // Uses:
      //    >  HINT.selMain
      //    >  EDIT.selVEsrc
      //    >< HINT.$main
      //    >< EDIT.layer
      //     < HINT.$content
      //     < EDIT.live
      // 2021-06-03 PerfektesChaos@de.wikipedia
      var $main, $top;
      if ( $area ) {
         HINT.$content = $area;
      }
      if ( ! HINT.$main ) {
         $top = $( HINT.selMain );
         switch ( $top.length ) {
            case 0:
               if ( $area ) {
                  HINT.$main = HINT.$content;
               }
               break;
            case 1:
               $main = $top;
               break;
            default:
               $main = $top.eq( 0 );
         }   // switch $top.length
         if ( $main ) {
            HINT.$main = $main.children().eq( 0 );
            if ( EDIT.layer  &&
                 ! $main.find( EDIT.selVEsrc ).length ) {
               EDIT.layer = false;
               EDIT.live  = false;
            }
         }
      }
   };   // BOX.first()



   BOX.flag = function ( application ) {
      // Tooltip on selection ranges requested
      // Precondition:
      //    application  -- PREGO object
      // Uses:
      //    >  HINT.texts.mark
      //    >  BOX.$swift
      //     < BOX.swift
      //    PREGO.app.translation()
      // 2017-10-06 PerfektesChaos@de.wikipedia
      if ( application ) {
         PREGO.app = application;
      }
      BOX.swift = PREGO.app.translation( HINT.texts.mark );
      BOX.$swift.attr( { title: BOX.swift } );
   };   // BOX.flag()



   BOX.flat = function ( $area, alive ) {
      // Hide boxes, if necessary
      // Precondition:
      //    $area  -- mw-content-text, or nil
      //    alive  -- leave BOX.$collapsed
      // Uses:
      //    >  BOX.$box
      //    >  EDIT.live
      //    >  API.errors
      //    >  API.scream
      //    >  HINT.lazy
      //    >  API.single
      //    >  HINT.launched
      //    >  HINT.selector
      //    >  Signature
      //    >  BOX.fgc
      //    >  HINT.ltr
      //    BOX.first()
      //    BOX.firing()
      //    BOX.fine()
      //    BOX.flip()
      //    GUIDER.fine()
      // 2021-06-03 PerfektesChaos@de.wikipedia
      BOX.first( $area );
      if ( BOX.$box ) {
         BOX.$box.hide();
      }
      if ( API.errors ) {
         BOX.firing( "?" );
      } else {
         BOX.fine();
      }
      if ( EDIT.live ) {
         if ( ! alive ) {
            BOX.flip();
         }
      } else if ( ! API.errors  &&
                  ! API.scream  &&
                  HINT.live  &&
                  GUIDER.live ) {
         GUIDER.fine( true );
      }
   };   // BOX.flat()



   BOX.flip = function ( $area ) {
      // Shrink box requested
      // Precondition:
      //    $area  -- mw-content-text, or nil
      // Uses:
      //    >  GUIDER.live
      //    >  HINT.selector
      //    >  HINT.ltr
      //    >  BOX.bgc
      //    >  Signature
      //    >  Version
      //    >  EDIT.live
      //    >  API.errors
      //    >  GUIDER.$pagename
      //    >< BOX.$collapsed
      //    BOX.first()
      //    face()
      //    BOX.firing()
      //    BOX.focus()
      //    EDIT.fine()
      //    (BOX.full)
      // 2021-06-03 PerfektesChaos@de.wikipedia
      BOX.first( $area );
      face();
      BOX.flat( $area, true );
      if ( ! GUIDER.live ) {
         if ( BOX.$collapsed ) {
            BOX.$collapsed.show();
         } else {
            BOX.$collapsed = $( "<div>" );
            BOX.$collapsed.addClass( HINT.selector + "-collapsed" )
                          .attr( { id:    HINT.selector + "-collapsed",
                                   role:  "button" } )
                          .css( { /* "clear":       ( HINT.ltr
                                                      ? "right":
                                                      "left" ),        */
                                  "padding-left":   "2px",
                                  "padding-right":  "2px",
                                  "padding-top":    "2px",
                                  "pointer-events": "all" } )
                          .text( Signature );
            BOX.focus( BOX.$collapsed, true, true );
         }
         BOX.firing( Version, true );
         BOX.$collapsed.css( { "background-color":  "#" + BOX.bgc } );
      }
      if ( EDIT.live  &&  ! API.errors ) {
         EDIT.fine();
      }
      if ( GUIDER.$pagename ) {
         GUIDER.$pagename.hide();
      }
   };   // BOX.flip()



   BOX.focus = function ( $apply, another, around ) {
      // Insertion in page top region or toolbox
      // Precondition:
      //    $apply   -- jQuery object
      //    another  -- try to add to indicators region
      //    around   -- button style in page
      // Uses:
      //    >  HINT.indicators
      //    >  HINT.selector
      //    >  HINT.$main
      //    >< HINT.$widget
      //    >< BOX.$top
      // 2021-06-03 PerfektesChaos@de.wikipedia
      var learn, light, s, $e;
      $apply.addClass( "noprint" );
      if ( another ) {
         if ( HINT.$widget === false ) {
            HINT.$widget = $( HINT.indicators );
            switch ( HINT.$widget.length ) {
               case 0:
                  HINT.$widget = null;
                  break;
               case 1:
                  break;
               default:
                  HINT.$widget = HINT.$widget.eq( 0 );
            }   // switch HINT.$widget.length
            learn = true;
         }
         if ( HINT.$widget ) {
            $apply.css( { "display":      "inline-block",
                          "line-height":  "1.2em",
                          "margin-left":  "3px",
                          "margin-right": "3px",
                          "padding":      "1px" } );
            HINT.$widget.append( $apply );
            light = true;
         } else {
            $apply.css( { "float":  ( HINT.ltr ? "right"
                                               : "left" ) } );
         }
      }
      if ( ! light ) {
         if ( ! BOX.$top ) {
            BOX.$top = $( "<div>" );
            BOX.$top.addClass( "noprint "
                               + HINT.selector + "-top" )
                    .attr( { id:  HINT.selector + "-top" } )
                    .css( { "clear": "both",
                            "width": "100%" } );
            $e = $( "<div>" );
            $e.css( { "clear": "both" } );
            HINT.$main.before( BOX.$top, $e );
            learn = true;
         }
         if ( around ) {
            s =  "#E0E0E0 #E0E0E0 #707070 #707070";
         } else {
            s = "transparent";
         }
         $apply.css( { "border-color":  s,
                       "border-style":  "solid",
                       "border-width":  "2px",
                       "margin-bottom": "3px" } );
         BOX.$top.prepend( $apply );
      }
      if ( learn   &&
           window.document.location.hash ) {
         window.document.location = window.document.location.href;
      }
   };   // BOX.focus()



   BOX.full = function () {
      // Analysis or expanded box requested
      // Uses:
      //    >  HINT.live
      //    >  BOX.$box
      //    >  HINT.$widget
      //    >  BOX.$collapsed
      //    >  HINT.selector
      //    >  GUIDER.live
      //    >  Version
      //    >< API.errors
      //    >< API.single
      //    >< EDIT.live
      //     < HINT.launch
      //    BOX.firing()
      //    EDIT.fire()
      //    API.full()
      //    (BOX.full)
      // 2021-06-03 PerfektesChaos@de.wikipedia
      var idRev;
      if ( HINT.live ) {
         if ( BOX.$box ) {
            if ( EDIT.live ) {
               API.errors = false;
            } else if ( HINT.$widget ) {
               BOX.firing( "?" );
            }
            if ( API.errors ) {
               BOX.$box.show();
            } else {
               BOX.$box.hide();
            }
         }
         BOX.firing( "...", false, "progress" );
         BOX.$collapsed.addClass( HINT.selector + "-progress" );
         if ( ! GUIDER.live ) {
            if ( ! API.single ) {
               API.single = mw.config.get( "wgPageName" );
            }
            if ( HINT.idRev  &&  HINT.idRev > 0 ) {
               idRev = HINT.idRev;
            }
         }
         if ( EDIT.live ) {
            EDIT.fire();
         } else {
            HINT.launch = true;
            API.full( API.single, idRev );
            BOX.firing( "?", false, "progress" );
         }
      } else if ( HINT.$widget ) {
         BOX.firing( "?", false, "progress" );
      }
   };   // BOX.full()



   BOX.future = function ( application ) {
      // Remark on uncategorized features requested
      // Precondition:
      //    application  -- PREGO object
      // Uses:
      //    >  HINT.texts.other
      //    >  HINT.selector
      //    >  BOX.$box
      //    >< PREGO.app
      //     < BOX.$other
      //    PREGO.app.translation()
      // 2021-05-26 PerfektesChaos@de.wikipedia
      var $e;
      if ( application ) {
         PREGO.app = application;
      }
      if ( PREGO.app ) {
         $e = $( "<span>" );
         $e.css( { "border-color":  "#" + BOX.boc,
                   "border-style":  "solid",
                   "border-width":  "1px",
                   "padding":       "0.4em" } )
           .html( PREGO.app.translation( HINT.texts.other ) );
         BOX.$other = $( "<div>" );
         BOX.$other.addClass( HINT.selector + "-future" )
                   .attr( { id:  HINT.selector + "-future" } )
                   .css( { "clear":          "both",
                           "padding-bottom": "1em",
                           "padding-top":    "1em" } )
                   .append( $e );
         BOX.$box.append( BOX.$other );
      }
   };   // BOX.future()



   CODMIRROR.fetch = function () {
      // Retrieve CodeMirror contents
      // Postcondition:
      //    Returns contents, if present
      // Uses:
      //    >  CODMIRROR.cm
      // 2018-07-06 PerfektesChaos@de.wikipedia
      var r;
      if ( CODMIRROR.first() ) {
			r = CODMIRROR.cm.doc.getValue();
      }
      return r;
   };   // CODMIRROR.fetch()



   CODMIRROR.first = function () {
      // Check whether CodeMirror is activated
      // Postcondition:
      //    Returns something, if present
      // Uses:
      //    >  window.CodeMirror
      //    >< CODMIRROR.cm
      //    mw.user.options.get()
      // 2018-07-06 PerfektesChaos@de.wikipedia
      var r, uo;
      if ( ! CODMIRROR.cm   &&
           typeof window.CodeMirror  ===  "function"   &&
           typeof window.CodeMirror.doc  ===  "object" ) {
         CODMIRROR.cm = window.CodeMirror;
      }
      if ( CODMIRROR.cm ) {
         uo = mw.user.options.get( "usecodemirror" );
         if ( typeof uo  ===  "number"
              &&     uo > 0 ) {
			   r = CODMIRROR.cm;
         }
      }
      return r;
   };   // CODMIRROR.first()



/*
   CODMIRROR.fire = function ( app ) {
   };   // CODMIRROR.fire()
*/



   EDIT.fading = function () {
      // Add link to toolbox portlet
      // Precondition:
      //    mediawiki.util available
      // Postcondition:
      //    Toolbox prepared and execution started
      // Uses:
      //    >  Signature
      //    >  EDIT.layer
      //    >  HINT.selector
      //     < HINT.$widget
      //    BOX.first()
      //    mw.util.addPortletLink()
      //    fair()
      //    PREGO.fire()
      // 2021-06-03 PerfektesChaos@de.wikipedia
      var dom;
      BOX.first();
      if ( EDIT.layer ) {
         dom = mw.util.addPortletLink( "p-tb",
                                           "#",
                                           Signature,
                                           HINT.selector + "-portlet",
                                           Version );
         HINT.$widget = $( dom );
         if ( dom.nodeName.toLowerCase() !== "li" ) {
            HINT.$widget = HINT.$widget.parent();
         }
         HINT.$widget.empty();
      }
      fair();
      PREGO.fire();
   };   // EDIT.fading()



   EDIT.fetch = function () {
      // Retrieve HTML textarea contents
      // Postcondition:
      //    Returns textarea contents, if present
      // Uses:
      //    >  EDIT.selTextbox
      //    >  HINT.source
      //    >  HINT.$main
      //    >  HINT.$content
      //    >< EDIT.selector
      //    >< EDIT.$source
      //     < EDIT.listen
      //     < HINT.$textarea
      // 2021-06-03 PerfektesChaos@de.wikipedia
      var r, $div;
      if ( ! EDIT.$source ) {
         if ( EDIT.layer ) {
            EDIT.selector = EDIT.selTextbox;
         } else if ( ! EDIT.selector ) {
            switch ( HINT.source ) {
               case "wikitext":
               case "proofread-page":
                  EDIT.selector = "#wpTextbox1";
                  break;
            }   // switch HINT.source
         }
         if ( EDIT.selector ) {
            if ( EDIT.layer ) {
               $div = HINT.$main;
            } else {
               $div = HINT.$content;
            }
            EDIT.$source = $div.find( EDIT.selector );
            if ( ! EDIT.$source.length ) {
               EDIT.live = false;
            }
         } else {
            EDIT.live = false;
         }
      }
      if ( EDIT.live && EDIT.$source && EDIT.$source.length ) {
         if ( EDIT.layer ) {
            r = EDIT.$source.text();
         } else {
            HINT.$textarea = EDIT.$source;
            r              = EDIT.$source.val();
         }
      }
      return r;
   };   // EDIT.fetch()



   EDIT.fine = function () {
      // Source evaluation without errors
      // Uses:
      //    >  EDIT.$source
      //     < EDIT.listen
      //    BOX.fine()
      //    (EDIT.focus)
      // 2021-06-03 PerfektesChaos@de.wikipedia
      if ( EDIT.$source ) {
         EDIT.listen = true;
         EDIT.$source.focusin( EDIT.focus );
      }
      BOX.fine();
   };   // EDIT.fine()



   EDIT.fire = function () {
      // Anaysis of source text area requested
      // Uses:
      //    >  TMPLXPAND.live
      //    CODMIRROR.fetch()
      //    WIKED.fetch()
      //    EDIT.fetch()
      //    API.fire()
      // 2021-06-03 PerfektesChaos@de.wikipedia
      var source;
      if ( ! TMPLXPAND.live ) {
         source = CODMIRROR.fetch();
         if ( ! source ) {
            WIKED.fetch();
         }
      }
      if ( ! source ) {
         source = EDIT.fetch();
      }
      if ( source ) {
         EDIT.listen = false;
         API.fire( source );
      }
   };   // EDIT.fire()



   EDIT.focus = function () {
      // Source area has been touched
      // Uses:
      //    >  Version
      //    >  BOX.bgc
      //    >  BOX.$collapsed
      //    >< EDIT.listen
      //    BOX.firing()
      // 2021-06-03 PerfektesChaos@de.wikipedia
      if ( EDIT.listen ) {
         BOX.firing( Version, true );
         BOX.$collapsed.css( { "background-color":  "#" + BOX.bgc } );
         EDIT.listen = false;
      }
   };   // EDIT.focus()



   LINTER.fire = function (  ) {
      // LintErrors page prerequisites completed
      // Uses:
      //     < LINTER.live
      //    mw.hook()
      //    (LINTER.form)
      // 2018-05-07 PerfektesChaos@de.wikipedia
      LINTER.live = true;
      mw.hook( "wikipage.content" ).add( LINTER.form );
   };   // LINTER.fire()



   LINTER.first = function () {
      // LintErrors page loading
      // Precondition:
      //    jquery.tablesorter available
      // Uses:
      //    >  LINTER.live
      //    mw.config.get()
      //    fair()
      //    (LINTER.fire)
      // 2018-05-07 PerfektesChaos@de.wikipedia
      if ( mw.config.get( "wgTitle" ).indexOf( "/" )  >  0
           &&  ! LINTER.live ) {
         fair( LINTER.fire );
      }
   };   // LINTER.first()



   LINTER.form = function ( $area ) {
      // LintErrors page has been loaded
      // Precondition:
      //    $area  -- mw-content-text
      // Uses:
      //    >  HINT.layer
      //     < LINTER.reEdit
      //     < LINTER.seek
      //     < LINTER.subst
      //    (LINTER.further)
      // 2019-04-27 PerfektesChaos@de.wikipedia
      var $table = $area.find( ".mw-datatable, .TablePager" );
      if ( $table.length ) {
         if ( typeof $table.tablesorter  ===  "function" ) {
            $table.tablesorter();
         }
/*
         if ( typeof HINT.layer  ===  "boolean" ) {
            if ( HINT.layer ) {
               LINTER.reEdit  = new RegExp( "([?&]action=)" +
                                            "edit" +
                                            "(&.+)?$" );
               LINTER.seek  = "action=edit";
               LINTER.subst = "$1parsermigration-edit$2";
            } else {
               LINTER.reEdit  = new RegExp( "([?&]action=)" +
                                            "parsermigration-edit" +
                                            "(&.+)?$" );
               LINTER.seek  = "action=parsermigration-edit";
               LINTER.subst = "$1edit$2";
            }
            $table.find( "a" ).each( LINTER.further );
         }
*/
      }
   };   // LINTER.form()



/*
   LINTER.further = function ( any, a ) {
      // Divert LintErrors page link
      // Precondition:
      //    any  -- number of link in table
      //    a    -- DOM object of <a>
      // Uses:
      //    >  LINTER.reEdit
      //    >  LINTER.seek
      //    >  LINTER.subst
      // 2018-05-02 PerfektesChaos@de.wikipedia
      var $a = $( a ),
          s  = $a.attr( "href" );
      if ( s.indexOf( LINTER.seek )  >  0 ) {
         $a.attr( "href",  s.replace( LINTER.reEdit, LINTER.subst ) );
      }
   };   // LINTER.further()
*/



   GUIDER.facet = function ( $activate ) {
      // Button for PREGO options arrived
      // Precondition:
      //    $activate  -- jQuery object of PREGO special page button
      // Uses:
      //    >  HINT.ltr
      //    >  GUIDER.$desc
      // 2018-05-02 PerfektesChaos@de.wikipedia
      if ( $activate ) {
         $activate.css( { "float":      ( HINT.ltr ? "right": "left" ),
                          "margin-top": "1em" } );
         GUIDER.$desc.before( $activate );
      }
   };   // GUIDER.facet()



   GUIDER.figure = function () {
      // Revision number input value has been changed
      // Uses:
      //    >  GUIDER.$rev
      //    >< GUIDER.reNaN
      // 2018-05-02 PerfektesChaos@de.wikipedia
      var s = GUIDER.$rev.val().trim();
      if ( ! GUIDER.reNaN ) {
         GUIDER.reNaN = new RegExp( "[^0-9]", "g" );
      }
      s = s.replace( GUIDER.reNaN, "" );
      GUIDER.$rev.val( s );
   };   // GUIDER.figure()



   GUIDER.filled = function () {
      // Page name input value has been changed
      // Uses:
      //    >  GUIDER.$input
      //    >  GUIDER.$rev
      // 2018-05-02 PerfektesChaos@de.wikipedia
      var s = GUIDER.$input.val().trim();
      GUIDER.$rev.attr( { disabled:  ( s ? false : true ) } );
   };   // GUIDER.filled()



   GUIDER.find = function () {
      // Page name submit button has been clicked
      // Uses:
      //    >  GUIDER.$input
      //    >  GUIDER.$rev
      //    >  GUIDER.$startPage
      //     < GUIDER.last
      //     < API.single
      //    GUIDER.fired()
      //    API.full()
      // 2021-06-03 PerfektesChaos@de.wikipedia
      var s = GUIDER.$input.val().trim();
      GUIDER.$input.val( s );
      GUIDER.fired();
      GUIDER.last = true;
      if ( s ) {
         API.single = s;
         API.full( s, GUIDER.$rev.val() );
      }
      GUIDER.$startPage.css( { "cursor": "progress" } );
   };   // GUIDER.find()



   GUIDER.fine = function ( action ) {
      // Precondition:
      //    action  -- boolean, or Event object
      // Pretty result of analysis
      // Uses:
      //    >  GUIDER.live
      //    >  GUIDER.$pagename
      //    >  GUIDER.$okay
      //    >  GUIDER.$textarea
      //    >  BOX.bgcOk
      //    >  GUIDER.$input
      //    >  GUIDER.$startText
      //    >  GUIDER.$startPage
      //    (GUIDER.fine)
      // 2021-06-03 PerfektesChaos@de.wikipedia
      var lapsus, $e;
      if ( GUIDER.live ) {
         lapsus = ( action !== true );
         if ( ( ! API.single  ||  lapsus )
              &&  GUIDER.$pagename ) {
            GUIDER.$pagename.hide();
         }
         if ( lapsus ) {
            GUIDER.$okay.hide();
            GUIDER.$textarea.css( { "background-color": "transparent" } )
                            .off( "focusin", GUIDER.fine );
            GUIDER.$input.off( "focusin", GUIDER.fine );
         } else {
            if ( API.single  ) {
               $e = GUIDER.$pagename.children();
               if ( ! $e.length ) {
                  $e = $( "<a>" );
                  $e.attr( { target: "_blank" } );
                  GUIDER.$pagename.append( $e );
               }
               $e.attr( { href: mw.util.getUrl( API.single ) } )
                 .text( API.single );
               GUIDER.$pagename.show();
            } else {
               GUIDER.$okay.show();
               GUIDER.$textarea.css( { "background-color":
                                                      "#" + BOX.bgcOk } )
                               .focusin( GUIDER.fine );
               GUIDER.$input.focusin( GUIDER.fine );
            }
         }
         GUIDER.$startText.css( { "cursor": "pointer" } );
         GUIDER.$startPage.css( { "cursor": "pointer" } );
      }
   };   // GUIDER.fine()



   GUIDER.finish = function ( application ) {
      // Add instructions to special page
      // Precondition:
      //    application  -- PREGO object
      // Uses:
      //    >  HINT.texts.desc
      //    >  HINT.texts.howTo
      //    >  GUIDER.$desc
      //    >  HINT.$content
      //    >  HINT.texts.domain
      //    >  Signature
      //    >  GUIDER.$doc
      //     < PREGO.app
      //    PREGO.app.translation()
      // 2021-06-03 PerfektesChaos@de.wikipedia
      var $e = $( "<div>" );
      PREGO.app = application;
      GUIDER.$desc.html( PREGO.app.translation( HINT.texts.desc ) );
      $e.css( { "clear":      "both",
                "margin-top": "8em" } )
        .html( PREGO.app.translation( HINT.texts.howTo ) );
      HINT.$content.append( $e );
      $e = $( "<a>" );
      $e.attr( { href:   "https://"
                         + PREGO.app.translation( HINT.texts.domain )
                         + "/wiki/"
                         + "User:PerfektesChaos/js/"
                         + Signature,
                 target: Signature } )
        .text( GUIDER.$doc.text() );
      GUIDER.$doc.text( "" )
                 .append( $e );
   };   // GUIDER.finish()



   GUIDER.fire = function () {
      // Textarea submit button has been clicked
      // Uses:
      //    >  GUIDER.$textarea
      //    >  GUIDER.reTrim
      //    >  GUIDER.$startText
      //     < GUIDER.last
      //     < API.single
      //     < HINT.launched
      //    GUIDER.fired()
      //    API.fire()
      // 2021-06-03 PerfektesChaos@de.wikipedia
      var s = GUIDER.$textarea.val();
      GUIDER.fired();
      GUIDER.last = false;
      if ( ! GUIDER.reTrim.test( s ) ) {
         API.single = false;
         API.fire( s );
         HINT.launched = true;
      }
      GUIDER.$startText.css( { "cursor": "progress" } );
   };   // GUIDER.fire()



   GUIDER.fired = function () {
      // Submit button has been clicked
      // Uses:
      //    >< GUIDER.reTrim
      //    GUIDER.flat()
      // 2017-08-04 PerfektesChaos@de.wikipedia
      GUIDER.flat();
      if ( ! GUIDER.reTrim ) {
         GUIDER.reTrim   = new RegExp( "^\\s*$" );
      }
   };   // GUIDER.fired()



   GUIDER.first = function () {
      // Prepare special page for equipping
      // Uses:
      //    >  GUIDER.using
      //    >< HINT.using
      //     < HINT.live
      //     < GUIDER.live
      //    PREGO.fire()
      //    fair()
      //    mw.loader.load()
      //    mw.hook()
      //    (GUIDER.furnish)
      // 2018-05-02 PerfektesChaos@de.wikipedia
      var i;
      PREGO.fire();
      for ( i = 0;  i < GUIDER.using.length;  i++ ) {
         HINT.using.push( GUIDER.using[ i ] );
      }   // for i
      fair();
      mw.loader.load( HINT.using );
      HINT.live   = true;
      GUIDER.live = true;
      mw.hook( "wikipage.content" ).add( GUIDER.furnish );
   };   // GUIDER.first()



   GUIDER.flat = function () {
      // Hide boxes, since any button has been clicked
      // Uses:
      //    >  BOX.$box
      //    GUIDER.fine()
      // 2021-06-03 PerfektesChaos@de.wikipedia
      if ( BOX.$box ) {
         BOX.$box.hide();
      }
      GUIDER.fine( false );
   };   // GUIDER.flat()



   GUIDER.foreign = function () {
      // Request messages
      // Precondition:
      //    mediawiki.api.messages available
      // Uses:
      //    >< API.Api
      //    UPDATE.fetch()
      //    mw.Api.loadMessagesIfMissing()
      //    (GUIDER.form)
      //    (API.fault)
      // 2018-05-20 PerfektesChaos@de.wikipedia
      var req = [ "general-form-reset",
                  "go" ],
          i;
      if ( ! API.Api ) {
         API.Api = new mw.Api();
      }
      UPDATE.fetch();
      for ( i = 0;  i < HINT.errors.length;  i++ ) {
         req.push( "linter-category-" + HINT.errors[ i ] );
      }   // for i
      API.Api.loadMessagesIfMissing( req ).done( GUIDER.form )
                                          .fail( API.fault );
   };   // GUIDER.foreign()



   GUIDER.form = function () {
      // Equip page with buttons
      // Precondition:
      //    answer  -- messages
      //    api.messages available
      // Uses:
      //    >  GUIDER.$formText
      //    >  GUIDER.suitable
      //    >  GUIDER.$formPage
      //    >  HINT.ltr
      //    >  PREGO.signature
      //     < GUIDER.$startText
      //     < GUIDER.$okay
      //     < GUIDER.$startPage
      //    mw.hook()
      //    (GUIDER.fire)
      //    (GUIDER.flat)
      //    (GUIDER.find)
      //    (GUIDER.filled)
      //    (GUIDER.finish)
      // 2021-06-03 PerfektesChaos@de.wikipedia
      var submit = mw.message( "go" ).text(),
          $div   = $( "<div>" ),
          $x     = $( "<span>" ),
          $b;
      $x.css( { "color":        "#FF0000",
                "font-weight":  "bolder" } )
        .text( "X" );
      GUIDER.$startText = $( "<span>" );
      GUIDER.$startText.addClass( "mw-ui-button mw-ui-progressive" )
                       .click( GUIDER.fire )
                       .css( { "color": "#FFFFFF" } )
                       .text( submit );
      GUIDER.$formText.append( GUIDER.$startText );
      GUIDER.$okay = $( "<span>" );
      GUIDER.$okay.css( { "background-color": "#" + BOX.bgcOk,
                          "margin-left":      "1em",
                          "margin-right":     "1em",
                          "padding":          "0.2em 0.5em" } )
                  .hide()
                  .text( GUIDER.suitable );
      GUIDER.$formText.append( GUIDER.$okay );
      $b = $( "<input>" );
      $b.addClass( "mw-ui-button" )
        .append( $x )
        .attr( { type: "reset" } )
        .click( GUIDER.flat )
        .css( { "display": "block",
                "float":   ( HINT.ltr ? "right": "left" ) } );
      GUIDER.$formText.append( $b );
      $div.css( { "clear": "both" } );
      GUIDER.$formPage.append( $div );
      $b = $( "<input>" );
      $b.addClass( "mw-ui-button" )
        .append( $x.clone() )
        .attr( { type: "reset" } )
        .click( GUIDER.flat )
        .click( GUIDER.filled )
        .css( { "float": ( HINT.ltr ? "right": "left" ) } );
      GUIDER.$formPage.append( $b );
      GUIDER.$startPage = $( "<span>" );
      GUIDER.$startPage.addClass( "mw-ui-button mw-ui-progressive" )
                       .click( GUIDER.find )
                       .css( { "color": "#FFFFFF" } )
                       .text( submit );
      GUIDER.$formPage.append( GUIDER.$startPage );
      mw.hook( PREGO.signature + ".ready" ).add( GUIDER.finish );
   };   // GUIDER.form()



   GUIDER.furnish = function ( $area ) {
      // Equip page with docpage and intro
      // Precondition:
      //    $area  -- mw-content-text
      //    DOM ready
      // Uses:
      //    >  Signature
      //    >  HINT.$body
      //    >  HINT.ltr
      //    >  BOX.bgcOk
      //    >  HINT.using
      //    >  PREGO.signature
      //    >  HINT.selector
      //     < HINT.$content
      //     < GUIDER.$doc
      //     < GUIDER.$desc
      //     < GUIDER.$formText
      //     < GUIDER.$textarea
      //     < GUIDER.$formPage
      //     < GUIDER.$input
      //     < GUIDER.$rev
      //     < HINT.$textarea
      //    face()
      //    PREGO.foreign()
      //    mw.loader.using()
      //    mw.hook()
      //    (GUIDER.filled)
      //    (GUIDER.foreign)
      //    (GUIDER.facet)
      // 2021-06-03 PerfektesChaos@de.wikipedia
      var $v = $( "head" ),
          $e = $v.find( "title" );
      $e.remove();
      $e = $( "<title>" );
      $e.text( Signature );
      $v.prepend( $e );
      HINT.$content = $area;
      HINT.$content.empty();
      face();
      $v = HINT.$body.find( "#firstHeading,#section_0" );
      if ( ! $v.length ) {
         $v = $( "h1" );
      }
      $v.eq( 0 ).text( Signature );
      $v = $( "<div>" );
      $v.css( { "clear":  "both" } );
      GUIDER.$doc = $( "<span>" );
      GUIDER.$doc.text( Signature + "@PerfektesChaos" );
      $e = $( "<span>" );
      $e.css( { "font-size": "smaller" } )
        .css( "margin-" + ( HINT.ltr ? "left": "right" ),
              "2em" )
        .text( Version );
      $v.append( GUIDER.$doc, $e );
      GUIDER.$desc = $( "<div>" );
      GUIDER.$desc.css( { "font-size": "111%" } )
                  .text( String.fromCharCode( 160 ) );
      $v.append( $v, GUIDER.$desc );
      HINT.$content.append( $v );
      GUIDER.$formText = $( "<form>" );
      GUIDER.$textarea = $( "<textarea>" );
      GUIDER.$textarea.addClass( "mw-ui-input" )
                      .attr( { name: "wikitext" } )
                      .css( { "background-color": "transparent",
                              "margin-top":       "2em",
                              "max-width":        "100%",
                              "width":            "100%" } );
      GUIDER.$formText.append( GUIDER.$textarea );
      GUIDER.$formPage = $( "<form>" );
      GUIDER.$formPage.css( { "clear":      "both",
                              "margin-top": "3em" } );
      GUIDER.$input = $( "<input>" );
      GUIDER.$input.addClass( "mw-ui-input" )
                   .attr( { maxlength: 255,
                            name:      "pagename",
                            size:      50,
                            type:      "text" } )
                   .css( { "float":     ( HINT.ltr ? "left": "right" ),
                           "width":     "auto",
                           "max-width": "auto" } )
                   .keyup( GUIDER.filled )
                   .mouseup( GUIDER.filled );
      GUIDER.$formPage.append( GUIDER.$input );
      GUIDER.$rev = $( "<input>" );
      GUIDER.$rev.addClass( "mw-ui-input" )
                 .attr( { disabled:    true,
                          inputmode:   "numeric",
                          maxlength:   12,
                          name:        "revision",
                          placeholder: "oldid",
                          size:        8,
                          type:        "text" } )
                 .css( { "display":       "inline-block",
                         "margin-left":  "1.5em",
                         "margin-right": "1.5em",
                         "width":        "auto",
                         "max-width":    "auto" } )
                 .keyup( GUIDER.figure )
                 .mouseup( GUIDER.figure );
      GUIDER.$formPage.append( GUIDER.$rev );
      HINT.$content.append( GUIDER.$formText, GUIDER.$formPage );
      GUIDER.$pagename = $( "<div>" );
      GUIDER.$pagename.addClass( [ HINT.selector + "-pagename",
                                   HINT.selector + "-fine" ] )
                      .attr( { id:  HINT.selector + "-pagename" } )
                      .css( { "background-color": "#" + BOX.bgcOk,
                              "float":            ( HINT.ltr ? "left"
                                                             : "right" ),
                              "margin-bottom":    "1em",
                              "padding":          "4px",
                              "pointer-events":   "all" } )
                      .hide();
      HINT.$content.before( GUIDER.$pagename );
      HINT.$textarea = GUIDER.$textarea;
      mw.loader.using( HINT.using, GUIDER.foreign );
      mw.hook( PREGO.signature + ".$button" ).fire( GUIDER.facet,
                                                    Signature );
   };   // GUIDER.furnish()



   PREGO.features = function ( applied ) {
      // User options available
      // Precondition:
      //    applied  -- object, may be null, with values
      // Uses:
      //    >  PREGO.pars
      //    >  PREGO.signature
      //    >  Signature
      //    >  HINT.nsn
      //    >  HINT.using
      //    >  PREGO.live
      //    >< HINT.live
      //    >< LINTER.live
      //    mw.hook()
      //    PREGO.form()
      //    LINTER.first()
      //    mw.loader.using()
      //    (BOX.feed)
      // 2019-01-19 PerfektesChaos@de.wikipedia
      var i, n, s, v, vals;
      if ( typeof applied  ===  "object"
           &&     applied ) {
         n = PREGO.pars.length;
         for ( i = 0;  i < n;  i++ ) {
            v = PREGO.pars[ i ];
            s = v[ 0 ];
            if ( typeof applied[ s ]  ===  v[ 1 ] ) {
               HINT[ s ]  =  applied[ s ];
            }
         }   // for i
         if ( typeof applied.layer  ===  "boolean" ) {
            delete applied.layer;
            mw.hook( PREGO.signature + ".forward" ).fire( Signature,
                                                          applied );
         }
      }
      if ( HINT.spaces ) {
         HINT.spaces = HINT.spaces.trim();
      }
      if ( PREGO.live ) {
         PREGO.form();
      } else if ( LINTER.live ) {
         LINTER.live = false;
         LINTER.first();
      } else {
         if ( HINT.spaces ) {
            if ( HINT.spaces === "*" ) {
               HINT.live = true;
            } else if ( HINT.spaces !== "-" ) {
               vals = HINT.spaces.split( " " );
               s    = HINT.nsn + "";
               for ( i = 0;  i < vals.length;  i++ ) {
                  if ( s === vals[ i ] ) {
                     HINT.live = true;
                     break;   // for i
                  }
               }   // for i
            }
         } else if ( HINT.nsn === 0 ) {
            HINT.live = true;
         }
         if ( HINT.live  &&  HINT.nsn >= 0 ) {
            mw.loader.using( HINT.using, BOX.feed );
         }
      }
   };   // PREGO.features()



   PREGO.feed = function () {
      // Provide PREGO
      // Uses:
      //    >  PREGO.signature
      //    >  PREGO.site
      //    >  PREGO.store
      //    >  PREGO.sub
      //    >  PREGO.maxage
      //    mw.loader.getState()
      //    mw.loader.state()
      //    REPOS.fire()
      // 2018-09-03 PerfektesChaos@de.wikipedia
      var sign = "ext.gadget." + PREGO.signature,
          rls;
      if ( ! mw.loader.getState( sign ) ) {
         rls = { };
         rls[ sign ] = "loading";
         mw.loader.state( rls );
         REPOS.fire( PREGO.site,
                     PREGO.store + PREGO.signature + PREGO.sub,
                     false,
                     { action: "raw",
                       ctype:  "text/javascript",
                       bcache: 1,
                       maxage: PREGO.maxage } );
      }
   };   // PREGO.feed()



   PREGO.fiat = function () {
      // Namespaces text input field has been generated
      // Uses:
      //    >  PREGO.$spaces
      //    >< PREGO.reNum
      //    >< PREGO.rooms
      //    >< PREGO.follow
      // 2018-05-02 PerfektesChaos@de.wikipedia
      var s = PREGO.$spaces.val(),
          i, k, got, rooms;
      if ( s.indexOf( "-" )  >=  0 ) {
         s = "-";
      } else if ( s.indexOf( "*" )  >=  0 ) {
         s = "*";
      } else {
         got = s.trim().split( " " );
         s   = "";
         if ( got.length > 0 ) {
            if ( typeof PREGO.rooms  !==  "object" ) {
               PREGO.follow = function ( a, b ) {
                                 return ( a < b  ?  -1  :  1 );
                              };
               PREGO.reNum  = new RegExp( "^[0-9]+$" );
               PREGO.rooms  = mw.config.get( "wgFormattedNamespaces" );
            }
            rooms = [ ];
            for ( i = 0;  i < got.length;  i++ ) {
               if ( PREGO.reNum.test( got[ i ] ) ) {
                  k = parseInt( got[ i ], 10 );
                  if ( ( k === 0  ||  PREGO.rooms[ k ] )   &&
                       $.inArray( k, rooms )  <  0 ) {
                     rooms.push( k );
                  }
               }
            }   // for i
            if ( rooms.length > 0 ) {
               rooms.sort( PREGO.follow );
               s = rooms.join( " " );
            }
         }
      }
      PREGO.$spaces.val( s );
   };   // PREGO.fiat()



   PREGO.field = function ( $applying ) {
      // Namespaces text input field has been generated
      // Precondition:
      //    $applying  --  jQuery object of text input field
      // Uses:
      //     < PREGO.$spaces
      // 2018-05-02 PerfektesChaos@de.wikipedia
      PREGO.$spaces = $applying;
      PREGO.$spaces.change( PREGO.fiat );
   };   // PREGO.field()



   PREGO.fire = function () {
      // User options request
      // Uses:
      //    >  PREGO.signature
      //    >  Signature
      //    PREGO.feed()
      //    mw.hook()
      //    (PREGO.features)
      // 2018-05-02 PerfektesChaos@de.wikipedia
      PREGO.feed();
      mw.hook( PREGO.signature + ".fetch" ).fire( Signature,
                                                  PREGO.features );
   };   // PREGO.fire()



   PREGO.form = function () {
      // Equip Special:Gadgets page with entry and form
      // Uses:
      //    >  HINT.doc
      //    >  HINT.texts
      //    >  HINT.launch
      //    >  HINT.last
      //    >  HINT.lazy
      //    >  HINT.layer
      //    >  HINT.spaces
      //    >  Signature
      //    mw.hook()
      //    (PREGO.fiat)
      // 2019-01-19 PerfektesChaos@de.wikipedia
      var support = ".wikipedia.org/wiki/" + HINT.doc.substr( 3 ),
          docs    = { "en": "//en" + support,
                      "de": "//de" + support },
          dialog, opts;
      opts   = [ { signature: "spaces",
                   type:      "text",
                   show:      HINT.texts[ "^^spaces" ],
                   val:       ( HINT.spaces ? HINT.spaces
                                            : "" ),
                   field:     PREGO.field },
                 { signature: "launch",
                   type:      "checkbox",
                   show:      HINT.texts[ "^^launch" ],
                   val:       HINT.launch },
                 { signature: "last",
                   type:      "checkbox",
                   show:      HINT.texts[ "^^last" ],
                   val:       HINT.last },
                 { signature: "lazy",
                   type:      "checkbox",
                   show:      HINT.texts[ "^^lazy" ],
                   val:       HINT.lazy }
/*
                 ,
                 { signature: "layer",
                   type:      "checkbox",
                   show:      HINT.texts[ "^^layer" ],
                   val:       HINT.layer }
*/
               ];
      dialog = { script:  Signature,
                 support: docs,
                 suffix:  HINT.texts[ "^suffix" ],
                 opts:    opts };
      mw.hook( PREGO.signature + ".form" ).fire( dialog );
   };   // PREGO.form()



   REPOS.fire = function ( at, access, append, alter ) {
      // Load from external URL
      // Precondition:
      //    at      -- Wikimedia Foundation site code, or not
      //    access  -- string with basic page name
      //    append  -- string with subpage, or not
      //    alter   -- parameter object, or MIME string, or not
      // Uses:
      //    >< REPOS.requests
      //    REPOS.foundation()
      //    mw.loader.load()
      // 2018-03-21 PerfektesChaos@de.wikipedia
      var source, syntax;
      if ( typeof REPOS.requests  !==  "object" ) {
         REPOS.requests = { };
      }
      if ( typeof REPOS.requests[ access ]  !==  "boolean" ) {
         REPOS.requests[ access ] = true;
         if ( append ) {
            source = access + append;
         } else {
            source = access;
         }
         if ( at ) {
            source = REPOS.foundation( at, source, alter );
            if ( typeof alter  ===  "object"
                 &&     alter   &&
                 typeof alter.ctype  ===  "string" ) {
               syntax = alter.ctype;
            }
         } else {
            syntax = alter;
         }
         mw.loader.load( source, syntax );
      }
   };   // REPOS.fire()



   REPOS.foundation = function ( at, access, alter ) {
      // Create URL within Wikimedia Foundation
      // Precondition:
      //    at      -- site code, or not
      //    access  -- string with page name
      //    alter   -- parameter object, or not
      // Postcondition:
      //    Returns full URL
      // 2018-03-21 PerfektesChaos@de.wikipedia
      var s = access,
          r = encodeURI( s );
      if ( typeof alter  ===  "object"
           &&     alter ) {
         r = "/w/index.php?title=" + r;
         if ( access.substr( -3 ) === ".js" ) {
            alter.ctype = "text/javascript";
         } else if ( access.substr( -4 ) === ".css" ) {
            alter.ctype = "text/css";
         }
         alter.action = "raw";
         for ( s in alter ) {
            r = r + "&" + s + "=" + encodeURI( alter[ s ] );
         }   // for s in alter
      } else {
         r = "/wiki/" + r;
      }
      if ( typeof at  ===  "string"
           &&     at ) {
         switch ( at ) {
            case "meta":
               r = "meta.wikimedia.org" + r;
               break;
            case "mw":
               r = "www.mediawiki.org" + r;
               break;
            case "w:en":
               r = "en.wikipedia.org" + r;
               break;
            default:
               r = window.location.host + r;
         }   // switch at
         r = "https://" + r;
      }
      return r;
   };   // REPOS.foundation()



   TMPLXPAND.first = function () {
      // Initialize ExpandTemplates
      // Uses:
      //    >  HINT.using
      //     < TMPLXPAND.live
      //     < HINT.live
      //     < EDIT.live
      //     < EDIT.selector
      //    (TMPLXPAND.further)
      // 2018-07-06 PerfektesChaos@de.wikipedia
      TMPLXPAND.live = true;
      HINT.live      = true;
      EDIT.live      = true;
      EDIT.selector  = "#output";
      mw.loader.using( HINT.using, TMPLXPAND.further );
   };   // TMPLXPAND.first()



   TMPLXPAND.further = function () {
      // Prepare ExpandTemplates
      // Precondition:
      //    Resources available
      // Uses:
      //    mw.hook()
      //    (BOX.flip)
      // 2018-05-20 PerfektesChaos@de.wikipedia
      mw.hook( "wikipage.content" ).add( BOX.flip );
   };   // TMPLXPAND.first()



   UPDATE.feed = function ( apply ) {
      // Memorize unknown category
      // Uses:
      //    >< UPDATE.o
      //    UPDATE.flush()
      // 2018-05-20 PerfektesChaos@de.wikipedia
      if ( typeof UPDATE.o  !==  "object" ) {
         UPDATE.o = { };
      }
      if ( typeof UPDATE.o.unknown  !==  "object" ) {
         UPDATE.o.unknown = [ ];
      }
      if ( $.inArray( apply, HINT.errors )  <  0 ) {
         HINT.errors.push( apply );
         UPDATE.o.unknown.push( apply );
      }
      UPDATE.flush();
   };   // UPDATE.feed()



   UPDATE.fetch = function () {
      // Consider memorized categories
      // Precondition:
      //    mediawiki.storage available
      // Uses:
      //    >  Signature
      //    >< HINT.errors
      //     < UPDATE.o
      //    UPDATE.flush()
      // 2018-05-20 PerfektesChaos@de.wikipedia
      var storage = mw.storage.get( Signature ),
          i, k, parsed, s, unknown;
      if ( typeof storage  ===  "string" ) {
         try {
            parsed = JSON.parse( storage );
            if ( typeof parsed  ===  "object"
                 &&     parsed ) {
               if ( typeof parsed.translations  ===  "object"
                    &&     parsed.translations ) {
                  UPDATE.o = { translations: parsed.translations };
               }
               if ( typeof parsed.unknown  ===  "object"
                    &&     parsed.unknown    &&
                    typeof parsed.unknown.length  ===  "number"
                    &&     parsed.unknown.length ) {
                  unknown = [ ];
                  for ( i = 0;  i < parsed.unknown.length;  i++ ) {
                     s = parsed.unknown[ i ];
                     if ( typeof s  ===  "string" ) {
                        s = s.trim();
                        if ( s ) {
                           k = $.inArray( s, HINT.errors );
                           if ( k < 0 ) {
                              HINT.errors.push( s );
                              unknown.push( s );
                           }
                        }
                     }
                  }   // for i
                  if ( unknown.length ) {
                     if ( typeof UPDATE.o  ===  "object" ) {
                        UPDATE.o.unknown = unknown;
                     } else {
                        UPDATE.o = { unknown: unknown };
                     }
                  }
                  if ( unknown.length !== parsed.unknown.length ) {
                     UPDATE.flush();
                  }
               }
            }
         } catch (e) {
         }
         if ( typeof UPDATE.o  !==  "object" ) {
            UPDATE.flush();
         }
      }
   };   // UPDATE.fetch()



   UPDATE.flush = function () {
      // Update unknown categories memory
      // Precondition:
      //    mediawiki.storage available
      // Uses:
      //    >  Signature
      //    >  UPDATE.o
      // 2018-05-20 PerfektesChaos@de.wikipedia
      var storage;
      if ( typeof UPDATE.o  ===  "object" ) {
         storage = JSON.stringify( UPDATE.o );
      }
      if ( storage ) {
         mw.storage.set( Signature, storage );
      } else {
         mw.storage.remove( Signature );
      }
   };   // UPDATE.flush()



   WIKED.fetch = function () {
      // Update text area from wikEd contents
      // Uses:
      //    >  window.wikEd
      //    >< WIKED.wikEd
      // 2018-07-06 PerfektesChaos@de.wikipedia
      if ( ! WIKED.wikEd   &&
           ( typeof window.wikEd  ===  "function"   ||
             ( typeof window.wikEd  ===  "object"
               &&     window.wikEd ) )    &&
           typeof window.wikEd.disabled         ===  "boolean"    &&
           typeof window.wikEd.highlightSyntax  ===  "boolean"    &&
           typeof window.wikEd.turnedOn         ===  "boolean"    &&
           typeof window.wikEd.useWikEd         ===  "boolean" ) {
         WIKED.wikEd = window.wikEd;
      }
      if ( WIKED.wikEd   &&
           ! WIKED.wikEd.disabled  &&
           WIKED.wikEd.useWikEd    &&
           WIKED.wikEd.turnedOn    &&
           WIKED.wikEd.highlightSyntax ) {
         WIKED.wikEd.UpdateTextarea();
      }
   };   // WIKED.fetch()



/*
   WIKED.fire = function () {
      var script = document.createElement('script');
	   script.src = '//en.wikipedia.org/w/index.php?title=User:Cacycle/wikEd.js&action=raw&ctype=text/javascript';
	   script.async = true;
	   document.getElementsByTagName('head')[0].appendChild(script);
   };   // WIKED.fire()
   */



   first();
}( window.mediaWiki, window.jQuery ) );



// Emacs
// Local Variables:
// coding: utf-8-dos
// fill-column: 80
// End:

/// EOF </nowiki>   lintHint/d.js