MediaWiki:Gadget-importUtility/proj.js

Aus schwarzer2000.de
< MediaWiki:Gadget-importUtility
Version vom 20. März 2019, 19:36 Uhr von Apollon (Diskussion | Beiträge) (1 Version importiert)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

Hinweis: Leere nach dem Speichern den Browser-Cache, um die Änderungen sehen zu können.

  • Firefox/Safari: Umschalttaste drücken und gleichzeitig Aktualisieren anklicken oder entweder Strg+F5 oder Strg+R (⌘+R auf dem Mac) drücken
  • Google Chrome: Umschalttaste+Strg+R (⌘+Umschalttaste+R auf dem Mac) drücken
  • Internet Explorer: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
  • Opera: Gehe zu Menü → Einstellungen (Opera → Einstellungen auf dem Mac) und dann auf Datenschutz & Sicherheit → Browserdaten löschen → Gespeicherte Bilder und Dateien.
/// Gadget-importUtility/proj.js
//  Support request pages
/// 2018-08-24 PerfektesChaos@de.wikipedia
//  ResourceLoader: compatible;
//    dependencies: mediawiki.api, mediawiki.user, mediawiki.util
//                  .batch. .cnf. .utl.
//  Namespaces:     4
//  Build:          .proj
//                  .archive .difflink .edit .greet
//                  .hold .importer .justify
//                  .quiet .rename .versions .zone
//  Documentation:  [[w:de:Wikipedia:Technik/Skin/Gadgets/importUtility]]
/// Fingerprint:    #0#0#
/// @license GPL [//www.mediawiki.org/w/COPYING] (+GFDL, LGPL, CC-BY-SA)
/// <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    =  0.905,
       Self       =  "proj",
       IUTIL      =  "importUtility",
       SIG        =  "ext.gadget." + IUTIL,
       SIGNATURE  =  SIG + "." + Self;
   if ( ! mw.loader.getState( SIGNATURE ) ) {
      ( function () {
         var rls  =  { };
         rls[ SIGNATURE ]  =  "loading";
         mw.loader.state( rls );
      }() );
   }
   if ( typeof mw.libs[ IUTIL ]  !==  "object"   ||
        ! mw.libs[ IUTIL ] ) {
      mw.libs[ IUTIL ]  =  { };
   }
   mw.libs[ IUTIL ].type  =  IUTIL;
   IUTIL                  =  mw.libs[ IUTIL ];
   if ( typeof IUTIL.vsn  ===  "string" ) {
      IUTIL.vsn  =  IUTIL.vsn + " ";
   } else {
      IUTIL.vsn  =  "";
   }
   IUTIL.vsn  =  IUTIL.vsn + Self.substr( 0, 1 ) + "=" + Version;



//-----------------------------------------------------------------------



   if ( typeof IUTIL.archive  !==  "object" ) {
      // Support section archiving, if desired (.archive.offer)
      // Dependencies: mediawiki.api mediawiki.util
      IUTIL.archive  =  { };



      IUTIL.archive.fault  =  function ( about ) {
         // Show API failure on archive stamp
         // Precondition:
         //    about  -- JSON info of ajax query or string
         // Uses:
         //    >  .archive.$div
         //    jQuery().empty()
         //    jQuery().css()
         //    jQuery().text()
         //    jQuery().append()
         //    mw.log()
         // Remark: Used as event handler -- 'this' is not IUTIL.archive
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var $div     =  IUTIL.archive.$div,
             $span    =  $( "<span>" ),
             $strong  =  $( "<strong>" ),
             $spec;
         $div.empty();
         $span.css( { "border":      "solid 2px #FF0000",
                      "color":       "#FF0000",
                      "margin-left": "5px" } );
         $strong.css( { "margin-right": "1em" } );
         $strong.text( "ERROR" );
         $span.append( $strong );
         if ( typeof about  ===  "string" ) {
            $spec  =  $( "<span>" );
            $spec.text( about );
            $span.append( $spec );
         }
         $div.append( $span );
         mw.log( {loud:true}, "IUTIL.archive.fault()", 2, about );
      };   // .archive.fault()



      IUTIL.archive.feed  =  function ( arrived ) {
         // Set archive marker by API
         // Precondition:
         //    arrived  -- JSON result of ajax query
         // Uses:
         //    >  mw.Api
         //    >  .type
         //    >  .vsn
         //    mw.user.tokens.get()
         //    .cnf.feature()
         //    .archive.flip()
         //    mw.Api.post()
         //    .archive.fault()
         //    (.archive.fine)
         //    (.archive.fault)
         // Remark: Used as event handler -- 'this' is not IUTIL.archive
         // 2016-04-30 PerfektesChaos@de.wikipedia
         var i       =  false,
             n       =  false,
             q,
             shift   =  false,
             stamp,
             story,
             sucks   =  "feed",
             sum     =  false,
             swap    =  false,
             w;
         if ( arrived ) {
            q  =  arrived.query;
            if ( q ) {
               w  =  q.normalized;
               if ( w ) {
                  w  =  w[ 0 ];
                  if ( w ) {
                     shift  =  w.to;
                     w      =  /#([1-9][0-9]*)$/.exec( w.from );
                     if ( w ) {
                        n  =  parseInt( w[ 1 ],  10 );
                     }
                  }
               }
               w  =  q.pageids;
               if ( w ) {
                  i  =  w[ 0 ];
               }
               if ( i ) {
                  w  =  q.pages;
                  if ( w ) {
                     w  =  w[ i ];
                     if ( w ) {
                        w  =  w.revisions;
                        if ( w ) {
                           w  =  w[ 0 ];
                           if ( w ) {
                              stamp  =  w.timestamp;
                              story  =  w[ "*" ];
                              if ( story ) {
                                 w  =  IUTIL.archive.flip( story );
                                 if ( w ) {
                                    if ( w[ 0 ] === story ) {
                                       swap   =  false;
                                       sucks  =  sucks + "/equal";
                                    } else {
                                       swap  =  w[ 0 ];
                                       sum   =  "/* " + w[ 1 ] + " */ ";
                                    }
                                 }
                              }
                           }
                        }
                     }
                  }
               }
            }
         }
         if ( n && shift && sum && swap && stamp ) {
            q  =  new mw.Api();
            w  =  { action:        "edit",
                    token:         mw.user.tokens.get( "csrfToken" ),
                    basetimestamp: stamp,
                    minor:         false,
                    section:       n,
                    summary:       sum
                                   + IUTIL.cnf.feature( "Archive", true )
                                   + " / " + IUTIL.type
                                   + " " + IUTIL.vsn,
                    text:          swap,
                    title:         shift };
            q.post( w ).done( IUTIL.archive.fine )
                       .fail( IUTIL.archive.fault );
         } else {
            IUTIL.archive.fault( sucks );
         }
      };   // .archive.feed()



      IUTIL.archive.fine  =  function () {
         // Show API success on archive stamp
         // Uses:
         //    >  .archive.$div
         //    jQuery().empty()
         //    jQuery().css()
         //    jQuery().text()
         //    jQuery().append()
         //    .cnf.feature()
         // Remark: Used as event handler -- 'this' is not IUTIL.archive
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var $div   =  IUTIL.archive.$div,
             $span  =  $( "<span>" );
         $div.empty();
         $span.css( { "border":      "solid 1px #00A000",
                      "color":       "#00A000",
                      "margin-left": "5px",
                      "padding":     "2px" } );
         $span.text( IUTIL.cnf.feature( "Archive", false ) );
         $div.append( $span );
      };   // .archive.fine()



      IUTIL.archive.fire  =  function ( address ) {
         // Set archive marker by API: Retrieve section content
         // Precondition:
         //    address  -- section number
         // Uses:
         //    >  mw.Api
         //    >  .cnf.submit
         //    >  mw.util.$content
         //     < .archive.$div
         //    jQuery().find()
         //    mw.Api.get()
         //    jQuery().empty()
         //    .batch.$flow()
         //    jQuery().append()
         //    (.archive.feed)
         //    (.archive.fault)
         // Remark: Used as event handler -- 'this' is not IUTIL.archive
         // 2015-06-12 PerfektesChaos@de.wikipedia
         var q   =  new mw.Api(),
             w   =  { action:       "query",
                      "continue":   "",
                      indexpageids: true,
                      prop:         "revisions",
                      rvlimit:      1,
                      rvprop:       "content|timestamp",
                      titles:       "Project:" + IUTIL.cnf.submit
                                               + "#" + address,
                      rvsection:    address },
             $d  =  mw.util.$content.find( "#importUtilityArchive_"
                                           + address );
         if ( $d.length ) {
            q.get( w ).done( IUTIL.archive.feed )
                      .fail( IUTIL.archive.fault );
            IUTIL.archive.$div  = $d;
            $d.empty();
            $d.append( IUTIL.batch.$flow( 16, "margin-left:10px" ) );
         }
      };   // .archive.fire()



      IUTIL.archive.flip  =  function ( already ) {
         // Modify text in order to set archive template
         // Precondition:
         //    already  -- text
         // Postcondition:
         //    Return Array, or false if nothing to do
         //           [0]  modified text
         //           [1]  basic section title
         // Uses:
         //    this
         //    >  .cnf.project.archive.sectDone
         //    >  .cnf.project.archive.sectTerm
         //    >  .cnf.project.archive.stop
         //    >  .cnf.project.archive.solved
         // 2013-01-28 PerfektesChaos@de.wikipedia
         var pA    =  IUTIL.cnf.project.archive,
             slot  =  already,
             s     =  " " + pA.sectDone + " ==",
             sT    =  " " + pA.sectTerm + " ",
             sum   =  false,
             i     =  slot.indexOf( s ),
             g;
         if ( i > 0 ) {
            sum   =  slot.substr( 0, i );
            slot  =  sum  +  sT  +  "=="  +  slot.substr( i + s.length );
         } else if ( slot.indexOf( sT )  <  0 ) {
            g  =  /\b((=+)([^=\n].*[^=\n]))\2\n/.exec( slot );
            if ( g ) {
               if ( g[ 1 ].length > 6 ) {
                  sum   =  g[ 1 ];
                  slot  =  sum  +  sT  +  g[ 2 ]  +  "\n"
                           +  slot.substr( g[ 0 ].length );
               }
            }
         }
         s  =  pA.stop;
         i  =  slot.indexOf( s );
         if ( i > 0 ) {
            slot  =  slot.substr( 0, i )  +  slot.substr( i + s.length );
         }
         i  =  slot.toLowerCase().indexOf( pA.solved.toLowerCase() );
         if ( i < 0 ) {
            slot  =  slot + "\n\n" + pA.solved + "1=~~~~}}";
         }
         if ( sum ) {
            g  =  new RegExp( "^==+ *([^ ].*[^ ]) *$" );
            g  =  g.exec( sum );
            if ( g ) {
               sum  =  g[ 1 ];
            }
         }
         return  ( slot === already  ?  false
                                     :  [ slot, sum ] );
      };   // .archive.flip()



      IUTIL.archive.found  =  function () {
         // Equip IU section with archive button, if appropriate
         // Precondition:
         //    access  -- index (not used)
         // Postcondition:
         //    Return true for continued iteration
         // Uses:
         //    this  -- DOM element
         //    >  .cnf.project.archive.sectDone
         //    .cnf.feature()
         //    jQuery()
         //    jQuery().text()
         //    jQuery().children()
         //    jQuery().attr()
         //    jQuery().css()
         //    jQuery().append()
         //    (.archive.fire)
         // Remark: Used as jQuery callback -- 'this' is DOM element
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var $h  =  $( this ),
             s   =  $h.children( "span.mw-headline" ).text(),
             g, $btn, $span;
         if ( s.indexOf( IUTIL.cnf.project.archive.sectDone )  >  0 ) {
            s  =  $h.children( "span.mw-editsection" )
                    .children( "a" ).attr( "href" );
            if ( s ) {
               g  =  /section=([1-9][0-9]*)\b/.exec( s );
               if ( g ) {
                  g  =  g[1];
                  $span  =  $( "<span>" );
                  $span.attr( "id", "importUtilityArchive_" + g );
                  $span.css( { "margin-left": "2em" } );
                  $btn  =  $( "<button />" );
                  $btn.attr( { "type": "button" } );
                  $btn.text( IUTIL.cnf.feature( "Archive", false ) );
                  $btn.click( function () {
                                 IUTIL.archive.fire( g );
                              } );
                  $span.append( $btn );
                  $h.append( $span );
               }
            }
         }
         return true;
      };   // .archive.found()



      IUTIL.archive.furnish  =  function () {
         // Equip page with appropriate archive buttons
         // Uses:
         //    this
         //    >  .cnf.project.archive.offer
         //    >  mw.util.$content
         //    >  .cnf.project.section
         //    jQuery().find()
         //    jQuery().each()
         //    (.archive.found)
         // 2014-10-10 PerfektesChaos@de.wikipedia
         if ( typeof IUTIL.cnf.project.archive.offer  ===  "object" ) {
            if ( IUTIL.cnf.project.archive.offer[ IUTIL.mode - 1 ] ) {
               mw.util.$content.find( IUTIL.cnf.project.section )
                               .each( this.found );
            }
         }
      };   // .archive.furnish()
   }   // .archive



