Jump to content

User:PerfektesChaos/js/WikiSyntaxTextMod/dM.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/// PerfektesChaos/js/WikiSyntaxTextMod/dM.js
/// 2019-11-12 PerfektesChaos@de.wikipedia
/// Fingerprint: #0#0#
/// @license: CC-by-sa/4.0 GPLv3
/// <nowiki>
//  WikiSyntaxTextMod: Main functions, not initially loaded
/* global mw:true, mediaWiki:false, window:false                       */
/* jshint forin:false,
          bitwise:true, curly:true, eqeqeq:true, latedef:true,
          laxbreak:true,
          nocomma:true, strict:true, undef:true, unused:true           */


if ( typeof mediaWiki  !==  "object" ) {   // disconnected
   mw  =  { config: false,
            libs:   { WikiSyntaxTextMod:  { debugging: false }
                    },
            log:    function () {"use strict";}
          };
}
( function ( mw ) {
   "use strict";
   var version  =  -7.32,
       sign     =  "WikiSyntaxTextMod",
       sub      =  "M",
       rls, self, WSTM;
   if ( typeof mw.loader  ===  "object" ) {
      rls   =  { };
      self  =  "user:PerfektesChaos/" + sign + "/" + sub;
      rls[ self ] = "loading";
      mw.loader.state( rls );
   }
   if ( typeof mw.libs[ sign ]  !==  "object" ) {   // isolated
      mw.libs[ sign ]  =  { };
   }
   WSTM  =  mw.libs[ sign ];
   if ( typeof WSTM.main  !==  "object" ) {
      WSTM.main  =  { };
   }
   WSTM.main.vsn   =  version;
   WSTM.main.self  =  self;
   if ( typeof WSTM.bb  !==  "object" ) {
      WSTM.bb  =  { };
   }
   if ( typeof WSTM.debugging  !==  "object" ) {
      WSTM.debugging  =  { };
   }
} ( mw ) );



/*
Uses:
   .hooks.fire()
   .lang.find()
   .prefs.fetch()
   .str.***()
   .util.isArray()
   .util.isbn.factory()
   .util.isElement()
   .util.isO_639_1()
   .util.regexp.fiat()
   .w.img.factory()
   .w.link.langs
   .w.link.namespace.factory()
   .w.link.replace.factory()
   .w.template.mod.factory()
   mw.log()
   jQuery()
Requires: JavaScript 1.3
          (String.charCodeAt String.fromCharCode String.replace)
 */



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



mw.libs.WikiSyntaxTextMod.bb.utilM  =  function (WSTM) {
   // Building block and run environment support
   // 2012-05-18 PerfektesChaos@de.wikipedia
   "use strict";
   if (typeof(WSTM.util) !== "object") {
      WSTM.util  =  { };
   }


   if (typeof(WSTM.util.fiatObjects) !== "function") {
      WSTM.util.fiatObjects  =  function (adult, activate, assign) {
         // Ensure existence of at least empty object
         // Precondition:
         //    adult     -- parent object
         //    activate  -- String with name of child object
         //    assign    -- optional object with initial definition
         //                 if containing object components,
         //                 they will be asserted as well
         // Postcondition:
         //    adult has been extended
         // Uses:
         //    .util.fiatObjects()  -- recursive
         // 2012-05-18 PerfektesChaos@de.wikipedia
         var elt,
             obj,
             s;
         if (typeof( adult[activate] )  !==  "object") {
            adult[activate]  =  (assign  ?  assign  :  { } );
         }
         if (assign) {
            obj  =  adult[activate];
            for (s in assign) {
               elt  =  assign[s];
               if (typeof(elt)  ===  "object") {
                  WSTM.util.fiatObjects(obj, s, elt);
               }
            }  //  s in obj
         }
      };   // .util.fiatObjects()
   }


   WSTM.util.fiatObjects(WSTM,  "debugging",  { loud: false });


};   // .bb.utilM()
mw.libs.WikiSyntaxTextMod.bb.utilM(mw.libs.WikiSyntaxTextMod);
delete mw.libs.WikiSyntaxTextMod.bb.utilM;



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



mw.libs.WikiSyntaxTextMod.bb.apiM  =  function (WSTM) {
   // Top level functions (exposed)
   // Uses:
   //    .util.fiatObjects()
   // 2012-06-18 PerfektesChaos@de.wikipedia
   "use strict";
   WSTM.util.fiatObjects(WSTM,  "api",  { });



   WSTM.api.edit  =  function (arglist) {
      // Execute syntax and user defined replacement in user context
      // Precondition:
      //    arglist  -- object   .wikitext  string
      //                         .summary   (optional) string
      // Postcondition:
      //    Returns  false   if .wikitext remains unchanged
      //             object  .wikitext  string modified, or error found
      //                     .diffpage  true if required
      //                     .summary   false or non-empty string
      //                     .minor     if minor edits only (not userdef)
      // Uses:
      //    >  .errors.collection
      //    >  .mod.lazy
      //    >  .main.less
      //    >  .config.mod
      //    >  .config.mod.summary
      //    >  .config.diffPage
      //    .warn.failed()
      //    .api.textMod()
      //    .str.trimR()
      //    .str.trimL()
      //    .str.trim()
      // 2013-12-09 PerfektesChaos@de.wikipedia
      var got     =  this.textMod(arglist.wikitext),
          lapsus  =  (WSTM.errors.collection || WSTM.warn.failed()),
          r       =  false,
          seed,
          sum;
      if (! got  &&  lapsus) {
         got  =  [ arglist.wikitext, false ];
      }
      if (got) {
         seed  =  false;
         sum   =  "";
         r  =  { wikitext: got[0],
                 minor:    (got[1] && WSTM.mod.lazy),
                 summary:  false,
                 diffpage: true,
                 lapsus:   lapsus };
         if (typeof(WSTM.main.less) === "boolean") {
            r.minor  =  r.minor && WSTM.main.less;
         }
         if (typeof(arglist.summary) === "string") {
            sum  =  WSTM.str.trimR(arglist.summary, true);
         }
         if (WSTM.config  &&  typeof(WSTM.config) === "object") {
            if (WSTM.config.mod  &&
                typeof(WSTM.config.mod) === "object") {
               if (typeof(WSTM.config.mod.summary) === "string") {
                  seed  =  WSTM.config.mod.summary;
               }
            }
         }
         if (typeof(seed) === "string") {
            if (sum.indexOf(seed) < 0) {
               sum  =  sum + " " + WSTM.str.trimL(seed, true);
            }
         }
         sum  =  WSTM.str.trim(sum, true);
         if (sum.length > 0) {
            r.summary  =  sum;
         }
         if (r.minor) {
            if (WSTM.config  &&  typeof(WSTM.config) === "object") {
               if (typeof(WSTM.config.diffPage) === "boolean") {
                  r.diffpage  =  WSTM.config.diffPage;
               }
            }
         }
      }   // any change
      return r;
   };   // .api.edit()



   WSTM.api.setContext  =  function (article, aNS, aDB) {
      // Define context for non-interactive article modifications
      // Precondition:
      //    article  -- string: wgTitle
      //    aNS      -- number: wgNamespaceNumber
      //    aDB      -- string: wgDBname
      //    If parameter omitted or false, that context is kept unchanged
      // Postcondition:
      //    Context is furnished
      // Uses:
      //     < .g.wTitle
      //     < .g.wNsNumber
      //     < .g.wDBname
      //    .g.factoryProject()
      // 2011-12-23 PerfektesChaos@de.wikipedia
      if (typeof(article) === "string") {
         WSTM.g.wTitle  =  article;
      }
      if (typeof(aNS) === "number") {
         WSTM.g.wNsNumber  =  aNS;
      }
      if (typeof(aDB) === "string") {
         WSTM.g.wDBname  =  aDB;
         WSTM.g.factoryProject();
      }
   };   // .api.setContext()



};   // .bb.apiM()
mw.libs.WikiSyntaxTextMod.bb.apiM(mw.libs.WikiSyntaxTextMod);
delete mw.libs.WikiSyntaxTextMod.bb.apiM;



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



