User:PerfektesChaos/js/WikiSyntaxTextMod/dO.js

/// PerfektesChaos/js/WikiSyntaxTextMod/dO.js // Objects for wiki syntax specific code /// 2019-08-01 PerfektesChaos@de.wikipedia /// Fingerprint: #0#0# /// @license: CC-by-sa/4.0 GPLv3 /// /* global mw:true, mediaWiki:false                                    */ /* jshint forin:false, nocomma:false, bitwise:true, curly:true, eqeqeq:true, latedef:true, laxbreak:true, strict:true, undef:true, unused:true                        */

if ( typeof mediaWiki !==  "object" ) {   // disconnected mw =  { libs:   { WikiSyntaxTextMod:  { } },           log:    function  {"use strict";} }; } ( function ( mw ) {  "use strict";   var version  =  -7.21,       sign     =  "WikiSyntaxTextMod",       sub      =  "O",       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.o  !==  "object" ) {      WSTM.o  =  { };   }   WSTM.o.vsn   =  version;   WSTM.o.self  =  self;   if ( typeof WSTM.bb  !==  "object" ) {      WSTM.bb  =  { };   }   if ( typeof WSTM.debugging  !==  "object" ) {      WSTM.debugging  =  { };   } } ( mw ) );

// Provides: //   .o.URL2wiki //   .o.Weblink //   .o.Wikilink //   .o.WikiTom /* Requires: JavaScript 1.3 (String.charCodeAt String.fromCharCode String.replace) */

//---

mw.libs.WikiSyntaxTextMod.bb.URL2wiki =  function (WSTM) { // Administration of wikilinks // 2013-03-15 PerfektesChaos@de.wikipedia // Class: //   Public: //      set //   Private: //      init // .law     true: https mandatory // .index   number: position of "://" in .source // .multiple number: of leading brackets '[' (0, 1, 2) // .newFrom number: of chars in .source for replacement region start // .newTo   number: of chars in .source for replacement region end // .scheme  URL protocol, may be false or terminated by ':' // .shift   replacement string (total)       , beginning at .newFrom // .show    non-empty title string // .sister  wikilink sister project // .site    domain (including port) // .slashed path etc.   // .source   wikitext // .start   wikilink prefix string terminated with ':', or false // .storage target of wikilink // .story   title of wikilink, or false // .suite   string: URL   false: wikilink // .suffix  aftermath, after "]" "use strict"; var U2W;

WSTM.o.URL2wiki =  function  { // .constructor for new // Postcondition: //   Returns .o.URL2wiki object // Uses: //   >  .o.URL2wiki:: //   .o.Wikilink.init // 2013-03-15 PerfektesChaos@de.wikipedia var p;     this.init; for (p in WSTM.o.URL2wiki) { this[ p ] =  WSTM.o.URL2wiki[ p ]; }  // for p in      return this; };  // .o.URL2wiki .constructor U2W =  WSTM.o.URL2wiki;

U2W.prototype.init =  function  { // Initialize existing URL2wiki object // Postcondition: //   .o.URL2wiki object has been reset // Uses: //   >  .o.URL2wiki:: //      >  .***      // 2013-03-15 PerfektesChaos@de.wikipedia this.index    =  -1; this.mode     =  0; this.multiple =  -1; this.newFrom  =  false; this.newTo    =  false; this.scheme   =  false; this.shift    =  false; this.show     =  false; this.sister   =  false; this.site     =  false; this.slashed  =  false; this.source   =  false; this.start    =  false; this.storage  =  false; this.story    =  false; this.suite    =  false; this.suffix   =  false; };  // .o.URL2wiki.init

U2W.prototype.fetch =  function  { // Retrieve URL segments from wikitext // Uses: //   >  .o.URL2wiki:: //      >  .source //      >  .index //      >< .move //       < .multiple //       < .newFrom //       < .site //       < .slashed //   .w.link.web.fetch // 2013-03-15 PerfektesChaos@de.wikipedia var i, s;     this.multiple  =  0; WSTM.w.link.web.fetch(this, true);  // cave! s =  this.source.substr(this.index + this.move); i =  s.indexOf(" "); if (i > 0) { s         =  s.substr(0, i); this.move =  i + 1; } else { this.move =  s.length; }     i  =  s.indexOf("/"); if (i > 0) { this.site =  s.substr(0, i); if (i < s.length - 1) { this.slashed =  s.substr(i); }     } else { this.site =  s;      } };  // .o.URL2wiki.fetch

U2W.prototype.finish =  function  { // Modify source string if URL improved // Postcondition: //   .o.URL2wiki object has been reset // Uses: //   >  .o.URL2wiki:: //      >  .source //       < .shift // 2013-03-15 PerfektesChaos@de.wikipedia };  // .o.URL2wiki.finish

U2W.prototype.fire =  function  { // Perform analysis // Postcondition: //   .o.URL2wiki object has been evaluated // Uses: //   >  .o.URL2wiki:: //      >  .scheme //      >  .site //      >  .slashed //      >  .show //       < .mode //       < .sister //       < .storage //       < .story //   .w.link.wiki.url // 2013-03-15 PerfektesChaos@de.wikipedia var i, g, s;     switch (this.scheme) { case "http:" : s =  "http://"; i =  7; break; case "https:" : s =  "https://"; i =  8; break; default: s =  "//"; i =  2; }  // switch .scheme s =  s + this.site; g =  WSTM.w.link.wiki.url(i, s, this.slashed, this.show); switch (typeof(g)) { case "string" :  // reformatted URL (later: object parts) this.mode  =  1; this.shift =  g;            break; case "object" :  // wikilink this.mode =  2; if (g[0]) { this.sister =  g[0]; }           this.storage  =  g[1]; this.story   =  g[2]; s            =  (this.sister  ?  this.sister + this.storage                                           :  this.storage); if (this.show || this.story) { this.story =  (this.show ? this.show : this.story); if (! this.sister &&  this.story === s) { this.story =  false; }           }            break; }  // switch typeof .url };  // .o.URL2wiki.fire

U2W.prototype.getMode =  function  { // Return state (1: URL refinement; 2: wikilink) false: unchanged // Uses: //   >  .o.URL2wiki:: //      >  .mode // 2013-03-15 PerfektesChaos@de.wikipedia return this.mode; };  // .o.URL2wiki.getMode

U2W.prototype.getRemoveFrom =  function  { // Return number of target chars since which to remove, or false // Uses: //   >  .o.URL2wiki:: //      >  .newFrom // 2013-03-15 PerfektesChaos@de.wikipedia return this.newFrom; };  // .o.URL2wiki.getRemoveFrom

U2W.prototype.getRemoveTo =  function  { // Return number of target chars to be removed, or false // Uses: //   >  .o.URL2wiki:: //      >  .newTo // 2013-03-15 PerfektesChaos@de.wikipedia return this.newTo; };  // .o.URL2wiki.getRemoveTo

U2W.prototype.getSuffix =  function  { // Return suffix to be integrated, or false // Uses: //   >  .o.URL2wiki:: //      >  .story //      >  .suffix //   .w.link.wiki.fore // 2013-03-15 PerfektesChaos@de.wikipedia var r =  false; if (this.mode === 2) {  // wikilink if (this.story && this.suffix) { r =  WSTM.w.link.wiki.fore(this.suffix, 0); if (r) { r =  this.suffix.substr(0, r); }        }      }      return r;   };   // .o.URL2wiki.getSuffix

U2W.prototype.getTarget =  function  { // Returns wikilink target, or URL // Uses: //   >  .o.URL2wiki:: //      >  .mode //      >  .sister //      >  .storage //   .getURL // 2013-03-15 PerfektesChaos@de.wikipedia var r;     if (this.mode === 2) {   // wikilink if (this.sister) { r =  this.sister + this.storage; } else { r =  this.storage; }     } else {   // reformatted URL r =  this.getURL; }     return r;   };   // .o.URL2wiki.getTarget

U2W.prototype.getTextReplace =  function  { // Returns replacement string, maybe false if nothing to do     // Uses: //   >  .o.URL2wiki:: //      >  .mode //      >  .shift //      >  .sister //      >  .storage //      >  .story //      >  .multiple //      .getTarget // 2013-03-15 PerfektesChaos@de.wikipedia var r;     switch (this.mode) { case 1 :  // reformatted URL r =  this.shift; break; case 2 :  // wikilink r =  this.getTarget; if (this.story) { r =  r + "|" + this.story; }           r  =  "[" + r + "]"; if (! this.multiple) { r =  "[" + r + "]"; }           break; default : r =  false; }  // switch .mode return r;  };   // .o.URL2wiki.getTextReplace

U2W.prototype.getTitle =  function  { // Returns link title, maybe "" if not necessary // Uses: //   >  .o.URL2wiki:: //      >  .story // 2013-03-15 PerfektesChaos@de.wikipedia return (this.story ? this.story : ""); };  // .o.URL2wiki.getTitle

U2W.prototype.getURL =  function  { // Returns URL, maybe reformatted // Uses: //   >  .o.URL2wiki:: //      >  .law //      >  .scheme //      >  .site //      >  .slashed // 2013-03-15 PerfektesChaos@de.wikipedia var r;     if (this.law) { r =  "https://"; } else { r =  (this.scheme  ?  this.scheme + "//"  :  "//"); }     r  =  r + this.site + "/" + (this.slashed ? this.slashed : ""); return r;  };   // .o.URL2wiki.getURL

U2W.prototype.set =  function (assign, access) { // Initialize existing weblink object // Precondition: //   assign  -- Weblink object, or string with URL //              object:    >  .scheme //                         >  .site //                         >  .slashed //                         >  .show //                         >  .suffix //   access  -- position of "://" in assign string // Postcondition: //   .o.URL2wiki object has been evaluated // Uses: //   >  .o.URL2wiki:: //       < .index //       < .source //       < .multiple //       < .scheme //       < .site //       < .slashed //       < .show //       < .suffix //      .init //      .fetch //      .fire //      .finish //   .str.substrEnd // 2013-03-15 PerfektesChaos@de.wikipedia this.init; switch (typeof(assign)) { case "string" :  // string with URL this.index  =  access; this.source =  assign; this.fetch; break; case "object" :  // Weblink this.multiple =  assign.multiple; this.scheme   =  assign.scheme; this.site     =  assign.site; this.slashed  =  assign.slashed; this.show     =  assign.show; this.suffix   =  assign.suffix; break; }  // switch .scheme if (this.site) { if (! this.scheme ||  this.scheme === "http:"                            ||  this.scheme === "https:") { if (WSTM.str.substrEnd(this.site, 4) ===  ".org") { this.fire; if (this.source) { this.finish; }           }         }      }   };   // .o.URL2wiki.set

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

//---

mw.libs.WikiSyntaxTextMod.bb.Weblink =  function (WSTM) { // Administration of weblinks // 2015-12-25 PerfektesChaos@de.wikipedia // Class: //   Public: //      set //      getIncrement //   Private: //      fault //      fenced //      fiat //      filled //      filter //      fire //      first //      fix //      flat //      friend //      fruit //      further //      format //      init // .lazy      false: any modification happened // .limited   true: enclosed in brackets (leading bracket '[') // .lackScheme true: relative URL protocol was set to https // .lowScheme true: URL protocol has been downcased // .leaf      true: template parameter; terminate suffix by '|' // .index     number: position of URL begin in .source // .join      number: start of interesting region in .node // .keep      number: length of URL // .maxTitle  number: limiting length for suspicious titles // .maxURL    number: limiting URL length // .mode      number: WikiTom mode // .move      number: string incrementation // .met       number: end of prolog // .moving    number: node incrementation on global search // .multiple  number: of leading brackets '['  (0, 1, 2) // .node      number: of current within .off // .off       parent WikiTom node // .points    Array of Arrays with found and replacement information // .scheme    URL protocol, may be false or terminated by ':' // .shift     replacement string for link target // .shower    non-empty title string (continued in fuerher node) // .source    wikitext including prolog // .url2w     URL2wiki object "use strict"; var WebLK;

WSTM.o.Weblink =  function (available, allow) { // .constructor for new // Precondition: //   available  -- limiting URL length, or false //   allow      -- limiting length for suspicious titles, or false // Postcondition: //   Returns .o.Weblink object // Uses: //   >  .o.Weblink:: //      >  .joinSuffix //      >< .re.schemes //       < .maxURL //       < .maxTitle //       < .points //   >  .w.link.protocol.weblinks // 2013-03-15 PerfektesChaos@de.wikipedia var p;     for (p in WSTM.o.Weblink) { this[ p ] =  WSTM.o.Weblink[ p ]; }  // for p in      if (! WebLK.re.schemes) { WebLK.re.schemes =  WSTM.w.link.protocol.weblinks; }     if (typeof(available) === "number") { this.maxURL =  available; }     if (typeof(allow) === "number") { this.maxTitle =  allow; }     this.points   =  new Array(WebLK.joinSuffix + 1); return this; };  // .o.Weblink .constructor WebLK =  WSTM.o.Weblink;

// Definition of constants // 2016-01-01 PerfektesChaos@de.wikipedia WebLK.joinProlog =  0; WebLK.joinLBrack =  1; WebLK.joinScheme =  2; WebLK.joinSite   =  3; WebLK.joinSlash  =  4; WebLK.joinSelect =  5; WebLK.joinShow   =  6; WebLK.joinRBrack =  7; WebLK.joinSuffix =  8; WebLK.maxTitle   =  300; WebLK.maxURL     =  511; WebLK.re         =  { schemes: "|ftp|git|http|https|mms|svn|", split:  new RegExp("[\"{}]"),                          stop:    "({,:.;?!\"\\"                        };

/*  WebLK.prototype.fruit  =  function (about) { // Debug info // Precondition: //   about  -- informative key, or nothing. // Debug // 2013-03-15 PerfektesChaos@de.wikipedia var e, i,   o  =  { }, s =  "|joinLBrack|joinProlog|joinRBrack|joinScheme|joinSelect|" + "joinShow|joinSite|joinSlash|joinSuffix|" + "lowScheme|maxTitle|maxURL|off|points|" + "re|source|url2w|"; for (e in this) { if (typeof(this[e]) !== "function") { if (s.indexOf("|"+e+"|") < 0) { o[e] =  this[e]; }  } }   // for e in this s =  (about  ?  " " + about  :  "" )   +   "  points"; for (i = 0; i <= WebLK.joinSuffix;  i++) { e =  this.points[ i ]; s =  s + "\n" + e[0] + "    >>"; if (typeof(e[1]) === "string") { s =  s + e[1].substr(0,350); } else { s =  s + e[1]; }  s  =  s + "<<    " + e[2]; }  // for i mw.log(WSTM.debugging,".o.Weblink.fruit"+s,0,o); };  // .o.Weblink.fruit

WebLK.prototype.facet =  function (about, adjacent) { // Retrieve string from range // Precondition: //   about      -- level to begin //                 .joinSite //                 .joinSlash //                 .joinShow //                 .joinRBrack //   adjacent   -- optional: number of last level to include // Postcondition: //   Returns string including range // Uses: //   >  .o.Weblink:: //      >  .points //      >  .joinSite //      >  .joinSlash //      >  .joinShow // 2013-03-15 PerfektesChaos@de.wikipedia var e, i,         k  =  (typeof(adjacent) === "number"  ?  adjacent  :  about), r =  ""; for (i = about; i <= k;  i++) { e =  this.points[ i ][1]; switch (i) { case WebLK.joinSite : if (i > about) { r =  r + "//"; }              break; case WebLK.joinSlash : e =  "/"; break; case WebLK.joinShow : if (i > about) { e =  " " + e;               } break; }  // switch i         if (e) { r =  r + e;         } }  //   // for i      return r;   };   // .o.Weblink.facet

WebLK.prototype.fair =  function  { // Perform user defined modifications // Uses: //   >  .o.Weblink:: //      >  .multiple //      >  .joinProlog //      >  .joinLBrack //      >  .joinShow //      >  .joinSuffix //      >  .joinScheme //      >  .joinSelect //      >  .joinRBrack //       < .mode //      .facet //      .feed //      .fit //      .fill //   >  .mod.url //   >  .o.WikiTom.TextOnly //    < .mod.lazy //   .w.link.replace.flip //   .str.substrEnd // 2013-03-15 PerfektesChaos@de.wikipedia var i, sB, sE, x;     if (this.multiple) { sB =  this.facet(WebLK.joinProlog, WebLK.joinLBrack); if (this.showing) { sE =  "]"; } else { sE =  this.facet(WebLK.joinShow, WebLK.joinSuffix); }     } else { this.fit(WebLK.joinSuffix, this.feed, false); sB =  this.facet(WebLK.joinProlog); sE =  this.facet(WebLK.joinSuffix); }     x  =  WSTM.w.link.replace.flip(WSTM.mod.url,                                     this.facet(WebLK.joinScheme, WebLK.joinSelect),                                    sB,                                     sE,                                     "url"); if (x) { if (typeof(x) === "object") { if (typeof(x[0]) === "string") { sB =  x[0]; if (sB) { if (WSTM.str.substrEnd(sB, 2) ===  "[[") {                     this.mode  =  WSTM.o.WikiTom.LinkWiki;                  }               }               this.fit(WebLK.joinProlog, sB, true);               this.fit(WebLK.joinLBrack, false, true);            }            if (x[1]) {               this.fill(x[1]);            }            if (typeof(x[2]) === "string") {               sE  =  x[2];               this.fit(WebLK.joinShow, false, true);               this.fit(WebLK.joinRBrack, false, true);               if (sE) {                  i  =  sE.indexOf("]");                  if (i >= 0) {                     this.fit(WebLK.joinShow,  sE.substr(0, i),  true);                     this.fit(WebLK.joinRBrack, "]", true);                     sE  =  sE.substr(i + 1);                  }               }               this.fit(WebLK.joinSuffix, sE, true);            }         } else {            this.fill(x);         }         WSTM.mod.lazy  =  false;      }   };   // .o.Weblink.fair

WebLK.prototype.fault =  function (adapt, abolish, align, around) { // Convert URL formatted by titled wikilink syntax // Precondition: //   adapt    -- string segment beginning with "//" //   abolish  -- position of Pipe in adapt //   align    -- position of "/" in adapt //   around   -- position of "]" in adapt // Uses: //   >  .o.Weblink:: //      >  .joinProlog //      >  .joinShow //      >  .joinSelect //       < .mod.lazy //      .facet //      .fit //      .fetch //      .fenced //   .errors.found // 2013-03-15 PerfektesChaos@de.wikipedia var i =  abolish, j =  adapt.indexOf(" "), s =  this.facet(WebLK.joinProlog); this.fit(WebLK.joinProlog,              s.substr(0,  s.length - 1),               true); s =  adapt.substr(0,  around + 2); if (j > 0 &&  j < abolish) { i =  j;      } this.fetch(s.substr(0, i), false); s =  adapt.substr(i + 1,  around - i); this.fit(WebLK.joinShow, s, false); if (i === j) { this.fit(WebLK.joinShow, s.replace(/\|/g, " "),  true); }     this.fenced(this.facet(WebLK.joinSelect), true); WSTM.mod.lazy =  false; WSTM.errors.found("weblinkWikilink", true,  "[[" + s);   };   // .o.Weblink.fault

WebLK.prototype.feed =  function  { // Retrieve not yet processed source string // Postcondition: //   Returns string // Uses: //   >  .o.Weblink:: //      >  .source //      >  .move // 2013-03-15 PerfektesChaos@de.wikipedia return this.source.substr(this.move); };  // .o.Weblink.feed

WebLK.prototype.fenced =  function (adjust, already) { // Escape bracket pairs within URL path and store // Precondition: //   adjust   -- string with potential bracket pairs //   already  -- Not initial scan // Postcondition: //   Returns adjust, or false if escaped and stored // Uses: //   >  .o.Weblink:: //      >  .joinSelect //      >  .joinRBrack //      >  .joinScheme //       < .mod.lazy //      .fit //      .facet //   .errors.found // Requires: JavaScript 1.3  charCodeAt // 2013-08-09 PerfektesChaos@de.wikipedia var i, k, s,         n      =  0, slash =  adjust, r     =  adjust; do { k =  slash.indexOf("]"); if (k > 0) { i =  slash.indexOf("["); if (i < 0) { break;  // while } else if (i <  k - 1) { if (slash.charCodeAt(k + 1) ===  93) { break;  // while } else { s =  slash.slice(i + 1,  k); if (s.length) { if (! /^[-a-z.A-Z_0-9]+$/.test(s)) { break;  // while }                 }                  if (k > 0) { slash  =  slash.substr(0, i)                                +  "&#91;" + s + "&#93;" + slash.substr(k + 1); n     +=  8; }              }            } else { break;  // while }        }      } while (k > 0);   // do      if (n) { if (! already) { this.fit(WebLK.joinSelect,                    adjust.substr(0,  slash.length - n),                     false); }        this.fit(WebLK.joinSelect, slash, true); this.fit(WebLK.joinRBrack, "", true); WSTM.mod.lazy =  false; WSTM.errors.found("weblinkBrackets",                          true,                           this.facet(WebLK.joinScheme, WebLK.joinSelect)); r =  false; }     return r;   };   // .o.Weblink.fenced

WebLK.prototype.fetch =  function (apply, already) { // Split URL string into components // Precondition: //   apply    -- string segment beginning with URL //   already  -- Not initial scan // Postcondition: //   object components are initialized or updated // Uses: //   >  .o.Weblink:: //      >  .joinScheme //      >  .joinSite //      >  .joinSelect //      >  .joinShow //      >  .joinSuffix //      .fit //      .facet // Requires: JavaScript 1.3  charCodeAt // 2013-03-15 PerfektesChaos@de.wikipedia var s      =  false, show   =  false, site   =  false, slash  =  false, suffix =  false, i      =  -1; if (apply) { i =  apply.indexOf("//"); }     if (i >= 0) { site =  apply.substr(i + 2); if (i > 3) { if (apply.charCodeAt(i - 1) ===  58) {   // ':' s =  apply.substr(0, i); } else { site =  false; }        } else if (i) { site =  false; }     }      this.fit(WebLK.joinScheme, s, already); if (site) { i =  site.indexOf(" "); if (i > 0) { site =  site.substr(0, i); show =  site.substr(i + 1); i    =  show.indexOf("]"); s    =  this.facet(WebLK.joinShow); if (s) { show =  show  +  s;            } if (i > 0) { suffix =  this.facet(WebLK.joinSuffix); suffix =  show.substr(i)  +  (suffix ? suffix : ""); show   =  show.substr(0, i); }        }         i  =  site.indexOf("/"); if (i > 0) { this.fit(WebLK.joinSlash, "/", already); slash =  site.substr(i + 1); site  =  site.substr(0, i); }        i  =  site.indexOf("?"); if (i > 0) { slash =  site.substr(i + 1) +  (slash  ?  "/" + slash  :  ""); site  =  site.substr(0, i); }        if (site.length < 5) {   // ix.de            this.fit(WebLK.joinScheme, false, true); } else { if (show) { this.fit(WebLK.joinShow, show, true); }           if (suffix) { this.fit(WebLK.joinSuffix, suffix, true); }        }      }      this.fit(WebLK.joinSite, site, already); this.fit(WebLK.joinSelect, slash, already); };  // .o.Weblink.fetch

WebLK.prototype.fiat =  function  { // Analyze and adjust URL and embedding within brackets // Uses: //   >  .o.Weblink:: //      >  .move //      >  .multiple //      >  .joinSite //      >  .joinScheme //      >  .joinSelect //      >  .leaf //      >  .joinSuffix //      >< .source //      .feed //      .fault //      .fit //      .facet //      .fenced //      .filled //      .frozen //    < .mod.lazy //   .errors.found //   .str.terminated // Requires: JavaScript 1.3  charCodeAt // 2013-09-06 PerfektesChaos@de.wikipedia var i, j, k, less, limit, n, s, slashed, suffix, m   =  -2; s    =  this.feed; i    =  s.indexOf("\n\n"); less =  (i > 0); if (less) { s           =  s.substr(0, i); this.source =  this.source.substr(0,  this.move + i); }     i      =  s.indexOf(" "); limit =  (i > 0); if (limit) { less =  true; s    =  s.substr(0, i); }     i  =  s.indexOf("/"); k =  s.indexOf("]"); n =  s.indexOf("\n"); if (this.multiple > 1 &&  k > 0) { m =  s.indexOf("|"); if (m > 0) { if (m < k               &&   s.charCodeAt(k + 1)  ===  93                &&   (n < 0  ||  n > k)) {   // ']' this.fault(s, m, i, k); } else { m =  -3; }        }         less  =  true; }     if (m < 0) { j =  s.indexOf(" "); if (j < 0) { m =  s.length; } else { m =  j;         } if (n >= 0 &&  n < m) { m    =  n;            less  =  true; }        if (k >= 0  &&  k < m) { m =  k;         } if (i > 0 &&  i < m) { this.fit(WebLK.joinSite, s.substr(0, i),  false); this.fit(WebLK.joinSlash, "/", false); slashed =  this.feed; if (limit) { i =  slashed.indexOf(" "); if (i > 0) { slashed =  slashed.substr(0, i); }           }            if (j > 0) { j =  slashed.indexOf(" "); if (j > 0) { slashed =  slashed.substr(0, j); } else { slashed =  false; }           }         } else { i =  s.indexOf("?", m); if (i > 0 &&  i < m) { slashed =  s.substr(i); this.fit(WebLK.joinSite, s.substr(0, i),  false); this.fit(WebLK.joinSlash, "/", true); WSTM.mod.lazy =  false; WSTM.errors.found("weblinkStrange",                                true,                                 this.facet(WebLK.joinScheme, WebLK.joinSlash)                                + slashed); } else { this.fit(WebLK.joinSite, s.substr(0, m),  false); this.fit(WebLK.joinSlash, "/", true); slashed =  false; }        }         if (slashed) { if (n > 0) { n =  slashed.indexOf("\n"); if (n > 0) { slashed =  slashed.substr(0, n); }           }            if (k > 0) { k =  slashed.indexOf("]"); if (k >= 0) { s =  slashed.substr(0, k); i =  s.indexOf("["); if (i < 0) { this.fit(WebLK.joinSelect, s, false); this.fit(WebLK.joinRBrack, "]", false); slashed =  false; suffix  =  this.feed; } else { slashed =  this.fenced(slashed, false); if (slashed) { i =  slashed.indexOf("]"); if (i < 0) { suffix =  false; } else { suffix  =  slashed.substr(i + 1); slashed =  slashed.substr(0, i); this.fit(WebLK.joinRBrack, "]", false); }                    }                  }                  if (suffix) { if (this.leaf) { suffix =  WSTM.str.terminated(suffix, "|"); }                    this.fit(WebLK.joinSuffix, suffix, false); }              }            } else if (this.limited) { this.fit(WebLK.joinSelect, slashed, false); i =  s.indexOf(" "); if (i > 0) { this.fit(WebLK.joinShow, s.substr(i + 1),  false); }              if (! less) { if (this.frozen) { slashed =  false; }              }               if (slashed) { this.fit(WebLK.joinRBrack, "]", true); WSTM.errors.found("weblinkBracketRight",                                   true,                                    this.facet(WebLK.joinScheme, WebLK.joinSelect)); slashed =  false; }           }            if (slashed) { if (this.multiple === 0) { slashed =  WSTM.str.terminated(slashed, " "); slashed =  WSTM.str.terminated(slashed, "\n"); slashed =  WSTM.str.terminated(slashed, " "); }              this.fit(WebLK.joinSelect, slashed, false); }        }         if (this.limited) { if (! this.facet(WebLK.joinRBrack)) { this.filled; }        }      }   };   // .o.Weblink.fiat

WebLK.prototype.fill =  function (apply) { // Process URL replacement // Precondition: //   apply  -- URL, or replaced string // Uses: //   >  .o.Weblink:: //       < .shift //       < .lazy //       < .mode //      .fetch //      .facet //   >  .o.WikiTom.TextOnly // 2013-03-15 PerfektesChaos@de.wikipedia this.fetch(apply, true); if (! this.facet(WebLK.joinSite)) { this.shift =  apply; this.lazy  =  false; this.mode  =  WSTM.o.WikiTom.TextOnly; }  };   // .o.Weblink.fill

WebLK.prototype.filled =  function  { // Analyze and adjust link title and suffix // Uses: //   >  .o.Weblink:: //      >  .source //      >  .maxTitle //      >  .joinScheme //      >  .joinSelect //      >  .joinShow //      >  .joinRBrack //      >  .leaf //      >  .joinSuffix //      >  .limited //      .feed //      .further //      .fit //      .facet //      .flat //   .str.terminated //   .str.trimR //   .errors.found // Requires: JavaScript 1.3  charCodeAt // 2013-03-15 PerfektesChaos@de.wikipedia var i, j, k, s, show; s =  this.feed; k =  s.charCodeAt(0); if (k === 32) {  // ' ' s =  s.substr(1); k =  s.indexOf("]"); if (k < 0) { if (s.length < this.maxTitle) { k =  this.further;   // return }        } else if (k < this.maxTitle) { i =  s.indexOf("");               }               this.fit(WebLK.joinSuffix, s, false);               if (i) {                  k     =  show.length;                  show  =  WSTM.str.trimR(show);                  if (show.length < k) {                     s  =  " " + s;                     this.fit(WebLK.joinShow, show, true);                     this.fit(WebLK.joinSuffix, s, true);                  }               }               i  =  2;               do {                  k  =  s.indexOf("", i); if (k > 0) { i =  k + 2; k =  s.indexOf("]", i); j =  s.indexOf("[[", i);                     if (j > 0  &&  k > 0  &&  k < j) {                        i  =  -2;                     }                  } else {                     k  =  s.indexOf("]", i);                     i  =  -3;                  }                  if (k > 0  &&  i < 0) {                     s  =  s.substr(0, k)  +  s.substr(k + 1);                     this.fit(WebLK.joinSuffix, s, true);                     break;   // while                  }               } while (k > 0);               k  =  0;            } else {               this.fit(WebLK.joinShow,  s.substr(0, k),  false);               this.fit(WebLK.joinRBrack, "]", false);               s  =  s.substr(k + 1);               if (this.leaf) {                  s  =  WSTM.str.terminated(s, "|");               }               this.fit(WebLK.joinSuffix, s, false);            }            this.flat;         } else {            k  =  -2;         }      } else  if (k === 93) {   // ']'         this.fit(WebLK.joinRBrack, "]", false);         s  =  s.substr(1);         if (this.leaf) {            s  =  WSTM.str.terminated(s, "|");         }         this.fit(WebLK.joinSuffix, s, false);      }      if (this.limited) {         if (k < 0) {            WSTM.errors.found("weblinkBracketRight",                              false,                              "[" + this.facet(WebLK.joinScheme,                                               WebLK.joinSelect));         }      }   };   // .o.Weblink.filled

WebLK.prototype.filter =  function  { // Test URL for user warning request // Uses: //   >  .o.Weblink:: //      >  .shift //      >  .joinScheme //      >  .joinSelect //      .facet //   .warn.filter // 2013-03-15 PerfektesChaos@de.wikipedia var s;     if (this.shift) { s =  this.shift; } else { s =  this.facet(WebLK.joinScheme, WebLK.joinSelect); }     WSTM.warn.filter(s, "url"); };  // .o.Weblink.filter

WebLK.prototype.finalize =  function  { // Terminate analysis // Uses: //   >  .o.Weblink:: //      >  .mode //      >  .joinProlog //      >  .joinLBrack //      >  .joinScheme //      >  .joinSelect //       < .index //       < .keep //      .facet //      .forward //   >  .o.WikiTom.LinkWeb // 2013-03-15 PerfektesChaos@de.wikipedia var s;     if (this.lazy) { s          =  this.facet(WebLK.joinProlog, WebLK.joinLBrack); this.index =  s.length; s          =  this.facet(WebLK.joinScheme, WebLK.joinSelect); this.keep  =  s.length; } else { this.forward; }  };   // .o.Weblink.finalize

WebLK.prototype.fire =  function  { // Start analysis // Uses: //   >  .o.Weblink:: //      >  .node //      >  .join //      >  .off //      >  .leaf //      >  .limited //      >  .index //      >  .joinProlog //      >  .multiple //      >  .met //      >  .joinLBrack //      >  .mark //      >  .joinScheme //      >  .scheme //      >  .lackScheme //      >  .lowScheme //      >  .joinSite //       < .source //      .fit //      .fiat //      .fix //      .facet //      .friend //      .fair //      .filter //      .finalize //   >  .o.WikiTom.LinkWeb //   >  .mod.url //   >  .warn.url //   .o.WikiTom.fetch //   .w.link.web.fetch //   .str.substrEnd // 2015-12-25 PerfektesChaos@de.wikipedia var i, s;     this.source  =  this.off.fetch(this.node, this.join, false); if (this.leaf &&  ! this.limited) { i =  this.source.indexOf("|", this.index); if (i > 0) { this.source =  this.source.substr(0, i); }     }      WSTM.w.link.web.fetch(this, this.limited); if ((this.multiple > 0) ===  this.limited) { this.fit(WebLK.joinProlog,                 this.source.substr(0, this.met),                  false); if (this.multiple) { s =  this.feed; this.fit(WebLK.joinLBrack, s.substr(0, this.mark),  false); if (this.mark > 1) { this.fit(WebLK.joinLBrack, "[", true); }        }         this.fit(WebLK.joinScheme, this.scheme, false); if (this.lackScheme || this.lowScheme) { this.fit(WebLK.joinScheme, this.scheme, true); }        this.fiat; this.fix; s =  this.facet(WebLK.joinSite); if (s) { if (WSTM.str.substrEnd(s, 4) ===  ".org") { this.friend; }           if (this.mode === WSTM.o.WikiTom.LinkWeb) { if (WSTM.mod.url) { this.fair; }              if (WSTM.warn.url) { if (this.mode === WSTM.o.WikiTom.LinkWeb) { this.filter; }              }            }         }         this.finalize; }  };   // .o.Weblink.fire

WebLK.prototype.fit =  function (about, apply, alter) { // Extend modified area // Precondition: //   about  -- level //   apply  -- string segment //   alter  -- string is modified // Uses: //   >  .o.Weblink:: //      >  .joinLBrack //      >  .joinScheme //      >  .joinSite //      >  .joinSelect //      >  .joinSuffix //      >< .points //      >< .move //       < .lazy //   .w.link.filter // 2015-09-12 PerfektesChaos@de.wikipedia var swap, e =  this.points[ about ], s =  (apply ? apply : ""); if (alter) { if (s !== (e[1] ? e[1] : "")) { e[2] =  true; }     } else if (apply) { e[0]       =  apply.length; this.move +=  e[0]; }     e[1]  =  s;      switch (about) { case WebLK.joinScheme: swap =  s.toLowerCase; if (swap !== s) { e[1] =  swap; e[2] =  true; }           if (alter) { e[2] =  apply; } else { e[0]      +=  2; this.move +=  2; }           break; case WebLK.joinSite: if (s) { swap =  WSTM.w.link.filter(s, false); swap =  (swap ? swap : s).toLowerCase; if (swap !== s) { e[1] =  swap; e[2] =  true; }           }            break; case WebLK.joinSelect: if (s) { swap =  WSTM.w.link.filter(s, false); if (swap &&  swap !== s) { e[1] =  swap; e[2] =  true; }           }            break; case WebLK.joinShow: if (! alter) { e[0] +=  1; this.move++; }           break; case WebLK.joinSuffix: if (! alter) { this.move -=  e[0]; }           break; }  // switch about if (e[2]) { this.lazy =  false; }  };   // .o.Weblink.fit

WebLK.prototype.fix =  function  { // Inspect resulting URL for suspicious content // Uses: //   >  .o.Weblink:: //      >  .re.schemes //      >  .joinScheme //      >  .joinSite //      >  .joinSelect //      >  .multiple //      >  .re.split //      >  .re.stop //      >  .maxURL //      .facet //   .str.substrExcept //   .util.isURL //   .str.substrEnd //   .errors.found // 2016-01-28 PerfektesChaos@de.wikipedia var s    =  this.facet(WebLK.joinScheme), site =  this.facet(WebLK.joinSite), scan; if (s) { scan =  "|"  +  WSTM.str.substrExcept(s, 1)  +  "|"; if (WebLK.re.schemes.indexOf(scan) < 0) { WSTM.errors.found("weblinkScheme",                             false,                              this.facet(WebLK.joinScheme, WebLK.joinSelect)); }        s  =  this.facet(WebLK.joinScheme, WebLK.joinSite); } else { s =  "//" + site; }     if (site  &&  WSTM.util.isURL(s)) { WSTM.errors.found("weblinkDomain", false, site); }     scan  =  this.facet(WebLK.joinSelect); if (scan) { s =  s + "/" + scan; if (scan.indexOf("''") > 3) { WSTM.errors.found("weblinkApostrophs", false, s); }        if (this.multiple === 1) { if (scan.indexOf("|") >= 0) { WSTM.errors.found("weblinkPipe", false, s); }        }         if (WebLK.re.split.test(scan)) { WSTM.errors.found("weblinkSpecial", false, s); }        if (WebLK.re.stop.indexOf(WSTM.str.substrEnd(scan, 1))             >=  0) { WSTM.errors.found("weblinkPunctuation", false, s); }        //  /<\/[a-z]+>/.test(s) }     if (s.length > this.maxURL) { WSTM.errors.found("weblinkURLlength", false, s); } };   // .o.Weblink.fix

WebLK.prototype.flat =  function  { // Standardize link title spacing // Postcondition: //   Returns true if shrinked // Uses: //   >  .o.Weblink:: //      >< .re.spaces //       < .mod.lazy //      .facet //   .str.trim // 2013-03-15 PerfektesChaos@de.wikipedia var s =  this.facet(WebLK.joinShow), n =  s.length, r =  false; if (s.indexOf("\n") >= 0) { WSTM.mod.lazy =  false; }     s  =  WSTM.str.trim(s, true); if (s) { if (! this.re.spaces) { this.re.spaces =  new RegExp("  +", "g"); }        s  =  s.replace(this.re.spaces, " "); r =  (s.length < n); } else { s =  false; r =  true; }     this.fit(WebLK.joinShow, s, r); return r;  };   // .o.Weblink.flat

WebLK.prototype.focus =  function (at, advance) { // Aggregate splitted information // Precondition: //   at       -- code of first element to be collected //   advance  -- code of last element to be collected // Postcondition: //   Returns  Array [old length, //                   replacement string, //                   replace it] // Uses: //   >  .o.Weblink:: //      >  .mode //      >  .lazy //      >  .points //      >  .joinShow //      .facet //   >  .o.WikiTom.LinkWeb // 2013-05-26 PerfektesChaos@de.wikipedia var e, i, s,         l  =  (this.mode !== WSTM.o.WikiTom.LinkWeb), m =  l,          n  =  0; if (this.lazy) { for (i = at; i <= advance;  i++) { e  =  this.points[ i ]; n +=  e[0]; }  // for i         s  =  false; } else { s =  this.facet(at, advance); for (i = at; i <= advance;  i++) { e  =  this.points[ i ]; n +=  e[0]; l  =  (l || e[2]); }  // for i         if (at === WebLK.joinShow  &&  this.points[ at ][1]  &&  ! m) { s =  " " + s;         } }     return  [n, s, l]; };  // .o.Weblink.focus

WebLK.prototype.format =  function (anode, access, around, arg) { // Initialize existing weblink object with node // Precondition: //   anode   -- parent node WikiTom object //   access  -- location object //              .i  start of "://" or "[" in .j      //               .j  start of interesting region in .k      //               .k  sibling number of location //   around  -- number of known leading brackets  '[' (0, 1) //   arg     -- template parameter on unbracket link // Postcondition: //   Returns position object to continue search //           .i  string position in entire node //           .k  node number //   .o.Weblink object was set, has been analyzed and reformatted //   WikiTom nodes in basic text have been updated // Uses: //   WikiTom.toString //   >  .o.Weblink:: //      >  .joinSuffix //      >  .joinScheme //      >< .move //       < .off //       < .node //       < .index //       < .join //       < .multiple //       < .limited //       < .leaf //       < .mode //       < .keep //       < .lazy //       < .moving //       < .shift //       < .shower //       < .points //      .fire //      .facet //   >  .o.WikiTom.LinkWeb // 2013-05-02 PerfektesChaos@de.wikipedia var i, r;     this.move      =  0; this.off      =  anode; this.node     =  access.k;      this.index     =  access.i;      this.join      =  access.j;      this.multiple  =  around; this.limited  =  (around > 0); this.leaf     =  arg; this.mode     =  WSTM.o.WikiTom.LinkWeb; this.keep     =  -1; this.lazy     =  true; this.moving   =  0; this.shift    =  false; this.shower   =  false; for (i = 0; i  <=  WebLK.joinSuffix;  i++) { this.points[ i ] =  [0, false, false]; }  // for i      this.fire; r =  { k:  this.node + this.moving }; if (this.moving) { r.i =  0; } else { r.i        =  this.join + this.index; this.index =  r.i;         if (this.keep > 0) { r.i +=  this.keep - 1; } else if (this.move < 0) { r.i +=  this.move; } else if (this.limited) { r.i +=  9; } else { r.i +=  2  +  this.facet(WebLK.joinScheme).length; }     }      return r;   };   // .o.Weblink.format

WebLK.prototype.forward =  function  { // Modify source text // Uses: //   >  .o.Weblink:: //      >  .joinProlog //      >  .joinLBrack //      >  .off //      >  .node //      >  .join //      >  .shift //      >  .joinScheme //      >  .joinSelect //      >  .mode //      >  .joinShow //      >  .joinSuffix //       < .index //       < .keep //      .focus //   >  .o.WikiTom:: //      .flip // 2013-05-26 PerfektesChaos@de.wikipedia var got =  this.focus(WebLK.joinProlog, WebLK.joinLBrack); this.index =  got[0]; if (got[2]) { this.off.flip(this.node, this.join, this.index, got[1]); this.index =  got[1].length; }     got  =  this.focus(WebLK.joinScheme, WebLK.joinSelect); if (typeof(this.shift) === "string") { got[1] =  this.shift; got[2] =  true; }     if (got[2]) { this.keep =  got[1].length; this.off.flip(this.node,                      this.join + this.index,                       got[0],                       got[1]); } else { this.keep =  got[0]; }     got  =  this.focus(WebLK.joinShow, WebLK.joinSuffix); if (got[2]) { this.off.flip(this.node,                      this.join + this.index + this.keep,                       got[0],                       got[1]); }     if (this.mode !== WSTM.o.WikiTom.LinkWeb) { this.keep =  -1; }  };   // .o.Weblink.forward

WebLK.prototype.freeze =  function (advanced) { // Freeze link target as recently formatted // Uses: //   >  .o.Weblink:: //      >  .keep //      >  .node //      >  .index //      >  .off //       < .mode //       < .lookup //   >  .o.WikiTom.folder // 2013-03-15 PerfektesChaos@de.wikipedia var url, r =  advanced; if (this.keep > 0) { url =  this.off.folder(this.index,                                 this.node,                                 this.index + this.keep,                                 this.node); if (url) { url.mode   =  WSTM.o.WikiTom.LinkWeb; url.lookup =  false; r          =  { i: 0, k: this.node +  (this.index ? 2 : 1) }; }     }      return r;   };   // .o.Weblink.freeze

WebLK.prototype.frozen =  function  { // Skip nowiki/comment WTOM within link title // Postcondition: //   Returns true if closing bracket found after WTOM // Uses: //   >  .o.Weblink:: //      >  .moving //      >  .node //      >  .off //      >  .maxTitle //   >  .o.WikiTom.TextOnly //   .o.WikiTom.focus //   .o.WikiTom.fetch // 2013-09-12 PerfektesChaos@de.wikipedia var i, other, s,         r  =  false; if (! this.moving) { other =  this.off.focus(this.node + 1); if (other) { if (other.mode > WSTM.o.WikiTom.TextOnly) { other =  this.off.focus(this.node + 2); if (other) { if (other.mode <= WSTM.o.WikiTom.TextOnly) { s =  this.off.fetch(this.node + 2,  0,  false); i =  s.indexOf("\n"); if (i >= 0) { s =  s.substr(0, i); }                    i  =  s.indexOf("]"); if (i >= 0) { if (i < WebLK.maxTitle) { s =  s.substr(0, i); r =  (s.indexOf("[") < 0); }                    }                  }               }            }         }      }      return r;   };   // .o.Weblink.frozen

WebLK.prototype.friend =  function  { // Check whether detected URL can be converted into wikilink // Uses: //   >  .o.Weblink:: //      >  .joinScheme //      >  .joinSite //      >  .joinSelect //      >  .joinShow //      >  .joinSuffix //      >  .limited //      >  .index //      >< .url2w //      >< .move //       < .mode //       < .shift //      .facet //      .fetch //      .fit //   >< .o.URL2wiki //      .set //      .getMode //      .getRemoveTo //      .getTextReplace //      .getTarget //      .getTitle //      .getURL //   >  .mod.wikilink //   >  .o.WikiTom.LinkWiki //   .errors.found // 2013-12-14 PerfektesChaos@de.wikipedia var t, u2w, x;     if (! this.url2w) { this.url2w =  new WSTM.o.URL2wiki; }     u2w  =  this.url2w; this.url2w.set({ multiple: this.multiple,                      scheme:   this.facet(WebLK.joinScheme),                       site:     this.facet(WebLK.joinSite),                       slashed:  this.facet(WebLK.joinSelect),                       show:     this.facet(WebLK.joinShow),                       suffix:   this.facet(WebLK.joinSuffix)                     },                     false); switch (this.url2w.getMode) { case 1 : this.fetch(this.url2w.getTextReplace, true); break; case 2 : if (this.limited) { this.mode =  WSTM.o.WikiTom.LinkWiki; this.fetch(false, true); x =  this.url2w.getTarget; this.fit(WebLK.joinSelect, x, true); t =  u2w.getTitle; if (t &&  t !== x) { this.fit(WebLK.joinShow, t + "]",  true); x =  this.url2w.getSuffix; if (x) { this.fit(WebLK.joinSuffix, x, true); }                 this.shift  =  "|"; } else if (t === "") { this.shift =  true; } else { this.shift =  "]"; }              if (this.shift === true) { this.shift =  "[" + x + "]"; this.fit(WebLK.joinShow,  "", true); this.move =  (this.index ? -1 : 0); } else { this.shift =  "[" + this.facet(WebLK.joinSelect) + this.shift; this.move  =  (this.index ? -2 : 0); }           } else { WSTM.errors.found("wikilinkURL",                                false,                                 u2w.getURL                                 + String.fromCharCode(10, 8658, 10)                                 + "" + u2w.getTarget + ""); }           break; }  // switch .url2w.get };  // .o.Weblink.friend

WebLK.prototype.further =  function  { // Skip over node // Postcondition: //   Returns  number < 0  iff ']' not found // Uses: //   >  .o.Weblink:: //      >  .node //      >  .off //      >  .maxTitle //       < .moving //       < .shower //      .facet //   >  .o.WikiTom.TextOnly //   .o.WikiTom.focus //   .o.WikiTom.fetch //   .errors.found // 2013-03-15 PerfektesChaos@de.wikipedia var got, m, s,         past  =  this.off.focus(this.node + 1), r    =  -2; if (past) { m =  past.mode; if (m > WSTM.o.WikiTom.TextOnly) { past        =  this.off.focus(this.node + 2); this.moving =  2; if (past) { m =  past.mode; if (m > WSTM.o.WikiTom.TextOnly) { this.moving =  3; }           }            if (m < WSTM.o.WikiTom.TextOnly) { s =  this.off.fetch(this.node + this.moving,  0,  false); r =  s.indexOf("]"); if (r >= 0 &&  r < this.maxTitle) { if (r) { this.shower =  s.substr(0, r); s           =  "\f" + this.shower + "\f"; got         =  /\f([^<\n]*)\f/.exec(s); if (got) { if (this.shower.indexOf("[") >= 0) { this.shower =  false; }                    } else { this.shower =  false; }                 } else { this.shower =  ""; }              }            }         }      }      if (this.shower === false) { WSTM.errors.found("weblinkBracketRight",                          false,                           "["                           + this.facet(this.joinScheme, this.joinSelect)); }     return r;   };   // .o.Weblink.further

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

//---

mw.libs.WikiSyntaxTextMod.bb.Wikilink =  function (WSTM) { // Administration of wikilinks // 2012-10-01 PerfektesChaos@de.wikipedia // Class: //   Public: //      getChange //      getError //      getIncrement //      getRemoveFrom //      getRemoveTo //      getSortkey //      getTargetLength //      getTextReplace //      getType //      getUserModified //      set //      setTarget //   Private: //      adjust //      analyze //      capitalize //      category //      closingBracket //      extend //      file //      language //      lineFeedAhead //      magic //      magic_ISBN //      namespace //      newline //      old2New //      pipeSymbols //      project //      specials  //  -> special //      target //      title //      unlink //      url //      init // .label   true: pipe trick completion // .lapsus  true: syntax error detected // .last    true: pipe at end of parameter list // .lead    true: target starts with ":" // .leader  true: first item in category or interlanguage sequence // .leap    true: leading whitespace // .learn   true: link modified by user replacement // .lfAhead true: line feed present before link // .lift    true: left brackets shifted // .limited true: enclosed in brackets (single bracket termination) // .lack    true: single  "[" heading // .lock    true: freeze wikilink targets // .index   number: position of "[[" in .source   // .inPipe   number: of chars in analyze until pipe symbol, or false   // .inTerm   number: of chars in analyze until terminating bracket   // .join     number: relative position of "[["   // .justify  number: default lang for project link   // .keySort  number: of chars to be unconditionally locked as sort key   // .mode     number: interwiki, category, media (file) etc.   // .move     number: incrementation on global search   // .newFrom  number: of chars in .source for replacement region start   // .newTo    number: of chars in .source for replacement region end   // .next     number: of chars in .suffix to be added, or all   // .node     number: of .onto within .off   // .nucleus  number: of target chars to be locked   // .off      WikiTom with spans, or false   // .onto     current WikiTom node   // .score    wikilink target   // .sequence media parameters   // .sister   'project:', if any   // .shift    replacement string (total)   // .show     non-empty title string   // .slang    'language:', if any   // .source   wikitext including "[[" at .index   // .special  category or interwiki content    // -> schedule   // .start    replacement string (preceeding)   // .subcase  downcased wgTitle   // .suffix   aftermath   "use strict";   var WikiLK;

WSTM.o.Wikilink =  function  { // .constructor for new // Postcondition: //   Returns .o.Wikilink object // Uses: //   >  .g.wTitle //    < .o.Wikilink.subcase //   .o.Wikilink.init //   .hooks.fire //   .str.deCapitalize // 2016-08-17 PerfektesChaos@de.wikipedia var p;     this.init; this.index   =  false; this.lock    =  false; this.move    =  false; this.newFrom =  false; this.node    =  false; this.off     =  false; this.onto    =  false; this.source  =  false; // this.lfAhead =  false; if (WSTM.hooks.fire("capitalize1")) { this.subcase =  WSTM.str.deCapitalize(WSTM.g.wTitle); } else { this.subcase =  WSTM.g.wTitle; }     for (p in WSTM.o.Wikilink) { this[ p ] =  WSTM.o.Wikilink[ p ]; }  // for p in      return this; };  // .o.Wikilink .constructor WikiLK =  WSTM.o.Wikilink;

// Definition of constants // 2012-10-24 PerfektesChaos@de.wikipedia WikiLK.ModeNull =  -9; WikiLK.ModeWeb  =  -7; WikiLK.ModeWiki =  91; WikiLK.ModeIw   =  93; WikiLK.ModeFile =   6; WikiLK.ModeCat  =  14; WikiLK.ModeMap  =  -5;  //   special weblink (... etc.) //                  6   special interwikilink (... etc.) //                  7   page

WikiLK.prototype.init =  function  { // Initialize existing wikilink object // Postcondition: //   .o.Wikilink object has been reset // Uses: //   >  .o.Wikilink:: //      >  .***      // 2015-12-20 PerfektesChaos@de.wikipedia this.label    =  false; this.lapsus   =  false; this.last     =  false; this.lead     =  false; this.leader   =  false; this.leap     =  false; this.learn    =  false; this.lift     =  false; this.limited  =  false; this.lock     =  false; this.inPipe   =  false; this.inTerm   =  false; this.join     =  false; this.justify  =  false; this.keySort  =  false; this.mode     =  false; this.move     =  false; this.newFrom  =  false; this.newTo    =  false; this.next     =  false; this.node     =  false; this.nucleus  =  false; this.off      =  false; this.onto     =  false; this.score    =  false; this.sequence =  false; this.shift    =  false; this.show     =  false; this.sister   =  false; this.slang    =  false; this.special  =  false; this.start    =  false; this.suffix   =  false; };  // .o.Wikilink.init

WikiLK.prototype.adjust =  function (analyze) { // Analyze entire link syntax, divide into major parts // Precondition: //   analyze  -- string with link content beginning with '[['      // Uses:      //    >  .w.link.namespace.nsFile      //    >  .o.Wikilink::      //       >  .ModeFile      //       >  .ModeMap      //       >  .show      //        < .lack      //        < .mode      //        < .limited      //        < .join      //        < .inTerm      //        < .inPipe      //        < .lapsus      //        < .move      //        < .leap      //        < .suffix      //        < .score      //        < .lift      //       .file      //       .extend      //       .newline      //       .url      //       .closingBracket      //       .pipeSymbols      //       .analyze      //     < .mod.lazy      //    .w.link.namespace.furnish      //    .w.link.wiki.iwMap      //    .str.trim      //    .errors.found      //    .str.isBlank      // Requires: JavaScript 1.3   charCodeAt      // 2016-02-05 PerfektesChaos@de.wikipedia      var s       =  analyze.substr(2),          inside  =  2,          join    =  s.indexOf("\n\n"),          lack    =  (analyze.substr(0, 2)  !==  ""),          later   =  false,          c,          e,          newl,          mid,          shift,          start,          swap;      if (join > 0) {         s  =  s.substr(0, join);      }   // paragraph found      join  =  s.indexOf(":");      if (join > 1) {         if (WSTM.w.link.namespace.furnish(s.substr(0, join),                                           false,                                           false)  ===             WSTM.w.link.namespace.nsFile) {            this.mode  =  this.ModeFile;   // (not Media:)            if (this.file(analyze.substr(2),  join + 1)) {               s  =  "";            }            join  =  s.indexOf("\n");            if (join > 0) {               s  =  s.substr(0, join);            }   // EOL -- image description might contain strange things         } else {            start  =  s.substr(0, join);            if ( start.indexOf("[[") < 0 ) {               swap  =  WSTM.w.link.wiki.iwMap(start);               if (swap) {                  this.mode  =  this.ModeMap;                  later      =  (swap !== start);                  if (later) {                     start  =  swap;                     s      =  start + s.substr(join);                  }   // adjust                  swap  =  s.substr(join + 1);                  mid   =  swap.indexOf("");                  if (mid > 0) {                     swap   =  swap.substr(0, mid);                     shift  =  WSTM.str.trim(swap, true);                     if (swap !== shift) {                        later  =  swap.length - shift.length;                        s      =  start  +  ":"  +  shift                                  +  s.substr(start.length + 1 + mid);                     }                     if (typeof(WSTM.util[ start ]) === "object") {                        e  =  WSTM.util[ start ];                        if (typeof(e.failure) === "function") {                           swap  =  s.substr(start.length + 1);                           swap  =  swap.substr(0,  swap.indexOf("]]"));                           e     =  e.failure(swap);                           switch (typeof e) {                              case "string" :   // simple correction                                 mid  =  start.length + 1 + swap.length;                                 s    =  WSTM.str.makeString(32,                                                  swap.length - e.length)                                         + start + ":" + e                                         + s.substr(mid);                                 break;                              case "object" :   // severe                                 WSTM.errors.found("badURI", true, e[1]);                                 break;                           }   // switch typeof e                        }                     }                     if (typeof(later) === "number") {                        s  =  WSTM.str.makeString(32, later)  +  s;                     }                  }               }   // interwiki mapping            }   // interwiki mapping         }      }   // may be prefixed      join          =  s.indexOf("]") + 2;      this.limited  =  (join > 1);      if (this.limited) {   // first terminating bracket found         inside  =  s.indexOf("[") + 2;         if (inside > 1) {            if (inside < join) {               if (this.mode !== this.ModeFile   &&                   inside === 2) {   // triple bracket, or even more                  c           =  s.charCodeAt(0);                  this.join   =  0;                  this.newTo  =  join;                  this.extend(32);                  while (WSTM.str.isBlank(c, false)                         ||  c === 91) {   // [                     s  =  s.substr(1);                     c  =  s.charCodeAt(0);                     this.join++;                     join--;                  }   // while                  WSTM.mod.lazy  =  false;                  WSTM.errors.found("tooManyLeftBrackets",                                    true,                                    analyze.substr(0, 100));               } else {   // got opening bracket inside, could be File:                  join          =  inside;                  s             =  s.substr(0,  join - 2);                  this.limited  =  false;               }            }         }         this.inTerm  =  join;      }      if (s) {         newl  =  s.indexOf("\n") + 2;         mid   =  s.indexOf("|") + 2;         if (! this.limited) {            if (this.mode === this.ModeFile) {               join  =  s.length;   // "]]" } else { this.extend(-1); if (newl > 1) { s =  s.substr(0,  newl - 1); }              if (mid > 1) { s =  s.substr(0, mid); }              if (s.length  &&  mid < 1) {   // not folded WSTM.errors.found("wikilinkBracketsAhead",                                   false,                                    mid +                                    "[[" + s.substr(0, 100));               }               s  =  false;            }         }      }      if (s) {         if (mid > 1) {            if (mid < join) {               this.inPipe  =  mid;            }         }         if (newl > 1) {            if (this.limited) {               if (newl < this.inTerm) {                  s     =  this.newline(s, newl);                  newl  =  false;               }   // newline within bracket pair            }            if (newl) {               s  =  s.substr(0,  newl - 2);               if (mid > newl) {                  this.inPipe  =  false;               }            }         }      }      if (s) {         while (WSTM.str.isBlank(s.charCodeAt(0), false)) {            s  =  s.substr(1);            join--;            if (this.inPipe) {               mid--;            }            this.extend(1);            this.leap  =  true;         }   // while ltrim         if (join === 2) {   // "[[\n"            WSTM.errors.found("linkTargetMissing",                              true,                              analyze.substr(0, 100));            this.extend(-1);            s  =  false;         } else if (s.charCodeAt(0) === 93) {   // ']'   // [[]            this.extend(-1);            s  =  false;         } else if (this.limited) {   // at least single brackets            if (s.length >= join) {               this.suffix  =  s.substr(join - 1);               s            =  s.substr(0,  join - 2);            }            if (this.url(s)) {               s  =  false;            }         }   // not empty      }      if (s) {   // neither URL nor empty         if (later) {            this.extend(1);         }         this.closingBracket(s);         if (this.score) {            if (this.inPipe) {               this.pipeSymbols(mid - 2);               if (lack || this.lack) {                  s  =  analyze.substr(0, 1);                  if (this.start) {                     this.start  =  this.start + s;                  } else {                     this.start  =  s;                  }                  this.extend(32, 0);                  this.join++;                  this.lift  =  true;               }            }            if (this.score || this.show) {               this.analyze;            } else if (this.score) {   // ??? impossible     ! this.score               this.extend(-1);            }         }   // local      }   };   // .o.Wikilink.adjust

WikiLK.prototype.analyze =  function  { // Analyze bracket content fractions and aftermath // Precondition: //   Fractions .score, .show, .suffix are defined. // Uses: //   >  .o.Wikilink:: //      >  .ModeMap //      >  .mode //      >  .lead //      >  .inPipe //      >  .newFrom //      >  .newTo //      >  .start //      >  .index //      >  .ModeWiki //      >  .lack //      >  .next //      >< .score //      >< .show //      >< .suffix //      >< .nucleus //      >< .leap //       < .label //       < .lock //       < .shift //       < .move //      .target //      .title //      .unlink //      .context //      .magic //      .extend //      .lineFeedAhead //   .str.substrEnd //   .w.link.wiki.fore //   .str.isLetter // Requires: JavaScript 1.3  charCodeAt // 2013-03-06 PerfektesChaos@de.wikipedia var c,         linking, n,         s;      if (this.score) { if (this.mode !== this.ModeMap) {  // not Interwiki mapping this.target; }        if (! this.mode) {   // not Category: if (! this.lead) { this.unlink; }           this.label  =  (this.inPipe  &&  ! this.show); if (this.label) { this.show =  this.context; this.extend(2); }  // context style   title (Abc) }     }      if (! this.mode) {   // magic? this.magic; if (this.show) { this.title; }     }      if (this.lock) { if (this.newFrom === 2 &&  ! this.nucleus) { n =  this.score.length; if (n > 0) { this.nucleus =  n;            } }     }      if (this.leap) { if (this.start) { c =  WSTM.str.substrEnd(this.start, 1); } else if (this.index > 0) { c =  this.source.substr(this.index - 1,  1); } else { c =  false; n =  10; }        if (c) { n =  c.charCodeAt(0); }        if (n === 10  ||  n === 32) { this.leap =  false; } else { this.extend(32); this.move++; }     }      if (! this.mode) { if (this.show) {  // titled if (WSTM.str.isLetter(WSTM.str.substrEnd(this.show, 1))) { // c'td?              n  =  WSTM.w.link.wiki.fore(this.suffix, 0); if (n) { this.show =  this.show  +  this.suffix.substr(0, n); this.extend(16, n); if (n < this.suffix.length) { // TODO 2013-03-06  (n > this.suffix.length)     IMPOSSIBLE. Bug! this.suffix =  this.suffix.substr(n); } else { this.suffix =  false; }              }            }   // isLetter if (typeof(this.newTo) === "number") { if (this.newTo >= this.inTerm) { if (typeof(this.score) === "string") { this.score =  this.score + "|" + this.show; this.show  =  false; }              }            }         }   // titled if (this.newFrom === 2) { this.mode =  this.ModeWiki; }     }      this.lineFeedAhead; if (typeof(this.newTo) === "number") { this.join =  (typeof(this.join) === "number"  ?  this.join                                                        :  0); if (this.newTo > this.join) { if (typeof(this.shift) === "boolean") { this.shift =  (this.score ? this.score : ""); }        }         if (this.newFrom <= 0) { linking =  (typeof(this.score) === "string") && this.newTo > this.join; if (linking) { if (typeof(this.start) === "string") { if (WSTM.str.substrEnd(this.start, 2) === "") {                    linking  =  this.leap;                  }               }            }            this.shift  =  (this.leap ? " " : "")                           +  (linking ? "[[" : "")                           +  (this.shift ? this.shift : "");         }         if (this.start  &&  this.newFrom <= 0) {            this.shift  =  this.start  +  (this.shift ? this.shift : "");         }         n  =  this.join  +  this.inTerm  +  (this.lack ? 1 : 2);         if (this.newTo  >=  n) {            if (this.score  &&  this.mode !== this.ModeFile) {               this.shift  =  (this.shift ? this.shift : "")  +  "";            }            if (this.suffix && this.next) {               s  =  this.suffix;               if (typeof(this.next) === "number") {                  s  =  s.substr(0, this.next);               }               this.shift  =  (this.shift ? this.shift : "")  +  s;            }   // suffix         }   // newTo      }      if (this.score) {         n  =  this.score.length;         if (n > this.move) {            this.move  =  n;         }      }   };   // .o.Wikilink.analyze

WikiLK.prototype.capitalize =  function  { // Capitalize wikilink if appropriate // Precondition: //   address  -- string with link target // Uses: //   >  .o.Wikilink:: //      >  .sister //      >  .show //      >< .score //      .extend //   .hooks.fire // 2012-09-27 PerfektesChaos@de.wikipedia var low2up, s,         start   =  this.score.substr(0, 1), swap   =  start.toUpperCase; if (start !== swap) {  // 1st letter downcased low2up =  true; if (this.sister) { s      =  this.sister.substr(0, 5) + ":"; low2up =  (s.substr(0, 5)  !==  "wikt:"); }  // no upcasing in Wiktionary if (low2up) { low2up =  WSTM.hooks.fire("wikilink_lower1",                                       [ this.score, this.show ]); }  // upcasing appropriate if (low2up) { this.score =  swap + this.score.substr(1); this.extend(1); }  // upcase }  // 1st letter downcased };  // .o.Wikilink.capitalize

WikiLK.prototype.category =  function  { // Handle category of page // Uses: //   >  .w.encountered.DEFAULTSORT //   >  .g.wTitle //   >  .g.wNsNumber //   >  .o.WikiTom.LinkCategory //   >  .o.Wikilink:: //      >  .sister //      >  .label //      >  .ModeCat //      >< .score //      >< .show //      >< .inPipe //       < .lock //       < .keySort //       < .mode //       < .special  //  -> schedule //       < .leader //      .extend //   .w.elem.sortkey //   .hooks //   .w.link.wiki.further // 2016-01-23 PerfektesChaos@de.wikipedia var s =  this.score.substr(0, 1), leave; if (s.toUpperCase !== s) { this.score =  s.toUpperCase + this.score.substr(1); this.extend(1); }     if (! this.sister) {   // if (this.inPipe) {  // if (this.show) { s =  WSTM.w.elem.sortkey(this.show); if (typeof(s) === "string") { if (! s.length) { this.show =  false; } else { this.show =  s;                  } this.extend(2); }              if (this.label) { this.show =  false; } else { if (WSTM.w.encountered.DEFAULTSORT) { if (WSTM.hooks.fire("sortkey_ignorecase")) { leave =  (this.show.toUpperCase ===                                   WSTM.w.encountered.DEFAULTSORT                                       .toUpperCase); } else { leave =  (this.show ===                                   WSTM.w.encountered.DEFAULTSORT); }                 } else if (WSTM.g.wNsNumber === 0) { if (WSTM.hooks.fire("sortkey_ignorecase")) { leave =  (this.show.toUpperCase ===                                   WSTM.g.wTitle.toUpperCase); } else { leave =  (this.show === WSTM.g.wTitle); }                 }                  if (leave) { this.show =  false; this.extend(2); }              }   // not possibly erroneous "|]]" }  // non-empty sortkey if (this.show) {  // non-empty sortkey if (WSTM.str.substrEnd(this.show, 1) ===  "|") { this.show =  this.show.substr(0,                                                 this.show.length - 1); }              if (this.lock) { this.keySort =  this.show.length; }              this.score  =  this.score + "|" + this.show; this.show  =  false; this.extend(2); this.inPipe =  false; } else {  // empty/emptied sortkey this.extend(1); }  // sortkey }  // pipe symbol this.mode    =  this.ModeCat; this.special =  this.score; this.leader  =  WSTM.w.link.wiki.further(                                   { mode:   WSTM.o.WikiTom.LinkCategory,                                     source: this.score } ); if ( ! this.lead             &&   typeof WSTM.lang.write === "object" ) { this.lead =  WSTM.lang.write.lead; }     }   // ! sister };  // .o.Wikilink.category

WikiLK.prototype.closingBracket =  function (adjust) { // Check or complete link content for second closing bracket // Precondition: //   adjust  -- string with link inner content //   Neither URL nor empty // Postcondition: //   this.score defined if appropriate // Uses: //   >  .o.Wikilink:: //      >  .ModeFile //      >< .suffix //      >< .mode //      >< .lapsus //       < .score //      .extend //   .errors.found // Requires: JavaScript 1.3  charCodeAt // 2013-01-22 PerfektesChaos@de.wikipedia var less =  true, n;     if (this.suffix) { if (this.suffix.charCodeAt(0) === 93) {  // ']' this.score =  adjust; if (this.suffix.length < 2) { this.suffix =  false; } else { this.suffix =  this.suffix.substr(1); if (this.suffix.charCodeAt(0) === 93                  &&false) {   // ']'   //////////////////////////////// n           =  this.suffix.length; this.lapsus =  true; this.suffix =  this.suffix.substr(1); this.extend(16, 3); if (this.suffix.charCodeAt(0) === 93) {  // ']' this.suffix =  this.suffix.substr(1); this.extend(16, 4); }                 WSTM.errors.found("tooManyRightBrackets",                                    true,                                    "" + this.score + "]"); }           }            less  =  false; }     }      if (less) { if (this.mode === this.ModeFile) { this.score =  adjust; } else { WSTM.errors.found("secondClosingBracket", true, adjust); if (this.lapsus) { this.extend(-1); } else {  // append ']' this.score =  adjust + "]"; this.extend(9); this.lapsus =  true; }        }      }   };   // .o.Wikilink.closingBracket

WikiLK.prototype.context =  function  { // Retrieve context title for fool:bar (Abc) // Postcondition: //   Returns link title //   RegExp was used. // Uses: //   >  .o.Wikilink:: //      >  .score //      >  .sister //      >< .rePipeTrick //      >< .reSpace //   >  .g.wNsIds //   .g.fetch //   .str.trimL // Requires: JavaScript 1.3  fromCharCode // Info: "Pipe trick" //      * Strip off and use as title //      ** anything looking like a namespace -- CSI: Miami //      ** bracketed suffix. //      ** comma ',' does not matter. // 2013-03-08 PerfektesChaos@de.wikipedia var got, r,         sB   =  "(" + String.fromCharCode(65288),          sE   =  ")" + String.fromCharCode(65289), // FF08 FF09 FULLWIDTH PARENTHESIS re  =  sB + sE; re  =  "([^" + re + "]*[^ " + re + "]) *" + "[" + sB + "].+[" + sE + "]"; re  =  new RegExp(re, ""); if (! this.rePipeTrick) { sB               =  "(" + String.fromCharCode(65288);         sE                =  ")" + String.fromCharCode(65289); // FF08 FF09 FULLWIDTH PARENTHESIS this.rePipeTrick =  sB + sE; this.rePipeTrick =     "([^" + this.rePipeTrick + "]*"                              +   "[^ " + this.rePipeTrick + "]) *" + "([" + sB + "].+[" + sE + "])$"; this.rePipeTrick =  new RegExp(this.rePipeTrick, ""); }     got  =  this.rePipeTrick.exec(this.score); r   =  (got ? got[1] : this.score); got =  r.indexOf(":", 1); if (got > 0) { if (this.sister) { r   =  r.substr(this.sister.length); got =  r.indexOf(":"); }     }      if (got) { if (WSTM.g.fetch(WSTM.g.wNsIds, "wgNamespaceIds")) { if (! this.reSpace) { this.reSpace =  new RegExp(" +", "g"); }           sB  =  r.substr(0, got).toLowerCase; sB =  sB.replace(this.reSpace, "_"); if (! WSTM.g.wNsIds[ sB ]) { got =  0; }        }         if (got) { r =  WSTM.str.trimL(r.substr(got + 1),  true,  false); }     }      return  r;   };   // .o.Wikilink.context

WikiLK.prototype.extend =  function (assign, around) { // Extend replacement region // Precondition: //   assign  -- kind of extension //              -1  -- no extension //               1  -- target region (beginning at 2) //               2  -- title region //               3  -- end of both target and title //               4  -- begin at 0, not at 2 //               8  -- end after first terminating bracket //               9  -- second terminating bracket appended //              16  -- append afterward characters //              32  -- begin and terminate at least at 0 //   around  -- position extending outside brackets //              assign=16   after second bracket //              assign=32   before first bracket // Uses: //   >  .o.Wikilink:: //      >  .inPipe //      >  .inTerm //      >< .newFrom //      >< .newTo // 2013-01-22 PerfektesChaos@de.wikipedia var n;     switch (assign) { case -1 : this.newFrom =  2; this.newTo   =  false; break; case 1 : case 2 : case 3 : case 8 : case 9 : case 16 : switch (assign) { case 1 : n =  (this.inPipe ? this.inPipe : this.inTerm); break; case 2 : case 3 : n =  this.inTerm; break; case 8 : n =  this.inTerm + 1; break; case 9 : n =  this.inTerm; break; case 16 : n =  this.inTerm + 2; if (around) { n +=  around; }                 break; }  // switch assign if (typeof(this.newTo) === "number") { if (n > this.newTo) { this.newTo =  n;               } } else { this.newTo =  n;            } break; case 4 : if (this.newFrom > 0) { this.newFrom =  0; }           break; case 32 : if (this.newFrom > 0) { this.newFrom =  0; }           if (around) { this.newFrom -=  around; }           if (typeof(this.newTo) !== "number") { this.newTo =  0; }           break; }  // switch assign };  // .o.Wikilink.extend

WikiLK.prototype.file =  function (analyze, ahead) { // Analyze Media embedding in File: namespace // Precondition: //   analyze  -- string with link content beginning after ''      //    ahead    -- position after ':' of namespace      // Postcondition:      //    Returns found object, or false      // Uses:      //    >  .o.Wikilink::      //       >  .off      //       >  .index      //       >  .node      //       >  .ModeFile      //        < .mode      //    .o.WikiTom.find      // 2015-11-02 PerfektesChaos@de.wikipedia      var r  =  this.off.find("",                              this.index + 2,                              this.node,                              true,                              false,                              false); if (r) { if (r.k === this.node) { this.filer(analyze, ahead, r.i, true); } else { this.filer(analyze,                      ahead,                       analyze.length + 1,                       false); }     }      return r;   };   // .o.Wikilink.file

WikiLK.prototype.filer =  function (analyze, ahead, after, all) { // Analyze leading section of Media embedding in File: namespace // Precondition: //   analyze  -- string with embedding start beginning after       //                truncated if links, templates, comments inside      //    ahead    -- position after ':' of namespace      //    after    -- position of termination in analyze (before ) //   all      -- full caption seems to be present // Uses: //   >  .o.Wikilink:: //      >  .index //      >  .node //      >  .ModeFile //      >< .newTo //       < .limited //       < .mode //       < .inTerm //       < .inPipe //       < .score //       < .last //       < .sequence //      .filing //      .str.trim //      .target //      .extend //   >  .w.link.namespace.nsFile //   .str.trim //   .w.link.namespace.fetch //   .mod.wikilink //   .w.img.format //   .str.substrEnd // 2017-09-13 PerfektesChaos@de.wikipedia var inside =  false, leap   =  false, loose  =  false, s      =  analyze.substr(ahead), slice  =  false, join   =  s.indexOf("|"), n;     this.limited  =  true; this.mode    =  this.ModeFile;   // (not Media: nor :File:) this.inTerm  =  (all  ?  after - this.index - 2  :  after); if (join > 2) { if (s.substr(0,join).indexOf("]]") < 0) { if ((/\|\s*$/.test(s))  &&   s.indexOf("|") < 0) { this.last =  true; }           this.inPipe  =  join; } else { join        =  -2; this.inPipe =  false; n           =  s.indexOf("\n{|"); if (n >= 0) { s =  s.substr(0, n); }        }      }      if (join > 2) { if (join + ahead <  after) { this.inPipe =  join + ahead; this.score  =  s.substr(0, join); slice       =  s.substr(join + 1); n           =  slice.indexOf("\n{|");   // /\n:*{|/ if (n >= 0) { slice =  slice.substr(0, n); }           inside  =  slice.indexOf("");            loose   =  (slice.indexOf("") < 0  &&  /\s$/.test(slice)); slice =  slice.substr(0,  this.inTerm - this.inPipe - 1); if (inside < 0 &&  n >= 0) { inside =  n;            } if (inside >= 0  &&                ahead + join + inside  <=  this.inTerm) { slice =  this.filing(ahead + join + 3); if (slice) { this.inTerm =  this.inPipe + slice.length + 2; if (/\s$/.test(slice)) { loose =  true; }                 leap  =  true; } else { this.inPipe =  false; }           } else if (all) { this.last =  true; }        }      }      if ( ! this.inPipe) { this.score =  s.substr(0,  this.inTerm - ahead); }     this.target;// TODO Ensure capitalization  CamelCase  Media title n          =  this.score.length; this.score =  WSTM.str.trim(this.score); if (n !== this.score.length) { n =  this.score.length - n;         if ( this.inPipe) { this.inPipe +=  n;         } this.inTerm +=  n;      } this.score =  WSTM.w.link.namespace.fetch(                                            WSTM.w.link.namespace.nsFile,                                            false,                                            false) + ":" + this.score; if (WSTM.mod.wikilink) {// TODO // WSTM.w.link.replace.flip(WSTM.mod.wikilink,     //                          this.score,      //                          false,      //                          false,      //                          "File:"); }     n  =  this.score.length; if (this.score !==  analyze.substr(0, n)) { this.shift =  this.score; }     if (this.inPipe) { this.sequence =  slice; slice =  WSTM.w.img.format(this); if (typeof(slice) === "string") { if ( ! this.shift) { this.shift =  this.score; }           if (slice.length) { this.shift  =  this.shift + "|" + slice + (leap ? "|" : ""); this.newTo +=  ahead  -  (leap ? 0 : 1); } else if (this.last) { this.shift =  this.shift + "|"; }           if (loose) { n =  s.length + this.inTerm - this.inPipe + 1; if (n > this.newTo) { this.newTo =  n;               } this.shift =  this.shift + s.substr(this.inTerm - ahead) + " ";           }            this.inPipe  =  false; }     } else { if (this.shift) { this.newTo =  this.inTerm + 2; loose      =  true; }        this.inTerm  =  n;         this.move    =  n;      } if (this.shift) { if (loose) { this.extend(3); } else { this.extend(1); this.newTo +=  2; }     }   };   // .o.Wikilink.filer

WikiLK.prototype.filing =  function (after) { // Shift Media title with links inside to the end of transclusion // Precondition: //   after  -- position of pipe in transclusion // Postcondition: //   Returns string with parameters, or false if nothing to do      // Uses: //   >  .o.Wikilink:: //      >  .source //      >  .off //      >  .index //      >  .node //       < .inPipe //    < .o.WikiTom.learnt //   .o.WikiTom.find //   .o.WikiTom.flip // 2015-10-12 PerfektesChaos@de.wikipedia var gotE  =  false, i     =  this.index + after, j     =  i,          k      =  this.node, n     =  0, loop  =  true, r     =  false, tom   =  this.off, // table  =  tom.find([/\n:*{|/, 0],      //                     i, k, true, false, false); table =  tom.find("\n{|", i, k, true, false, false), gotB, m,         s; //if (table) { //mw.log(WSTM.debugging,".o.Wikilink.filing table",0,table); //}     do { gotB =  tom.find("", j, k, true, false, false);         gotE  =  tom.find("", j, k, true, false, false); if (table) { if (table.k < gotE.k ||                (table.k === gotE.k  &&  table.i < gotE.i)) { gotB =  false; }        }         loop  =  (gotB && gotE); if (loop) { //mw.log(WSTM.debugging,".o.Wikilink.filing gotB && gotE",0); if (! n) { s =  tom.fetch(this.node); if (gotB.k === this.node) { s =  s.substr(0, gotB.i); }              n  =  s.lastIndexOf("|"); }           if (gotB.k === gotE.k) { loop =  (gotB.i < gotE.i); } else { loop =  (gotB.k < gotE.k); }           if (loop) { j =  gotE.i + 2; k =  gotE.k;            } else { r =  s.substr(i,  n - i); gotE =  false; }        }      } while (loop);   // do //mw.log(WSTM.debugging,".o.Wikilink.filing +loop",0); if (gotE) { //mw.log(WSTM.debugging,".o.Wikilink.filing gotE",0); s =  tom.fetch(gotE.k); s =  s.substr(0, gotE.i); m =  s.lastIndexOf("|"); if (s.substr(m + 1, 1) ===  "}") { m =  -1; }        if (m >= j) { s =  s.substr(m); j =  s.indexOf("[[");            if (j > 0  &&  gotE.k === this.node) {               n  =  j;            } else {               tom.flip(gotE.k, m, s.length, "");               tom.flip(this.node,  i - 1,  0,  s);               n  +=  s.length;            }         }         r  =  tom.fetch(this.node).substr(i,  n - i);      }      return r;   };   // .o.Wikilink.filing

WikiLK.prototype.language =  function (ahead) { // Analyze wikilink beginning whether it starts with language // Check language identification, remove wgContentLanguage // Precondition: //   ahead     -- position of ':' in this.score (>0) //   .justify  -- behaviour if no explicit "lang" identified //                1        adjust with wgContentLanguage //                2        adjust with "en" //                false (else) //                         do nothing than trimming and downcasing // Postcondition: //   Returns true iff language stripped off from this.score //   RegExp was used. // Uses: //   >  .g.projLang //   >  .g.projLone //   >  .lang.write.linklang //   >  .lang.write.lead //   >  .o.Wikilink:: //      >  .mode //      >  .ModeFile //      >< .justify //      >< .score //       < .lead //       < .slang //      .extend //   .str.trimL //   .lang.flop //   .str.trimR // 2014-10-10 PerfektesChaos@de.wikipedia var learnt =  false, left   =  false, r      =  false, s      =  this.score.substr(0, ahead), slang  =  false,   // language specification story;             // heading part of article title s =  WSTM.str.trimL(s, false); if (s.length < ahead) { learnt =  true; }  // trimmed story =  WSTM.lang.flop(s); if (! story) { slang =  WSTM.str.trimR(s, false).toLowerCase; if (slang !== s) { learnt =  true; }     }   // matching lang? if (! slang) { if (this.justify) { switch (this.justify) { case 1 : slang  =  false; learnt =  story; break; case 2 : slang  =  "en"; learnt =  true; break; }  // switch this.justify left =  true; } else if ( typeof WSTM.lang.write === "object" ) { if (this.mode !== this.ModeFile) { slang     =  WSTM.lang.write.linklang; this.lead =  WSTM.lang.write.lead; learnt    =  true; }        }      }      if (slang === WSTM.g.projLang) { if (! WSTM.g.projLone) { slang  =  false; learnt =  true; }     }      if (learnt || slang || story) {   // language or similar identified this.score =  this.score.substr(ahead + 1); if (story) { this.score =  story + ":" + this.score; slang      =  false; } else { this.score =  WSTM.str.trimL(this.score, false); if (left) { this.score =  s + ":" + this.score; }        }         if (slang) { this.slang =  slang + ":"; r          =  true; }        this.extend(1); this.justify =  false; } else { if (this.justify) { if (this.lead) { this.lead =  false; this.extend(1); }        }      }      return r;   };   // .o.Wikilink.language

WikiLK.prototype.lineFeedAhead =  function  { // Ensure that a category or interlanguage starts on a new line // Uses: //   >  .o.Wikilink:: //      >  .mode //      >  .ModeIw //      >  .ModeWiki //      >  .ModeCat //      >  .slang //      >  .show //      >  .source //      >  .index //      >< .start //      >< .move //      .extend //   .util.isO_639_1      .lang.flop //   .errors.found //   .str.isBlank // Requires: JavaScript 1.3  charCodeAt // 2017-01-30 PerfektesChaos@de.wikipedia var c, k, s, m;     if (this.mode === this.ModeIw) { if (this.slang.length === 3) {  // like "bd:" if (WSTM.lang.flop(this.slang.substr(0, 2))) { this.mode =  this.ModeWiki;   // downgrade   "bd"/"wd" }  // not a language code }  // A2 language code if (this.mode === this.ModeIw) {  // still interlanguage if (this.show) { WSTM.errors.found("interlanguageTitled",                                false,                                 this.score + "|" + this.show); this.show =  false; }  // titled }     }   // interlanguage supposed if (this.mode === this.ModeCat ||  this.mode === this.ModeIw) { if (this.start) { if (this.start >= 3) { s =  this.start; k =  s.length - 3; c =  s.charCodeAt(k); }        } else { if (this.index > 0) { s =  this.source; k =  this.index - 1; c =  s.charCodeAt(k); } else { c =  false; }        }         if (c  &&  c !== 10) { m =  0; while (WSTM.str.isBlank(c, true)) { m++; if (! k) { break;  // while }              k--; c =  s.charCodeAt(k); }           if (c === 10) { if (this.start) { this.start =  s.substr(0,  k - 2); } else { this.start =  ""; }              this.extend(32, m); this.move -=  m + 2; } else { // TODO 2016-06 if (this.start) { k          =  this.start.length - 2; this.start =  this.start.substr(0, k)  +  "\n"; } else { this.start =  "\n"; }              this.extend(32);   // 2017-01-30 (32,1) -> (32) this.move++; }        }   // no break }  // category or interlanguage };  // .o.Wikilink.lineFeedAhead

WikiLK.prototype.magic =  function  { // Analyze wikilink whether it is actually a magic word // Precondition: //   Neither File nor Category // Uses: //   >  .o.Wikilink:: //      >  .show //      >  .score //      .magic_ISBN // 2010-10-01 PerfektesChaos@de.wikipedia var s =  (this.show  ?  this.score + "|" + this.show                            :  this.score); if (s.indexOf("ISBN") >= 0) { this.magic_ISBN; }     /*         PMID Nummer   min.6 Richtig: PMID 4957203 Falsch: PMID:4957203 Falsch: PubMed 4957203 RFC ISSN DOI gleichrangig Linkziele schützen */  };   // .o.Wikilink.magic

WikiLK.prototype.magic_ISBN =  function  { // Analyze wikilink and context whether it is actually magic ISBN // Precondition: //   Wikilink contains magic word "ISBN" in some way // Uses: //   >  .g.re.ISBN //   >  .o.Wikilink:: //      >  .suffix //      >  .ModeNull //      >< .show //      >< .score //       < .inPipe //       < .mode //       < .shift //     .extend //   .w.elem.isbn.format //   .str.substrEnd // Requires: JavaScript 1.3  charCodeAt // 2015-07-29 PerfektesChaos@de.wikipedia var found =  false, k,         later, n,         narrow, swap; if (this.show) { narrow =  this.show.length; swap   =  ">"  +  this.show; if (narrow > 7) { if (narrow >= 14) { swap =  swap  +  this.suffix; } else { swap =  false; }        }         if (swap) { swap  =  swap + "\t"; found =  WSTM.g.re.ISBN.exec(swap); }        if (swap && found && found.index) { found =  false; }        if (found) { k    =  0; n    =  swap.length; swap =  WSTM.w.elem.isbn.format(found); if (! swap) { swap =  found[0]; }  // unchanged if (WSTM.str.substrEnd(swap, 1) ===  "\t") { swap =  swap.substr(0,  n - 1); if (narrow <= 7) { k--; }           }   // end of source this.shift  =  swap.substr(1); if (narrow <= 7) { k +=  found[0].length - 5; } else { k +=  2; }           this.extend(16, k); }  // |ISBN]] + number }     if (!  (found || this.show)) { later =  (this.score === "ISBN"); if (later) { swap =  "ISBN " + this.suffix; } else { swap =  this.score; }        swap   =  ">" + swap + "\t"; found =  WSTM.g.re.ISBN.exec(swap); if (found && found.index) { found =  false; }        if (found) { k    =  (later  ?  found[0].length - 6  :  0); swap =  WSTM.w.elem.isbn.format(found); if (! swap) { swap =  found[0]; }  // unchanged n =  swap.length - 1; if (swap.charCodeAt(n) === 9) {  //  \t swap =  swap.substr(0, n); if (later) { k--; }           }            this.extend(16, k); this.shift =  swap.substr(1); }  // [[ISBN + number      }      if (found) {         this.extend(4);         this.show    =  false;         this.score   =  false;         this.inPipe  =  false;         this.mode    =  this.ModeNull;      }   };   // .o.Wikilink.magic_ISBN

WikiLK.prototype.namespace =  function (ahead) { // Analyze wikilink beginning whether it starts with namespace // Precondition: //   ahead  -- position of ':' in this.score (>0) // Uses: //   >  .o.Wikilink:: //      >  .sister //      >  .slang //      >  .lead //      >  .inPipe //      >< .score //      >< .show //       < .nucleus //       < .lock //      .extend //      .category //      .specials //      .capitalize //   >  .w.link.namespace.nsCategory //   >  .w.link.namespace.nsSpecial //   >  .w.link.namespace.nsPage //   .w.link.namespace.furnish //   .w.link.namespace.fetch //   .w.link.wiki.decode // 2012-10-01 PerfektesChaos@de.wikipedia var space =  this.score.substr(0, ahead), key   =  WSTM.w.link.namespace.furnish(space,                                                  this.slang,                                                  this.sister), s,         swap; if (key) {  // relevant namespace? s          =  (this.sister || this.slang  ?  "en"  :  false); this.score =  this.score.substr(ahead + 1); swap       =  WSTM.w.link.namespace.fetch(key, s, this.score); if (swap) { if (space !== swap) { this.extend(1); }           space  =  swap; }        if (this.lead  &&  ! this.sister) {   // :File:  or  :Category: this.sister =  ":"; this.extend(1); }        s  =  WSTM.w.link.wiki.decode(this.score,                                       true, false, true, true); if (s) { this.score =  s;            this.extend(1); }        if (this.lock  &&  ! this.sister  &&  this.show) { this.nucleus =  space.length + 1 + this.score.length; if (this.nucleus + 2 !==  this.inPipe) { this.extend(1); }        }         switch (key) { case WSTM.w.link.namespace.nsCategory : this.category; break; case WSTM.w.link.namespace.nsSpecial : this.specials; break; }  // switch key if (this.score) { this.capitalize; this.score =  space + ":" + this.score; }     }   // key };  // .o.Wikilink.namespace

WikiLK.prototype.newline =  function (analyze, address) { // Repair line break within wikilink, if appropriate // Precondition: //   analyze  -- string with link inner content //   address  -- position of '\n' in environment (>1) // Postcondition: //   Returns repaired analyzed string, or false // Uses: //   >  .o.Wikilink:: //      >  .inTerm //      >  .inPipe //      >  .join //      >< .score //       < .lapsus //      .extend //    < .mod.lazy //   .str.setChar // 2012-05-09 PerfektesChaos@de.wikipedia var maxd =  50, newl, r    =  analyze, leak =  (address < maxd                    ||   this.inTerm - address  <  maxd); if (leak) { this.extend(3); } else if (this.inPipe) { if (address < maxd) {  // left of pipe leak =  (this.inPipe - address  <  maxd); this.extend(1); } else {  // right of pipe leak =  (address - this.inPipe  <  maxd); this.extend(2); }     }      // TODO   maybe  [[File:      if (leak) {   // error detected and repairing         r     =  WSTM.str.setChar(analyze,  32,  address - 2);   // ' '         newl  =  r.indexOf("\n") + 2;         if (newl > 1  &&  newl < this.join) {   // newline(s) left            this.extend(-1);            r  =  false;         }         this.lapsus     =  true;         WSTM.mod.lazy   =  false;      } else {         this.extend(-1);         r  =  false;      }      return r;   };   // .o.Wikilink.newline

WikiLK.prototype.old2New =  function  { // Perform user defined replacements // Precondition: //   .mod.wikilink is defined. // Uses: //   >  .o.Wikilink:: //      >  .source //      >  .index //      >  .ModeNull //      >< .show //      >< .suffix //      >< .score //      >< .learn //      >< .start //      >< .mode //       < .next //      .extend //   >  .mod.wikilink //   .w.link.replace.flip //   .str.trimR //   .str.substrEnd // Requires: JavaScript 1.3  charCodeAt // 2013-12-11 PerfektesChaos@de.wikipedia var i,         j,          n,          s,          sB  =  this.source.substr(0,  this.index + 2), sE =  (this.show  ?  "|" + this.show  :  "")   +   "]]"   + (this.suffix ? this.suffix : ""), sO, x  =  WSTM.w.link.replace.flip(WSTM.mod.wikilink,                                          this.score,                                          sB, sE, "");      if (x) {         this.learn  =  true;         this.extend(1);         if (typeof(x) === "string") {            this.score  =  x;         } else {            if (x[0]) {               if (x[0] !== sB) {                  for (j = 0;  j < sB.length;  j++) {                     if (x[0].charCodeAt(j) !== sB.charCodeAt(j)) {                        break;   // for j                     }                  }   // for j               }            }            if (x[1]) {               j  =  x[1].indexOf(""); if (j >= 0) { mw.log(WSTM.debugging,                        ".o.Wikilink.old2New TODO ]] in replaced",                         2); }              j  =  x[1].indexOf("|"); if (j >= 0) { mw.log(WSTM.debugging,                        ".o.Wikilink.old2New TODO pipe in replaced",                         2); }              if (this.score !== x[1]) { this.score =  x[1]; this.extend(3); }           }            if (x[0]) { sO =  x[0]; n  =  sB.length; for (j = 0; j < n;  j++) { if (sO.charCodeAt(j) !== sB.charCodeAt(j)) { break;  // for j                  } }  // for j               if (j >= 0) { this.start =  sO.substr(j); }              j   =  n - j - 2; sB =  WSTM.str.substrEnd(this.start, 2); if (sB === "") {                 n           =  this.start.length - 2;                  this.start  =  this.start.substr(0, n);               } else {   // unlink                  this.extend(4);                  this.shift  =  this.start + this.score;                  this.mode   =  this.ModeNull;               }               if (j > 0) {                  this.extend(32, j);               }            }            if (x[2] === sE) {               x[2]  =  false;            }            if (x[2]) {               sO  =  x[2];               if ( ! this.mode) {                  this.mode  =  0;               }               if (x[3]) {                  this.shift   =  this.start + this.score + sO;                  this.mode    =  this.ModeNull;                  this.show    =  false;                  this.suffix  =  "";                  this.extend(4);                  this.extend(16, sO.length);   // 2013-12-11 //  -1  -- no extension //   1  -- target region (beginning at 2) //   2  -- title region //   3  -- end of both target and title //   4  -- begin at 0, not at 2 //   8  -- end after first terminating bracket //   9  -- second terminating bracket appended //  16  -- append afterward characters //  32  -- begin and terminate at least at 0 mw.log(WSTM.debugging,"WikiLK.old2New sO="+sO,0);   //2013-12-01               } else {                  j  =  sO.indexOf(""); if (this.mode <= 0 ||  ! j) { if (j >= 0) { n =  this.suffix.length; for (i = sO.length; i && n;  i--, n--) { if (this.suffix.charCodeAt(n)                              !== sO.charCodeAt(i)) { break;  // for i                           } }  // for i                        if (i || n) { this.extend(16, n); this.next =  i;                        } if (sO.charCodeAt(0) === 124) {  // '|' sO =  sO.substr(1); j--; }                       this.show    =  (j  ?  sO.substr(0, j)                                            :  false); this.suffix =  sO.substr(j + 2); }                    j  =  -1; if (x[0]) { this.extend(3); }                 } else { this.show =  false; }              }               if (j > 0) { s =  sO.substr(0, j); if (s.indexOf("[") < 0) { this.show  =  WSTM.str.trimR(s, true); j         +=  2; } else { j =  -2; }              } else if (j === 0) { j =  2; }              if (this.show) { i =  this.show.indexOf("|"); if (i > 0) { this.score  =  this.score + this.show.substr(0, i); this.show   =  this.show.substr(i + 1); }              }               if (this.suffix) { n =  this.suffix.length; } else { n =  0; }              this.extend(2); }           if (this.mode < 0) { this.start  =  false; this.show   =  false; this.score  =  false; this.inPipe =  false; }        }   // modified }  // user defined replacements };  // .o.Wikilink.old2New

WikiLK.prototype.pipeSymbols =  function (align) { // Analyze pipe symbol(s) within wikilink // Precondition: //   align  -- position of '|' in this.score  (>=0) // Uses: //   >  .o.Wikilink:: //      >  .ModeFile //      >< .score //      >< .mode //       < .lapsus //       < .show //      .extend //   .str.trimL //   .errors.found // 2012-10-18 PerfektesChaos@de.wikipedia var lead, less, mid, n,         s,          shine  =  this.score.substr(align + 1); if (align > 0) { this.score =  this.score.substr(0, align); } else { this.score =  false; }     s  =  WSTM.str.trimL(shine, false); n =  s.length; if (n < shine.length) { this.extend(2); }  // ltrim if (n === 0) { if (! this.score) {  // | WSTM.errors.found("meaninglessLinkTarget", true, ""); this.extend(-1); shine =  false; }     }      if (shine) { mid =  s.indexOf("|"); if (mid < 0) { this.show =  shine; } else {  // second pipe if (mid === 0) {  // directly following s   =  s.substr(1); mid =  s.indexOf("|"); this.extend(2); this.lapsus =  true; if (mid < 0) { s =  WSTM.str.trimL(s, false); if (! s.length) { s =  false; }              }            } else { less =  true; if (this.score) { lead =  false; less =  (this.mode !== this.ModeFile); } else {  // empty target, something like   b lead       =  true; this.score =  WSTM.str.trimR(s.substr(0, mid),                                                false); s          =  WSTM.str.trimL(s.substr(mid + 1),                                                false); mid        =  s.length; this.extend(2); }              if (less && s) { if (s.substr(0, mid).indexOf("{{") <  0) { WSTM.errors.found("multiplePipeSymbols",                                      lead,                                       "[["  +  (lead ? "|" : "")                                       +  this.score  +  "|"                                       +  s.substr(0, 50));                                        // this.source.substr(                     if (this.lapsus) {                        this.extend(-1);                        s  =  false;                     } else {                        this.lapsus  =  true;                     }                  }               }   // less            }            this.show  =  s;         }   // second pipe      }   };   // .o.Wikilink.pipeSymbols

WikiLK.prototype.project =  function (ahead) { // Analyze wikilink beginning whether it starts with project // Precondition: //   ahead  -- position of ':' in this.score (>0) // Postcondition: //   Returns true iff project stripped off from this.score //   RegExp was used. // Uses: //   >  .o.Wikilink:: //      >< .score //       < .lead //       < .sister //       < .justify //      .extend //   .str.trimL //   .str.camelCasing //   .w.link.projects.friend // 2012-12-06 PerfektesChaos@de.wikipedia var join, kind, sole =  "|commons|mediawiki|meta|", swap, r    =  false, s    =  this.score.substr(0, ahead); if (ahead === 1) { if (s === s.toUpperCase) { s =  false; // ":sv:S:t Eriksplan (tunnelbanestation)" }     }      if (s) { r =  WSTM.w.link.projects.friend(s, true); }     if (r) {   // project identified kind =  r[0]; swap =  r[1]; this.score =  WSTM.str.trimL(this.score.substr(ahead + 1),                                       false); if (this.score.length <  ahead + 1) { this.extend(1); }  // trimmed if (kind === 3) { if (sole.indexOf("|" + swap + "|") >  0) { this.sister =  swap + ":"; if (this.score.charCodeAt(4) === 58) {  // ':' join =  4; } else if (this.score.charCodeAt(5) === 58) {  // ':' join =  5; } else { join =  0; }              if (join) { s =  this.score.substr(0, join).toLowerCase; if (s === "file"  ||  s ===  "image") { swap =  this.score; join++; this.score  =  this.score.substr(join); this.score  =  WSTM.str.trimL(this.score, false); this.score  =  WSTM.str.camelCasing(this.score); this.lead   =  true; this.sister =  this.sister + "File:"; if (swap !==  this.sister + this.score) { this.extend(1); }                    kind  =  false; swap =  false; }              }            }         }         if (kind) { if (this.lead) {  // superfluous heading ':' this.extend(1); }           this.lead  =  true; if (swap) { this.sister  =  swap + ":"; this.justify =  kind; if (swap !== s) { this.extend(1); }           } else {   // itself this.justify =  2; this.extend(1); }        } else if (swap) {   // project major namespace this.score =  swap + ":" + this.score; this.extend(1); }  // mode }  // affiliated project return r;  };   // .o.Wikilink.project

WikiLK.prototype.specials =  function  { // Handle link into special namespace // Precondition: //   .score is defined, special namespace already stripped off. // Uses: //   >  .o.Wikilink:: //      >  .ModeNull //      >< .RE_ISBN //      >< .score //       < .inPipe //       < .show //       < .shift //       < .mode //      .extend //   .hooks.fire //   .util.code.isbn // 2017-01-01 PerfektesChaos@de.wikipedia var got, s   =  this.score.substr(0, 1); if (! WikiLK.RE_ISBN) { WikiLK.RE_ISBN =  "^([^/]+)" + "/(ISBN *)?" + "([-0-9]{9,}[0-9X]|[-0-9]{13,})$"; WikiLK.RE_ISBN =  new RegExp(WikiLK.RE_ISBN, "i"); }     if (s.toUpperCase !== s) { this.score =  s.toUpperCase + this.score.substr(1); this.extend(1); }     got  =  WikiLK.RE_ISBN.exec(this.score); if (got) { if (WSTM.hooks.fire("booksources", got[1])) { s   =  got[3]; got =  WSTM.util.code.isbn(s); if (got[0]) { if (got[1]) { s =  got[1]; }           }            this.extend(4); this.shift  =  "ISBN " + s;            this.extend(16, 0); this.inPipe =  false; this.show   =  false; this.score  =  false; this.mode   =  this.ModeNull; }     }   };   // .o.Wikilink.specials

WikiLK.prototype.target =  function  { // Analyze wikilink target // Precondition: //   .score is defined. // Uses: //   >  .o.Wikilink:: //      >  .ModeFile //      >  .justify //      >  .ModeIw //      >< .score //      >< .show //      >< .lead //      >< .slang //      >< .sister //       < .mode //       < .leap //       < .special //       < .leader //      .extend //      .project //      .language //      .namespace //      .capitalize //      .old2New //   >  .lang.chr.zwsp //   >  .lang.chr.zwnj //   >  .lang.chr.zwj //   >  .o.WikiTom.LinkInterWiki //   >  .mod.wikilink //   .w.link.filter //   .str.isBlank //   .str.trimL //   .w.link.wiki.target //   .w.link.wiki.further // Requires: JavaScript 1.3  charCodeAt   fromCharCode // 2012-11-06 PerfektesChaos@de.wikipedia var s    =  WSTM.w.link.filter(this.score,                                      this.show                                      ||  (this.mode === this.ModeFile)), join, label, lang, re; if (s) { this.score =  s;         this.extend(1); }  // undesired character removed if (WSTM.str.isBlank(this.score.charCodeAt(0), false)) { this.score =  WSTM.str.trimL(this.score.substr(1), true); if (! this.show) { this.leap  =  true; }     }      while (this.score.charCodeAt(0) === 58) {   // ':' this.lead  =  true; this.score =  WSTM.str.trimL(this.score.substr(1), true); }  // while leading ':' join =  this.score.indexOf(":"); if (join > 0) { label =  this.project(join); lang  =  false; if (! label) { lang =  this.language(join); }        if (label  ||  (lang && this.lead)) {   // one already in effect join =  this.score.indexOf(":"); if (join > 0) { if (label) {  //   project:lang:Lemma ?? this.language(join); } else if (this.lead) {  //   :lang:project:Lemma ?? this.project(join); }           }   // ':'  ':'         }         if (! this.slang             &&  this.justify === 2) {  // no lang, but needed this.slang =  "en:"; this.extend(1); this.lead =  true; }        if (this.slang) {   // lang detected // 200A  8203  ZERO WIDTH SPACE // 200B  8204  ZERO WIDTH NON-JOINER // 200C  8205  ZERO WIDTH JOINER if (WSTM.lang.chr.zwsp.indexOf(":" + this.slang) >=  0) { if (this.score.indexOf("&#x200A;") >= 0) { re =  new RegExp("&#x200A;", "g"); s  =  String.fromCharCode(8203); if (re.test(this.score)) { this.score =  this.score.replace(re, s); }              }            }            if (this.score.indexOf("&zw") >= 0) { if (WSTM.lang.chr.zwnj.indexOf(":" + this.slang) >=  0) { re =  new RegExp("&zwnj;", "g"); if (re.test(this.score)) { s          =  String.fromCharCode(8204); this.score =  this.score.replace(re, s); }              }               if (WSTM.lang.chr.zwj.indexOf(":" + this.slang)  >=  0) { re =  new RegExp("&zwj;", "g"); if (re.test(this.score)) { s          =  String.fromCharCode(8205); this.score =  this.score.replace(re, s); }              }            }            if (this.sister) { this.sister =  this.sister + this.slang; this.lead   =  true; } else if (this.lead) { this.sister =  ":" + this.slang; } else {  // (! this.lead) -- interlanguage this.mode    =  this.ModeIw;   // .interlanguage this.special =  this.slang + this.score; this.sister  =  this.slang; s            =  this.slang.substr(0,                                                  this.slang.length - 1); this.leader  =  WSTM.w.link.wiki.further(                                  { mode:   WSTM.o.WikiTom.LinkInterWiki,                                    source: s } ); }        }         join  =  this.score.indexOf(":"); }  // ':'      s  =  WSTM.w.link.wiki.target(this.score,  ! this.show); if (s) { this.score =  s;         this.extend(1); if (join > 0) {  // adjust join =  this.score.indexOf(":"); }     }      if (join > 0) {   // namespace? this.namespace(join); }  // namespace? if (this.show) { if (WSTM.str.isBlank(this.show.charCodeAt(0), false)) { this.show =  WSTM.str.trimL(this.show.substr(1), true); this.leap =  true; }        this.capitalize; }  // titled? if (this.sister) { this.score =  this.sister + this.score; }     if (this.lead  &&  ! this.sister) { if (this.score.charCodeAt(0) !== 47) {  // '/' this.lead =  false; }     }      if (WSTM.mod.wikilink && this.score) { this.old2New; }  // user defined replacements };  // .o.Wikilink.target

WikiLK.prototype.title =  function  { // Analyze wikilink title and representation // Precondition: //   this.show not a Category // Uses: //   >  .o.Wikilink:: //      >< .show //      >< .suffix //      >< .next //       < .leap //      .extend //   .str.trimR //   .str.isBlank //   .str.trimL // Requires: JavaScript 1.3  charCodeAt // 2012-12-27 PerfektesChaos@de.wikipedia var k,         leap, m =  this.show.length, n;     this.show  =  WSTM.str.trimR(this.show, false); n =  this.show.length; if (n < m) { leap =  false; if (this.suffix) { k =  this.suffix.charCodeAt(0); if (k === 10) { leap =  true; } else { leap =  WSTM.str.isBlank(k, true); }        }         if (leap) {   // whitespace follows this.extend(2); } else { this.suffix =  " "  +  (this.suffix ? this.suffix : ""); this.extend(16, 0); this.next =  (this.next ? this.next++ : 1); }     }   // rtrim if (WSTM.str.isBlank(this.show.charCodeAt(0), false)) { this.show =  WSTM.str.trimL(this.show.substr(1), false); this.extend(32); this.leap =  true; }  // ltrim };  // .o.Wikilink.title

WikiLK.prototype.unlink =  function  { // Analyze link whether it can be unlinked or merged with title // Precondition: //   Wikilink without leading colon ':' // Uses: //   >  .g.wTitle //   >  .g.wNsNumber //   >  .o.Wikilink:: //      >  .sister //      >  .subcase //      >  .off //      >  .onto //      >  .ModeNull //      >  .lapsus //      >< .score //      >< .show //      >< .suffix //      >< .next //       < .inPipe //       < .shift //       < .mode //      .extend //   .hooks.fire //   .str.deCapitalize //   .errors.found //   .w.link.wiki.fore //   .str.isLetter // 2016-08-17 PerfektesChaos@de.wikipedia var lower =  WSTM.hooks.fire("capitalize1"), sw    =  (lower ? WSTM.str.deCapitalize(this.score)                           : this.score), io, j,         n,          sh; if (! this.sister &&  WSTM.g.wNsNumber === 0) { io =  0; if (sw === this.subcase) {  // unlink io =  1; WSTM.errors.found("wikilinkSelf", false, false); } else if (sw.indexOf(this.subcase + "#") ===  0) {   // intern io =  2; }        if (io > 0) { if (this.off && this.onto) { if (this.off.isNodeInSpan(this.onto)) { io =  -1; }           }         }         if (io === 1) {   // unlink this.inPipe =  false; if (this.show) { this.shift =  this.show; this.show  =  false; } else { this.shift =  this.score; }           this.score  =  false; this.extend(4); this.extend(16, 0); this.mode =  this.ModeNull; } else if (io === 2) {  // internal this.score =  this.score.substr(WSTM.g.wTitle.length); this.extend(1); }     }   // same project if (this.show) { sh =  (lower ? WSTM.str.deCapitalize(this.show)                       : this.show); if (sw === sh &&  ! this.sister) { this.score =  this.show; this.show  =  false; this.extend(3); this.inPipe =  false; } else if (n &&  ! this.lapsus) { n =  sw.length; if (sw ===  sh.substr(0, n)                &&   WSTM.str.isLetter(sh.substr(n - 1,  1))                // Ferrari F2001B                //     !==       Ferrari F2001B                &&   WSTM.str.isLetter(sh.substr(n, 1))) { j =  WSTM.w.link.wiki.fore(sh, n); if (j) { if (j + n ===  sh.length) { this.score =  this.show.substr(0, n); this.show  =  this.show.substr(n); j          =  this.show.length; if (j > 0) { if (this.suffix) { this.suffix =  this.show + this.suffix; if (! this.next) { this.next =  j;                           } } else { this.suffix =  this.show; if (! this.next) { this.next =  true; }                       }                     }                     this.show  =  false; this.extend(16, 0); this.inPipe =  false; }  // link range unchanged }  // do not merge sophisticated link titles } else if (this.suffix) { if (sh ===  sw.substr(0, sh.length)) { j =  WSTM.w.link.wiki.fore(this.suffix, 0); if (j) { if (sw ===  sh + this.suffix.substr(0, j)) { this.suffix =  this.suffix.substr(j); this.show =  false; this.extend(16, j); this.inPipe =  false; }                 }               }            }         }   // title === target, or part }  // titled };  // .o.Wikilink.unlink

WikiLK.prototype.url =  function (adjust) { // Analyze bracket content whether it starts with an URL // Precondition: //   adjust  -- string with possible link target, left trimmed // Postcondition: //   Returns true iff adjust starts with an URL // Uses: //   >  .o.Wikilink:: //      >  .suffix //      >  .ModeWeb //       < .lapsus //       < .mode //       < .move //       < .shift //      .extend //   .util.isURL // Requires: JavaScript 1.3  charCodeAt // 2016-01-20 PerfektesChaos@de.wikipedia var r =  false, s;     switch (adjust.charCodeAt(1)) { case 47 :   //  '/' r =  (adjust.charCodeAt(0) === 47); break; case 116 :  //  't'            s  =  adjust.substr(0, 4); r =  (s === "http"  ||  s === "ftp:"); break; }  // switch charCodeAt(1) if (r &&  WSTM.util.isURL(adjust, true, true)) { r =  true; this.extend(3); this.extend(4); if (this.suffix) { if (this.suffix.charCodeAt(0) === 93) {  // ']' this.extend(8);  // post first bracket }  // terminating double brackets }  // follow this.lapsus =  true; this.mode   =  this.ModeWeb; this.move   =  adjust.length + 2; this.shift  =  "[" + adjust; }     return r;   };   // .o.Wikilink.url

WikiLK.prototype.getBracketShift =  function  { // Returns true if leading bracket has been shifted to the right // Uses: //   >  .o.Wikilink:: //      >  .leap //      >  .lift // 2012-10-10 PerfektesChaos@de.wikipedia return (this.leap || this.lift); };  // .o.Wikilink.getBracketShift

WikiLK.prototype.getChange =  function  { // Returns true if any need for changes // Uses: //   >  .o.Wikilink:: //      >  .shift //      >  .newTo //      >  .newFrom //      >  .source //      >  .index // 2012-09-19 PerfektesChaos@de.wikipedia var r =  (typeof(this.shift) === "string"); if (r) { r =  (typeof(this.newTo) === "number"); if (r) { if (this.newFrom === 2) { r =  (this.source.substr(this.index + 2,  this.newTo - 2)                      !==   this.shift); } else { r =  (typeof(this.newFrom) === "number"); }        }      }      return r;   };   // .o.Wikilink.getChange

WikiLK.prototype.getError =  function  { // Return true if severe syntax error detected (repaired if change) // Uses: //   >  .o.Wikilink:: //      >  .lapsus // 2010-10-01 PerfektesChaos@de.wikipedia return this.lapsus; };  // .o.Wikilink.getError

WikiLK.prototype.getIncrement =  function  { // Returns number of chars to advance in basic text // Uses: //   >  .o.Wikilink:: //      >  .move // 2010-10-01 PerfektesChaos@de.wikipedia return this.move; };  // .o.Wikilink.getIncrement

WikiLK.prototype.getLeader =  function  { // Returns true if category/interlanguage has been first occurrence // Uses: //   >  .o.Wikilink:: //      >  .leader // 2012-04-26 PerfektesChaos@de.wikipedia return this.leader; };  // .o.Wikilink.getLeader

WikiLK.prototype.getRemoveFrom =  function  { // Returns number of target chars since which to remove, or false // Uses: //   >  .o.Wikilink:: //      >  .newFrom //      >  .newTo // 2011-05-03 PerfektesChaos@de.wikipedia var k =  this.newFrom; if (k) { if (typeof(this.newTo) !== "number") { k =  false; }     }      return  k;   };   // .o.Wikilink.getRemoveFrom

WikiLK.prototype.getRemoveTo =  function  { // Returns number of target chars to be removed, or false // Uses: //   >  .o.Wikilink:: //      >  .newTo // 2010-10-01 PerfektesChaos@de.wikipedia return this.newTo; };  // .o.Wikilink.getRemoveTo

WikiLK.prototype.getSortkey =  function  { // Returns number of chars to be unconditionally locked, or false // Uses: //   >  .o.Wikilink:: //      >  .keySort // 2010-10-01 PerfektesChaos@de.wikipedia return this.keySort; };  // .o.Wikilink.getSortkey

WikiLK.prototype.getSpecial =  function  { // Returns category or interlanguage content // Uses: //   >  .o.Wikilink:: //      >  .special  //  -> schedule // 2010-10-01 PerfektesChaos@de.wikipedia return this.special; };  // .o.Wikilink.getSpecial

WikiLK.prototype.getTargetLength =  function  { // Returns number of target chars to lock, or false if not adhere // Uses: //   >  .o.Wikilink:: //      >  .lock //      >  .score //      >  .nucleus // 2010-10-01 PerfektesChaos@de.wikipedia //   [1]      var r  =  false; if (this.lock && this.score) { r =  (this.nucleus ? this.nucleus : this.score.length); }     return  r;   };   // .o.Wikilink.getTargetLength

WikiLK.prototype.getTextReplace =  function  { // Returns replacement string, maybe false if nothing to do     // Uses: //   >  .o.Wikilink:: //      >  .shift // 2010-10-01 PerfektesChaos@de.wikipedia return this.shift; };  // .o.Wikilink.getTextReplace

WikiLK.prototype.getTitle =  function  { // Returns title string, maybe false // Uses: //   >  .o.Wikilink:: //      >  .show // 2018-11-19 PerfektesChaos@de.wikipedia return this.show; };  // .o.Wikilink.getTitle

WikiLK.prototype.getType =  function  { // Returns special link type, or false if not a link //   .ModeNull    unlinked (magic, self-reference, or replaced) //   .ModeWeb     weblink //   .ModeWiki    normal wikilink //   .ModeFile    file (not Media:) //   .ModeCat     category //   .ModeIw      interlanguage //                special interwikilink (... etc.) //                page //   .ModeMap     special weblink (... etc.) // Uses: //   >  .o.Wikilink:: //      >  .mode // 2010-10-22 PerfektesChaos@de.wikipedia return this.mode; };  // .o.Wikilink.getType

WikiLK.prototype.getUserModified =  function  { // Returns true if user defined modification performed // Uses: //   >  .o.Wikilink:: //      >  .learn // 2010-10-01 PerfektesChaos@de.wikipedia return this.learn; };  // .o.Wikilink.getUserModified

WikiLK.prototype.set =  function (anode, access, adhere) { // Initialize existing wikilink object with node // Precondition: //   anode    -- parent node object //   access   -- anode position {i,k} where '[[' starts      //    adhere   -- true: freeze link targets      // Postcondition:      //    .o.Wikilink object was set and has been analyzed      //    RegExp was used.      // Uses:      //    WikiTom.toString      //    >  .o.Wikilink::      //        < .onto      //        < .node      //        < .index      //        < .lack      //        < .lock      //        < .off      //        < .move      //        < .newFrom      //        < .source      //       .init      //       .adjust      // 2013-02-15 PerfektesChaos@de.wikipedia      this.init;      this.off      =  anode;      this.node     =  access.k;      this.onto     =  anode.focus(this.node);      this.index    =  access.i;      this.lack     =  access.lack;      this.lock     =  adhere;      this.move     =  2;      this.newFrom  =  2;      this.source   =  this.onto.toString;      this.adjust(this.source.substr(this.index));   };   // .o.Wikilink.set

/*  WikiLK.prototype.setTarget  =  function (adjust) { // Initialize existing wikilink object with target string // Precondition: //   adjust   -- target string // Postcondition: //   .o.Wikilink object was set and has been analyzed //   RegExp was used. // Uses: //   WikiTom.toString //   >  .o.Wikilink:: //       < .source //      .init //      .adjust // 2010-11-06 PerfektesChaos@de.wikipedia this.init; this.source  =  adjust; this.adjust(this.source); };  // .o.Wikilink.setTarget

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

//---

mw.libs.WikiSyntaxTextMod.bb.WikiTom =  function (WSTM) { // Text and wikisyntax node // 2012-07-07 PerfektesChaos@de.wikipedia "use strict"; var WTOM;

WSTM.o.WikiTom =  function (assign, above) { // .constructor for new // Precondition: //   assign  -- string //   above   -- parent Node   root: null // Postcondition: //   Returns new WikiTom // 2012-03-12 PerfektesChaos@de.wikipedia this.parent   =  above;    // Object this.source   =  assign;   // String   basic or no change in children this.learnt   =  false;    // boolean  any (minor) modification this.lookup   =  true;     // boolean  may be searched this.limited  =  false;    // boolean  end of block this.mode     =  0;        // Number   kind of node // this.children              // Array    of WikiTom nodes // this.scope                 // String   group description return this; };  // .o.WikiTom .constructor WTOM =  WSTM.o.WikiTom;

// Definition of constants // 2016-01-12 PerfektesChaos@de.wikipedia WTOM.type           =  "WikiTom"; WTOM.WSTMinternal   =  -9; WTOM.TextOnly       =   1; WTOM.Nowiki         =  10; WTOM.Inline         =  11; WTOM.CodedBlock     =  13; WTOM.CodedInline    =  14; WTOM.CodeBlock      =  15; WTOM.Code           =  16; WTOM.Comment        =  18; WTOM.CommentOld     =  19; WTOM.Tag            =  20; WTOM.TagUnary       =  21; WTOM.TagBegin       =  22; WTOM.TagEnd         =  23; WTOM.TagBinary      =  29; WTOM.LinkWiki       =  31; WTOM.LinkFile       =  32;   // link to File: even without NS WTOM.LinkTemplate    =  33;   // link to Template: even in {{ WTOM.LinkCategory   =  34; WTOM.LinkExtWiki    =  35; WTOM.LinkInterWiki  =  36; WTOM.LinkWikiTotal  =  38;   // link to entire Link including WTOM.LinkWikiPipe   =  38; WTOM.LinkWeb        =  39; WTOM.MagicWord      =  41; WTOM.ParserFun      =  42; WTOM.Template       =  43; WTOM.TmplBrackets   =  44; WTOM.TmplParName    =  45; WTOM.TmplParAssign  =  46; WTOM.TmplParValue   =  47; WTOM.TmplParAccess  =  48; WTOM.FileParam      =  48; WTOM.Sortkey        =  50; WTOM.Table          =  60; WTOM.TableRow       =  61; WTOM.TableAttr      =  62;

WTOM.prototype.fade =  function  { // Deconstruct WikiTom node // Postcondition: //   Allocated members are destroyed. // Uses: //   >- this.children //   >- this.source //   this.children.fade // 2012-03-07 PerfektesChaos@de.wikipedia var i;  if (this.source) { delete this.source; }  if (this.children) { for (i = 0; i < this.children.length;  i++) { this.children[i].fade; }  // for i      delete this.children; } };  // .o.WikiTom.fade

WTOM.prototype.fetch =  function (assigned, ahead, alone) { // Access string in WikiTom // Precondition: //   assigned  -- sibling number to be accessed //   ahead     -- string position to start within assigned //                ahead < 0  count from end //   alone     -- retrieve charCodeAt only // Postcondition: //   Returns  string,  or false if assigned not found // Uses: //   >  this.children //   >  this.source //   this.children.toString //   mw.log // 2012-07-17 PerfektesChaos@de.wikipedia var j,      r  =  false; if (this.children) { if (assigned < this.children.length) { r =  this.children[assigned].toString; } else { mw.log(WSTM.debugging,               ".WikiTom.fetch node beyond length " + assigned,                3,                this); r =  ""; }  } else {   // plain string if (assigned) { mw.log(WSTM.debugging,               ".WikiTom.fetch bad node for string " + assigned,                3,                this); } else if (this.source) { r =  this.source; } else {  // empty page r =  ""; }  }   if (r && ahead) { if (ahead < 0) { j =  r.length + ahead; if (j > 0) { r =  r.substr(j); }     } else { r =  r.substr(ahead); }  }   if (r && alone) { r =  r.charCodeAt(0); }  return r; };   // .o.WikiTom.fetch

WTOM.prototype.find =  function (achieve, already, assigned, allow, alone, attached) { // Find term in WikiTom // Precondition: //   achieve   -- string or regexp info to be searched //                regexp info: //                [0]  RegExp object //                [1]  bracket number //   already   -- string position to start //   assigned  -- sibling number containing already //   allow     -- permit inspection of children //   alone     -- skip after element limitation since assigned //   attached  -- achieve is deeper than application request // Postcondition: //   Returns  false, if achieve not found,  or found info object //            .i      string position of beginning //            .k      sibling number //            .m      regexp match for bracket number, if regexp //            .r      regexp result array, if regexp //            .child  object if allow and attached //                    .i  string position of beginning in child //                    .k  child number //                    .o  WikiTom child itself //   RegExp was used. // Uses: //   >  this.lookup //   >  this.source //   >  this.children //   >  this.limited //   this.children.find   -- recursive // 2012-06-16 PerfektesChaos@de.wikipedia var join, node, e,      i,       j,       n,       s,       r     =  false; if (this.lookup) { join =  (typeof(already) === "number"  ?  already  :  0); node =  (typeof(assigned) === "number"  ?  assigned  :  0); if (typeof(this.children) === "object") { if (allow) { n =  this.children.length; j =  join; for (i = node; i < n;  i++) { e =  this.children[i]; r =  e.find(achieve, j, 0, attached, false, attached); if (r) { if (attached) { r.child =  { i: r.i,                                   k: r.k,                                   o: this }; }                 r.k  =  i;                  break;   // for i               } if (alone && e.limited) { break;  // for i               } j =  0; }  // for i         } } else if (! node) {  // plain string s =  this.source; n =  s.length; if (n) { if (join) { if (n > join) { s =  s.substr(join); } else { n =  0; }           }            if (n) { if (typeof(achieve) === "string") { j =  s.indexOf(achieve); if (j >= 0) { r =  { i:  join + j,                             k:  0 }; }              } else { j =  s.search(achieve[0]); if (j >= 0) { r =  s.match(achieve[0]); r =  { i:  join + j,                             k:  0, m: r[ achieve[1] ], r: r }; }              }            }         }      }   }   return r; };   // .o.WikiTom.find

WTOM.prototype.fixTab =  function (adjust) { // Remove tab chars from WikiTom, if any // Precondition: //   adjust  -- WikiTom to be changed, if necessary //              >  .mode //              >  .children //              >< .source // Postcondition: //   adjust is updated // Uses: //   >  this.CodedBlock //   this.fixTab   -- recursive //   .w.chr.fixTab //   this.fresh // 2012-03-23 PerfektesChaos@de.wikipedia var j,      s;   if (adjust.mode !== WTOM.CodedBlock) { if (adjust.children) { for (j = 0; j < adjust.children.length;  j++) { this.fixTab(adjust.children[j]); }  // for j      } else if (adjust.source) { s =  WSTM.w.chr.fixTab(adjust.source); if (s) { adjust.fresh(s); }     }   } };   // .o.WikiTom.fixTab

WTOM.prototype.flip =  function (assigned, ahead, amount, apply) { // Exchange string in WikiTom // Precondition: //   assigned  -- sibling number containing ahead //   ahead     -- string position to start exchange within assigned //   amount    -- number of characters to remove within assigned //   apply     -- string to be inserted // Postcondition: //   Returns entire node string, or false // Uses: //   >  this.children //   >  this.limited //   >  this.lookup //   >  this.mode //   >< this.source //   this.children.toString //   this.fade //   this.fresh //   .str.setString //   mw.log // 2012-04-30 PerfektesChaos@de.wikipedia var s =  false, r =  false, p;  if (this.children) { if (assigned < this.children.length) { r =  this.children[assigned].toString; } else { s =  "node beyond length"; }  } else {   // plain string if (assigned) { s =  "bad node for string"; } else { r =  this.source; }  }   if (s) { mw.log(WSTM.debugging,            ".WikiTom.flip " + s + " " + assigned,             3,             this); } else { r =  WSTM.str.setString(r, ahead, amount, apply); if (this.children) { s =  new WSTM.o.WikiTom(r, this); p =  this.children[assigned]; s.limited =  p.limited; s.lookup  =  p.lookup; s.mode    =  p.mode; this.children[assigned] =  s;         p.fade; s.fresh(false); } else { this.fresh(r); }  }   return r; };   // .o.WikiTom.flip

WTOM.prototype.flush =  function (avoid) { // Remove one child // Precondition: //   avoid  -- child number // Postcondition: //   this has been updated // Uses: //   >  this.children //   mw.log // 2012-04-23 PerfektesChaos@de.wikipedia var q =  this.children; if (q) { if (avoid < q.length) { q.splice(avoid, 1); } else { mw.log(WSTM.debugging,               ".WikiTom.flush bad node for discard; r=" + avoid                + " / " + q.length,                3,                this); }  } else { mw.log(WSTM.debugging,            ".WikiTom.flush no child to discard; r=" + avoid,             3,             this); } };  // .o.WikiTom.flush

WTOM.prototype.focus =  function (assign) { // Access particular child // Precondition: //   assign  -- child number // Postcondition: //   Returns WikiTom;  or  false if failed // Uses: //   >  this.children // 2012-03-25 PerfektesChaos@de.wikipedia var r =  false; if (this.children) { if (assign < this.children.length) { r =  this.children[assign]; }  } else if (assign) { mw.log(WSTM.debugging,            ".WikiTom.focus  has no children",             3,             this); } else { r =  this; }  return r; };   // .o.WikiTom.focus

WTOM.prototype.fold =  function (assign, align, append, allow) { // Split child with searchable string content // Precondition: //   assign  -- child number //   align   -- position where to split //   append  -- true: insert after;  false: insert before //   allow   -- true: permit initial string separation // Postcondition: //   Returns inserted WikiTom, even if string is empty; //           or  false if failed // Uses: //   >  this.source //   >  this.children //   mw.log // 2012-07-07 PerfektesChaos@de.wikipedia var r =  false, s;  if (this.children) { if (assign < this.children.length) { if (align) { r =  this.children[assign]; if (r.children) { r =  false; mw.log(WSTM.debugging,                     ".WikiTom.fold no string node: " + assign,                      3,                      this); } else { s =  r.source; if (align <= s.length) { if (append) { r.source =  s.substr(0, align); s        =  s.substr(align); } else { this.children[assign].source =  s.substr(align); s        =  s.substr(0, align); }              } else { r =  false; mw.log(WSTM.debugging,                        ".WikiTom.fold > string end: " + align,                         3,                         this); }           }         } else { s =  ""; }        if (r) { r =  new WSTM.o.WikiTom(s, this); this.children.splice((append ? assign+1 : assign), 0,  r); r.learnt =  this.learnt; }     } else { mw.log(WSTM.debugging,               ".WikiTom.fold invalid child number: " + assign,                3,                this); }  } else if (allow) { this.children =  [ new WSTM.o.WikiTom(this.source, this) ]; } else { mw.log(WSTM.debugging,            ".WikiTom.fold  has no children",             3,             this); }  return r; };   // .o.WikiTom.fold

WTOM.prototype.folder =  function (ahead, assign, after, adjacent) { // Subdivide separated section, even over multiple children // Precondition: //   ahead     -- begin position within assign //   assign    -- child number of begin //   after     -- end position within adjacent //   adjacent  -- child number of end // Postcondition: //   Returns inserted WikiTom // Uses: //   >  this.source //   >  this.children //   this.fold //   mw.log // 2012-03-18 PerfektesChaos@de.wikipedia var beg, end, r     =  false, i,      later, n,      s;   if (this.children) { if (adjacent < assign ||  adjacent > this.children.length) { mw.log(WSTM.debugging,               ".WikiTom.folder bad nodes for string; b="                + assign + " e=" + adjacent                + " / " + this.children.length,                3,                this); } else { r =  true; for (i = assign; i <= adjacent;  i++) { if (this.children[i].children) { mw.log(WSTM.debugging,                     ".WikiTom.folder no string: b=" + assign,                      3,                      this); r =  false; break;  // for i            } }  // for i         if (r) { beg =  false; end =  false; n   =  adjacent; if (after) { r =  this.fold(adjacent, after, false); if (r) { end =  r;                  n++; }           }         }         if (r) { i =  assign; if (ahead) { r =  this.fold(assign, ahead, true); if (r) { beg =  r;                  end  =  false; i++; n++; }           }         }         if (r) { s =  ""; if (end) { s =  end.source; }           if (i < n) { for (n = n-1; n > i;  n--) { s =  this.children[i].toString + s;               }   // for i               this.children.splice(i,  n - i - 1); }           if (beg) { s =  beg.source + s;            } this.children[i].source =  s;            r                        =  this.children[i]; }     }   } else { if (assign || adjacent) { mw.log(WSTM.debugging,               ".WikiTom.folder bad nodes for string b="                + assign + " e=" + adjacent,                3,                this); } else { later =  (after < this.source.length); n     =  (ahead ? 2 : 1)  +  (later ? 1 : 0); this.children =  new Array(n); i             =  0; if (ahead) { s                =  this.source.substr(0, ahead); this.children[0] =  new WSTM.o.WikiTom(s, this); i                =  1; }        s                 =  this.source.substr(ahead,  after - ahead); this.children[i] =  new WSTM.o.WikiTom(s, this); r                =  this.children[i]; if (later) { i++; s                =  this.source.substr(after); this.children[i] =  new WSTM.o.WikiTom(s, this); }        if (this.learnt) { for (i = 0; i < n;  i++) { this.children[i].learnt =  true; }  // for i         } }  }   return r; };   // .o.WikiTom.folder

WTOM.prototype.fork =  function (at, advance, ancestor, assign, attach) { // Introduce deeper level // Precondition: //   at        -- child number of begin //   advance   -- child number of end;  advance >= at   //    ancestor  -- name of family (tag etc.) //   assign    -- family mode //   attach    -- true: 'include' tag // Postcondition: //   Nodes from at until advance (including) created at parent at. //   Returns parent, if succeeded, else false // Uses: //   >< this.children //   >< this.parent //    < this.mode //    < this.scope //    < this.source //   mw.log // 2012-04-14 PerfektesChaos@de.wikipedia var i,      r  =  false; if (this.children) { r          =  new WSTM.o.WikiTom(false, this); r.children =  this.children.slice(at,  advance + 1); r.mode     =  assign; r.scope    =  ancestor; for (i = 0; i < r.children.length;  i++) { r.children[i].parent =  r;         if (attach) { r.children[i].include =  true; } else { r.children[i][ancestor] =  true; }     }   // for i      this.children[at]  =  r;      if (advance > at) { this.children.splice(at + 1, advance - at); }     if (at) { delete r.source; }     r.parent  =  this; } else { mw.log(WSTM.debugging, ".WikiTom.fork no children", 3, this); }  return r; };   // .o.WikiTom.fork

WTOM.prototype.free =  function  { // Replace parents of children by this parent // Uses: //   >  this.children //   >  this.parent // 2012-04-22 PerfektesChaos@de.wikipedia var e,      i,       n;   if (this.children) { n =  this.children.length; for (i = 0; i < n;  i++) { e =  this.children[i]; e.free; e.parent =  this; }  // for i   } };  // .o.WikiTom.free

WTOM.prototype.fresh =  function (apply) { // Mark this and above nodes as modified // Precondition: //   apply  -- optional string to be stored // Postcondition: //   nodes are marked. // Uses: //   >  this.children //   >  this.parent //    < this.source //    < this.learnt //   this.fresh   -- recursive // 2012-03-23 PerfektesChaos@de.wikipedia this.learnt =  true; if (this.children) { this.source =  false; } else if (apply) { this.source =  apply; } else if (typeof(apply) === "string") { this.source =  ""; }  if (this.parent) { this.parent.fresh(false); } };  // .o.WikiTom.fresh

WTOM.prototype.getCount =  function  { // How many nodes? // Postcondition: //    Return current node count. // Uses: //   >  this.children // 2012-03-19 PerfektesChaos@de.wikipedia var r =  0; if (this.children) { r =  this.children.length; }  return r; };   // .o.WikiTom.getCount

WTOM.prototype.isNodeInSpan =  function  { // Is this node within ... span? // Postcondition: //   Returns true, if anode within span, else false // Uses: //   >  .w.encountered.include // 2012-04-06 PerfektesChaos@de.wikipedia var r =  false; if (WSTM.w.encountered.include) { r =  (this.include ? true : false); }  return r; };   // .o.WikiTom.isNodeInSpan

WTOM.prototype.replace =  function (apply, assign) { // Precondition: //   apply   -- RegExp object,  or Array of replacement pairs //   assign  -- single replacement,  or false if replacement pairs // Postcondition: //   Nodes are modified // Uses: //   >  this.children //   >  this.lookup //   >  this.mode //   >  .o.WikiTom.TextOnly //   >< this.source //   this.replace   -- recursive //   .util.translate.flip //   this.fresh // 2019-08-01 PerfektesChaos@de.wikipedia var i,      n,       s;   if (this.lookup) { if (this.children) { n =  this.children.length; for (i = 0; i < n;  i++) { this.children[i].replace(apply, assign); }  // for i      } else { if (this.mode <= WTOM.TextOnly) { s =  this.source; if (s) { if (typeof(assign) === "string") { n =  s.replace(apply, assign); } else { n =  WSTM.util.translate.flip(s, apply); }              if (n !== s) { this.fresh(n); }           }         }      }   } };   // .o.WikiTom.replace

WTOM.prototype.toString =  function  { // Postcondition: //   Returns string // Uses: //   >  this.source //   >  this.children //   >  this.learnt //   this.toString // 2012-05-16 PerfektesChaos@de.wikipedia var i,      n,       p,       r  =  this.source; if (this.children) { if (this.learnt ||  ! r) { n =  this.children.length; r =  ""; for (i = 0; i < this.children.length;  i++) { p =  this.children[i]; if (p) { //            if (p.hasOwnProperty("toString")) {   /// failed if (p.toString) { r =  r + p.toString; }           }         }   // for i      } } else if (! r) { r =  ""; }  return r; };   // .o.WikiTom.toString

WTOM.prototype.trimL =  function (any) { // Trim leftmost node from heading spacing charcodes of any kind // Precondition: //   any  -- true: remove also zero width and direction marks // Postcondition: //   Returns true, if whitespace removed //   leftmost node modified, if whitespace // Uses: //   >  this.source //   >  this.children //   >  .o.WikiTom.lookup //   >  .o.WikiTom.mode //   >  .o.WikiTom.TextOnly //   .str.trimL //   this.fresh // 2013-04-29 PerfektesChaos@de.wikipedia var n,      r  =  false, s =  false; if (this.children) { n =  this.children[0]; if (n.lookup) { if (n.mode <= WTOM.TextOnly) { if (n.source) { s =  n.source; }        }      }   } else if (this.source) { s =  this.source; }  if (s) { n =  s.length; s =  WSTM.str.trimL(s, any); r =  (s.length < n); if (r) { if (this.children) { this.children[0].fresh(s); } else { this.fresh(s); }     }   }   return r; };   // .o.WikiTom.trimL

WTOM.prototype.trimR =  function (any, also) { // Trim rightmost node from trailing spacing charcodes of any kind // Precondition: //   any   -- true: include zero width and direction marks //   also  -- true: remove also line break // Postcondition: //   Returns true, if whitespace removed //   rightmost node modified, if whitespace // Uses: //   >  this.source //   >  this.children //   >  .o.WikiTom.lookup //   >  .o.WikiTom.mode //   >  .o.WikiTom.TextOnly //   .str.trimR //   .str.substrEnd //   this.fresh // 2012-05-28 PerfektesChaos@de.wikipedia var n,      p,       r  =  false, s =  false; if (this.children) { p =  this.children[this.children.length - 1]; if (p.lookup) { if (p.mode <= WTOM.TextOnly) { if (p.source) { s =  p.source; }        }      }   } else if (this.source) { s =  this.source; }  if (s) { n =  s.length; s =  WSTM.str.trimR(s, any, also); r =  (s.length < n); if (r) { if (this.children) { p.fresh(s); } else { this.fresh(s); }     }   }   return r; };   // .o.WikiTom.trimR

WTOM.prototype.DEBUGparent =  function  { // Replace parent objects by brief string for debugging report // Uses: //   >  this.parent //   >  this.children //   this.toString // 2012-04-22 PerfektesChaos@de.wikipedia var e,      i,       n;   if (this.parent) { this.parent =  this.parent.toString.substr(0, 100); }  if (this.children) { n =  this.children.length; for (i = 0; i < n;  i++) { e =  this.children[i].DEBUGparent; }  // for i   } };  // .o.WikiTom.DEBUGparent

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

//---

( function ( WSTM ) {  "use strict";   var sub      =  "O",       self     =  WSTM.o.self,       version  =  WSTM.o.vsn,       rls;   if ( typeof WSTM.main  ===  "object" &&    WSTM.main   && typeof WSTM.main.wait ===  "function" ) {      // Start on import: callback to waiting ...      WSTM.main.wait( sub, version );   } else 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: utf-8-dos // fill-column: 80 // End:

/// EOF  WikiSyntaxTextMod/dO.js