//-----------------------------------------------------------------------



   if ( typeof IUTIL.difflink  !==  "object" ) {
      // Guess REVISIONID form subst:REVISIONTIMESTAMP
      // Dependencies: mediawiki.api
      IUTIL.difflink  =  { };



      IUTIL.difflink.fault  =  function ( arrived ) {
         // Show API failure on difflink generation
         // Precondition:
         //    arrived  -- JSON info of ajax query
         // Uses:
         //    .utl.fault()
         //    mw.log()
         // Remark: Used as event handler -- 'this' is not IUTIL.difflink
         // 2013-01-05 PerfektesChaos@de.wikipedia
         IUTIL.utl.fault( false );
         mw.log( {loud:true}, "IUTIL.difflink.fault()", 2, arrived );
      };   // .difflink.fault()



      IUTIL.difflink.fire  =  function ( applicant ) {
         // Turn REVISIONTIMESTAMP of request into difflink
         // Precondition:
         //    applicant  -- originator nick, or false
         // Uses:
         //    this
         //    >  .cnf.project.difflink.start
         //    >  mw.Api
         //     < .idPage
         //    .edit.feed()
         //    .zone.factory()
         //    .utl.format()
         //    mw.config.get()
         //    mw.Api.get()
         //    (.difflink.found)
         //    (.difflink.fault)
         // 2015-06-12 PerfektesChaos@de.wikipedia
         var b, e, i, s, w,
             d  =  false,
             q  =  IUTIL.cnf.project.difflink.start;
         if ( q ) {
            s  =  IUTIL.edit.feed( false );
            if ( s ) {
               i  =  s.indexOf( q );
               if ( i > 0 ) {
                  s  =  s.substr( i + q.length,  14 );
                  if ( /^[0-9]{14}$/.test( s ) ) {
                     d  =  IUTIL.zone.factory( s );
                  }
               }
            }
         }
         if ( d ) {
            IUTIL.idPage  =  mw.config.get( "wgArticleId" );
            i  =  d.valueOf();
            d  =  15000;
            b  =  new Date( i + d );
            e  =  new Date( i - d );
            q  =  new mw.Api();
            w  =  { action:     "query",
                    "continue": "",
                    prop:       "revisions",
                    rvlimit:    3,
                    rvprop:     "ids",
                    rvuser:     applicant,
                    rvstart:    IUTIL.utl.format( b ),
                    rvend:      IUTIL.utl.format( e ),
                    pageids:    IUTIL.idPage };
            q.get( w ).done( this.found )
                      .fail( this.fault );
         }
      };   // .difflink.fire()



      IUTIL.difflink.found  =  function ( arrived ) {
         // Show API success on difflink generation
         // Precondition:
         //    arrived  -- JSON result of ajax query
         // Uses:
         //    >  .idPage
         //    >  .cnf.project.difflink.suggest
         //    >  .cnf.project.difflink.start
         //    .edit.feed()
         // Remark: Used as event handler -- 'this' is not IUTIL.difflink
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var q  =  arrived.query,
             i, k, s;
         if ( q ) {
            q  =  arrived.query;
            if ( q ) {
               q  =  q.pages;
               if ( q ) {
                  q  =  q[ IUTIL.idPage ];
                  if ( q ) {
                     q  =  q.revisions;
                     if ( q ) {
                        q  =  q[ 0 ];
                        if ( q ) {
                           q  =  q.revid;
                        }
                     }
                  }
                  if ( q ) {
                     s  =  IUTIL.edit.feed( false );
                     if ( s ) {
                        k  =  IUTIL.cnf.project.difflink.start;
                        i  =  s.indexOf( k );
                        if ( i > 0 ) {
                           s  =  s.substr( 0, i )  +  "</span>"
                                 + "([{{fullurl:{{PAGENAME}}|diff="
                                 + q + "}} "
                                 + IUTIL.cnf.project.difflink.suggest
                                 + "])"
                                 + s.substr( i + k.length + 25 );
                           IUTIL.edit.feed( s );
                        }
                     }
                  }
               }
            }
         }
      };   // .difflink.found()
   }   // .difflink