mw.libs.WikiSyntaxTextMod.bb.errorsM  =  function (WSTM) {
   // Detected syntax error handling
   // Uses:
   //    .util.fiatObjects()
   // 2012-10-11 PerfektesChaos@de.wikipedia
   "use strict";
   WSTM.util.fiatObjects(WSTM,  "errors",  { });
   WSTM.errors.maximum   =  7;
   WSTM.errors.selector  =  "WSTM-errors";



   WSTM.errors.fashion  =  function (apply) {
      // Format one message entry as HTML list item
      // Precondition:
      //    apply  -- message entry; Array[4]
      //              [0] number/identifier of error message
      //              [2] additional information as found, or false
      //              [3] multiplicity
      // Postcondition:
      //    Return HTML list item
      // Uses:
      //    .lang.text.fetch()
      //    .str.escapeLight()
      // 2013-05-06 PerfektesChaos@de.wikipedia
      var r  =  "\n<li>";
      if (apply[3] > 1) {
         r  =  r + "<em>(" + apply[3] + "&times;)</em> ";
      }
      r  =  r + WSTM.lang.text.fetch(apply[0]);
      if (apply[2]) {
         r  =  r + "<br />\n" + WSTM.str.escapeLight(apply[2]);
      }
      r  =  r + "</li>\n";
      return r;
   };   // .errors.fashion()



   WSTM.errors.fill  =  function () {
      // Provide list of syntax error messages to insert into wiki text
      // Precondition:
      //    this.collection is an object (not empty)
      // Postcondition:
      //    Set .errors.story to string with entire text, or false
      // Uses:
      //    >  .errors.collection
      //    >  .errors.more
      //     < .errors.story
      //    .lang.text.fetch()
      //    .str.escapeLight()
      //    .errors.frozen()
      // 2012-10-03 PerfektesChaos@de.wikipedia
      var l  =  true,
          n  =  this.collection.length,
          s  =  "",
          e,
          i;
      n  =  (n > this.more  ?  this.more  :  n);
      for (i = 0;  i < n;  i++) {
         e  =  this.collection[i];
         if (e[1]) {
            if (l) {
               s  =  WSTM.lang.text.fetch("_ErrorBeginAuto"
                                          +  (this.more === 1  ?  "1"
                                                               :  "N") )
                     + s;
            }
            s  =  s + "\n* " + WSTM.lang.text.fetch(e[0]);
            if (e[2]) {
               s  =  s + ": " + WSTM.str.escapeLight(e[2]);
            }
            l  =  false;
         }
      }   // for i
      l  =  true;
      for (i = 0;  i < n;  i++) {
         e  =  this.collection[i];
         if ( ! e[1]) {
            if (l) {
               s  =  WSTM.lang.text.fetch("_ErrorBeginMan"
                                          +  (this.more === 1  ?  "1"
                                                               :  "N")  )
                     + "\n"
                     + s;
            }
            s  =  s + "\n* " + WSTM.lang.text.fetch(e[0]);
            if (e[2]) {
               s  =  s + ": " + WSTM.str.escapeLight(e[2]);
            }
            l  =  false;
         }
      }   // for i
      s  =  s.replace(/-->/g, "--&gt;");
      if (this.collection.length > this.more) {
         s  =  s + "\n\n"
                 + WSTM.lang.text.fetch("_ErrorLimitMore")
                 + " (" + this.collection.length + ")\n";
      }
      this.story  =  this.frozen() + "\n" + s + "\n-->\n";
   };   // .errors.fill()



   WSTM.errors.filter  =  function () {
      // Extract current message section from entire sessionStorage
      // Postcondition:
      //    Return current message section string; or all messages
      // Uses:
      //    >  .errors.swap
      //    >  .errors.joint
      // 2013-04-17 PerfektesChaos@de.wikipedia
      var r  =  this.swap,
          n;
      if (r) {
         if (this.joint > 0) {
            r  =  r.substr(this.joint);
         }
         n  =  r.indexOf("</WSTM>", 12);
         if (n > 0) {
            r  =  r.substr(0,  n + 7);
         }
      } else {
         r  =  "";
      }
      return r;
   };   // .errors.filter()



   WSTM.errors.finalize  =  function (append, always) {
      // Initiate error message display in appropriate manner
      // Precondition:
      //    append  -- force insertion directly in current HTML page
      //    always  -- force display
      // Uses:
      //    >  .errors.config.errorlimit
      //    >  jQuery
      //    >< .errors.collection
      //     < .errors.story
      //     < .errors.more
      //    .warn.failed()
      //    mw.user.options.get()
      //    .errors.flat()
      //    .errors.flip()
      //    .errors.fill()
      //    .errors.furnish()
      //    .errors.flush()
      // 2013-12-09 PerfektesChaos@de.wikipedia
      var live  =  false;
      this.story  =  false;
      if (always  &&  ! this.collection) {
         this.collection  =  [ ];
      }
      if (typeof(this.collection) === "object") {
         if (typeof(WSTM.config.errorlimit) === "number") {
            if (WSTM.config.errorlimit > 0) {
               this.more  =  WSTM.config.errorlimit;
            } else {
               this.more  =  0;
            }
         } else {
            this.more  =  this.maximum;
         }
         if (this.more || append || always) {
            if (typeof(mw.user) === "object") {
               if (mw.user.options) {
                  if (mw.user.options.get("uselivepreview")) {
                     live  =  true;
                  }
               }
            }
            if (typeof(window.jQuery) === "function") {
               if (live && append) {
                  this.flat();
               } else if (! append) {
                  if (! this.flip()) {
                     this.fill();
                  }
               } else if (append || always) {
                  this.flush(this.furnish());
               }
            }
         }
      }
   };   // .errors.finalize()



   WSTM.errors.first  =  function () {
      // Reset sessionStorage in case of history
      // Uses:
      //    >  sessionStorage
      //    >  .errors.swift
      // 2015-03-10 PerfektesChaos@de.wikipedia
      var s;
      if (typeof(window.sessionStorage) === "object") {
         s  =  window.sessionStorage.getItem(this.swift);
         if (typeof(s) === "string"  &&  s) {
            window.sessionStorage.setItem(this.swift, "");
         }
      }
   };   // .errors.first()



   WSTM.errors.fixed  =  function () {
      // Hide error message display from current HTML page
      // Uses:
      //    >  .errors.selector
      //    jQuery()
      // Remark: Used as event handler -- 'this' is not WSTM.main
      // 2012-10-03 PerfektesChaos@de.wikipedia
      var $e  =  window.jQuery( "#" + WSTM.errors.selector );
      if ( $e.length ) {
         $e.attr("style", "display: none;");
      }
   };   // .errors.fixed()



   WSTM.errors.flat  =  function () {
      // Put removeable list of error messages directly into HTML page
      // Precondition:
      //    this.collection is not empty
      // Postcondition:
      //    Message box has been placed into HTML page
      // Uses:
      //    >  mw
      //     < .errors.collection
      //    .errors.furnish()
      //    .errors.flush()
      //    (.errors.fixed)
      //    (.errors.focus)
      // 2012-10-11 PerfektesChaos@de.wikipedia
      var s   =  this.furnish(),
          $e;
      s   =  "<div style='float:right'>"
             + "<a id='WSTM-errors-hide'"
               + " href='#'>"
             + "<img src='"
                  + "//upload.wikimedia.org/"
                    + "wikipedia/commons/thumb/2/2f/"
                    + "No_red.svg/20px-No_red.svg.png"
                  + "' /></a></div>\n"
             + s;
      $e  =  this.flush(s);
      if ($e) {
         $e.find("#WSTM-errors-hide").click(this.fixed);
         window.jQuery(mw).bind("LivePreviewDone", this.focus);
      }
      this.collection  =  false;
   };   // .errors.flat()



   WSTM.errors.flip  =  function () {
      // Try to put error messages into sessionStorage
      // Postcondition:
      //    Return true, iff successful
      // Uses:
      //    >  sessionStorage
      //    >  .errors.starter
      //    >  .errors.swift
      //    .errors.fixing()
      //    .errors.flop()
      //    .errors.furnish()
      // 2015-03-10 PerfektesChaos@de.wikipedia
      var r  =  false,
          s;
      if (typeof(window.sessionStorage) === "object") {
         this.fixing();
         s  =  window.sessionStorage.getItem(this.swift);
         if (typeof(s) === "string") {
            s  =  this.flop(s);
         } else {
            s  =  "";
         }
         s  =  s + "\n" + this.starter + "\n"
                   + this.furnish()
                   + "\n</WSTM>\n";
         s  =  s.replace(/\n\n+/, "\n");
         window.sessionStorage.setItem(this.swift, s);
         r  =  (window.sessionStorage.getItem(this.swift) === s);
      }
      return r;
   };   // .errors.flip()



   WSTM.errors.flop  =  function (adjust) {
      // Remove section from tagged string
      // Precondition:
      //    adjust  -- string to be cleared
      // Postcondition:
      //    Returns cleared string
      // Uses:
      //    >  .errors.starter
      // 2012-10-17 PerfektesChaos@de.wikipedia
      var i, j,
          r;
      if (typeof(adjust) === "string") {
         r  =  adjust;
         if (adjust.length) {
            i  =  r.indexOf(this.starter);
            if (i >= 0) {
               j  =  r.indexOf("</WSTM>",  i + 12);
               if (j > i) {
                  r  =  r.substr(0, i)  +  r.substr(j + 7);
               }
            }
            r  =  r.replace(/\n\n+/, "\n");
            r  =  (r === "\n"  ?  ""  :  r);
         }
      } else {
         r  =  "";
      }
      return r;
   };   // .errors.flop()



   WSTM.errors.flush  =  function ( attach ) {
      // Insert error message on HTML page below headline
      // Precondition:
      //    Wikiserver HTML page in interactive mode
      //    attach  -- HTML string with message body
      // Postcondition:
      //    Returns jQuery of message area
      //    Message area is inserted into page
      // Uses:
      //    >  .errors.selector
      //    .main.focus()
      //    jQuery()
      // 2019-09-20 PerfektesChaos@de.wikipedia
      var $div  =  window.jQuery( "<div>" ),
          $e    =  window.jQuery( "#" + this.selector ),
          $u    =  WSTM.main.focus();
      $e.remove();
      $div.attr( { "class": "error remindErrorMessages-noContent",
                   "id":    this.selector } );
      $div.css( { border:  "solid 3px",
                  padding: "3px" } );
      $div.html( attach );
//    $e  =  window.jQuery(s);
      $u.before( $div );
      return  ( $u.length ? $u : false );
   };   // .errors.flush()



   WSTM.errors.focus  =  function () {
      // Scroll to error message display in current HTML page
      // Uses:
      //    >  .errors.selector
      //    jQuery()
      // Remark: Used as event handler -- 'this' is not WSTM.main
      // 2012-10-03 PerfektesChaos@de.wikipedia
      var o  =  window.jQuery("#" + WSTM.errors.selector).offset();
      window.scrollTo(0, o.top);
   };   // .errors.focus()



   WSTM.errors.format  =  function () {
      // Show list of syntax error messages on HTML page below headline
      // Precondition:
      //    Wikiserver HTML page in interactive mode
      //    .errors.story is defined; containing:  * plain text messages
      // Postcondition:
      //    Message list is removed from wiki text
      //    Message area is inserted into page
      // Uses:
      //    >  .errors.story
      //    >  jQuery
      //    >  .errors.swift
      //    >  sessionStorage
      //    >< .errors.swap
      //    .lang.text.fetch()
      //    .errors.flush()
      //    .errors.fixing()
      //    .errors.filter()
      //    .errors.flop()
      // 2012-10-18 PerfektesChaos@de.wikipedia
      var re,
          s;
      if (typeof(this.story) === "string") {
         s   =  this.story.replace(/</g, "&lt;").replace(/>/g, "&gt;");
         //                        " ' \
         re  =  new RegExp("\n\\* ", "g");
         s   =  s.replace(re, "</li>\n<li>");
         s   =  "\n" + s + "\n";
         re  =  /(\n[^<]?.*)<\/li>\n<li>/g;
         s   =  s.replace(re, "$1\n<ul class='error-detail'>\n<li>");
         re  =  /(\n<li>.+[^>])\n/g;
         s   =  s.replace(re, "$1</li>\n</ul>\n");
         s   =  s.replace(/\n\n/g, "<br />\n");
         s   =  "<p class='error-explanation'><em>"
                + WSTM.lang.text.fetch( "_ErrorBegin" +
                             (this.story.search(/\n\*.+\n?.*\n\*/) === -1
                                                 ?  "1"
                                                 :  "N") )
                + "</em></p>"
                + s
                + "\n<p class='error-explanation'>"
                + WSTM.lang.text.fetch("_ErrorEpilog")
                + "<br /><em>-- WikiSyntaxTextMod</em> "
                + "<small>(PerfektesChaos)</small></p>";
         if (typeof(window.jQuery) === "function") {
            this.flush(s);
         }
      } else if (this.swap) {
         this.fixing();
         s  =  this.filter();
         this.flush(s);
         s  =  this.flop(this.swap);
         window.sessionStorage.setItem(this.swift, s);
         this.swap  =  false;
      }
   };   // .errors.format()



   WSTM.errors.found  =  function (alert, auto, add) {
      // Manage detected error
      // Precondition:
      //    alert  -- number/identifier of error message
      //    auto   -- true: automatic attempt
      //    add    -- additional information as found, or false
      //              plain wikitext; will be HTML-escaped
      // Uses:
      //    >  .debugging
      //    >< .errors.collection
      //    mw.log()
      // 2012-05-06 PerfektesChaos@de.wikipedia
      var err  =  [ alert, auto, add, 1 ],
          e, i, n;
      if (this.collection) {
         n  =  this.collection.length;
         for (i = 0;  i < n;  i++) {
            e  =  this.collection[i];
            if (e[0] === alert  &&
                e[1] === auto  &&
                e[2] === add) {
               e[3]++;
               err[3]  =  e[3];
               break;   // for i
            }
         }   // for i
         if (err[3] === 1) {
            this.collection.push(err);
         }
      } else {
         this.collection  =  [ err ];
      }
      if (WSTM.debugging) {
         mw.log(WSTM.debugging, ".errors.found()", 1, err);
      }
   };   // .errors.found()



   WSTM.errors.furnish  =  function () {
      // Format list of error messages directly as HTML
      // Precondition:
      //    this.collection is an object (not empty)
      // Postcondition:
      //    Returns HTML string with formatted message content
      // Uses:
      //    >  .errors.collection
      //    >  .errors.more
      //    .errors.fashion()
      //    .lang.text.fetch()
      //    .warn.fetch()
      // 2013-05-06 PerfektesChaos@de.wikipedia
      var n  =  this.collection.length,
          r  =  "",
          u  =  "",
          e,
          i;
      n  =  (n > this.more  ?  this.more  :  n);
      for (i = 0;  i < n;  i++) {
         e  =  this.collection[i];
         if (e[1]) {
            u  =  u + this.fashion(e);
         }
      }   // for i
      if (u) {
         r  =  WSTM.lang.text.fetch("_ErrorBeginAuto"
                                    +   (this.more === 1  ?  "1"
                                                          :  "N") )
               +    "\n<ul>\n"  +  u  +  "\n</ul>";
         u  =  "";
      }
      for (i = 0;  i < n;  i++) {
         e  =  this.collection[i];
         if (! e[1]) {
            u  =  u + this.fashion(e);
         }
      }   // for i
      if (u) {
         r  =  r  +  "\n\n"
               +    WSTM.lang.text.fetch("_ErrorBeginMan"
                                         +   (this.more === 1  ?  "1"
                                                               :  "N") )
               +    "\n<ul>\n"  +  u  +  "\n</ul>";
      }
      r  =  "<p class='error-explanation'><em>"
            + WSTM.lang.text.fetch( "_ErrorBegin" +
                                    (n === 1  ?  "1"  :  "N") )
            + "</em></p>"
      + r;
      if (this.collection.length > this.more) {
         r  =  r + "\n\n"
                 + WSTM.lang.text.fetch("_ErrorLimitMore")
                 + " (" + this.collection.length + ")\n";
      }
      r  =  r  +  WSTM.warn.fetch();
      r  =  r  + "\n<p class='error-explanation'>"
               + "<em>-- WikiSyntaxTextMod</em> "
               + "<small>(PerfektesChaos)</small></p>";
      return  r;
   };   // .errors.furnish()



};   // .bb.errorsM()
mw.libs.WikiSyntaxTextMod.bb.errorsM(mw.libs.WikiSyntaxTextMod);
delete mw.libs.WikiSyntaxTextMod.bb.errorsM;



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



mw.libs.WikiSyntaxTextMod.bb.gM  =  function (WSTM) {
   // Variables for global usage in WSTM
   // Uses:
   //    .util.fiatObjects()
   // 2013-03-18 PerfektesChaos@de.wikipedia
   "use strict";
   WSTM.util.fiatObjects( WSTM,  "g",
                          { learnt: false,
                            re:     {  s: { }  },
                            s:      {  re: { }  }
                          } );
   WSTM.util.fiatObjects( WSTM,  "str",
                          { re:     { }
                          } );
   WSTM.str.locateEntities  =  false;
   WSTM.str.sortLang        =  false;
   WSTM.str.sortMode        =  false;



   WSTM.g.factory  =  function () {
      // Initialize global variables, e.g. build compiled RegExp
      // Precondition:
      //    None
      // Postcondition:
      //    Set of dynamic global variables defined.
      // Uses:
      //    >  .mod.lock
      //    >< .g.learnt
      //    >< .g.wDBname
      //    >< .g.wNsNumber
      //    >< .g.wTitle
      //     < .g.re.ISBN
      //     < .str.sortLang
      //    .util.isbn.factory()
      //    .g.fetch()
      //    .g.factoryProject()
      // 2019-11-12 PerfektesChaos@de.wikipedia
      if ( ! this.learnt) {
         this.fetch(this.wDBname,   "wgDBname");
         this.fetch(this.wPageLang, "wgContentLanguage");
         this.fetch(this.wNsNumber, "wgNamespaceNumber");
         this.fetch(this.wTitle,    "wgTitle");
         if (typeof(this.wDBname) !== "string") {
            this.wDBname  =  "";
         }
         if (typeof(this.wNsNumber) !== "number") {
            this.wNsNumber  =  0;
         }
         if (typeof(this.wTitle) !== "string") {
            this.wTitle  =  "";
         }
         this.factoryProject();
         this.re.ISBN       =  WSTM.util.isbn.factory(WSTM.mod.lock);
         this.re.ISBN       =  new RegExp(this.re.ISBN, "i");
         WSTM.str.sortLang  =  this.projLang;
         this.learnt        =  true;
      }
   };   // .g.factory



   WSTM.g.factoryProject  =  function () {
      // Define global project context
      // Precondition:
      //    DB name (wgDBname) is defined
      // Postcondition:
      //    project context variables defined.
      // Uses:
      //    >  .g.wDBname
      //     < .g.projLang
      //     < .g.projType
      //     < .g.projLone
      //    .g.fetchDB()
      //    .hooks.fire()
      //    .lang.translate.factory()
      // 2012-12-07 PerfektesChaos@de.wikipedia
      var project, sole;
      if (typeof(this.wDBname) === "string") {
         sole           =  "|commons|mediawiki|meta|";
         project        =  this.fetchDB(this.wDBname);
         this.projLang  =  project[0];
         this.projType  =  project[1];
         this.projLone  =  (sole.indexOf(this.projType) > 0);
         WSTM.hooks.fire("*");
         WSTM.lang.translate.factory();
      }
   };   // .g.factoryProject()



   WSTM.g.fetchDB  =  function (around) {
      // Interprete WMF DBname
      // Precondition:
      //    around  -- DBname project identification
      // Postcondition:
      //    Returns Array[2]   [0]=projLang  [1]=projType
      // Uses:
      //    >< .g.re.wmfDB
      // 2012-12-07 PerfektesChaos@de.wikipedia
      var r  =  [ "en", "wikipedia" ],
          got;
      if (! this.re.wmfDB) {
         this.re.wmfDB  =  "^" + "([a-z]+)"
                                   + "(_[a-z_]+)?"
                           + "(wik(?:i"
                                 + "(?:books"
                                   + "|data"
                                   + "|media"
                                   + "|news"
                                   + "|quote"
                                   + "|source"
                                   + "|versity"
                                   + "|voyage)?"
                               + "|tionary)"
                           + "|mediawiki)$";
         this.re.wmfDB  =  new RegExp(this.re.wmfDB, "");
      }
      got  =  this.re.wmfDB.exec(around);
      if (got) {
         r[0]  =  got[1];
         if (got[3] !== "wiki") {
            r[1]  =  got[3];
         }
         if (r[0].length > 3) {
            switch (r[0]) {
               case "simple":
                  break;
               case "commons":
               case "foundation":
               case "incubator":
               case "mediawiki":
               case "meta":
               case "species":
               case "usability":
                  r[1]  =  r[0];
                  r[0]  =  "en";
                  break;
            }
         } else {
            if (typeof(got[2]) === "string") {
               if (got[2]) {   //   "bat_smgwiki"   "be_x_oldwiki"
                  r[0]  =  r[0] + "-" + got[2];
               }
            }
         }
      }
      // https://noc.wikimedia.org/conf/all.dblist
      return  r;
   };   // .g.fetchDB()



};   // .bb.gM()
mw.libs.WikiSyntaxTextMod.bb.gM(mw.libs.WikiSyntaxTextMod);
delete mw.libs.WikiSyntaxTextMod.bb.gM;



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