//-----------------------------------------------------------------------



   if ( typeof IUTIL.edit  !==  "object" ) {
      // Edit request page section
      // Dependencies: mediawiki.util
      IUTIL.edit  =  { };



      IUTIL.edit.failing  =  function ( about ) {
         // Warn on missing data
         // Precondition:
         //    about  -- explanation, or false
         // Uses:
         //    this
         //    >  .$msg
         //    jQuery()
         //    jQuery().text()
         //    jQuery().append()
         //    jQuery().css()
         //    .cnf.feature()
         //    .utl.fault()
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var $msg   =  $( "<strong>" );
         var $span  =  $( "<span>" );
         $span.text( IUTIL.cnf.feature( "Error" ) );
         $msg.append( $span );
         $span  =  $( "<span>" );
         $span.css( { "margin-left":  "1em",
                      "margin-right": "1em" } );
         $span.text( "*" );
         $msg.append( $span );
         $span  =  $( "<span>" );
         $span.text( IUTIL.cnf.feature( "ErrorData" )
                     +   ( about  ?  " (" + about + ")"  :  "" ) );
         $msg.append( $span );
         IUTIL.utl.fault( $msg, IUTIL.$msg );
      };   // .edit.failing()



      IUTIL.edit.fault  =  function ( about ) {
         // Bounce invalid request
         // Uses:
         //    this
         //    >< .cnf.project.edit.swap
         //    .edit.feed()
         //    .edit.flag()
         //    mw.log()
         // 2012-12-19 PerfektesChaos@de.wikipedia
         this.feed( this.feed( false )
                    +  "\n\n"
                    +  IUTIL.cnf.project.edit.swap  +  " --~~~~" );
         this.flag( "Swap" );
         mw.log( {loud:true}, "IUTIL.edit.fault()", 2, about );
      };   // .edit.fault()



      IUTIL.edit.feed  =  function ( apply ) {
         // Retrieve content of text area
         // Precondition:
         //    apply  -- false: retrieve content;  string: insert
         //    document.ready
         // Postcondition:
         //    Return textarea string; or false
         // Uses:
         //    this
         //    >  .edit.$textarea
         //    >  wikEd
         //    jQuery().val()
         //    wikEd.UpdateFrame()
         //    wikEd.UpdateTextarea()
         // 2013-01-05 PerfektesChaos@de.wikipedia
         var i, j, l,
             r  =  false;
         if ( this.$textarea ) {   // editing
            l  =  ( typeof apply  ===  "string" );
            if ( l ) {
               r  =  apply;
               i  =  r.indexOf( "<!-- *** " );
               if ( i > 0 ) {
                  j  =  r.indexOf( " *** -->",  i );
                  if ( j > 0 ) {
                     r  =  r.substr( 0, i )  +  r.substr( j + 8 );
                  }
               }
               this.$textarea.val( r );
            }
            if ( window.wikEd
                 &&  typeof window.wikEd  ===  "object"
                 &&  ! window.wikEd.disabled
                 &&  window.wikEd.turnedOn
                 &&  window.wikEd.useWikEd
                 &&  window.wikEd.UpdateFrame
                 &&  window.wikEd.UpdateTextarea ) {
               if ( l ) {
                  window.wikEd.UpdateFrame();
               } else {
                  window.wikEd.UpdateTextarea();
               }
            }
            if ( apply === false ) {
               r  =  this.$textarea.val();
            }
         }   // editing
         return r;
      };   // .edit.feed()



      IUTIL.edit.fetch  =  function () {
         // Retrieve transfer information from edit area
         // Postcondition:
         //    Returns object with appropriate data, or false
         //       .lang        -- source language other than current
         //       .from        -- source page
         //       .target      -- target page
         //       .originator  -- user
         //       .requestID   -- oldid of user request
         //       .versions    -- non-empty: found
         //       .sanitized   -- non-empty: found
         // Uses:
         //    this
         //    >  .cnf.project
         //    >  .mode
         //    >  .cnf.project.edit.shift
         //    >  .cnf.project.edit.source
         //    >  .versions.sketch
         //    >< .cnf.project.edit.reFrom
         //    >< .cnf.project.edit.reTo
         //    .edit.feed()
         //    mw.config.get()
         //    mw.Title.newFromText()
         //    .edit.failing()
         //    .edit.filter()
         // 2015-11-08 PerfektesChaos@de.wikipedia
         var r  =  false,
             s  =  this.feed( false ),
             env, g, o, p;
         if ( s ) {
            env  =  mw.config.get( [ "wgContentLanguage",
                                     "wgFormattedNamespaces" ] );
            p  =  IUTIL.cnf.project.edit;
            if ( ! p.reFrom ) {
               p.reFrom  =  new RegExp( p.source );
            }
            g  =  p.reFrom.exec( s );
            if ( g ) {
               r  =  g[ 2 ].replace( /\[/g, "" )
                           .replace( /\]/g, "" );
               o  =  new mw.Title.newFromText( r );
               if ( o ) {
                  r  =  { "from": o.getPrefixedText() };
               }
               if ( g[ 1 ] ) {
                  if ( g[ 1 ]  !==  env.wgContentLanguage ) {
                     r.lang  =  g[ 1 ];
                  }
               }
            }
            if ( r ) {
               if ( s.indexOf( IUTIL.versions.sketch )  >  0 ) {
                  r.versions  =  "*";
               }
               if ( ! p.reTo ) {
                  p.reTo  =  new RegExp( p.shift );
               }
               g  =  p.reTo.exec( s );
               if ( g ) {
                  o  =  new mw.Title.newFromText( g[ 1 ] );
                  if ( o ) {
                     r.target  =  o.getPrefixedText();
                  }
               }
               o  =  s.indexOf( "<span style=\"display:none\"" );
               if ( o >= 0 ) {
                  s  =  s.substr( o + 25 );
                  g  =  "{{fullurl:{{PAGENAME}}|diff=";
                  p  =  s.indexOf( g );
                  if ( p > 0 ) {
                     p  =  s.substr( p + g.length );
                     g  =  /^([0-9]+)\}\}/.exec( p );
                     if ( g ) {
                        r.requestID  =  g[ 1 ];
                     }
                  }
                  o  =  s.indexOf( "\n" );
                  if ( o > 0 ) {
                     s  =  s.substr( 0, o );
                  }
                  o  =  s.indexOf( "</span>" );
                  if ( o > 0 ) {
                     s  =  s.substr( 0,  o + 1 );
                  }
                  g  =  />([^#/|<\n]+).*</.exec( s );
                  if ( g ) {
                     s  =  g[ 1 ].replace( /\[/g, "" )
                                 .replace( /\]/g, "" );
                     o  =  new mw.Title.newFromText( s );
                     if ( o ) {
                        r.originator  =  o.getPrefixedText();
                     }
                  }
               }
               if ( ! r.target ) {
                  r.target  =  r.from;
                  if ( r.lang ) {
                     if ( ! IUTIL.cnf.space ) {
                        IUTIL.cnf.space  =
                                          env.wgFormattedNamespaces[ 2 ];
                     }
                     if ( r.originator ) {
                        r.target  =  IUTIL.cnf.space + ":"
                                     + r.originator + "/"
                                     + r.target;
                     } else {
                        this.failing( IUTIL.cnf.space );
                     }
                  }
               }
               r  =  this.filter( r );
            } else {
               this.failing( false );
            }
         }
         return r;
      };   // .edit.fetch()



      IUTIL.edit.fiat  =  function () {
         // Mark section as done
         // Uses:
         //    this
         //    .cnf.feature()
         //    .edit.feed()
         //    .edit.fill()
         // 2012-12-18 PerfektesChaos@de.wikipedia
         var got,
             signal  =  IUTIL.cnf.feature( "Done", true ),
             story   =  this.feed( false ),
             s,
             i       =  story.indexOf( "\n" ),
             re;
         if ( i > 6 ) {
            s  =  story.substr( 0, i );
            if ( s.substr( 0, 2 )  ===  "==" ) {
               if ( s.indexOf( signal )  <  0 ) {
                  re   =  new RegExp( "^(=+[^=].*[^= ]) *(=+) *$", "" );
                  got  =  re.exec( s );
                  if ( got ) {
                     story  =  got[1] + " " + signal + " " + got[2]
                               +  story.substr( i );
                     this.feed( story );
                  }
               }
            }
         }
         this.fill( "Done" );
      };   // .edit.fiat()



      IUTIL.edit.field  =  function () {
         // Ensure availability of edit area object
         // Uses:
         //    this
         //    >  mw.util.$content
         //    >< .edit.$textarea
         //    jQuery().find()
         //    jQuery().attr()
         // 2012-12-16 PerfektesChaos@de.wikipedia
         var $form;
         if ( ! this.$textarea ) {
            $form  =  mw.util.$content.find( "#editform" );
            if ( $form.length ) {
               this.$textarea  =  $form.find( "#wpTextbox1" );
               if ( this.$textarea.length ) {
                  if ( this.$textarea.attr( "readonly" ) ) {
                     this.$textarea  =  false;
                  }
               } else {
                  this.$textarea  =  false;
               }
            }
         }
      };   // .edit.field()



      IUTIL.edit.file  =  function () {
         // Export page: Open form
         // Uses:
         //    mw.util.getUrl()
         //    window.open()
         // 2014-09-28 PerfektesChaos@de.wikipedia
         window.open( mw.util.getUrl( "Special:Export" ),
                      "_blank" );
window.alert(".edit.file()\n Noch nicht so weit.");
      };   // .edit.file()



      IUTIL.edit.fill  =  function ( action, add ) {
         // Add process note on edit area and summary
         // Precondition:
         //    action  -- keyword
         //    add     -- additional remark
         // Uses:
         //    this
         //    .edit.feed()
         //    .cnf.feature()
         //    .utl.firm()
         //    .edit.flag()
         // 2014-10-10 PerfektesChaos@de.wikipedia
          var s  =  this.feed( false )
                    + "\n* "
                    + IUTIL.cnf.feature( action, true );
          if ( add ) {
             s  =  s + " * " + add;
          }
          s  =  s + " --" + IUTIL.utl.firm();
          this.feed( s );
          this.flag( action );
      };   // .edit.fill()



      IUTIL.edit.filter  =  function ( ask ) {
         // Sanitize retrieved content
         // Precondition:
         //    ask    -- input object
         // Postcondition:
         //    Returns same or sanitized ask
         //             < .sanitized
         // Uses:
         //    .utl.fault()
         //    .cnf.feature()
         //    window.alert()
         // 2014-01-03 PerfektesChaos@de.wikipedia
         var r  =  ask,
             stuff, symbol, $span, $strong;
         if ( ask ) {
            for ( symbol in r ) {
               stuff  =  r[ symbol ];
               if ( stuff.indexOf( "<" )  >=  0 ) {
                  $span    =  $( "<span>" );
                  $strong  =  $( "<strong>" );
                  r[ symbol ]  =  stuff.replace( /</g, "&lt;" );
                  r.sanitized  =  symbol;
                  window.alert( IUTIL.cnf.feature( "Malicious" )
                                + " '" + symbol + "'" );
                  $span.text( stuff );
                  $strong.append( $span );
                  $strong.append( $( "<br />" ) );
                  $strong.append( $( "<br />" ) );
                  $span  =  $( "<span>" );
                  $span.text( stuff );
                  $strong.append( $span );
                  IUTIL.utl.fault( $strong );
               }
            }   // for symbol in r
         }
         return r;
      };   // .edit.filter()



      IUTIL.edit.finish  =  function () {
         // Remove edit section content
         // Uses:
         //    this
         //    .edit.feed()
         //    .edit.flag()
         // 2012-12-15 PerfektesChaos@de.wikipedia
         this.feed( "" );
         this.flag( "Completed" );
      };   // .edit.finish()



      IUTIL.edit.finished  =  function () {
         // Mark section as resolved for archiving
         // Uses:
         //    this
         //    .archive.flip()
         //    .edit.feed()
         //    .edit.flag()
         // 2012-12-25 PerfektesChaos@de.wikipedia
         var story  =  this.feed( false );
         story  =  IUTIL.archive.flip( story );
         if ( story ) {
            this.feed( story );
            this.flag( "Archive" );
         }
      };   // .edit.finished()



      IUTIL.edit.fire  =  function ( action ) {
         // Perform action on page section editing
         // Precondition:
         //    action  -- keyword
         //               omitted: Start page processing
         // Uses:
         //    this
         //    >  .edit.$textarea
         //    .edit.field()
         //    .edit.finished()
         //    .greet.failed()
         //    .edit.finish()
         //    .edit.fiat()
         //    .edit.file()
         //    .rename.fire()
         //    .edit.fix()
         //    .edit.fill()
         //    .greet.fire()
         //    .edit.forward()
         //    .edit.fault()
         //    .greet.furnish()
         //    .edit.furnish()
         // 2013-01-16 PerfektesChaos@de.wikipedia
         this.field();
         if ( this.$textarea ) {
            switch ( action ) {
               case "Archive" :
                  this.finished();
                  break;
               case "Cancel" :
                  IUTIL.greet.failed();
                  break;
               case "DeleteIssue" :
                  this.finish();
                  break;
               case "Done" :
                  this.fiat();
                  break;
               case "Export" :
                  this.file();
                  break;
               case "Move" :
                  IUTIL.rename.fire();
                  break;
               case "PageAdapt" :
                  this.fix();
                  break;
               case "Moved" :
               case "PageAdapted" :
               case "Started" :
               case "UserNotified" :
                  this.fill( action );
                  break;
               case "SendNotifier" :
                  IUTIL.greet.fire();
                  break;
               case "Start" :
                  this.forward();
                  break;
               case "Swap" :
                  this.fault();
                  break;
              case "UserNotify" :
                  IUTIL.greet.furnish();
                  break;
               default:
                  this.furnish();
                  break;
            }   // switch action
         }
      };   // .edit.fire()



      IUTIL.edit.fix  =  function () {
         // Adapt target page content
         // Uses:
         //    this
         //     < .mod.lang
         //    .edit.fetch()
         //    .utl.fold()
         //    .edit.fill()
         //    .justify.fire()
         //    .cnf.feature()
         //    .utl.fault()
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var o  =  this.fetch(),
             g, t, $msg, $strong;
         if ( typeof o  ===  "object" ) {
            t  =  IUTIL.utl.fold( o.target );
            if ( t[ 1 ] === 2 ) {
               this.fill( "PageAdapting" );
               g  =  IUTIL.utl.fold( o.from );
               IUTIL.justify.fire( t[ 2 ], g[ 0 ], g[ 2 ] );
            } else {
               $msg     =  $( "<span>" );
               $strong  =  $( "<strong>" );
               $strong.text( IUTIL.cnf.feature( "Error" ) );
               $msg.append( $strong );
               $strong  =  $( "<strong>" );
               $strong.css( { "margin-left":  "1em",
                              "margin-right": "1em" } );
               $strong.text( "*" );
               $msg.append( $strong );
               $strong  =  $( "<strong>" );
               $strong.text( IUTIL.cnf.feature( "NoUserPg", false ) );
               $msg.append( $strong );
               IUTIL.utl.fault( $msg );
            }
         }
      };   // .edit.fix()



      IUTIL.edit.flag  =  function ( action ) {
         // Update summary
         // Precondition:
         //    action  -- keyword
         // Uses:
         //    this
         //    >  mw.util.$content
         //    >< .edit.$summary
         //    jQuery().find()
         //    jQuery().val()
         //    .cnf.feature()
         // 2012-12-15 PerfektesChaos@de.wikipedia
         var i, s;
         if ( ! this.$summary ) {
            this.$summary  =  mw.util.$content.find( "#wpSummary" );
         }
         s  =  this.$summary.val();
         i  =  s.indexOf( " */" );
         if ( i > 0 ) {
            s  =  s.substr( 0,  i + 3 )   +   " ";
         } else {
            s  =  s + " * ";
         }
         s  =  s  +  IUTIL.cnf.feature( action, true );
         this.$summary.val( s );
      };   // .edit.flag()



      IUTIL.edit.flip  =  function ( at ) {
         // Inform about temporary target page
         //    at  -- target (subpage)
         // Uses:
         //    >  .cnf.project.edit.staff
         //    >  .$div
         //    >< .cnf.space
         //    mw.config.get()
         //    mw.util.getUrl()
         //    .cnf.feature()
         // 2014-12-30 PerfektesChaos@de.wikipedia
         var sub    =  ":" + IUTIL.cnf.project.edit.staff + "/" + at,
             $a     =  $( "<a>" ),
             $div   =  $( "<div>" ),
             $span  =  $( "<span>" );
         if ( ! IUTIL.cnf.space ) {
            IUTIL.cnf.space  =
                           mw.config.get( "wgFormattedNamespaces" )[ 2 ];
         }
         sub  =  IUTIL.cnf.space + sub;
         $a.attr( { "href":   mw.util.getUrl( sub ),
                    "target": "_blank" } );
         $a.text( sub );
         $div.attr( { "id": "importUtility_tmp" } );
         $div.css( { "border":        "#778899 2px solid",
                     "margin-bottom": "1em",
                     "margin-top":    "1em",
                     "padding":       "1em" } );
         $span.css( { "font-style":   "italic",
                      "font-weight":  "bold",
                      "margin-right": "2em" } );
         $span.text( IUTIL.cnf.feature( "TempPage", false ) );
         $div.append( $span );
         $div.append( $a );
         IUTIL.$div.prepend( $div );
      };   // .edit.flip()



      IUTIL.edit.force  =  function ( action, assign, $append ) {
         // Insert button into suite
         // Precondition:
         //    action   -- keyword
         //    assign   -- label key, if not action
         //    $append  -- container, or false
         // Uses:
         //    this
         //    >  .edit.$buttons
         //    .cnf.feature()
         //    jQuery()
         //    jQuery().attr()
         //    jQuery().css()
         //    jQuery().text()
         //    jQuery().append()
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var $btn  =  $( "<button />" ),
             $c    =  ( $append ? $append : this.$buttons );
         $btn.attr( { "id":   "importUtility_act_" + action,
                      "type": "button" } );
         $btn.css( { "margin-right": "1em" } );
         $btn.click( function () {  IUTIL.edit.fire( action );  } );
         $btn.text( IUTIL.cnf.feature( (  assign ? assign
                                                 : action ) ) );
         $c.append( $btn );
      };   // .edit.force()



      IUTIL.edit.forward  =  function () {
         // Start special page run
         // Uses:
         //    this
         //    window
         //    >  .mode
         //    >  .cnf.project.spec.sourceTW
         //    >  .cnf.project.edit.staff
         //    >  .cnf.project.spec.sourceIU
         //    >  .cnf.swift
         //    >  .importer.live
         //    >  window.sessionStorage
         //    .edit.fetch()
         //    .utl.fold()
         //    .edit.flip()
         //    mw.util.getUrl()
         //    .importer.fire()
         //    window.open()
         //    .edit.fill()
         // 2018-06-20 PerfektesChaos@de.wikipedia
         var o  =  this.fetch(),
             i, p, s, t;
         if ( typeof o  ===  "object" ) {
            p  =  IUTIL.cnf.project.spec;
            if ( typeof o.requestID  ===  "string" ) {
               s  =  " * [[Special:Diff/" + o.requestID + "]]";
            } else {
               s  =  "";
            }
            if ( typeof o.originator  ===  "string" ) {
               s  =  s + " * [[user:" + o.originator + "]]";
            } else {
               o.originator  =  "NO USERNAME AVAILABLE";
            }
            if ( IUTIL.mode === 1 ) {
               p  =  { "interwiki":            o.lang,
                       "frompage":             o.from,
                       "mw-interwiki-comment": p.sourceTW + s
                     };
               t  =  IUTIL.utl.fold( o.target );
               switch ( t[ 0 ] ) {
                  case 0 :   // (main)
                     if ( t[ 1 ] === o.from ) {
// // Bugmeldung 2015-11-06 springt nicht an
                        p.namespace  =  0;
                     } else {
                        p.namespace  =  2;
                        p[ "mw-interwiki-rootpage-interwiki" ]  =
                                      IUTIL.cnf.project.edit.staff + "/";
                        this.flip( o.from );
                     }
                     break;
                  case 2 :   // user:
                     i  =  t[ 1 ].lastIndexOf( "/" );
                     if ( i > 1 ) {
                        s  =  t[ 1 ].substr( 0,  i + 1 );
                     } else {
                        s  =  t[ 1 ] + "/";
                     }
                     p.namespace                             =  2;
                     p[ "mw-interwiki-rootpage-interwiki" ]  =  s;
                     p.originator  =  o.originator;
                     break;
               }   // switch t[ 0 ]
            } else {
               s  =  p.sourceIU + s + " * [[";
               if ( o.lang ) {
                  s  =  s + o.lang + ":";
               }
               s  =  s + o.from + "]]";
               p  =  { "mw-interwiki-rootpage-upload": o.target,
                       "mw-import-comment":            s,
                       "usernamePrefix":               o.lang
                     };
            }
            if ( IUTIL.mode === 1 ) {
               IUTIL.importer.fire( p );
            } else {
               if ( window.sessionStorage ) {
                  try {
                     s  =  JSON.stringify( p );
                     window.sessionStorage.setItem( IUTIL.cnf.swift, s );
                  } catch ( e ) {
                     mw.log( {loud:true},
                             "IUTIL.edit.forward() sessionStorage fault",
                             2 );
                  }
               } else {
                  mw.log( {loud:true},
                          "IUTIL.edit.forward() No sessionStorage",
                          2 );
               }
               window.open( mw.util.getUrl( "Special:Import" ),
                            "_blank" );
               this.fill( "Start" );
            }
         }
      };   // .edit.forward()



      IUTIL.edit.furnish  =  function () {
         // Insert button suite on request page (editing)
         // Precondition:
         //    document ready
         // Uses:
         //    this
         //    >  .mode
         //    >  .cnf.project.edit.delIss
         //    >  .$div
         //    >< .edit.$buttons
         //    .utl.furnish()
         //    .hold.flat()
         //    jQuery()
         //    jQuery().attr()
         //    jQuery().prepend()
         //    .edit.fetch()
         //    .versions.fire()
         //    .edit.force()
         //    .difflink.fire()
         //    .quiet.fresh()
         // 2014-12-30 PerfektesChaos@de.wikipedia
         var o;
         IUTIL.utl.furnish();
         IUTIL.hold.flat();
         if ( ! this.$buttons ) {
            this.$buttons  =  $( "<div>" );
            this.$buttons.attr( "id", "importUtilityButtons" );
            o  =  this.fetch();
            if ( o ) {
               if ( o.from  &&  ! o.versions ) {
                  IUTIL.versions.fire( o );
               }
            }
            if ( IUTIL.mode === 2 ) {
               this.force( "Export" );
            }
            this.force( "Start" );
            this.force( "Started", "Tic" );
            if ( o ) {
               if ( o.lang ) {
                  this.force( "Move" );
                  this.force( "Moved", "Tic" );
               }
            }
            this.force( "PageAdapt" );
            this.force( "PageAdapted", "Tic" );
            this.force( "UserNotify" );
            this.force( "UserNotified", "Tic" );
            if ( IUTIL.cnf.project.edit.delIss[ IUTIL.mode - 1 ] ) {
               this.force( "DeleteIssue" );
            }
            if ( IUTIL.mode === 1 ) {
               if ( o ) {
                  if ( ! o.lang ) {
                     this.force( "Swap" );
                  }
               }
            } else {
               this.force( "Done" );
               this.force( "Archive" );
            }
            IUTIL.$div.prepend( this.$buttons );
            if ( o ) {
               IUTIL.difflink.fire( o.originator );
            }
            IUTIL.quiet.fresh();
         }
      };   // .edit.furnish()
   }   // .edit