mw.libs.WikiSyntaxTextMod.bb.hooksM  =  function (WSTM) {
   // Hook functionality for registration
   // Uses:
   //    .util.fiatObjects()
   // 2012-06-27 PerfektesChaos@de.wikipedia
   "use strict";
   WSTM.util.fiatObjects(WSTM, "hooks");



   WSTM.hooks.finalize  =  function (apply) {
      // Register function for endrun, or execute
      // Precondition:
      //    apply  -- function for registration, or false for final run
      // Uses:
      //    >< .hooks.endrun[]
      // 2012-06-27 PerfektesChaos@de.wikipedia
      var i;
      if (apply) {
         if (this.endrun) {
            this.endrun.push(apply);
         } else {
            this.endrun  =  [ apply ];
         }
      } else if (WSTM.hooks.endrun) {
         for (i = 0;  i < this.endrun.length;  i++) {
            this.endrun[i]();
         }
      }   // for i
   };   // .hooks.finalize()



};   // .bb.hooksM()
mw.libs.WikiSyntaxTextMod.bb.hooksM(mw.libs.WikiSyntaxTextMod);
delete mw.libs.WikiSyntaxTextMod.bb.hooksM;



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



mw.libs.WikiSyntaxTextMod.bb.langM  =  function (WSTM) {
   // Invariant localization functions
   // Uses:
   //    .util.fiatObjects()
   // 2012-10-08 PerfektesChaos@de.wikipedia
   "use strict";
   WSTM.util.fiatObjects(WSTM,  "lang",
                         { proj:      { },
                           s:         { },
                           templates: { },
                           text:      { },
                           translate: { read:  [ "en" ],
                                        write: [ "en" ] }
                         } );



   WSTM.lang.find  =  function (adjust) {
      // Find less common language code and replace by major language
      // Precondition:
      //    adjust  -- language code, also ISO 639-2 and RFC 1766 subtag
      // Postcondition:
      //    Returns appropriate language code, ISO 639-1 downcased
      // Uses:
      //    >  .lang.trans
      //    .lang.fragment()
      // 2012-11-20 PerfektesChaos@de.wikipedia
      var r  =  this.fragment(adjust),
          s  =  this.trans[ r ];
      if (s) {
         r  =  s;
      }
      return  r;
   };   // .lang.find()



   WSTM.lang.fix  =  function (adjust) {
      // Fix frequently mistaken language code
      // Precondition:
      //    adjust  -- language code
      // Postcondition:
      //    Returns appropriate language code
      // Uses:
      //    >  .lang.correct
      // 2012-11-20 PerfektesChaos@de.wikipedia
      var r  =  adjust.toLowerCase(),
          s  =  this.correct[ r ];
      if (s) {
         r  =  s;
      }
      return  r;
   };   // .lang.fix()



   WSTM.lang.flop  =  function (adjust) {
      // Analyze whether prefix is not a wikiproject language code
      // Precondition:
      //    adjust    -- heading characters before ':' in a wikilink
      // Postcondition:
      //    Returns false   iff language in any wikiproject
      //            String  iff heading part of page name
      //    RegExp was used.
      // Uses:
      //    >  .w.link.langs
      //    >  .w.link.wiki.iwPrenatal
      //    >  .w.link.projects3
      //    >< .g.re.lang
      //    .str.trimL()
      //    .util.isO_639_1()
      // 2015-10-07 PerfektesChaos@de.wikipedia
      var s     =  WSTM.str.trimL(adjust, false),
          got,
          k,
          r;
      if (! WSTM.g.re.lang) {
         WSTM.g.re.lang  =  "^(" + WSTM.w.link.langs + ") *$";
         WSTM.g.re.lang  =  new RegExp(WSTM.g.re.lang, "i");
      }
      got  =  WSTM.g.re.lang.exec(s);
      if (got) {
         r    =  s;
         got  =  got[1];
         s    =  got.toLowerCase();
         k    =  got.length;
         if (k === 2) {
            if (s === "wp") {
               r  =  "WP";
            } else if (WSTM.util.isO_639_1(s)) {
               s  =  "|" + s + "|";
               if (WSTM.w.link.wiki.iwPrenatal.indexOf(s) < 0) {
                  r  =  false;
               }
            }
         } else if (k === 3) {
            if (s === "doi") {
               r  =  s;
            } else if (WSTM.w.link.projects3.indexOf(s) >= 0) {
               r  =  false;
            }
         } else if (s === "simple") {
            r  =  false;
   //    } else if (slang === "minnan") {
   //    } else if (slang === "tokipona") {
         } else if (k > 5) {
            k  =  s.indexOf("-");
            if (k === 2  ||  k === 3) {
               /*  |bat-smg|be-x-old|cbk-zam|fiu-vro|map-bms|nds-nl
                   |roa-rup|roa-tara|ru-sib
                   |zh-classical|zh-min-nan|zh-yue|  */
               if (/^[a-z][a-z][a-z]?-[a-z][a-z][-a-z]*/.test(got)) {
                  r  =  false;
               }
            }
         }
      } else {
         r  =  s;
      }   // matching lang?
      return r;
   };   // .lang.flop()



   WSTM.lang.forward  =  function () {
      // Is current project language written from left to right?
      // Uses:
      //    >  .g.projLang
      //    >  .lang.chr.rtl
      //    >< .lang.ltr
      // Postcondition:
      //    Returns  true for ltr project language,  false for rtl
      // 2015-10-28 PerfektesChaos@de.wikipedia
      var s;
      if (typeof(this.ltr) !== "boolean") {
         s         =  ":" + WSTM.g.projLang + ":";
         this.ltr  =  (WSTM.lang.chr.rtl.indexOf(s) < 0);
      }
      return this.ltr;
   };   // .lang.forward()



   WSTM.lang.fragment  =  function (adjust) {
      // Remove RFC 1766 subtag from language code
      // Precondition:
      //    adjust  -- language code (trimmed)
      // Postcondition:
      //    Returns downcased ISO 639 language code
      // Requires: JavaScript 1.3   charCodeAt()
      // 2011-12-25 PerfektesChaos@de.wikipedia
      var r  =  adjust.toLowerCase();
      if (r.length > 4) {
         if (r.charCodeAt(2) === 45) {   // '-'
            r  =  r.substr(0, 2);
         }
      }
      return  r;
   };   // .lang.fragment()



   WSTM.lang.text.fetch  =  function (access) {
      // Retrieve localized text string
      // Precondition:
      //    access  -- identifier
      // Postcondition:
      //    Returns  string with most appropriate message
      // Uses:
      //    >  .lang.text.trsl
      //    >< .g.wUserLang
      //    >< .g.userLang
      //    .g.fetch()
      //    .lang.find()
      // Remark: May be called by event handler -- 'this' is not used
      // 2012-07-31 PerfektesChaos@de.wikipedia
      var e  =  WSTM.lang.text.trsl[ access ],
          r  =  false;
      if (typeof(e) === "object") {
         if (typeof(WSTM.g.userLang) !== "string") {
            WSTM.g.fetch(WSTM.g.wUserLang, "wgUserLanguage");
            WSTM.g.userLang  =  WSTM.lang.find(WSTM.g.wUserLang);
         }
         r  =  e[ WSTM.g.userLang ];
         if (typeof(r) !== "string") {
            r  =  e.en;
         }
      } else {
         r  =  "***" + access + "***";
      }
      return r;
   };   // .lang.text.fetch()



   WSTM.lang.translate.factory  =  function () {
      // Define global project context
      // Precondition:
      //    project context is defined
      // Postcondition:
      //    translation variables defined
      // Uses:
      //    >  .g.projLang
      //    >  .g.wDBname
      //    >  .config.lang.accept
      //    >< .lang.translate.read
      //    .lang.translate.further()
      //    .lang.translate.flush()
      //    .lang.translate.finish()
      // 2012-11-10 PerfektesChaos@de.wikipedia
      var sep  =  "[ ,;/]+",
          got, i, n;
      this.further(WSTM.g.projLang, this.read, true);
      this.further(WSTM.g.wDBname, this.read, false);
      if (WSTM.config  &&  typeof(WSTM.config) === "object") {
         if (WSTM.config.lang  &&
             typeof(WSTM.config.lang) === "object") {
            if (typeof(WSTM.config.lang.accept) === "string") {
               got  =  WSTM.config.lang.accept.split(new RegExp(sep));
               n    =  got.length;
               for (i = 0;  i < n;  i++) {
                  this.further(got[i], this.read, false);
               }   // for i
            }
         }
      }
      this.flush(WSTM.g.projLang, WSTM.g.wDBname);
      this.finish(0);
   };   // .lang.translate.factory()



   WSTM.lang.translate.fair  =  function (accept, assign) {
      // Furnish an import action
      // Precondition:
      //    accept  -- space separated language list
      //    assign  -- make single import
      // Postcondition:
      //    import languages added.
      // Uses:
      //    >  .lang.translate.read
      //     < .lang.write
      //    .lang.translate.further()
      //    .lang.translate.finish()
      // 2014-10-10 PerfektesChaos@de.wikipedia
      this.further( accept, this.read, false );
      this.finish( -1 );
      if ( assign ) {
         WSTM.lang.write  =  { lead:     true,
                               linklang: false };
      }
   };   // .lang.translate.fair()



   WSTM.lang.translate.feed  =  function (adapt, access, adjust, apply, alone) {
      // Make option sequence from identifier
      // Precondition:
      //    adapt   -- string to be extended, "" or terminated with '|'
      //    access  -- string with element identifier
      //    adjust  -- string with canonical element value
      //    apply   -- string or Array of languages or projects
      //    alone   -- result neither beginning nor terminated with '|'
      // Postcondition:
      //    Return extended adapt string, terminated with '|'
      // Uses:
      //    >  .lang.translate.d
      //    .lang.translate.fiat()
      // 2012-09-09 PerfektesChaos@de.wikipedia
      var r  =  adapt + adjust + "|",
          q  =  this.d[access],
          x  =  (typeof(apply) === "string"  ?  [ apply ]  :  apply),
          n  =  x.length,
          i, j, m,
          e,
          s;
      if (q) {
         for (i = 0;  i < n;  i++) {
            e  =  q[ x[i] ];
            if (e) {
               if (typeof(e) === "object") {
                  m  =  e.length;
               } else {
                  e  =  [ e ];
                  m  =  1;
               }
               for (j = 0;  j < m;  j++) {
                  s  =  e[j];
                  if (s) {
                     s  =  this.fiat(s) + "|";
                     if (r.indexOf("|" + s)  <  0) {
                        r  =  r + s;
                     }
                  }
               }   // for j
            }
         }   // for i
      }
      if (alone) {
         r  =  r.substr(0,  r.length - 1).substr(1);
      }
      return  r;
   };   // .lang.translate.feed()



   WSTM.lang.translate.fetch  =  function (access) {
      // Retrieve canonical keyword in local language
      // Precondition:
      //    access  -- identifier     REDIRECT DEFAULTSORT DISPLAYTITLE
      // Postcondition:
      //    Returns keyword in major translation, case kept
      // Uses:
      //    >  .lang.translate.d
      //    >  .lang.translate.write
      //    .lang.translate.fiat()
      // 2012-09-27 PerfektesChaos@de.wikipedia
      var q  =  this.d[access],
          r  =  access,
          i,
          n,
          w;
      if (q) {
         n  =  this.write.length;
         for (i = 0;  i < n;  i++) {
            w  =  q[ this.write[i] ];
            if (w) {
               if (typeof(w) === "object") {
                  w  =  w[0];
               }
               switch (typeof(w)) {
                  case "object" :
                     w  =  this.fiat(w);
                     break;
                  case "boolean" :
                     w  =  access;
                     break;
               }   // switch typeof(w)
               r  =  w;
               break;   // for i
            }
         }   // for i
      }
      return  r;
   };   // .lang.translate.fetch()



   WSTM.lang.translate.fiat  =  function (access) {
      // Make element from .q entry
      // Precondition:
      //    access  -- string, false, or Array of charcodes
      // Postcondition:
      //    Return keyword string, or false
      // Uses:
      //    >  .lang.translate.reSpace
      // Requires: JavaScript 1.3   fromCharCode()
      // 2012-09-21 PerfektesChaos@de.wikipedia
      var r  =  access,
          i,
          n;
      if (typeof(access) === "object") {
         r  =  "";
         n  =  access.length;
         for (i = 0;  i < n;  i++) {
            r  =  r + String.fromCharCode(access[i]);
         }   // for i
      }
      if (r.indexOf(" ") > 0) {
         if (! this.reSpace) {
            this.reSpace  =  new RegExp(" ", "g");
         }
         r  =  r  +  "|"  +  r.replace(this.reSpace, "_");
      }
      return  r;
   };   // .lang.translate.fiat()



   WSTM.lang.translate.finish  =  function (apply) {
      // Finalize translation
      // Precondition:
      //    apply  -- 0: read/write,  -1: read,  1: write
      //    project context is defined and extended
      // Postcondition:
      //    translation variables defined
      // Uses:
      //    .w.link.namespace.factory()
      //    .w.img.factory()
      // 2012-09-14 PerfektesChaos@de.wikipedia
      WSTM.w.link.namespace.factory(apply, false);
      WSTM.w.img.factory(apply);
   };   // .lang.translate.finish()



   WSTM.lang.translate.flush  =  function (able, around) {
      // Define write translation
      // Precondition:
      //    able    -- language
      //    around  -- project (DBname)
      // Postcondition:
      //    project context writing defined
      // Uses:
      //    >  .lang.chr.cjk
      //     < .lang.translate.write
      //     < .w.chr.lang.cjk
      //    .lang.translate.further()
      //    .w.img.factory()
      // 2012-09-07 PerfektesChaos@de.wikipedia
      var i, n;
      this.write  =  [ "en" ];
      this.further(able, this.write, true);
      this.write.unshift(around.toLowerCase());
      n  =  this.write.length;
      for (i = 0;  i < n;  i++) {
         if (WSTM.lang.chr.cjk.indexOf( ":"+this.write[i]+":" )  >=  0) {
            WSTM.w.chr.lang.cjk  =  true;
            break;
         }
      }   // for i
   };   // .lang.translate.flush()



   WSTM.lang.translate.further  =  function (add, assign, ahead) {
      // Add language (even 2nd level) to Array
      // Precondition:
      //    add     -- string of single language
      //    assign  -- Array of languages
      //    ahead   -- true: put in front
      // Postcondition:
      //    assign is modified, if add not yet element
      // Uses:
      //    .util.isElement()
      // Requires: JavaScript 1.3   charCodeAt()
      // 2012-09-01 PerfektesChaos@de.wikipedia
      var s   =  add.toLowerCase(),
          s2;
      if (s.length > 4) {
         if (s.charCodeAt(2) === 45) {   // '-'
            s2  =  s.substr(0, 2);
            if (!  WSTM.util.isElement(assign, s2)) {
               if (ahead) {
                  assign.unshift(s2);
               } else {
                  assign.push(s2);
               }
            }
         }
      }
      if (!  WSTM.util.isElement(assign, s)) {
         if (ahead) {
            assign.unshift(s);
         } else {
            assign.push(s);
         }
      }
   };   // .lang.translate.further()



};   // .bb.langM()
mw.libs.WikiSyntaxTextMod.bb.langM(mw.libs.WikiSyntaxTextMod);
delete mw.libs.WikiSyntaxTextMod.bb.langM;



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



mw.libs.WikiSyntaxTextMod.bb.mainM  =  function (WSTM) {
   // Top level functions (internal)
   // 2012-05-26 PerfektesChaos@de.wikipedia
   "use strict";
   WSTM.main.maxMsg  =  5;



   WSTM.main.fault  =  function (alert, about) {
      // Submit error message caused by user input
      // Precondition:
      //    alert  -- error message
      //    about  -- user context, or false to suppress
      // Uses:
      //    >  window
      //    >< .main.maxMsg
      //    .lang.text.fetch()
      // 2012-05-26 PerfektesChaos@de.wikipedia
      var s;
      if (window) {
         s  =  (about  ?  " " + about  :  "");
         if (typeof(window.console) === "object") {
            window.console.info("PerfektesChaos::WikiSyntaxTextMod" + s
                                + "\n" + alert);
         }
         if (WSTM.main.maxMsg) {
            s  =  window.confirm(WSTM.lang.text.fetch("ERROR") + ":\r\n"
                                 + alert + "\r\n"
                                 + "PerfektesChaos/js/WikiSyntaxTextMod"
                                 + s);
            if (s) {
               WSTM.main.maxMsg--;
            } else {
               WSTM.main.maxMsg  =  0;
            }
         }
      }
   };   // .main.fault()



   WSTM.main.full  =  function () {
      // Execute syntax and user defined replacement related to HTML page
      // Precondition:
      //    Wikiserver environment for editpage with "editform"
      //    prefs ready
      // Postcondition:
      //    wpTextbox1 value of "editform" is modified, if appropriate.
      //    If modified, DiffView is to be displayed to the user
      //               (if not suppressed by WikisyntaxTextMod_DiffPage).
      // Uses:
      //    >  .ia.$editform
      //    >  .errors.story
      //    >  .debugging.live
      //    .prefs.fetch()
      //    .main.textarea()
      //    .api.edit()
      //    .errors.finalize()
      //    "editform"
      //        < .wpSummary
      //       >  .wpDiff
      // Remark: Used as event handler -- 'this' is not WSTM.main
      // 2015-03-09 PerfektesChaos@de.wikipedia
      var stuff    =  WSTM.main.textarea(false, false),
          button,
          perform,
          s,
          task,
          $field;
      if (typeof(WSTM.prefs.fetch) === "function") {
         WSTM.prefs.fetch();
      }
      if (typeof(stuff) === "string") {
         task    =  { wikitext: stuff,
                      summary:  false };
         $field  =  WSTM.ia.$editform.find("#wpSummary");
         if ($field.length) {
            if (WSTM.ia.$editform.find("#wpMinoredit").length) {
               task.summary  =  $field.val();
            } else {
               $field  =  false;   // newsection
            }
         } else {
            $field  =  false;
         }
         perform  =  WSTM.api.edit(task);
         if (perform) {
            s  =  perform.wikitext;
            WSTM.errors.finalize( ! perform.diffpage,  perform.lapsus );
            if (WSTM.errors.story) {
               s  =  WSTM.errors.story + s;
            }
            if (perform.diffpage) {
               if (typeof(WSTM.debugging) === "object") {
                  if (typeof(WSTM.debugging.live) === "boolean") {
                     perform.diffpage  =  ! WSTM.debugging.live;
                     if (WSTM.debugging.live) {
                        mw.log(WSTM.debugging,
                               ".main.full() diffpage",
                               1);
                     }
                  }
               }
            }
            WSTM.main.textarea(s, perform.diffpage);
            if (perform.summary && $field) {
               $field.val(perform.summary);
            }
            if (perform.diffpage) {
               /*
               var $button  =  WSTM.ia.$editform.find("#wpDiff");
               if ($button.length) {
                  window.onbeforeunload  =  null;   // stop editwarner
                  $button.click();
               }
               */
               // DOM, not hooked by editwarner:
               button  =  window.document.getElementById("wpDiff");
               if (button !== null) {
                  button.click();
               }
            }   // human stupidity vs. artificial intelligence
         }   // any change
      }   // Textarea
   };   // .main.full()



};   // .bb.mainM()
mw.libs.WikiSyntaxTextMod.bb.mainM(mw.libs.WikiSyntaxTextMod);
delete mw.libs.WikiSyntaxTextMod.bb.mainM;



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