//-----------------------------------------------------------------------



   if ( typeof IUTIL.greet  !==  "object" ) {
      // User notification form
      // Dependencies: mediawiki.util
      IUTIL.greet  =  { };



      IUTIL.greet.failed  =  function (  ) {
         // Remove user notification form
         // Uses:
         //    >  .$msg
         //    jQuery().empty()
         // 2013-01-16 PerfektesChaos@de.wikipedia
         IUTIL.$msg.empty();
      };   // .greet.failed()



      IUTIL.greet.fire  =  function () {
         // Send user notification
         // Uses:
         //    this
         //    >  .$msg
         //    jQuery().find()
         //    jQuery().val()
         //    .utl.filter()
         //    .notify.fire()
         // 2013-01-21 PerfektesChaos@de.wikipedia
         var $ta  =  IUTIL.$msg.find( "#greeting" ),
             s    =  $ta.val();
         if ( s ) {
            do {
               if ( s.charCodeAt( 0 )  <=  32 ) {
                  s  =  s.substr( 1 );
               } else {
                  break;   // while s
               }
            } while ( s );
            s  =  IUTIL.utl.filter( s );
         }
         IUTIL.notify.fire( s );
      };   // .greet.fire()



      IUTIL.greet.furnish  =  function () {
         // Create user notification form
         // Uses:
         //    this
         //    >  .$msg
         //    >  .cnf.project.source
         //    >  .cnf.user.greetcols
         //    jQuery().empty()
         //    jQuery().css()
         //    jQuery().attr()
         //    jQuery().text()
         //    .edit.fetch()
         //    .quiet.find()
         //    mw.util.getUrl()
         //    .cnf.feature()
         //    jQuery().append()
         //    .edit.force()
         //    jQuery().append()
         //    known.fire()
         // 2014-12-25 PerfektesChaos@de.wikipedia
         var o  =  IUTIL.edit.fetch(),
             n, slot, $a, $div, $span, $textarea;
         IUTIL.$msg.empty();
         if ( o ) {
            IUTIL.$msg.css( { "border":        "solid 2px #808080",
                              "margin-bottom": "1em",
                              "margin-top":    "1em",
                              "padding":       "1em" } );
            slot  =  o.originator;
            if ( IUTIL.quiet.find( slot ) ) {
               $div  =  $( "<div>" );
               $div.css( { "border":        "solid 1px #800000",
                           "color":         "#800000",
                           "font-weight":   "bold",
                           "margin-bottom": "0.5em",
                           "padding":       "0.5em" } );
               $a  =  $( "<a>" );
               $a.attr( { "href":   mw.util.getUrl(
                                        IUTIL.cnf.project.quiet.source ),
                          "target": "_blank" } );
               $a.text( IUTIL.cnf.feature( "Robinson", false ) );
               $div.append( $a );
               IUTIL.$msg.append( $div );
            }
            $span  =  $( "<span>" );
            $span.text( String.fromCharCode( 8594, 160 ) );
            IUTIL.$msg.append( $span );
            $a  =  $( "<a>" );
            $a.attr( { "href":   mw.util.getUrl( "User:" + slot ),
                       "target": "_blank" } );
            $a.text( slot );
            $span  =  $( "<span>" );
            $span.text( String.fromCharCode( 32, 160, 32 ) );
            IUTIL.$msg.append( $span );
            IUTIL.edit.force( "SendNotifier", false, IUTIL.$msg );
            IUTIL.edit.force( "Cancel", false, IUTIL.$msg );
            $div  =  $( "<div>" );
            $div.css( { "margin-top": "1em" } );
            $span  =  $( "<span>" );
            $span.text( IUTIL.cnf.feature( "GreetingAdd", false ) );
            $div.append( $span );
            $span  =  $( "<strong>" );
            $span.css( { "margin-left": "1em" } );
            $span.text( IUTIL.cnf.feature( "NoPreview", false ) );
            $div.append( $span );
            $div.append( $( "<br />" ) );
            $textarea  =  $( "<textarea>" );
            if ( typeof IUTIL.cnf.user.greetcols  ===  "number" ) {
               n  =  IUTIL.cnf.user.greetcols;
               n  =  ( n < 10 ?  0  : n );
            }
            $textarea.attr( { "cols": ( n ? n : 80 ),
                              "id":   "greeting",
                              "rows": "4" } );
            $div.append( $textarea );
            IUTIL.$msg.append( $div );
            IUTIL.known.fire( slot );
         }
      };   // .greet.furnish()
   }   // .greet



//-----------------------------------------------------------------------



   if ( typeof IUTIL.hold  !==  "object" ) {
      // Utilitiy for inuse stamp
      // Dependencies: mediawiki.api
      IUTIL.hold  =  { lapsus: false };



      IUTIL.hold.fault  =  function ( about ) {
         // Show API failure on hold stamp
         // Precondition:
         //    about  -- JSON info of ajax query or string
         // Uses:
         //    >  .hold.$div
         //    jQuery().css()
         //    jQuery().text()
         //    jQuery().append()
         //    mw.log()
         // Remark: Used as event handler -- 'this' is not IUTIL.hold
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var $span    =  $( "<span>" ),
             $strong  =  $( "<strong>" ),
             $spec;
         $strong.text( "ERROR" );
         $span.append( $strong );
         if ( typeof about  ===  "string" ) {
            $spec  =  $( "<span>" );
            $spec.text( about );
            $spec.css( { "margin-left": "2em" } );
            $span.append( $spec );
         }
         IUTIL.utl.fault( $span, IUTIL.hold.$div );
         mw.log( {loud:true}, "IUTIL.hold.fault()", 2, about );
      };   // .hold.fault()



      IUTIL.hold.feed  =  function ( arrived ) {
         // Set hold marker by API
         // Precondition:
         //    arrived  -- JSON result of ajax query
         // Uses:
         //    >  mw.Api
         //    >  .type
         //    >  .vsn
         //    mw.config.get()
         //    mw.user.tokens.get()
         //    .cnf.feature()
         //    .hold.flip()
         //    mw.Api.post()
         //    .hold.fault()
         //    (.hold.fine)
         //    (.hold.fault)
         // Remark: Used as event handler -- 'this' is not IUTIL.hold
         // 2016-04-30 PerfektesChaos@de.wikipedia
         var got    =  false,
             i      =  false,
             n      =  false,
             shift  =  false,
             sucks  =  "feed",
             swap   =  false,
             q,
             sum,
             w;
         if ( arrived ) {
            q  =  arrived.query;
            if ( typeof q  ===  "object" ) {
               w  =  q.normalized;
               if ( typeof w  ===  "object" ) {
                  w  =  w[ 0 ];
                  if ( typeof w  ===  "object" ) {
                     shift  =  w.to;
                     w      =  /#([1-9][0-9]*)$/.exec( w.from );
                     if ( typeof w  ===  "object" ) {
                        n  =  parseInt( w[ 1 ],  10 );
                     }
                  }
               }
               if ( typeof q.pageids  ===  "object" ) {
                  i  =  q.pageids[ 0 ];
               }
               if ( i ) {
                  q  =  q.pages;
                  if ( q ) {
                     q  =  q[ i ];
                     if ( q ) {
                        q  =  q.revisions;
                        if ( typeof q  ===  "object" ) {
                           q  =  q[ 0 ];
                           if ( typeof q  ===  "object" ) {
                              got  =  { revid:     q.revid,
                                        user:      q.user,
                                        timestamp: q.timestamp,
                                        story:     q[ "*" ]
                                      };
                           }
                        }
                     }
                  }
               }
            }
         }
         if ( got ) {
            q  =  mw.config.get( [ "wgCurRevisionId",
                                   "wgUserName" ] );
            if ( parseInt(  got.revid,  10 )  ===  q.wgCurRevisionId
                 ||  got.user  ===  q.wgUserName ) {
               w  =  IUTIL.hold.flip( got.story );
               if ( w ) {
                  if ( w[ 0 ] === got.story ) {
                     swap   =  false;
                     sucks  =  sucks + "/equal";
                  } else {
                     swap  =  w[ 0 ];
                     sum   =  "/* " + w[ 1 ] + " */ ";
                  }
               }
            } else {
               IUTIL.hold.flop();
            }
         }
         if ( n && shift && swap ) {
            q  =  new mw.Api();
            w  =  { action:        "edit",
                    token:         mw.user.tokens.get( "csrfToken" ),
                    basetimestamp: got.timestamp,
                    minor:         false,
                    section:       n,
                    summary:       sum
                                   + IUTIL.cnf.feature( "Hold", true )
                                   + " / " + IUTIL.type
                                   + " " + IUTIL.vsn,
                    text:          swap,
                    title:         shift };
            q.post( w ).done( IUTIL.hold.fine )
                       .fail( IUTIL.hold.fault );
         } else if ( ! got ) {
            IUTIL.hold.fault( sucks );
         }
      };   // .hold.feed()



      IUTIL.hold.fine  =  function () {
         // Show API success on hold stamp
         // Uses:
         //    >  .hold.$div
         //    jQuery().empty()
         //    jQuery().append()
         //    .cnf.feature()
         // Remark: Used as event handler -- 'this' is not IUTIL.hold
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var $div   =  IUTIL.hold.$div,
             $span  =  $( "<span>" );
         $div.empty();
         $span.css( { "background-color": "#000000",
                      "color":            "#FFD700",
                      "font-weight":      "bold",
                      "margin-left":      "2em",
                      "padding":          "5px",
                      "white-space":      "nowrap"
                    } );
         $span.text( IUTIL.cnf.feature( "Hold", false ) );
         $div.append( $span );
      };   // .hold.fine()



      IUTIL.hold.fire  =  function ( address ) {
         // Set hold marker by API: Retrieve section content and info
         // Precondition:
         //    address  -- section number
         // Uses:
         //    >  .hold.lapsus
         //    >  mw.Api
         //    >  .cnf.submit
         //    >  mw.util.$content
         //     < .hold.$div
         //    jQuery().find()
         //    mw.Api.get()
         //    jQuery().empty()
         //    .batch.$flow()
         //    jQuery().append()
         //    (.hold.feed)
         //    (.hold.fault)
         // Remark: Used as event handler -- 'this' is not IUTIL.hold
         // 2015-06-14 PerfektesChaos@de.wikipedia
         var q, w, $d;
         if ( ! IUTIL.hold.lapsus ) {
            q   =  new mw.Api();
            w   =  { action:       "query",
                     "continue":   "",
                     indexpageids: true,
                     prop:         "revisions",
                     rvlimit:      1,
                     rvprop:       "ids|user|content|timestamp",
                     titles:       "Project:" + IUTIL.cnf.submit
                                              + "#" + address,
                     rvsection:    address };
            $d  =  mw.util.$content.find( "#importUtilityHold_"
                                          + address );
            if ( $d.length ) {
               q.get( w ).done( IUTIL.hold.feed )
                         .fail( IUTIL.hold.fault );
               IUTIL.hold.$div  = $d;
               $d.empty();
               $d.append( IUTIL.batch.$flow( 16, "margin-left:10px" ) );
            }
         }
      };   // .hold.fire()



      IUTIL.hold.flat  =  function () {
         // Grey out own hold box
         // Uses:
         //    > mw.util.$content
         //    jQuery().find()
         //    mw.config.get()
         //    jQuery().css()
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var $box  =  mw.util.$content.find( "#importUtilityHold_box" ),
             $user;
         if ( $box.length ) {
            $user  =  $box.find( "#importUtilityHold_user" );
            if ( $user.text()  ===   mw.config.get( "wgUserName" ) ) {
               $box.css( { "background-color": "#D0D0D0",
                           "border-color":     "#B0B0B0",
                           "border-width":     "1px",
                           "color":            "#808080",
                           "padding":          "3px" } );
               $box.find( "b, span, strong" )
                   .css( { "font-weight": "normal" } );
            }
         }
      };   // .hold.flat()



      IUTIL.hold.flip  =  function ( already ) {
         // Modify text in order to set hold template
         // Precondition:
         //    already  -- text
         // Postcondition:
         //    Return Array, or false if nothing to do
         //           [0]  modified text
         //           [1]  basic section title
         // Uses:
         //    this
         //    >  .cnf.project.hold.section
         //    >  .cnf.project.hold.stamp
         //    mw.config.get()
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var pH    =  IUTIL.cnf.project.hold,
             slot  =  already,
             s     =  " " + pH.section + " ",
             sum   =  false,
             i     =  slot.indexOf( s ),
             g;
         if ( i < 0 ) {
            g  =  /^((=+)([^=\n].*[^=\n]))\2\s*\r?\n/.exec( slot );
            if ( g ) {
               if ( g[ 1 ].length > 6 ) {
                  sum   =  g[ 3 ];
                  slot  =  g[ 2 ]  +  sum  +  s  +  g[ 2 ]  +  "\n"
                           +  slot.substr( g[ 0 ].length );
                  sum   =  sum.replace( /^\s*(\S.+\S)\s*$/, "$1" )
                           + " " + pH.section;
               }
            }
         }
         s  =  "{{" + pH.stamp + "|";
         if ( slot.indexOf( s )  <  0 ) {
            i     =  slot.indexOf( "==\n" )  +  3;
            slot  =  slot.substr( 0, i )
                     +  s + mw.config.get( "wgUserName" ) + "|"
                     +  "~~~~~}}\n"
                     +  slot.substr( i );
         }
         if ( sum ) {
            g  =  new RegExp( "^==+ *([^ ].*[^ ]) *$" );
            g  =  g.exec( sum );
            if ( g ) {
               sum  =  g[ 1 ];
            }
         }
         return  ( slot === already  ?  false
                                     :  [ slot, sum ] );
      };   // .hold.flip()



      IUTIL.hold.flop  =  function () {
         // Mark edit conflict
         // Uses:
         //    this
         //    >  mw.util.$content
         //    jQuery().find()
         //    jQuery().each()
         //    (.hold.foul)
         // 2014-10-10 PerfektesChaos@de.wikipedia
         mw.util.$content.find( ".importUtility_Hold" )
                         .each( this.foul );
      };   // .hold.flop()



      IUTIL.hold.foul  =  function () {
         // Equip section with edit conflict mark
         // Precondition:
         //    access  -- index (not used)
         // Postcondition:
         //    Return true for continued iteration
         // Uses:
         //    this  -- DOM element
         //    >  .cnf.project.hold.section
         //    .cnf.feature()
         //    jQuery()
         //    jQuery().empty()
         //    jQuery().css()
         //    jQuery().text()
         //    jQuery().append()
         // Remark: Used as jQuery callback -- 'this' is DOM element
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var $h     =  $( this ),
             $span  =  $( "<span>" );
         $h.empty();
         $span.css( { "background-color": "#FF0000",
                      "color":            "#FFFFFF",
                      "font-weight":      "bold",
                      "padding":          "5px" } );
         $span.text( IUTIL.cnf.feature( "Conflict", false ) );
         $h.append( $span );
      };   // .hold.foul()



      IUTIL.hold.found  =  function () {
         // Equip section with hold button, if appropriate
         // Precondition:
         //    access  -- index (not used)
         // Postcondition:
         //    Return true for continued iteration
         // Uses:
         //    this  -- DOM element
         //    >  .cnf.project.hold.section
         //    .cnf.feature()
         //    jQuery()
         //    jQuery().text()
         //    jQuery().children()
         //    jQuery().attr()
         //    jQuery().css()
         //    jQuery().append()
         //    (.hold.fire)
         // Remark: Used as jQuery callback -- 'this' is DOM element
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var $h  =  $( this ),
             s   =  $h.children( "span.mw-headline" ).text(),
             g, $btn, $span;
         if ( s.indexOf( IUTIL.cnf.project.hold.section )  <  0 ) {
            s  =  $h.children( "span.mw-editsection" )
                    .children( "a" ).attr( "href" );
            if ( s ) {
               g  =  /section=([1-9][0-9]*)\b/.exec( s );
               if ( g ) {
                  g  =  g[1];
                  $span  =  $( "<span>" );
                  $span.attr( { "id":    "importUtilityHold_" + g,
                                "class": "importUtility_Hold" } );
                  $span.css( { "margin-left": "2em" } );
                  $btn  =  $( "<button />" );
                  $btn.attr( { "type": "button" } );
                  $btn.text( IUTIL.cnf.feature( "Hold", false ) );
                  $btn.click( function () {
                                 IUTIL.hold.fire( g );
                              } );
                  $span.append( $btn );
                  $h.append( $span );
               }
            }
         }
         return true;
      };   // .hold.found()



      IUTIL.hold.furnish  =  function () {
         // Equip page with appropriate hold buttons
         // Uses:
         //    this
         //    >  mw.util.$content
         //    >  .cnf.project.section
         //    jQuery().find()
         //    jQuery().each()
         //    (.hold.found)
         // 2014-10-10 PerfektesChaos@de.wikipedia
         mw.util.$content.find( IUTIL.cnf.project.section )
                         .each( this.found );
      };   // .hold.furnish()
   }   // .hold



//-----------------------------------------------------------------------




   if ( typeof IUTIL.importer  !==  "object" ) {
      // Utilitiy for import execution by API
      // Dependencies: mediawiki.api
      IUTIL.importer  =  { live:    false,
                           promise: false };



      IUTIL.importer.fault  =  function ( about ) {
         // Show API failure on import token
         // Precondition:
         //    about  -- JSON info of ajax query or string, or false
         // Uses:
         //    >  .importer.token
         //    .cnf.feature()
         //    jQuery().css()
         //    jQuery().text()
         //    jQuery().append()
         //    .utl.fault()
         //    mw.log()
         // Remark: Used as event handler -- 'this' is not IUTIL.importer
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var $msg     =  $( "<span>" ),
             $span    =  $( "<span>" ),
             $strong  =  $( "<strong>" ),
             scream   =  ( IUTIL.importer.token ? "NoImport"
                                                : "NoToken" );
         $strong.css( { "margin-right": "1em" } )
                .text( IUTIL.cnf.feature( "Error", false ) );
         $msg.append( $strong );
         $span.text( IUTIL.cnf.feature( scream, false ) );
         $msg.append( $span );
         if ( about ) {
            $msg.append( "<br />" );
            $span  =  $( "<span>" );
            $span.css( { "font-style": "italic" } )
                 .text( about );
            $msg.append( $span );
         }
         IUTIL.utl.fault( $msg );
         mw.log( {loud:true}, "IUTIL.importer.fault()", 2, about );
      };   // .importer.fault()



      IUTIL.importer.fine  =  function ( arrived ) {
         // Show API success on import
         // Precondition:
         //    about  -- JSON info of ajax query or string
         // Uses:
         //    .cnf.feature()
         //    jQuery().text()
         //    jQuery().css()
         //    jQuery().append()
         //    .batch.fine()
         //    .edit.fill()
         // Remark: Used as event handler -- 'this' is not IUTIL.importer
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var $msg     =  $( "<span>" ),
             $span    =  $( "<span>" ),
             number, story, tell;
         if ( typeof arrived  ===  "object"   &&
              typeof arrived[ "import"]  ===  "object" ) {
            tell  =  arrived[ "import"][ 0 ];
            if ( typeof tell  ===  "object"   &&
                 typeof tell.revisions  ===  "number" ) {
               number  =  tell.revisions;
               if ( number === 1 ) {
                  story  =  IUTIL.cnf.feature( "Imported1", false );
               } else if ( number ) {
                  story  =  number + " "
                            + IUTIL.cnf.feature( "ImportedN", false );
               } else {
                  story  =  IUTIL.cnf.feature( "Imported0", false );
               }
            }
         }
         if ( ! story ) {
            story  =  "???";
         }
         $span.text( IUTIL.cnf.feature( "Imported", false ) );
         $msg.append( $span );
         $msg.append( $( "<br />" ) );
         $span  =  $( "<span>" );
         $span.css( { "font-style": "italic" } );
         $span.text( story );
         $msg.append( $span );
         IUTIL.batch.fine( $msg );
         IUTIL.edit.fill( "Imported", story );
      };   // .importer.fine()



      IUTIL.importer.fire  =  function ( acquire ) {
         // Trigger import via API; first step: achieve token
         // Precondition:
         //    acquire  -- request details
         // Uses:
         //    this
         //    >  mw.Api
         //    >< .importer.token
         //     < .importer.request
         //     < .importer.promise
         //    .cnf.feature()
         //    .batch.fired()
         //    mw.Api.get()
         //    (.importer.forward)
         //    (.importer.fault)
         // 2015-06-12 PerfektesChaos@de.wikipedia
         var w;
         this.request  =  acquire;
         IUTIL.batch.fired( "GetToken" );
         if ( typeof this.token  ===  "string" ) {
            IUTIL.importer.forward( false );
         } else {
            this.token  =  false;
            w           =  { action:     "query",
                             "continue": "",
                             meta:       "tokens",
                             type:       "csrf" };
            if ( ! this.promise ) {
               this.promise  =  new mw.Api();
            }
            this.promise.get( w ).done( this.forward )
                                 .fail( this.fault );
         }
      };   // .importer.fire()



      IUTIL.importer.forward  =  function ( arrived ) {
         // Token available, perform import
         // Precondition:
         //    arrived  -- JSON info of ajax token query; false: proceed
         // Uses:
         //    >  .importer.request
         //    >  .importer.token
         //    >  .importer.promise
         //    .batch.fired()
         //    .importer.fault()
         //    (.importer.fine)
         //    (.importer.fault)
         // Remark: Used as event handler -- 'this' is not IUTIL.importer
         // 2018-04-02 PerfektesChaos@de.wikipedia
         var that  =  IUTIL.importer,
             g     =  that.request,
             w     =  { action: "import",
                        token:  false },
             src;
         if ( typeof arrived  ===  "object"   &&
              typeof arrived.query  ===  "object"   &&
              typeof arrived.query.tokens  ===  "object"   &&
              typeof arrived.query.tokens.csrftoken  ===  "string" ) {
            that.token  =  arrived.query.tokens.csrftoken;
            IUTIL.batch.fired();
            w.token  =  that.token;
         }
         if ( ! w.token ) {
            that.fault( false );
         } else if ( IUTIL.mode === 1 ) {
            w.summary           =  g[ "mw-interwiki-comment" ];
            w.interwikisource   =  g.interwiki;
            w.interwikipage     =  g.frompage;
            w.fullhistory       =  true;
            w.assignknownusers  =  true;
            if ( g.namespace ) {
               src  =  "user:" + g[ "mw-interwiki-rootpage-interwiki" ];
            }
         } else {
//          w.xml         Uploaded XML file
            w.summary  =  g[ "mw-import-comment" ];
            src        =  g[ "mw-interwiki-rootpage-upload" ];
// // Bugmeldung 2015-11-06      Encoding bei post IU, auch transwiki
         }
         if ( src ) {
            w.rootpage  =  encodeURI( src );
         }
         that.promise.post( w ).done( that.fine )
                               .fail( that.fault );
      };   // .importer.forward()
   }   // .importer