mw.libs.WikiSyntaxTextMod.bb.mod  =  function (WSTM) {
   // User modification and warning request
   // 2016-01-30 PerfektesChaos@de.wikipedia
   // Uses:
   //    >< .mod.*
   //     < .warn
   "use strict";
   if (typeof(WSTM.mod) !== "object") {
      WSTM.mod   =  { "*":
                      { comment:  false,  // <!--  -->
                        file:     false,  // [[file:]] or gallery or .ext
                        lazy:     true,   // no visible change
                        lenient:  false,  // config.mod.tested
                        lock:     false,  // text replacement expected
                        luxury:   false,  // any no-comment replacement
                        plain:    false,  // any text outside protected
                        table:    false,  // table re-formatting
                        tag:      false,  // tag context
                        text:     false,  // no <poem> nor tag nor quote
                        template: false,  // {{any or [[template:any]]
                        url:      false,  // //x.y
                        wiki:     false   // [[any]]
                      }
                    };
   }



   WSTM.mod.furnish  =  function () {
      // (Re-)initialize user modification and warning request
      // Uses:
      //    >  .config.mod.*
      //    >  .config.warn.*
      //    >< .mod.*
      //    >< .warn.*
      //     < .mod.luxury
      //     < .mod.lock
      //    .util.isArray()
      //    .w.link.replace.factory()
      //    .w.template.mod.factory()
      //    .warn.furnish()
      // 2016-01-30 PerfektesChaos@de.wikipedia
      var base  =  this["*"],
          cnf, p;
      for (p in base) {
         this[p]  =  base[p];
      }   // for p in WSTM.mod.*
      if (typeof(WSTM.config) === "object"  &&  WSTM.config) {
         cnf  =  WSTM.config;
         if (typeof(cnf.mod) === "object"  &&  cnf.mod) {
            if (typeof(cnf.mod.tested) === "boolean") {
               this.lenient  =  cnf.mod.tested;
            }
            if (typeof(cnf.mod.plain) === "object"  &&
                WSTM.util.isArray(cnf.mod.plain)) {
               this.plain  =  { name: ".config.mod.plain",
                                raw:  cnf.mod.plain };
            }
            if (typeof(cnf.mod.url) === "object"  &&
                WSTM.util.isArray(cnf.mod.url)) {
               p         =  { name: ".config.mod.url",
                              raw:  cnf.mod.url };
               this.url  =  WSTM.w.link.replace.factory(p);
            }
            if (typeof(cnf.mod.wikilink) === "object"  &&
                WSTM.util.isArray(cnf.mod.wikilink)) {
               p              =  { name: ".config.mod.wikilink",
                                   raw:  cnf.mod.wikilink };
               this.wikilink  =  WSTM.w.link.replace.factory(p);
            }
            if (typeof(cnf.mod.comment) === "object"  &&
                WSTM.util.isArray(cnf.mod.comment)) {
               this.comment  =  { name: ".config.mod.comment",
                                  raw:  cnf.mod.comment };
            }
            if (typeof(cnf.mod.template) === "object"
                &&     cnf.mod.template) {
               this.template  =
                           WSTM.w.template.mod.factory(cnf.mod.template);
            }
            if (typeof(cnf.mod.table) !== "undefined"
                &&     cnf.mod.table) {
               this.table  =  true;
            }
         }
         if (cnf.warn  &&  typeof(cnf.warn) === "object") {
            WSTM.warn.furnish();
         }
      }
      this.luxury  =  (this.plain || this.template);
      this.lock    =  this.luxury;
   };   // .mod.furnish()



};   // .bb.mod()
mw.libs.WikiSyntaxTextMod.bb.mod(mw.libs.WikiSyntaxTextMod);
delete mw.libs.WikiSyntaxTextMod.bb.mod;



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



mw.libs.WikiSyntaxTextMod.bb.prefsM  =  function (WSTM) {
   // Preferences (interactive on Special:Gadgets etc.)
   // 2013-09-27 PerfektesChaos@de.wikipedia
   "use strict";
   WSTM.util.fiatObjects(WSTM,  "prefs",  { });



   WSTM.prefs.form  =  function () {
      // Equip Special:Gadgets page with entry and form
      // Uses:
      //    >  .prefs.supply
      //    >  .g.wUserLang
      //    >  .type
      //    >  .config.diffPage
      //    >  .config.portlet
      //    >< .prefs.launched
      //    .g.fetch()
      //    .lang.find()
      //    .lang.text.fetch()
      //    mw.libs.preferencesGadgetOptions.form()
      // 2016-10-09 PerfektesChaos@de.wikipedia
      var dialog, slang, texts;
      if ( mw.libs[ WSTM.prefs.supply ]
           &&   typeof(mw.libs[ WSTM.prefs.supply ])  ===  "object"
           &&   ! WSTM.prefs.launched
           &&   mw.libs[ WSTM.prefs.supply ].form
           &&   mw.libs[ WSTM.prefs.supply ].form() ) {
         WSTM.prefs.launched  =  true;
         WSTM.g.fetch(WSTM.g.wUserLang, "wgUserLanguage");
         slang  =  WSTM.lang.find(WSTM.g.wUserLang);
         texts  =  WSTM.lang.text;
         switch ( slang ) {
            case "als" :
            case "bar" :
            case "dsb" :
            case "frr" :
            case "gsw" :
            case "hsb" :
            case "ksh" :
            case "lb" :
            case "nds" :
            case "pdc" :
            case "pdt" :
            case "pfl" :
            case "sli" :
            case "stq" :
            case "vmf" :
               slang  =  "de";
               break;
            case "de" :
               break;
            default:
               slang  =  "en";
         }   // switch
         dialog  =  {
                  script:  WSTM.type,
                  support: "//" + slang + ".wikipedia.org/wiki/"
                           + "User:PerfektesChaos/js/"
                           + WSTM.type,
                  suffix:  texts.fetch("_PrefsDescription"),
                  opts:    [ { signature: "diffPage",
                               type:      "checkbox",
                               show:      texts.fetch("_Prefs.diffPage"),
                               val:       WSTM.config.diffPage
                             },
                             { signature: "portlet",
                               type:      "checkbox",
                               show:      texts.fetch("_Prefs.portlet"),
                               val:       WSTM.config.portlet
                             }
                           ]
         };
         mw.libs[ WSTM.prefs.supply ].form( dialog );
      }
   };   // .prefs.form()



};   // .bb.prefsM()
mw.libs.WikiSyntaxTextMod.bb.prefsM(mw.libs.WikiSyntaxTextMod);
delete mw.libs.WikiSyntaxTextMod.bb.prefsM;




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