//-----------------------------------------------------------------------




   if ( typeof IUTIL.justify  !==  "object" ) {
      // Prepare for content modification of user page
      // Dependencies: mediawiki.api
      IUTIL.justify  =  { };



      IUTIL.justify.fault  =  function ( arrived ) {
         // Show API failure on user page check
         // Precondition:
         //    arrived  -- JSON info of ajax query, or false
         // Uses:
         //    >  .justify.slot
         //    jQuery().text()
         //    jQuery().css()
         //    jQuery().append()
         //    .utl.fault()
         //    mw.log()
         // Remark: Used as event handler -- 'this' is not IUTIL.justify
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var $msg     =  $( "<span>" ),
             $span    =  $( "<span>" ),
             $strong  =  $( "<strong>" );
         $strong.text( IUTIL.cnf.feature( "Error" ) );
         $msg.append( $strong );
         $strong  =  $( "<strong>" );
         $strong.css( { "margin-left":  "1em",
                        "margin-right": "1em" } );
         $strong.text( "*" );
         $msg.append( $strong );
         $strong  =  $( "<strong>" );
         $strong.text( IUTIL.cnf.feature( "NotFound" ) );
         $msg.append( $strong );
         $msg.append( $( "<br />" ) );
         $span  =  $( "<span>" );
         $span.css( { "font-style": "italic" } );
         $span.text( IUTIL.justify.slot );
         $msg.append( $span );
         IUTIL.utl.fault( $msg );
         mw.log( {loud:true}, "IUTIL.justify.fault()", 2, arrived );
      };   // .justify.fault()



      IUTIL.justify.fire  =  function ( adjust, accept, ancestor ) {
         // Check whether user page exists
         // Precondition:
         //    adjust    -- user page title
         //    accept    -- source language
         //    ancestor  -- source page name
         // Uses:
         //    this
         //    >  mw.Api
         //     < .justify.slot
         //     < .justify.slang
         //     < .justify.source
         //    .utl.furnish()
         //    (.justify.found)
         //    (.justify.fault)
         // 2015-06-14 PerfektesChaos@de.wikipedia
         var q  =  new mw.Api(),
             w  =  { action:     "query",
                     "continue": "",
                     prop:       "info" };
         IUTIL.utl.furnish();
         this.slot    =  "user:" + adjust;
         this.slang   =  accept;
         this.source  =  ancestor;
         w.titles     =  this.slot;
         q.get( w ).done( this.found )
                   .fail( this.fault );
      };   // .justify.fire()



      IUTIL.justify.found  =  function ( arrived ) {
         // Process API result on user page check, open edit window
         // Precondition:
         //    arrived  -- JSON info of ajax query, or false
         // Uses:
         //    >  .justify.slot
         //    >  .justify.slang
         //    >  .justify.source
         //    >  .type
         //    .cnf.feature()
         //    jQuery().text()
         //    jQuery().css()
         //    jQuery().append()
         //    .batch.fine()
         //    .edit.fill()
         //    mw.util.getUrl()
         //    .justify.fault()
         // Remark: Used as event handler -- 'this' is not IUTIL.justify
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var $msg   =  $( "<span>" ),
             $span  =  $( "<span>" ),
             q      =  false,
             s;
         if ( arrived ) {
            q  =  arrived.query;
            if ( q ) {
               q  =  q.pageids;
               if ( q ) {
                  q  =  q[ 0 ];
               }
            }
         }
         if ( q ) {
            s  =  IUTIL.cnf.feature( "Modifying" );
            $span.text( s );
            $msg.append( $span );
            $msg.append( "<br />" );
            $span  =  $( "<span>" );
            $span.css( { "font-style": "italic" } );
            $span.text( IUTIL.justify.slot );
            $msg.append( $span );
            IUTIL.batch.fine( $msg );
            IUTIL.edit.fill( s, IUTIL.justify.slot );
            q  =  { action: "edit" };
            q[ IUTIL.type ]  =  IUTIL.justify.slang + ":"
                                + IUTIL.justify.source;
            window.open( mw.util.getUrl( IUTIL.justify.slot, q ),
                         "_blank" );
         } else {
            IUTIL.justify.fault();
         }
      };   // .justify.found()
   }   // .justify




//-----------------------------------------------------------------------



   if ( typeof IUTIL.notify  !==  "object" ) {
      // Utilitiy for user notification
      // Dependencies: mediawiki.api mediawiki.util
      IUTIL.notify  =  { };



      IUTIL.notify.fault  =  function ( arrived ) {
         // Show API failure on message body access
         // Precondition:
         //    arrived  -- JSON info of ajax query
         // Uses:
         //    .cnf.feature()
         //    jQuery().css()
         //    jQuery().text()
         //    jQuery().append()
         //    .utl.fault()
         //    mw.log()
         // Remark: Used as event handler -- 'this' is not IUTIL.notify
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var $msg     =  $( "<span>" ),
             $strong  =  $( "<strong>" );
         $strong.text( IUTIL.cnf.feature( "Error" ) );
         $strong  =  $( "<strong>" );
         $strong.css( { "margin-left":  "1em",
                        "margin-right": "1em" } );
         $strong.text( "*" );
         $msg.append( $strong );
         $strong  =  $( "<strong>" );
         $strong.text( ".notify" );
         $msg.append( $strong );
         IUTIL.utl.fault( $msg );
         mw.log( {loud:true}, "IUTIL.notify.fault()", 2, arrived );
      };   // .notify.fault()



      IUTIL.notify.fine  =  function () {
         // Show API success on user notification
         // Uses:
         //    >  .$msg
         //    >  .notify.submitter
         //    .batch.fine()
         //    jQuery().attr()
         //    mw.util.getUrl()
         //    jQuery().css()
         //    jQuery().text()
         //    jQuery().append()
         //    .edit.fill()
         // Remark: Used as event handler -- 'this' is not IUTIL.notify
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var $a  =  $( "<a>" );
         IUTIL.batch.fine( "UserNotified" );
         $a.attr( { "href":   mw.util.getUrl( IUTIL.notify.submitter ),
                    "target": "_blank" } );
         $a.css( { "margin-left": "2em" } );
         $a.text( "*" );
         IUTIL.$msg.append( $a );
         IUTIL.edit.fill( "UserNotified" );
      };   // .notify.fine()



      IUTIL.notify.fire  =  function ( append ) {
         // Notify user
         // Precondition:
         //    append  -- additional greetings
         // Uses:
         //    this
         //    >  .cnf.project.notify.skeleton
         //    >  .cnf.project.notify.sect
         //    >  .type
         //    >  .vsn
         //    >  mw.Api
         //     < .notify.submitter
         //    .edit.fetch()
         //    .utl.fold()
         //    .utl.factory()
         //    mw.user.tokens.get()
         //    mw.Api.post()
         //    .batch.fired()
         //    .edit.fill()
         //    .edit.failing()
         //    (.notify.fine)
         //    (.notify.fault)
         // 2016-04-30 PerfektesChaos@de.wikipedia
         var say  =  IUTIL.cnf.project.notify.skeleton,
             sum  =  IUTIL.cnf.project.notify.sect,
             w    =  IUTIL.edit.fetch(),
             t,      // translation map
             p, q;
         if ( w.originator ) {
            t  =  { "l": ( w.lang ? w.lang : "" ),
                    "u": w.originator };
            if ( w.from ) {
               t.s  =  ( w.lang  ?  w.lang + ":" + w.from  :  w.from );
            }
            if ( w.target ) {
               t.t  =  w.target;
               p    =  IUTIL.utl.fold( t.t );
               if ( p && say ) {
                  t.n  =  p[ 0 ];
                  say  =  say // + "|a={{{a}}}"       TODO
                              + "|l={{{l}}}"
                              + "|n={{{n}}}"
                              + "|s={{{s}}}"
                              + "|t={{{t}}}"
                              + "|u={{{u}}}";
                  if (  append ) {
                     say  =  say + "|g=" + append;
                  }
               }
            } else {
               say  =  false;
            }
            this.submitter  =  "User talk:" + w.originator;
            if ( say ) {
               say   =  "{{subst:"
                        + IUTIL.utl.factory( say, t )
                        + "}}~~~~"
                        + "\n<!--" + IUTIL.type + " " + IUTIL.vsn
                                   + "-->";
            }
            if ( sum ) {
               sum   =  IUTIL.utl.factory( sum, t );
            }
         } else {
            this.submitter  =  false;
         }
         if ( say && sum && this.submitter ) {
            q  =  new mw.Api();
            w  =  { action:  "edit",
                    token:   mw.user.tokens.get( "csrfToken" ),
                    minor:   false,
                    section: "new",
                    summary: sum,
                    text:    say,
                    title:   this.submitter };
            q.post( w ).done( IUTIL.notify.fine )
                       .fail( IUTIL.notify.fault );
            IUTIL.batch.fired();
            IUTIL.edit.fill( "UserNotifying" );
         } else {
            IUTIL.edit.failing( false );
         }
      };   // .notify.fire()
   }   // .quiet