mw.libs.WikiSyntaxTextMod.bb.warn  =  function (WSTM) {
   // User modification and warning request
   // Uses:
   //    >< .warn.*
   // 2013-04-04 PerfektesChaos@de.wikipedia
   "use strict";
   if (typeof(WSTM.warn) !== "object") {
      WSTM.warn  =  {};
   }



   WSTM.warn.failed  =  function () {
      // Returns true iff any warning detected
      // Postcondition:
      // Uses:
      //    >  .warn.detected
      // 2013-04-04 PerfektesChaos@de.wikipedia
      return (this.detected ? true : false);
   };   // .warn.failed()



   WSTM.warn.fetch  =  function () {
      // Returns HTML code for detected issues
      // Postcondition:
      // Uses:
      //    >  .warn.detected
      //    .lang.text.fetch()
      // 2013-06-14 PerfektesChaos@de.wikipedia
      var r  =  "",
          e, got, i, n, scope;
      if (this.detected) {
         r  =  WSTM.lang.text.fetch("_WarnUserDefined") + "\n<ul>";
         for (scope in this.detected) {
            got  =  this.detected[scope];
            n    =  got.length;
            r    =  r + "\n<ul>";
            for (i = 0;  i < n;  i++) {
               e  =  got[i];
               if (e[1] === 1) {
                  e  =  e[0];
               } else {
                  e  =  "<i>" + e[1] + "&times;</i> &nbsp; " + e[0];
               }
               r  =  r + "<li>" + e + "</li>";
            }   // for i
            r  =  r + "\n</ul>";
         }   // for scope in .detected
         r  =  r + "\n</ul>\n";
      }
      return r;
   };   // .warn.fetch()



   WSTM.warn.fill  =  function (access, assembly) {
      // Initialize user warning request
      // Precondition:
      //    access    -- component
      //    assembly  -- "RegExp" (change every item), "string", "object"
      // Uses:
      //    >  .config.warn.*
      //    >< .warn.*
      //    .util.isArray()
      //    .errors.found()
      //    .util.regexp.fiat()
      // Requires: JavaScript 1.3   charCodeAt()
      // 2014-12-19 PerfektesChaos@de.wikipedia
      var s  =  typeof(WSTM.config.warn[access]),
          cnf, e, i, n, re, t, tmp;
      if (s === "undefined") {
         this[access]  =  false;
      } else {
         cnf  =  WSTM.config.warn[access];
         switch (s) {
            case "object" :
               if (WSTM.util.isArray(cnf)) {
                  tmp  =  [ ];
                  n    =  cnf.length;
                  re   =  false;
                  for (i = 0;  i < n;  i++) {
                     e  =  cnf[i];
                     t  =  (e ? typeof(e) : "-");
                     if (t === "string" || t === assembly) {
                        tmp.push(cnf[i]);
                     } else {
                        WSTM.errors.found("Invalid",
                                          false,
                                          ".config.warn." + access
                                          + "[" + i + "]");
                        re  =  true;
                     }
                  }   // for i
                  if (re) {
                     tmp  =  false;
                  }
               } else {
                  WSTM.errors.found("Invalid",
                                    false,
                                    "Array .config.warn." + access);
               }
               break;
            case "string" :
               this[access]  =  [ cnf ];
               break;
            default:
               tmp  =  false;
               WSTM.errors.found("Invalid",
                                 false,
                                 ".config.warn." + access);
         }   // switch typeof(cnf)
         if (tmp) {
            this[access]  =  [ ];
            n             =  tmp.length;
            for (i = 0;  i < n;  i++) {
               re  =  tmp[i];
               if (re  &&  assembly === "RegExp") {
                  if (re.charCodeAt(0) !== 94) {   // '^'
                     re  =  "^.*" + re;
                  }
                  if (re.charCodeAt(re.length - 1)  !==  36) {   // '$'
                     re  =  re + ".*$";
                  }
                  re  =  WSTM.util.regexp.fiat(re,
                                               false,
                                               ".config.warn." + access
                                               + "[" + i + "]");
               }
               if (re) {
                  this[access].push(re);
               }
            }   // for i
            if (! this[access].length) {
               delete this[access];
               this[access]  =  false;
            }
         } else {
            this[access]  =  false;
         }
      }
   };   // .warn.fill()



   WSTM.warn.filter  =  function (approve, against) {
      // Process suspicious string
      // Precondition:
      //    approve  -- suspicious string
      //    against  -- code of filter type
      // Uses:
      //    >  .warn.*
      //    .str.escapeLight()
      // .warn.found()
      // 2013-06-14 PerfektesChaos@de.wikipedia
      var res  =  this[against],
          got, i, n;
      if (res) {
         n  =  res.length;
         for (i = 0;  i < n;  i++) {
            got  =  res[i].exec(approve);
            if (got) {
               this.found(against, WSTM.str.escapeLight(got[0]));
               break;   // for i
            }
         }   // for i
      }
   };   // .warn.filter()



   WSTM.warn.found  =  function (against, apply) {
      // Store a detected warning
      // Precondition:
      //    against  -- code of filter type
      //    apply    -- details (HTML-escaped)
      // Postcondition:
      //    Stored
      // Uses:
      //    >< .warn.detected
      // 2013-06-14 PerfektesChaos@de.wikipedia
      var e, g, i, n;
      if (! this.detected) {
         this.detected  =  {};
      }
      if (! this.detected[against]) {
         this.detected[against]  =  [];
      }
      g  =  this.detected[against];
      n  =  g.length;
      for (i = 0;  i < n;  i++) {
         e = g[i];
         if (e[0] === apply) {
            e[1]++;
            g  =  false;
            break;   // for i
         }
      }   // for i
      if (g) {
         g.push( [ apply, 1 ] );
      }
   };   // .warn.found()



   WSTM.warn.furnish  =  function () {
      // Initialize user warning request
      // Uses:
      //    >  .config.warn.*
      //    >< .warn.*
      //    .warn.fill()
      // 2015-11-05 PerfektesChaos@de.wikipedia
      var cnf  =  WSTM.config;
      if (cnf  &&  typeof(cnf) === "object"  &&
          cnf.warn  &&  typeof(cnf.warn) === "object") {
         this.fill("attribute",    "object");
         this.fill("char",         "number");
         this.fill("comment",      "string");
         this.fill("entity",       "string");
         this.fill("parserfun",    "string");
         this.fill("plain",        "RegExp");
         this.fill("property",     "string");
         this.fill("tag",          "string");
         this.fill("template",     "string");
         this.fill("transclusion", "string");
         this.fill("url",          "RegExp");
         this.fill("variable",     "string");
         this.fill("wikilink");
         if (typeof(cnf.warn.templateParamDup) === "boolean") {
            this.templateParamDup  =  cnf.warn.templateParamDup;
         }
      }
   };   // .warn.furnish()



};   // .bb.warn()
mw.libs.WikiSyntaxTextMod.bb.warn(mw.libs.WikiSyntaxTextMod);
delete mw.libs.WikiSyntaxTextMod.bb.warn;



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



( function ( WSTM ) {
   "use strict";
   var sub      =  "M",
       self     =  WSTM.main.self,
       version  =  WSTM.main.vsn,
       rls;
   if ( ! WSTM.main.bb) {
      WSTM.main.bb  =  { };
   }
   WSTM.main.bb[ sub ]  =  { load: true,
                             vsn:  version };
   if ( typeof WSTM.main.wait  ===  "function" ) {
      // Start on import: callback to waiting ...
      WSTM.main.wait( sub, version );
   }
   if ( typeof mw.loader  ===  "object"   &&
        typeof mw.hook  !==  "undefined" ) {
      rls = { };
      rls[ self ] = "ready";
      mw.loader.state( rls );
      mw.hook( "WikiSyntaxTextMod/" + sub + ".ready" )
        .fire( [ sub, version ] );
   }
} ( mw.libs.WikiSyntaxTextMod ) );



// Emacs
// Local Variables:
// coding: iso-8859-1-dos
// fill-column: 80
// End:

/// EOF </nowiki>   WikiSyntaxTextMod/dM.js