//-----------------------------------------------------------------------



   if ( typeof IUTIL.quiet  !==  "object" ) {
      // Utilitiy for Robinson list -- users not to be notified
      // Dependencies: mediawiki.api
      IUTIL.quiet        =  { };
      IUTIL.quiet.store  =  IUTIL.type + "_Robinson";



      IUTIL.quiet.fault  =  function ( arrived ) {
         // Show API failure on Robinson list access
         // Precondition:
         //    arrived  -- JSON info of ajax query
         // Uses:
         //    .cnf.feature()
         //    jQuery().css()
         //    jQuery().text()
         //    jQuery().append()
         //    .utl.fault()
         //    mw.log()
         // Remark: Used as event handler -- 'this' is not IUTIL.quiet
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var $msg     =  $( "<span>" ),
             $strong  =  $( "<strong>" );
         $strong.text( IUTIL.cnf.feature( "Error" ) );
         $strong  =  $( "<strong>" );
         $strong.css( { "margin-left":  "1em",
                        "margin-right": "1em" } );
         $strong.text( "*" );
         $msg.append( $strong );
         $strong  =  $( "<strong>" );
         $strong.text( ".quiet" );
         $msg.append( $strong );
         IUTIL.utl.fault( $msg );
         mw.log( {loud:true}, "IUTIL.quiet.fault()", 2, arrived );
      };   // .quiet.fault()



      IUTIL.quiet.fetch  =  function () {
         // Retrieve data and revision ID of Robinson list storage
         // Postcondition:
         //    Returns revision ID
         // Uses:
         //    this
         //    >  window.localStorage
         //    >  .quiet.store
         //     < .quiet.story
         // Remark: Used as event handler -- 'this' is not IUTIL.quiet
         // 2013-01-16 PerfektesChaos@de.wikipedia
         var r  =  -1,
             g;
         if ( typeof window.localStorage  ===  "object" ) {
            this.story  =  window.localStorage.getItem( this.store );
            if ( this.story ) {
               g  =  /\f#([0-9]+)\n/.exec( "\f" + this.story );
               if ( g ) {
                  r  =  parseInt( g[1], 10 );
               }
            } else {
               this.story  =  "";
            }
         }
         return r;
      };   // .quiet.fetch()



      IUTIL.quiet.find  =  function ( aware ) {
         // Check user name with Robinson list storage
         // Precondition:
         //    aware  -- User name in question, may be empty
         // Postcondition:
         //    Returns true if enlisted
         // Uses:
         //    this
         //    >  window.localStorage
         //    >  .quiet.store
         //    >< .quiet.story
         // Remark: Used as event handler -- 'this' is not IUTIL.quiet
         // 2013-01-16 PerfektesChaos@de.wikipedia
         var r  =  false;
         if ( aware ) {
            if ( typeof window.localStorage  ===  "object" ) {
               this.story  =  window.localStorage.getItem( this.store );
            }
            if ( this.story ) {
               r  =  ( this.story.indexOf( "\n" + aware + "\n" )  >  0 );
            }
         }
         return r;
      };   // .quiet.find()



      IUTIL.quiet.fresh  =  function () {
         // Update Robinson list on localStorage
         // Uses:
         //    this
         //    >  mw.Api
         //    >  .cnf.project.quiet.source
         //    (.quiet.furnish)
         //    (.quiet.fault)
         // 2015-06-12 PerfektesChaos@de.wikipedia
         var q  =  new mw.Api(),
             w  =  { action:       "query",
                     "continue":   "",
                     indexpageids: true,
                     prop:         "revisions",
                     rvlimit:      1,
                     rvprop:       "ids|content",
                     titles:       IUTIL.cnf.project.quiet.source };
         q.get( w ).done( this.furnish )
                   .fail( this.fault );
      };   // .quiet.fresh()



      IUTIL.quiet.furnish  =  function ( arrived ) {
         // Refresh localStorage with Robinson list page, if changed
         // Precondition:
         //    arrived  -- JSON result of ajax query
         // Uses:
         //    this
         //    >  .quiet.store
         //     < .quiet.story
         //    >< window.localStorage
         //    .quiet.fetch()
         // Remark: Used as event handler -- 'this' is not IUTIL.quiet
         // 2013-01-16 PerfektesChaos@de.wikipedia
         var k  =  -1,
             q  =  arrived.query,
             s  =  false,
             w;
         if ( q ) {
            q  =  arrived.query;
            if ( q ) {
               w  =  q.pageids;
               if ( w ) {
                  k  =  w[ 0 ];
                  if ( IUTIL.quiet.fetch() === k ) {
                     k  =  -2;
                  }
               }
            }
            if ( q  &&  k > 0 ) {
               q  =  q.pages;
               if ( q ) {
                  q  =  q[ k ];
                  k  =  -3;
                  if ( q ) {
                     q  =  q.revisions;
                     if ( q ) {
                        q  =  q[ 0 ];
                        if ( q ) {
                           s  =  q[ "*" ];
                           k  =  q.revid;
                        }
                     }
                  }
               }
            }
         }
         if ( s ) {
            q  =  new RegExp( "\n# *\\[\\[[^:\n]+:([^\n]+)\\]\\]" );
            k  =  "#" + k + "\n\n";
            do {
               w  =  q.exec( s );
               if ( w ) {
                  k  =  k  +  w[ 1 ]  +  "\n";
                  s  =  s.substr( w.index + w[ 0 ].length);
               }
            } while ( w );
            k  =  k + "|";
            if ( typeof window.localStorage  ===  "object" ) {
               try {
                  window.localStorage.setItem( IUTIL.quiet.store, k );
               } catch ( e ) {
                  IUTIL.quiet.story  =  k;
               }
            } else {
               IUTIL.quiet.story  =  k;
            }
         }
      };   // .quiet.furnish()
   }   // .quiet



//-----------------------------------------------------------------------



   if ( typeof IUTIL.rename  !==  "object" ) {
      // Utilitiy for renaming user subpage (workaround)
      // Dependencies: mediawiki.api
      IUTIL.rename  =  { };



      IUTIL.rename.fault  =  function ( arrived ) {
         // Show API failure on page move
         // Precondition:
         //    arrived  -- JSON info of ajax query
         // Uses:
         //    .utl.fault()
         //    mw.log()
         // Remark: Used as event handler -- 'this' is not IUTIL.rename
         // 2013-01-01 PerfektesChaos@de.wikipedia
         IUTIL.utl.fault( false );
         mw.log( {loud:true}, "IUTIL.rename.fault()", 2, arrived );
      };   // .rename.fault()



      IUTIL.rename.fine  =  function () {
         // Show API success on page move
         // Uses:
         //    .batch.fine()
         //    .edit.fill()
         // Remark: Used as event handler -- 'this' is not IUTIL.rename
         // 2013-01-01 PerfektesChaos@de.wikipedia
         IUTIL.batch.fine( "Moved" );
         IUTIL.edit.fill( "Moved" );
      };   // .rename.fine()



      IUTIL.rename.fire  =  function () {
         // Move target page
         // Workaround for:   Special:Import target page limitation
         // Uses:
         //    >  mw.Api
         //    >  .type
         //    >  .vsn
         //    .edit.fetch()
         //    .utl.fold()
         //    .cnf.feature()
         //    jQuery().css()
         //    jQuery().text()
         //    jQuery().append()
         //    .utl.fault()
         //    mw.user.tokens.get()
         //    mw.Api.post()
         //    .batch.fired()
         //    .edit.fill()
         //    .edit.failing()
         // (.rename.fine)
         // (.rename.fault)
         // 2016-04-30 PerfektesChaos@de.wikipedia
         var shift   =  false,
             source  =  false,
             w       =  IUTIL.edit.fetch(),
             q, $msg, $strong;
         if ( w ) {
            if ( w.from && w.target ) {
               q  =  IUTIL.utl.fold( w.target );
               if ( q ) {
                  source  =  w.from;
                  shift   =  w.target;
                  if ( q[ 0 ]  ===  2 ) {   // user
                     if ( q[ 2 ] ) {
                        source  =  q[ 2 ] + source;
                     } else {
                        shift  =  false;
                     }
                  }
               }
            }
         }
         if ( source ) {
            if ( source === shift ) {
               $msg     =  $( "<span>" );
               $strong  =  $( "<strong>" );
               $strong.text( IUTIL.cnf.feature( "Error" ) );
               $msg.append( $strong );
               $strong  =  $( "<strong>" );
               $strong.css( { "margin-left":  "1em",
                              "margin-right": "1em" } );
               $strong.text( "*" );
               $msg.append( $strong );
               $strong  =  $( "<strong>" );
               $strong.text( IUTIL.cnf.feature( "MoveToSame" ) );
               $msg.append( $strong );
               IUTIL.utl.fault( $msg );
            } else if ( shift ) {
               q  =  new mw.Api();
               w  =  { action:      "move",
                       token:       mw.user.tokens.get( "csrfToken" ),
                       from:        source,
                       to:          shift,
                       reason:      "Workaround for "
                                    + "[[Special:Import]]"
                                    + " target page limitation * "
                                    + IUTIL.type + " " + IUTIL.vsn,
                       movetalk:    true,
                       noredirect:  true };
               q.post( w ).done( IUTIL.rename.fine )
                          .fail( IUTIL.rename.fault );
               IUTIL.batch.fired();
               IUTIL.edit.fill( "Moving" );
            } else {
               $msg     =  $( "<span>" );
               $strong  =  $( "<strong>" );
               $strong.text( IUTIL.cnf.feature( "Error" ) );
               $msg.append( $strong );
               $strong  =  $( "<strong>" );
               $strong.css( { "margin-left":  "1em",
                              "margin-right": "1em" } );
               $strong.text( "*" );
               $msg.append( $strong );
               $strong  =  $( "<strong>" );
               $strong.text( IUTIL.cnf.feature( "MoveSpace" ) );
               $msg.append( $strong );
               IUTIL.utl.fault( $msg );
            }
         } else {
            IUTIL.edit.failing( false );
         }
      };   // .rename.fire()
   }   // .rename



//-----------------------------------------------------------------------



   if ( typeof IUTIL.versions  !==  "object" ) {
      // Utilitiy for counting the number of versions expected to import
      // Dependencies: mediawiki.api mediawiki.util
      IUTIL.versions  =  { max:     1000,
                           promise: false,
                           sketch: "<!--#rv-->"
                         };



      IUTIL.versions.fault  =  function ( arrived ) {
         // Show API failure on user notification
         // Precondition:
         //    arrived  -- JSON info of ajax query
         // Uses:
         //    .utl.fault()
         //    mw.log()
         // Remark: Used as event handler -- 'this' is not IUTIL.versions
         // 2012-12-31 PerfektesChaos@de.wikipedia
         IUTIL.utl.fault( false );
         mw.log( {loud:true}, "IUTIL.versions.fault()", 2, arrived );
      };   // .versions.fault()



      IUTIL.versions.fetch  =  function ( arrived ) {
         // Retrieve array length from JSON result
         // Precondition:
         //    arrived  -- JSON result of ajax query
         // Postcondition:
         //    Returns number
         // Uses:
         // 2012-12-31 PerfektesChaos@de.wikipedia
         var r  =  -1,
             i, q;
         if ( typeof arrived  ===  "object" ) {
            q  =  arrived.query;
            if ( q ) {
               i  =  q.pageids[ 0 ];
               q  =  q.pages;
               if ( q  &&  i > 0 ) {
                  q  =  q[ i ];
                  if ( q ) {
                     r  =  q.revisions.length;
                  }
               }
            }
         }
         return r;
      };   // .versions.fetch()



      IUTIL.versions.figure  =  function ( add ) {
         // Display version number in box end edit field
         // Precondition:
         //    add  -- non-null: more versions
         // Uses:
         //    this
         //    >  .versions.number
         //    >  .versions.max
         //    >  .cnf.project.edit.sketch
         //    >  .versions.lazy
         //    >  .$msg
         //    >  .versions.sketch
         //    .cnf.feature()
         //    jQuery().empty()
         //    jQuery().css()
         //    jQuery().text()
         //    jQuery().append()
         //    .edit.feed()
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var s    =  "#00A000",
             d    =  new Date(),
             say  =  this.number,
             $s;
         if ( this.number > this.max ) {
            s    =  "#FF0000";
            say  =  say  +  ( add ? "++" : "" )
                    +  " (&gt;" + this.max + ")";
         }
         if ( ! this.lazy ) {
            IUTIL.$msg.empty();
            IUTIL.$msg.css( { "border":       "solid 1px",
                              "border-color": s,
                              "color":        s,
                              "margin":       "3px",
                              "padding":      "1em" } );
            $s  =  $( "<span>" );
            $s.text( IUTIL.cnf.project.edit.sketch );
            IUTIL.$msg.append( $s );
            $s  =  $( "<strong>" );
            $s.text( say );
            IUTIL.$msg.append( $s );
         }
         say  =  IUTIL.edit.feed( false )  +  "\n* "
                 +  IUTIL.cnf.project.edit.sketch
                 +  " '''" + say + "''' "
                 + this.sketch + " " + d.toLocaleString();
         IUTIL.edit.feed( say );
      };   // .versions.figure()



      IUTIL.versions.fire  =  function ( about ) {
         // Start version counting
         // Precondition:
         //    about  -- source page information
         //                 .lang  -- source language other than current
         //                 .from  -- source page
         // Uses:
         //    this
         //    document
         //    >  mw.Api
         //     < .versions.lazy
         //     < .versions.source
         //     < .versions.promise
         //     < .versions.optURL
         //     < .versions.query
         //    .batch.fired()
         //    mw.util.wikiScript()
         //    mw.Api.get()
         //    (.versions.find)
         //    (.versions.fault)
         // 2015-06-12 PerfektesChaos@de.wikipedia
         var h, p;
         IUTIL.batch.fired( "Checking" );
         this.lazy    =  false;
         this.source  =  about.from;
         if ( ! this.promise ) {
            this.promise  =  new mw.Api();
         }
         this.query   =  { action:       "query",
                           "continue":   "",
                           indexpageids: true,
                           prop:         "info",
                           titles:       this.source };
         if ( about.lang ) {
            h            =  window.document.location.hostname;
            p            =  window.document.location.protocol + "//";
            this.optURL  =  { url:  "//" + about.lang
                                         + h.substr( h.indexOf( "." ) )
                                         + mw.util.wikiScript( "api" )
                            };
            this.query.origin  =  p + h;
         } else {
            this.optURL  =  null;
         }
         this.promise.get( this.query, this.optURL ).done( this.find )
                                                    .fail( this.fault );
      };   // .versions.fire()



      IUTIL.versions.find  =  function ( arrived ) {
         // Start version counting
         // Precondition:
         //    arrived  -- JSON result of ajax query
         // Uses:
         //    document
         //    >  .versions.promise
         //    >  .versions.source
         //    >< .versions.query
         //     < .versions.number
         //    .cnf.feature()
         //    .edit.feed()
         //    jQuery().text()
         //    jQuery().append()
         //    jQuery().css()
         //    .utl.fault()
         //    .batch.fired()
         //    mw.Api.get()
         //    (.versions.found)
         //    (.versions.fault)
         // Remark: Used as event handler -- 'this' is not IUTIL.versions
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var sucks  =  "ErrorAjax",
             that   =  IUTIL.versions,
             id, q, say, $msg, $span;
         if ( typeof arrived.query  ===  "object" ) {
            q  =  arrived.query;
            if ( typeof q.pageids  ===  "object" ) {
               id  =  q.pageids[ 0 ];
               if ( id === -1 ) {
                  sucks  =  "ErrorNoSource";
               } else if ( typeof q.pages  ===  "object" ) {
                  q  =  q.pages[ id ];
                  if ( typeof q  ===  "object" ) {
                     if ( typeof q.redirect  ===  "undefined" ) {
                        sucks  =  false;
                     } else {
                        sucks  =  "ErrorRedirect";
                     }
                  }
               }
            }
         }
         if ( sucks ) {
            say    =  IUTIL.cnf.feature( sucks );
            $msg   =  $( "<span>" );
            $span  =  $( "<span>" );
            $span.text( say );
            $msg.append( $span );
            if ( sucks !== "ErrorAjax" ) {
               IUTIL.edit.feed( say + " * "
                                + "[[" + IUTIL.versions.source + "]]" );

               $msg.append( "<br />" );
               $span  =  $( "<span>" );
               $span.css( { "font-style": "italic" } );
               $span.text( IUTIL.versions.source );
               $msg.append( $span );
            }
            IUTIL.utl.fault( $msg );
// // Bugmeldung  2015-11-06  anschliessend Bearbeitungsabschnitt zu
         } else {
            IUTIL.batch.fired( "Counting" );
            that.number         =  0;
            that.query.prop     =  "revisions";
            that.query.rvlimit  =  "max";
            that.promise.get( that.query,
                              that.optURL ).done( that.found )
                                           .fail( that.fault );
         }
      };   // .versions.find()



      IUTIL.versions.found  =  function ( arrived ) {
         // Some versions counted
         // Precondition:
         //    arrived  -- JSON result of ajax query
         // Uses:
         //    >  .versions.max
         //    >  .versions.lazy
         //    >  .$msg
         //    >  .versions.promise
         //    >< .versions.number
         //    .versions.fetch()
         //    .versions.figure()
         //    jQuery().css()
         //    jQuery().text()
         //    jQuery().append()
         //    mw.Api.get()
         //    .cnf.feature()
         //    .utl.fault()
         //    (.versions.found)   -- self
         //    (.versions.fault)
         // Remark: Used as event handler -- 'this' is not IUTIL.versions
         // 2016-07-09 PerfektesChaos@de.wikipedia
         var that  =  IUTIL.versions,
             n     =  that.fetch( arrived ),
             q, $msg, $s;
         if ( n > 0 ) {
            that.number  +=  n;
            if ( typeof arrived[ "continue" ]  ===  "object" ) {
               q  =  arrived[ "continue" ];
            }
            if ( that.number > that.max ) {
               that.figure( q );
            } else if ( q ) {
               $.extend( that.query, q );
               if ( ! that.lazy ) {
                  $s  =  $( "<span>" );
                  $s.css( { "margin-left": "2em" } );
                  $s.text( ( that.number - 1 ) + ", "
                           + that.number + ", "
                           + ( that.number + 1 ) + ", ..." );
                  IUTIL.$msg.append( $s );
               }
               if ( q ) {
                  that.promise.get( that.query,
                                    that.optURL ).done( that.found )
                                                 .fail( that.fault );
               } else {
                  mw.log( {loud:true}, "IUTIL.versions.found() ?", 2 );
               }
            } else {
               that.figure( false );
            }
         } else {
            $msg  =  $( "<span>" );
            $s    =  $( "<strong>" );
            $s.text( IUTIL.cnf.feature( "NotFound" ) );
            $msg.append( $s );
            $s  =  $( "<strong>" );
            $s.css( { "margin-left":  "1em",
                      "margin-right": "1em" } );
            $s.text( "*" );
            $msg.append( $s );
            $s  =  $( "<strong>" );
            $s.text( that.source );
            $msg.append( $s );
            IUTIL.utl.fault( $msg );
            mw.log( {loud:true},
                    "IUTIL.versions.found() Not found", 2, arrived );
         }
      };   // .versions.found()
   }   // .versions



//-----------------------------------------------------------------------



   if ( typeof IUTIL.zone  !==  "object" ) {
      // Utilitiy for difference between server timeoffset and local time
      // Dependencies: mediawiki.api
      // Memorized at window.localStorage.timeoffset
      IUTIL.zone         =  { };
      IUTIL.zone.maxage  =  10800;   // 3 h



      IUTIL.zone.factory  =  function ( appoint ) {
         // Get Date object from yyyymmddHHMMSS timestamp in local time
         // Precondition:
         //    appoint  -- yyyymmddHHMMSS string
         // Postcondition:
         //    Return Date object
         // Uses:
         //    this
         //   .zone.fetch()
         // 2013-01-23 PerfektesChaos@de.wikipedia
         var g  =  [ appoint.substr(  0, 4 ),   // yyyy
                     appoint.substr(  4, 2 ),   // mm
                     appoint.substr(  6, 2 ),   // dd
                     appoint.substr(  8, 2 ),   // HH
                     appoint.substr( 10, 2 ),   // MM
                     appoint.substr( 12, 2 )    // SS
                   ],
             j  =  this.fetch();
   		return  new Date( Date.UTC( parseInt( g[0], 10 ),
                                     parseInt( g[1], 10 )  -  1,
                                     parseInt( g[2], 10 ),
                                     parseInt( g[3], 10 ),
                                     parseInt( g[4], 10 )  -  j,
                                     parseInt( g[5], 10 ) ) );
      };   // .zone.factory()



      IUTIL.zone.fetch  =  function ( alt ) {
         // Retrieve server timeoffset of local time
         // Precondition:
         //    alt  -- fallback value, if number,  or ignored
         // Postcondition:
         //    Return number; at least 0
         // Uses:
         //    this
         //    >  window.localStorage.timeoffset
         //    >  mw.Api
         //    >< .zone.justify
         //    (.zone.found)
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var r  =  0,
             p, q, w;
         if ( window.localStorage ) {
            w  =  window.localStorage.getItem( "timeoffset" );
            if ( w ) {
               w  =  /([+-][0-9]+)\s*(?:@([0-9]+))?/.exec( w );
               if ( w ) {
                  this.justify  =  parseInt( w[ 1 ],  10 );
                  q             =  w[ 2 ];
                  if ( q ) {
                     q  =  parseInt( q, 10 );
                     p  =  new Date();
                     p  =  p.getTime() / 1000;
                     if ( p - q  >  IUTIL.zone.maxage ) {   // 3 h
                        w  =  false;
                     }
                  }
               }
            }
            if ( ! w ) {
               q  =  new mw.Api();
               p  =  { action:     "query",
                       "continue": "",
                       meta:       "siteinfo" };
               q.get( p ).done( this.found );
            }
         }
         if ( typeof this.justify  !==  "number" ) {
            if ( typeof alt  ===  "number" ) {
               this.justify  =  alt;
            }
         }
         if ( typeof this.justify  ===  "number" ) {
            r  =  this.justify;
         }
         return r;
      };   // .zone.fetch()



      IUTIL.zone.found  =  function ( arrived ) {
         // Evaluate siteinfo query
         // Precondition:
         //    arrived  -- JSON result of ajax query
         // Uses:
         //    >  window.localStorage.timeoffset
         //     < .zone.justify
         // Remark: Used as event handler -- 'this' is not IUTIL.zone
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var q  =  arrived,
             d, s;
         if ( q ) {
            q  =  q.query;
            if ( q ) {
               q  =  q.general;
               if ( q ) {
                  q  =  q.timeoffset;
                  if ( typeof q  ===  "number" ) {
                     this.justify  =  q;
                     if ( window.localStorage ) {
                        d  =  new Date();
                        d  =  Math.floor( d.getTime() / 1000 );
                        s  =  ( this.justify < 0  ?  "-"  :  "+" )
                              +  this.justify  +  " @"  +  d;
                        window.localStorage.setItem( "timeoffset", s );
                     }
                  }
               }
            }
         }
      };   // .zone.found()
   }   // .zone



//-----------------------------------------------------------------------



   if ( typeof IUTIL.project  !==  "object" ) {
      // Open action on request project page
      // Dependencies: mediawiki.api
      IUTIL.proj  =  { };



      IUTIL.proj.fair  =  function () {
         // Process request page open action
         // Precondition:
         //    request page view document is ready, resources available
         // Uses:
         //    mw.config.get()
         //    .proj.focus()
         //    (.edit.fire)
         // Remark: Used as event handler -- 'this' is not IUTIL.proj
         // 2014-10-10 PerfektesChaos@de.wikipedia
         if ( mw.config.get( "wgIsArticle" ) ) {
            IUTIL.proj.focus();
         } else {
            IUTIL.edit.fire();
         }
      };   // .proj.fair()



      IUTIL.proj.fire  =  function () {
         // Perform page open action on request project page
         // Uses:
         //    >  Self
         //    >  .cnf.project.minutes
         //    >  .mode
         //    >  .cnf.project.submitTW
         //    >  .cnf.project.submitUP
         //    >< .start
         //     < .cnf.submit
         //    .zone.fetch()
         //    mw.loader.using()
         //    jQuery().ready()
         //    (.proj.fair)
         // 2018-06-07 PerfektesChaos@de.wikipedia
         if ( typeof IUTIL.start  ===  "string"
              &&     IUTIL.start  ===  Self ) {
            IUTIL.start  =  false;
            IUTIL.zone.fetch( IUTIL.cnf.project.minutes );
            if ( IUTIL.mode === 1 ) {
               IUTIL.cnf.submit  =  IUTIL.cnf.project.submitTW;
            } else {
               IUTIL.cnf.submit  =  IUTIL.cnf.project.submitUP;
            }
            mw.loader.using( [ "mediawiki.api",
                               "mediawiki.Title",
                               "mediawiki.user",
                               "mediawiki.util" ],
                             function () {
                                $( IUTIL.proj.fair );
                             } );
         }
      };   // .proj.fire()



      IUTIL.proj.focus  =  function () {
         // Divert all section edit links on request page to new window
         // Precondition:
         //    request page view document is ready
         // Uses:
         //    document.links
         //    .archive.furnish()
         //    .hold.furnish()
         // 2014-10-10 PerfektesChaos@de.wikipedia
         var n  =  window.document.links.length,
             e, i, s;
         for ( i = 0;  i < n;  i++ ) {
            e  =  window.document.links[ i ];
            s  =  e.href;
            if ( s.indexOf( "&action=edit&section=" )  >  0 ) {
               e.target  =  "_blank";
               if ( s.indexOf( "&preview=" )  >  0 ) {
                  e.href  =  s.replace( /&preview=no/,
                                             "&preview=yes&" );
               } else if ( s.indexOf( "&section=new" )  <  0 ) {
                  e.href  =  s.replace( /&action=edit&/,
                                        "&action=edit&preview=yes&" );
               }
            }
         }   // for i
         IUTIL.archive.furnish();
         IUTIL.hold.furnish();
      };   // .proj.focus()
   }   // .proj



//-----------------------------------------------------------------------



   function fire() {
      // Script unit has been loaded
      // Uses:
      //    >  SIGNATURE
      //    >  .type
      //    >  Self
      //    >  Version
      //    >  .start
      //    >  SIG
      //    mw.loader.getState()
      //    mw.loader.state()
      //    mw.hook()
      //    .utl.fire()
      // 2018-08-24 PerfektesChaos@de.wikipedia
      var rls, sign;
      if ( mw.loader.getState( SIGNATURE )  !==  "ready" ) {
         rls = { };
         rls[ SIGNATURE ] = "ready";
         mw.loader.state( rls );
         sign  =  IUTIL.type + "." + Self;
         mw.hook( sign + ".ready" ).fire( { type: sign,
                                            vsn:  Version } );
         mw.hook( IUTIL.type + ".utl.ready" ).add( IUTIL[ Self ].fire );
      }
   }   // fire()



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



// Emacs
// Local Variables:
// End:

/// EOF   importUtility/proj.js    </nowiki>