User:PerfektesChaos/js/WikiSyntaxTextMod/dU.js

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


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



/*
Requires: JavaScript 1.3
          (Object.toSource
           String.charCodeAt String.fromCharCode String.replace)
 */



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



mw.libs.WikiSyntaxTextMod.bb.utilU  =  function ( WSTM ) {
   // General Utilities
   // 2021-10-26 PerfektesChaos@de.wikipedia
   "use strict";


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


   WSTM.util.fiatObjects( WSTM,  "debugging",  { loud: false } );
   WSTM.util.fiatObjects( WSTM,  "util",
                          { code:      { },
                            date:      { },
                            dnb:       { },
                            gtin:      { },
                            isbn:      { },
                            issn:      { },
                            re:        { },
                            regexp:    { },
                            translate: { }
                          } );



   WSTM.util.isArray  =  function ( anything ) {
      // Is anything an array?
      // Precondition:
      //    anything  -- thing to be tested
      // Postcondition:
      //    Returns true, if Array
      // 2012-02-01 PerfektesChaos@de.wikipedia
      var r  =  ( anything !== null );
      if ( r ) {
         r  =  ( typeof anything  === "object" );
         if ( r ) {
            r  =  ( anything.constructor.toString().substr( 0, 17 )
                                 .indexOf( "function Array()" )  >=  0 );
         }
      }   // non-null
      return  r;
   };   // .util.isArray()



   WSTM.util.isElement  =  function ( array, access ) {
      // Is anything element of an array?
      // Precondition:
      //    array   -- Array to be searched; may be empty or false
      //    access  -- thing to be found
      // Postcondition:
      //    Returns true, if access is element of array
      // 2016-01-21 PerfektesChaos@de.wikipedia
      var r  =  false,
          i;
      if ( typeof array  ===  "object"
          &&  array
          &&  typeof array.length === "number" ) {
         for ( i = 0;  i < array.length;  i++ ) {
            if ( array[ i ] === access ) {
               r  =  true;
               break;   // for i
            }
         }   // for i
      }
      return  r;
   };   // .util.isElement()



   WSTM.util.isEscValid  =  function (attempt) {
      // Are bad percent escapings in attempt?
      // Precondition:
      //    attempt  -- string with possible percent escapings
      // Postcondition:
      //    Returns  string with violating sequence
      //             false if correct
      // Uses:
      //    >< .util.re.hex2
      // 2021-10-26 PerfektesChaos@de.wikipedia
      var i  =  0,
          r  =  false,
          s;
      do {   // while i >= 0
         i = attempt.indexOf( "%", i );
         if ( i >= 0 ) {
            s = attempt.substr( i + 1,  2 );
            if ( s.length === 2 ) {
               if ( s === "00" ) {
                  r  =  "%00";
                  break;   // while i >= 0
               }
               if ( typeof WSTM.util.re.hex2  !==  "object" ) {
                  WSTM.util.re.hex2  =
                                  new RegExp( "[0-9A-Fa-f][0-9A-Fa-f]" );
               }
               if ( WSTM.util.re.hex2.test( s ) ) {
                  i = i + 2;
               } else {
                  r  =  "%" + s;
                  break;   // while i >= 0
               }
            } else {
               r  =  "%" + s;
               break;   // while i >= 0
            }
         }
      } while ( i >= 0 );
      return  r;
   };   // .util.isEscValid()



   WSTM.util.isO_639_1  =  function ( ask ) {
      // Is string a valid ISO 639-1 language code?
      // Precondition:
      //    ask  -- lowercase 2 letter query string
      // Postcondition:
      //    Returns  true  iff  ask is a valid ISO 639-1 language code
      // 2016-09-14 PerfektesChaos@de.wikipedia
      var s  =   "|aa|ab|ae|af|ak|am|an|ar|as|av|ay|az"
               + "|ba|be|bg|bh|bi|bm|bn|bo|br|bs"
               + "|ca|ce|ch|co|cr|cs|cu|cv|cy"
               + "|da|de|dv|dz"
               + "|ee|el|en|eo|es|et|eu"
               + "|fa|ff|fi|fj|fo|fr|fy"
               + "|ga|gd|gl|gn|gu|gv"
               + "|ha|he|hi|ho|hr|ht|hu|hy|hz"
               + "|ia|id|ie|ig|ii|ik|io|is|it|iu"
               + "|ja|jv"
               + "|ka|kg|kj|kk|kl|km|kn|ko|kr|ks|ku|kv|kw|ky"
               + "|la|lb|lg|li|ln|lo|lt|lv"
               + "|mg|mh|mi|mk|ml|mn|mr|ms|mt|my"
               + "|na|nb|nd|ne|ng|nl|nn|no|nr|nv"
               + "|oc|oj|om|or|os"
               + "|pa|pi|pl|ps|pt"
               + "|qu"
               + "|rm|rn|ro|ru|rw"
               + "|sa|sc|sd|se|sg|sh|si|sk|sl|sm|sn"
               + "|so|sq|sr|ss|st|su|sv|sw"
               + "|ta|te|tg|th|ti|tk|tl|tn|to|tr|ts|tt|tw|ty"
               + "|ug|uk|ur|uz"
               + "|ve|vi|vo"
               + "|wa|wo"
               + "|xh"
               + "|yi|yo"
               + "|za|zh|zu|";
      return  ( s.indexOf( ask ) > 0 );
   };   // .util.isO_639_1()



   WSTM.util.isURL  =  function ( attempt, allow, any ) {
      // Is attempt a valid URL?
      // Precondition:
      //    attempt  -- string with trimmed URL
      //    allow    -- permit other schemes than http https ftp
      //    any      -- permit invalid www domains
      // Postcondition:
      //    Returns  string with error hint
      //             false if correct
      // Uses:
      //    >< .util.re.whitespace
      //     < .util.re.nonAlNum2
      //     < .util.re.all0alpha
      //     < .util.re.alphaNum
      //     < .util.re.nonAlNumBeg
      //     < .util.re.nonAlNumEnd
      //     < .util.re.urlPort
      //     < .util.re.urlProtocol
      //     < .util.re.urlPunycode
      //    .str.isASCII()
      //    .lang.fetch()
      // 2021-10-26 PerfektesChaos@de.wikipedia
      var r  =  false,
          got, i, n, parts, s, scheme;
      if ( typeof this.re.whitespace  !==  "object" ) {
         this.re.nonAlNum2    =  new RegExp( "[^a-z0-9][^a-z0-9]" );
         this.re.all0alpha    =  new RegExp( "^[^a-z]+$" );
         this.re.alphaNum     =  new RegExp( "[a-z0-9]+" );
         this.re.nonAlNumBeg  =  new RegExp( "^[^a-z0-9]" );
         this.re.nonAlNumEnd  =  new RegExp( "[^a-z0-9]$" );
         this.re.whitespace   =  new RegExp( "\\S\\s+\\S" );
         this.re.urlPort      =  new RegExp( "^(.+):[0-9]+$" );
         this.re.urlProtocol  =  new RegExp( "^(?:(https?|s?ftp):)?" +
                                             "//.",
                                             "i" );
         this.re.urlPunycode  =  new RegExp( "^xn--[a-z0-9]+" +
                                             "(-[a-z0-9]+)?$",
                                             "i" );
      }
      if ( this.re.whitespace.test( attempt ) ) {
         r  =  "whitespace";
      } else if ( allow ) {
         // TODO   mailto:
      } else {
         got  =  this.re.urlProtocol.exec( attempt );
         if (got) {
            scheme  =  got[ 1 ];
            if (scheme) {
               scheme  =  scheme.toLowerCase();
            } else {
               scheme  =  "http";
            }
            s  =  attempt.substr( got[ 0 ].length - 1 );
            i  =  s.indexOf( "/" );
            if (i > 0) {
               s  =  s.substr( 0, i );
            }
         } else {
            r  =  "scheme:resource";
         }
      }
      if ( s   &&   s.indexOf( ":" )  >  0
           &&   "http https ftp".indexOf( scheme ) >= 0 ) {
         got  =  this.re.urlPort.exec( s );
         if (got) {
            s  =  got[ 1 ];
         } else {
            r  =  "port";
            s  =  false;
         }
      }
      if ( s  &&  ! any ) {
         s      =  s.toLowerCase();
         parts  =  s.split( "." );
         n      =  parts.length;
         if ( n > 1 ) {
            for ( i = 0;  i < n;  i++ ) {
               s  =  parts[ i ];
               if ( ! this.re.alphaNum.test( s ) ) {
                  if ( WSTM.str.isASCII( s ) ) {
                     if ( s.substr( 0, 4 )  ===  "xn--" ) {
                        if ( ! this.re.urlPunycode.test( s ) ) {
                           r  =  "Punycode: " + s;
                        }
                     } else if ( i  ===  n - 1
                                 &&  this.re.all0alpha.test( s ) ) {
                        r  =  "TLD: ." + s;
                     } else if ( this.re.nonAlNumBeg.test( s )   ||
                                 this.re.nonAlNumEnd.test( s ) ) {
                        r  =  "." + s + ".";
                        break;   // for i
                     } else if (  this.re.nonAlNum2.test( s ) ) {
                        r  =  "." + s + ".";
                        break;   // for i
                     }
                  } else if (i  ===  n - 1) {
                     if ( ! WSTM.lang.fetch( "TLD.IDN" ).test( s ) ) {
                        r  =  "TLD (IDN): ." + s;
                     }
                  }
               }
            }   // for i
         } else {
            r  =  "TLD-";
         }
      }
      return  r;
   };   // .util.isURL()



   WSTM.util.roman2int  =  function ( attempt ) {
      // What does this roman number mean?
      // Precondition:
      //    attempt  -- string with trimmed roman number
      // Postcondition:
      //    Returns  string with original code or digits
      // Uses:
      //    >< .util.romanDigits
      // 2019-08-20 PerfektesChaos@de.wikipedia
      var s  =  attempt.toUpperCase(),
          d, i, j, k, l, r;
      if ( typeof this.romanDigits  !==  "object" ) {
         this.romanDigits  =  { "I": 1,
                                "V": 5,
                                "X": 10,
                                "L": 50,
                                "C": 100,
                                "D": 500,
                                "M": 1000 };
      }
      for ( i = 0;  i < s.length;  i++ ) {
         k  =  this.romanDigits[ s.charAt( i ) ];
         if ( k ) {
            d  =  d  ||  [ ];
            d.push( k );
         } else {
            d  =  false;
            break;   // for i
         }
      }   // for i
      if ( d ) {
         r  =  0;
         j  =  0;
         l  =  true;
         for ( i = d.length - 1;  i >= 0;  i-- ) {
            k  =  d[ i ];
            if ( k > j ) {
               r  =  r + k;
               l  =  true;
            } else if ( k < j ) {
               r  =  r - k;
               l  =  false;
            } else if ( l ) {
               r  =  r + k;
            } else {
               r  =  r - k;
            }
            j  =  k;
         }   // for i--
         r  =  r + "";
      }
      return  r  ||  attempt;
   };   // .util.roman2int()



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



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



mw.libs.WikiSyntaxTextMod.bb.dating  =  function ( WSTM ) {
   // Date and time analysis, error message
   // Public:
   //    .util.date.fetch()
   //    .util.date.format()
   // 2019-11-29 PerfektesChaos@de.wikipedia
   "use strict";



   WSTM.util.fiatObjects( WSTM.util,  "date",
                          { domax: [ false, 31, 29, 31, 30, 31, 30,
                                            31, 31, 30, 31, 30, 31 ],
                            units: [ "era",
                                     "year",
                                     "month",
                                     "dom",
                                     "hour",
                                     "minute",
                                     "second",
                                     "msec",
                                     "mysec" ],
                            words: { doweek: [ "Sunday",
                                               "Monday",
                                               "Tuesday",
                                               "Wednesday",
                                               "Thursday",
                                               "Friday",
                                               "Saturday" ],
                                     dow:   { n: 3 },
                                     month: [ false,
                                              "January",
                                              "February",
                                              "March",
                                              "April",
                                              "May",
                                              "June",
                                              "July",
                                              "August",
                                              "September",
                                              "October",
                                              "November",
                                              "December" ],
                                     mon:   { n: 3 } },
                            re:    { }
                          } );



   WSTM.util.date.fetch  =  function ( attempt, ahead, alien ) {
      // Retrieve date
      // Precondition:
      //    attempt  -- string with presumable date and time
      //    ahead    -- true: future moment permitted
      //    alien    -- string with other language code than en, or false
      // Postcondition:
      //    Returns object of components, or false if not ISO or future
      // Uses:
      //    >< .util.date.re.*
      //    .lang.l
      //    .str.trim()
      //    .util.date.formal()
      // 2019-11-29 PerfektesChaos@de.wikipedia
      var s  =  WSTM.str.trim(attempt),
          got, o, r;
      if ( typeof this.re.yyyy  !==  "object" ) {
         this.re.dd    =  new RegExp( "^-([0-3]?[0-9])([T ].*)?$" );
         this.re.hh    =  new RegExp( "^([0-2][0-9])(:.*)?$" );
         this.re.min   =  new RegExp( "^:([0-5][0-9])(:.*)?$" );
         this.re.mon   =  new RegExp( "^-([01]?[0-9])(-.+)?$" );
         this.re.ss    =  new RegExp( "^:([0-6][0-9])([. ].*)?$" );
         this.re.yyyy  =  new RegExp( "^([1-9][0-9]*)(-.+)?$" );
      }
      got  =  this.re.yyyy.exec( s );
      if (got) {
         r  =  { year:   parseInt(got[1], 10) };
         s  =  got[2];
         if (s) {
            got  =  this.re.mon.exec(s);
            if (got) {
               r.month  =  parseInt(got[1], 10);
               s        =  got[2];
               if (s) {
                  got  =  this.re.dd.exec(s);
                  if (got) {
                     r.dom  =  parseInt(got[1], 10);
                     s      =  got[2];
                     if (s) {
                        s  =  s.substr(1);
                     }
                  } else {
                     r  =  false;
                     s  =  false;
                  }
               } else {
                  r  =  false;
                  s  =  false;
               }
            } else {
               r  =  false;
            }
         }
      }
      if (s) {
         got  =  this.re.hh.exec(s);
         if (got) {
            if ( ! r) {
               r  =  { };
            }
            r.hour  =  parseInt(got[1], 10);
            s       =  got[2];
            if (s) {
               got  =  this.re.min.exec(s);
               if (got) {
                  r.minute  =  parseInt(got[1], 10);
                  s         =  got[2];
                  if (s) {
                     got  =  this.re.ss.exec(s);
                     if (got) {
                        r.second  =  parseInt(got[1], 10);
                        s         =  got[2];
                     } else {
                        r  =  false;
                     }
                  } else {
                     r  =  false;
                  }
               } else {
                  r  =  false;
               }
            }
         }
      }
      if ( ! r ) {
         o  =  WSTM.lang.l;
         if ( typeof o.en  ===  "object"   &&
              typeof o.en.date  ===  "object"   &&
              typeof o.en.date.fetch  ===  "function") {
            r  =  o.en.date.fetch( attempt );
         }
         if ( ! r  &&
              typeof o[ alien ]  ===  "object"   &&
              typeof o[ alien ].date  ===  "object"   &&
              typeof o[ alien ].date.fetch  ===  "function") {
            r  =  o[ alien ].date.fetch( attempt );
         }
      }
      if ( r ) {
         r  =  this.formal( r, ahead );
      }
      return  ( r || false );
   };   // .util.date.fetch()



   WSTM.util.date.fiat  =  function ( attempt ) {
      // Equip object of components with JS object
      // Precondition:
      //    attempt  -- object of components
      //                >< .date
      // 2015-12-23 PerfektesChaos@de.wikipedia
      var ih   =  0,
          im   =  0,
          ims  =  0,
          is   =  0;
      switch ( typeof attempt.date ) {
         case "boolean":
         case "object":
            break;
         default:
            if ( typeof attempt.year  ===  "number"   &&
                 typeof attempt.month  ===  "number"   &&
                 typeof attempt.dom  ===  "number" ) {
               if ( typeof attempt.hour  ===  "number" ) {
                  ih  =  attempt.hour;
                  if ( typeof attempt.minute  ===  "number" ) {
                     im  =  attempt.minute;
                     if ( typeof attempt.second  ===  "number" ) {
                        is  =  attempt.second;
                        if ( typeof attempt.msec  ===  "number" ) {
                           ims  =  attempt.msec;
                           if ( typeof attempt.mysec  ===  "number" ) {
                              ims  =  ims  +  0.001 * attempt.mysec;
                           }
                        }
                     }
                  }
               }
               attempt.date  =  new Date( attempt.year,
                                          attempt.month - 1,
                                          attempt.dom - 1,
                                          ih, im, is, ims );
            } else {
               attempt.date  =  false;
            }
      }   // switch typeof attempt.date
      return  attempt.date;
   };   // .util.date.fiat()



   WSTM.util.date.fill  =  function ( at, assembly ) {
      // Create month name translation map for lang
      // Precondition:
      //    at        -- .lang.l.*.date object
      //    assembly  -- object to collect
      // Postcondition:
      //    assembly has been equipped by lang
      // Uses:
      //    >< .util.date.re
      //    >< .util.date.re.digits
      //     < .lang.l.*.date.greg12
      // 2019-11-29 PerfektesChaos@de.wikipedia
      var m, min, r, s;
      if ( typeof at.monAbbr  ===  "object" ) {
         if ( typeof at.monAbbr.n  ===  "number" ) {
            min  =  at.monAbbr.n;
         }
         for ( m in at.monAbbr ) {
            if ( typeof this.re  !==  "object" ) {
               this.re  =  { };
            }
            if ( typeof this.re.digits  !==  "object" ) {
               this.re.digits  =  new RegExp( "^\\d+$" );
            }
            if ( typeof m  ===  "number"   ||
                 this.re.digits.test( m ) ) {
               s              =  at.monAbbr[ m ].toLowerCase();
               assembly[ s ]  =  m;
               r              =  true;
            }
         }   // for m in at.monAbbr
      }
      if ( typeof at.monFull  ===  "object" ) {
         for ( m in at.monFull ) {
            s              =  at.monFull[ m ].toLowerCase();
            assembly[ s ]  =  m;
            r              =  true;
            if ( min  &&  s.length > min ) {
               s              =  s.substr( 0, min);
               assembly[ s ]  =  m;
            }
         }   // for m in at.monFull
      }
      return  r;
   };   // .util.date.fill()



   WSTM.util.date.filler  =  function ( at ) {
      // Create month name translation map
      // Precondition:
      //    at       -- .lang.l.*.date object
      // Postcondition:
      //    .lang.l.*.date object equipped by component
      // Uses:
      //    this
      //    >  .lang.l.*.date.consider
      //     < .lang.l.*.date.greg12
      //    .util.date.fill()
      // 2015-11-26 PerfektesChaos@de.wikipedia
      var o     =  { },
          live  =  this.fill( at, o ),
          i, l, x;
      if ( typeof at.consider  ===  "object" ) {
         for ( i = 0;  i < at.consider.length;  i++ ) {
            x  =  WSTM.lang.l[ at.consider[i] ];
            if ( typeof x  ===  "object"   &&
                 typeof x.date  ===  "object" ) {
               l     =  this.fill( x.date, o );
               live  =  ( live || l );
            }
         }   // for i
      }
      if ( live ) {
         at.greg12  =  { };
         for ( x in o ) {
            i  =  o[ x ];
            switch ( typeof i ) {
               case "number":
                  at.greg12[ x ]  =  i;
                  break;
               case "string":
                  at.greg12[ x ]  =  parseInt( i, 10 );
                  break;
            }   // switch typeof i
         }   // for x in o
      } else {
         at.greg12  =  null;
      }
   };   // .util.date.filler()



   WSTM.util.date.find  =  function ( attempt, at ) {
      // Translate month name into month number
      // Precondition:
      //    attempt  -- string with presumable month name
      //    at       -- .lang.l.*.date object
      // Postcondition:
      //    Returns month number 1...12, or false
      // Uses:
      //    this
      //    >< .lang.l.*.date.greg12
      //    .util.date.filler()
      // 2015-11-26 PerfektesChaos@de.wikipedia
      var r, s;
      if ( typeof at.greg12  !==  "object" ) {
         this.filler( at );
      }
      if ( at.greg12 ) {
         s  =  attempt.toLowerCase();
         if ( typeof at.greg12[ s ]  ===  "number" ) {
            r  =  at.greg12[ s ];
         }
      }
      return  ( r || false );
   };   // .util.date.find()



   WSTM.util.date.formal  =  function ( attempt, ahead ) {
      // Check validity of datetime components
      // Precondition:
      //    attempt  -- object of components, or false
      //    ahead    -- true: future moment permitted
      // Postcondition:
      //    Returns attempt, or false if invalid or unpermitted future
      // Uses:
      //    this
      //    >< .util.date.current
      //    .util.date.further()
      //    .util.date.full()
      // 2016-01-04 PerfektesChaos@de.wikipedia
      var r  =  attempt,
          j, m, n;
      if ( r ) {
         if ( typeof r.year  ===  "number" ) {
            j  =  r.year;
            this.further( r );
         } else {
            r.year  =  false;
         }
      }
      if ( r ) {
         if ( typeof r.month  ===  "number" ) {
            m  =  r.month;
            if ( m < 1  ||  m > 12 ) {
               r  =  false;
            }
         } else {
            r.month  =  false;
         }
      }
      if ( r ) {
         if ( typeof r.dom  ===  "number" ) {
            n  =  r.dom;
            if ( n > 0  &&  n <= 31 ) {
               if (m) {
                  if (n > this.full(r)) {
                     r  =  false;
                  }
               } else if ( j ) {
                  r  =  false;
               }
            } else {
               r  =  false;
            }
         } else {
            r.dom  =  false;
         }
      }
      if ( r ) {
         if ( typeof r.hour  ===  "number" ) {
            if (r.hour < 0  ||  r.hour > 23) {
               r  =  false;
            }
         } else {
            r.hour  =  false;
         }
      }
      if ( r ) {
         if ( typeof r.minute  ===  "number" ) {
            if ( r.minute < 0  ||  r.minute > 59 ) {
               r  =  false;
            }
         } else {
            r.minute  =  false;
         }
      }
      if ( r ) {
         if ( typeof r.second  ===  "number" ) {
            if (r.second < 0  ||  r.second > 60) {
               r  =  false;
            } else {
               if ( typeof r.minute  ===  "number" ) {
                  if (r.second === 60  &&  r.minute !== 59) {
                     r  =  false;
                  }
               } else if ( typeof r.hour  ===  "number" ) {
                  r  =  false;
               }
            }
         } else {
            r.second  =  false;
         }
      }
      if ( r && ahead && j && m && n ) {
         if ( typeof this.current  !==  "object" ) {
            this.current  =  new Date();
         }
         if ( j > this.current.getUTCFullYear() ) {
            r  =  false;
         } else if (j === this.current.getUTCFullYear()  &&
                    m  >  this.current.getUTCMonth()) {
            if ( m  >  this.current.getUTCMonth() + 1   ||
                 n  >  this.current.getUTCDate() ) {
               r  =  false;
            }
         }
      }
      return  ( r || false );
   };   // .util.date.formal()



   WSTM.util.date.format  =  function ( attempt, apply ) {
      // Format date
      // Precondition:
      //    attempt  -- object of components
      //    apply    -- Array with layout description
      //                number: ISO, maximum permitted components
      //                string: PHP
      //                Array: [0] country code
      //                       [1] country subtype (lowercase)
      //                       [2] mode
      //                       [3] number of maximum permitted components
      // Postcondition:
      //    Returns string
      // Uses:
      //    this
      //    .util.date.formatISO()
      //    .util.date.formatPHP()
      // 2015-12-23 PerfektesChaos@de.wikipedia
      var r  =  "",
          f, n, o;
      switch ( typeof apply ) {
         case "number":
            r  =  this.formatISO( attempt, apply );
            break;
         case "object":
            if ( apply ) {
               o  =  WSTM.lang.l;
               if ( typeof o[ apply[ 0 ] ]  ===  "object" ) {
                  o  =  o[ apply[ 0 ] ];
                  if ( apply[ 1 ]   &&
                       typeof o[ apply[ 1 ] ]  ===  "object"   &&
                       typeof o[ apply[ 1 ] ].date  ===  "object"   &&
                       typeof o[ apply[ 1 ] ].date.format
                                                      ===  "function" ) {
                     f  =  o[ apply[ 1 ] ].date.format;
                  } else if ( typeof o.date  ===  "object"   &&
                              typeof o.date.format  ===  "function" ) {
                     f  =  o.date.format;
                  }
               }
               if ( typeof apply[ 3 ]  ===  "number" ) {
                  n  =  apply[ 3 ];
               }
            }
            break;
         case "string":
            r  =  this.formatPHP( attempt, apply );
            break;
      }   // switch typeof apply
      if ( f ) {
         r  =  f( attempt, apply [2 ], n );
      } else if ( ! r) {
         r  =  this.formatISO( attempt, n );
      }
      return  r;
   };   // .util.date.format()



   WSTM.util.date.formatISO  =  function ( attempt, amount ) {
      // Format date in ISO (human: space between date and time)
      // Precondition:
      //    attempt  -- object of components
      //    amount   -- number of maximum permitted components, else max
      // Postcondition:
      //    Returns string
      // Uses:
      //    this
      //    >  .util.date.units
      //    >< .util.date.isoFormat
      //    .str.makeString()
      // 2015-12-23 PerfektesChaos@de.wikipedia
      var r  =  "",
          i, k, n, o;
      if ( attempt.year ) {
         r  =  "" + attempt.year;
         n  =  4 - r.length;
         if ( n ) {
            r  =  WSTM.str.makeString( 48, n )  +  r;
         }
         if ( typeof this.isoFormat  !==  "object" ) {
            this.isoFormat  =  { month:  { n:  10,  sep: "-" },
                                 dom:    { n:  10,  sep: "-" },
                                 hour:   { n:  10,  sep: " " },
                                 minute: { n:  10,  sep: ":" },
                                 second: { n:  10,  sep: ":" },
                                 msec:   { n: 100,  sep: "." },
                                 mysec:  { n: 100,  sep: "" }
                               };
         }
         k  =  ( typeof amount  ===  "number"  ?  amount
                                               :  this.units.length );
         for ( i = 2;  i <= k;  i++ ) {
            o  =  this.units[ i ];
            n  =  attempt[ o ];
            if ( typeof n  ===  "number" ) {
               o  =  this.isoFormat[ o ];
               r  =  r + o.sep;
               if ( n < o.n ) {
                  r  =  r + "0";
                  if ( o.n === 100  &&  n < 10 ) {
                     r  =  r + "0";
                  }
               }
               r  =  r + n;
            } else {
               break;   // for i
            }
         }   // for i
      }
      return  r;
   };   // .util.date.formatISO()



   WSTM.util.date.formatPHP  =  function (attempt, apply, assign) {
      // Format date by PHP specifiers
      // Precondition:
      //    attempt  -- object of components
      //    apply    -- string: PHP code like #time:
      //    assign   -- object with localised names
      //                "month":  Array of month names;
      //                          counting from 1 (1=January)
      //                "mon":    Array of abbreviated month names;
      //                          counting from 1 (1=Jan)
      //                          number: length of abbreviation
      //                "doweek": Array of day of week names;
      //                          counting from 0 (0=Sunday)
      //                "dow":    Array of abbreviated day of week names;
      //                          counting from 0 (0=Sun)
      //                          number: length of abbreviation
      // Uses:
      //    this
      //    >  .util.date.domax
      //    .str.substrEnd()
      //    .util.date.furnish()
      //    .util.date.formatISO()
      //    .util.date.fiat()
      //    .util.date.further()
      //    .util.date.formatPHP()   -- self-recursive
      //    .util.date.full()
      // 2017-01-01 PerfektesChaos@de.wikipedia
      var r  =  "",
          i, n, o, s, v;
      if ( typeof this.phpCodes  !==  "object" ) {
         this.phpCodes  =  { Y:   { s: "year",  n: 4 },
                             y:   { s: "year",  n: 2,  m: 2 },
                             L:   true,
                             M:   { s: "month",  o: "mon" },
                             F:   { s: "month",  o: "month" },
                             m:   { s: "month",  n: 1 },
                             n:   { s: "month",  n: 2 },
                             t:   true,
                             W:   true,
                             z:   true,
                             j:   { s: "dom",  n: 1 },
                             d:   { s: "dom",  n: 2 },
                             D:   true,
                             l:   true,
                             w:   true,
                             N:   true,
                             G:   { s: "hour",  n: 1 },
                             H:   { s: "hour",  n: 2 },
                             g:   true,
                             h:   true,
                             a:   true,
                             A:   true,
                             i:   { s: "minute",  n: 2 },
                             s:   { s: "second",  n: 2 },
                             c:   true,
                             r:   true,
                             U:   true,
                             e:   true,
                             I:   true,
                             O:   true,
                             P:   true,
                             T:   true,
                             Z:   true,
                             '"': true };
      }
      for ( i = 0;  i <= apply.length;  i++ ) {
         s  =  apply.substr( i, 1 );
         switch ( typeof this.phpCodes[ s ] ) {
            case "object":
               o  =  this.phpCodes[ s ];
               if ( typeof o.s  ===  "string" ) {
                  if ( typeof attempt[ o.s ]  ===  "number") {
                     v  =  attempt[ o.s ];
                     if ( typeof o.n  ===  "number" ) {
                        switch (o.n) {
                           case 2:
                              if ( typeof o.m  ===  "number" ) {
                                 if ( v < 100 ) {
                                    if ( v < 10 ) {
                                       v  =  "0" + v;
                                    }
                                 } else {
                                    v  =  WSTM.str.substrEnd( "" + v,
                                                              2 );
                                 }
                              } else {
                                 if ( v < 10 ) {
                                    v  =  "0" + v;
                                 }
                              }
                              break;
                           case 4:
                              if ( v < 1000 ) {
                                 v  =  WSTM.str.substrEnd( "000" + v,
                                                           4 );
                              }
                              break;
                        }   // switch o.n
                     } else if ( typeof o.o  ===  "string" ) {
                        v  =  this.furnish(v, o.o, assign);
                     }
                     r  =  r + v;
                  }
               }
               break;
            case "boolean":
               switch ( s ) {
                  case '"':
                     i++;
                     n  =  apply.indexOf( '"', i );
                     if ( n < 0 ) {
                        r  =  r + apply.substr( i );
                        i  =  apply.length;
                     } else {
                        r  =  r  +  apply.substring( i, n );
                        i  =  n;
                     }
                     break;
                  case "A":
                  case "a":
                     if ( typeof attempt.hour  ===  "number" ) {
                        if ( attempt.hour > 12 ) {
                           v  =  "PM";
                        } else {
                           v  =  "AM";
                        }
                        if (s === "a") {
                           v  =  v.toLowerCase();
                        }
                        r  =  r + v;
                     }
                     break;
                  case "c":   // ISO
                     r  =  r + this.formatISO( attempt );
                     break;
                  case "D":
                  case "l":
                  case "N":
                  case "w":
                     if ( this.fiat( attempt ) ) {
                        v  =  attempt.date.getDay();
                        switch ( s ) {
                           case "D":
                              v  =  this.furnish( v, "dow", assign );
                              break;
                           case "l":
                              v  =  this.furnish( v, "doweek", assign );
                              break;
                           case "N":   // Sunday = 7
                              if ( ! v ) {
                                 v  =  7;
                              }
                              break;
                           case "w":   // Sunday = 0
                              break;
                        }   // switch s
                        r  =  r + v;
                     }
                     break;
                  case "e":
                  case "I":
                  case "O":
                  case "P":
                  case "T":
                  case "Z":
                     if ( this.fiat( attempt ) ) {
                        v  =  attempt.date.getTimezoneOffset();
                        switch ( s ) {
                           case "e":
                           case "T":
                              if ( ! v) {
                                 v  =  "UTC";
                                 break;
                              }   // fall through
                           case "O":
                           case "P":
                              o  =  (v < 0);
                              if ( o ) {
                                 v  =  v * -1;
                              }
                              n  =  v % 60;
                              v  =  v  -  n * 60;
                              if ( n < 10 ) {
                                 n  =  "0" + n;
                              }
                              if ( v < 10 ) {
                                 v  =  "0" + v;
                              }
                              if ( s === "P" ) {
                                 v  =  ":" + v;
                              }
                              v  =  n + v;
                              if ( o ) {
                                 v  =  "-" + v;
                              } else {
                                 v  =  "+" + v;
                              }
                              break;
                           case "I":
                              v  =  "0";
                              break;
                           case "Z":
                              v  =  v * 60;
                              break;
                        }   // switch s
                        r  =  r + v;
                     }
                     break;
                  case "g":
                  case "h":
                     if ( typeof attempt.hour  ===  "number" ) {
                        v  =  ( attempt.hour > 12  ?  attempt.hour - 12
                                                   :  attempt.hour );
                        if ( s === "h"  &&  v < 10 ) {
                           v  =  "0" + v;
                        }
                        r  =  r + v;
                     }
                     break;
                  case "L":   // leap year
                     r  =  r  +  (this.further(attempt) ? "1" : "0" );
                     break;
                  case "r":   // RFC 2822
                     r  =  r + this.formatPHP(attempt,
                                              "D, j M Y H:i:s O");
                     break;
                  case "t":
                     r  =  r + this.full(attempt);
                     break;
                  case "U":   // 1970-01-01
                     if ( this.fiat( attempt ) ) {
                        r  =  r + attempt.date.getTime() * 1000;
                     }
                     break;
                  case "W":
                  case "z":
                     if ( typeof attempt.month  ===  "number"  &&
                          typeof attempt.dom  ===  "number" ) {
                        v  =  attempt.dom - 1;
                        if ( attempt.month === 2 ) {
                           v  +=  31;
                        }
                        if ( typeof attempt.year  ===  "number" ) {
                           if ( attempt.month > 2 ) {
                              for ( n = attempt.month - 1;
                                    n === 2;
                                    n-- ) {
                                 v  +=  this.domax[ n ];
                              }   // for n--
                              this.fiat( attempt );
                              if ( ! attempt.leap) {
                                 v--;
                              }
                           }
                           if ( s === "W" ) {   // woy  ISO 8601
                              if ( typeof attempt.jan1  !==  "number" ) {
                                 o  =  new Date( attempt.year, 0, 0 );
                                 attempt.jan1  =  o.getDay();
                              }
                              if ( attempt.jan1 < 4 ) {
                                 v  -=  attempt.jan1;
                              }
                              v  =  Math.ceil( ++v / 7 );
// erste Kalenderwoche im Jahr
// Woche mit dem ersten Januar-Donnerstag definiert.
                           }
                           r  =  r + v;
                        } else if ( s === "z"  &&  attempt.month <= 2 ) {
                           r  =  r + v;
                        }
                     }
                     break;
               }   // switch s
               break;
            default:
               r  =  r + s;
         }   // switch typeof phpCodes[ s ]
      }   // for i
      return  r;
   };   // .util.date.formatPHP()



   WSTM.util.date.full  =  function ( attempt ) {
      // Number of days in month
      // Precondition:
      //    attempt  -- object of components
      //                >  .month
      //                >  .leap
      // Postcondition:
      //    Returns number, may be zero if no month provided
      // Uses:
      //    this
      //    >  .util.date.domax
      //    .util.date.further()
      // 2016-05-14 PerfektesChaos@de.wikipedia
      var r = 0,
          m;
      if ( typeof attempt.month  ===  "number" ) {
         m  =  attempt.month;
         if ( m >= 1  &&  m <= 12 ) {
            r  =  this.domax[ m ];
            if ( m === 2 ) {
               this.further( attempt );
               if ( ! attempt.leap ) {
                  r  =  28;
               }
            }
         }
      }
      return  r;
   };   // .util.date.full()



   WSTM.util.date.furnish  =  function (at, as, assign, again) {
      // Retrieve textual representation of date component
      // Precondition:
      //    at       -- number
      //    as       -- string with keyword (month, mon, doweek, dow)
      //    assign   -- object with localised names, or not
      //                "month":  Array of month names;
      //                          counting from 1 (1=January)
      //                "mon":    Array of abbreviated month names;
      //                                counting from 1 (1=Jan)
      //                          object else:
      //                                 n: length of abbreviation
      //                                 suffix: if desired
      //                "doweek": Array of day of week names;
      //                          counting from 0 (0=Sunday)
      //                "dow":    Array of abbreviated day of week names;
      //                                counting from 0 (0=Sun)
      //                          object else:
      //                                 n: length of abbreviation
      //                                 suffix: if desired
      //    again    -- true: fallback mode, not again
      // Postcondition:
      //    Returns string
      // Uses:
      //    this
      //    >  .util.date.words
      //    .util.date.furnish()   -- self-recursive
      // 2016-03-22 PerfektesChaos@de.wikipedia
      var o, r, s;
      if ( typeof assign  ===  "object"  &&
           typeof assign[ as ]  ===  "object" ) {
         o  =  assign[ as ];
         if ( typeof o.length  ===  "number" ) {
            r  =  o[ at ];
         } else if (as.length === 3  &&
                     typeof o.n  ===  "number" ) {
            s  =  (as === "mon"  ?  "month"  :  "doweek" );
            if ( typeof assign[ s ]  ===  "object"  &&
                 typeof assign[ s ][ at ]  ===  "string" ) {
               r  =  assign[ s ][ at ].substr( 0, o.n );
               if ( typeof o.suffix  ===  "string" ) {
                  r  =  r + o.suffix;
               }
            }
         }
      }
      if ( ! r ) {
         if ( again ) {
            r  =  "<" + at + ">";
         } else {
            r  =  this.furnish( at, as, this.words, true );
         }
      }
      return  r;
   };   // .util.date.furnish()



   WSTM.util.date.further  =  function ( attempt ) {
      // Is this a leap year?
      // Precondition:
      //    attempt  -- object of components
      //                >  .bc
      //                >  .year
      //                >< .leap
      // Postcondition:
      //    Returns boolean
      // 2018-01-28 PerfektesChaos@de.wikipedia
      var r, j;
      if ( typeof attempt.leap  ===  "boolean" ) {
         r  =  attempt.leap;
      } else {
         r  =  false;
         if ( typeof attempt.year  ===  "number"   &&
              ( typeof attempt.bc  ===  "undefined"  ||
                ! attempt.bc ) ) {
            j  =  attempt.year;
            if ( j > 0  &&  j <= 2100 ) {
               if ( !  j % 4    &&
                    ( j % 100   ||   !  j % 400 ) ) {
                  r  =  true;
               }
            }
         }
         attempt.leap  =  r;
      }
      return  r;
   };   // .util.date.further()



//-----------------------------------------------------------------------
};   // .bb.dating()
mw.libs.WikiSyntaxTextMod.bb.dating( mw.libs.WikiSyntaxTextMod );
delete mw.libs.WikiSyntaxTextMod.bb.dating;



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



mw.libs.WikiSyntaxTextMod.bb.idcodes  =  function ( WSTM ) {
   // ID code syntax analysis, error message
   // Public:
   //    .util.code.dnb()
   //    .util.code.doi()
   //    .util.code.isbn()
   //    .util.code.issn()
   //    .util.code.lccn()
   //    .util.code.pmc()
   //    .util.code.pmid()
   //    .util.code.urn()
   //    .util.code.viaf()
   //    .util.code.zdb()
   // Uses:
   //    .util.fiatObjects()
   // 2020-02-07 PerfektesChaos@de.wikipedia
   "use strict";



   WSTM.util.fiatObjects( WSTM.util, "code",
                          { re: { } } );



   WSTM.util.code.fetch  =  function ( attempt, amount, allowX, about ) {
      // Retrieve Array with digits
      // Precondition:
      //    attempt  -- string with presumable code; digits space hyphens
      //    amount   -- number of maximum permitted digits
      //    allowX   -- number; of (last) position for permitted xX
      //                boolean; xX at last position permitted
      //    about    -- string with thematic context
      // Postcondition:
      //    Returns Array of digits including 10, or false if invalid
      // Uses:
      //    >  .str.sticks
      //    >  .str.spaces
      //    .errors.found()
      // Requires: JavaScript 1.3   charCodeAt()   fromCharCode()
      // 2016-06-10 PerfektesChaos@de.wikipedia
      var k  =  0,
          n  =  attempt.length,
          r  =  new Array( amount ),
          c,
          i;
      for ( i = 0;  i < n;  i++ ) {
         c  =  attempt.charCodeAt( i );
         if ( c >= 48  &&  c <= 57 ) {   // 0...9
            c  -=  48;
            if ( k < amount ) {
               r[ k ]  =  c;
            } else {
               r  =  false;
               WSTM.errors.found( "badCodeDigitcount",
                                  false,
                                  about + ": " + attempt );
               break;   // for i
            }
            k++;
         } else if ( c === 88  ||  c === 120 ) {   // X x
            if ( allowX   &&   i  ===  n - 1 ) {
               if ( allowX === true   ||   allowX  ===  k + 1 ) {
                  r[ k ]  =  10;
                  k++;
               } else {
                  r  =  false;
               }
            } else {
               r  =  false;
            }
            if ( ! r ) {
               WSTM.errors.found( "badCodeX",
                                  false,
                                  about + ": " + attempt);
            }
            break;   // for i
         } else if ( c !== 32  &&  c !== 45 ) {   // space hyphen
            c  =  String.fromCharCode(c);
            if ( WSTM.str.sticks.indexOf( c ) < 0  &&
                 WSTM.str.spaces.indexOf( c ) < 0 ) {
               r  =  false;
               WSTM.errors.found( "badCodeChar",
                                  false,
                                  about + ": " + attempt );
               break;   // for i
            }
         }
      }   // for i
      if ( r ) {
         if ( k < amount ) {
            r.splice( k,  amount - k );
         }
      }
      return  r;
   };   // .util.code.fetch()



   WSTM.util.code.dnb  =  function ( adjust ) {
      // Check DNB code
      // Precondition:
      //    adjust  -- DNB code (no leading keyword)
      // Postcondition:
      //    Returns false if valid, or true if invalid
      // Uses:
      //    .util.dnb.failure()
      // 2013-06-23 PerfektesChaos@de.wikipedia
      return  WSTM.util.dnb.failure( adjust, "DNB" );
   };   // .util.code.dnb()



   WSTM.util.code.doi  =  function ( adjust, allow ) {
      // DOI syntax analysis, error message
      // Precondition:
      //    adjust  -- identifier (trimmed)
      //    allow   -- permit Wikisyntax characters;  else interwiki link
      // Postcondition:
      //    Returns false if valid, or Array with error info [1]
      // Uses:
      //    .util.doi.format()
      // 2013-06-27 PerfektesChaos@de.wikipedia
      return  WSTM.util.doi.format( adjust, allow );
   };   // .util.code.doi()



   WSTM.util.code.ean  =  function ( adjust ) {
      // Check EAN code
      // Precondition:
      //    adjust  -- EAN code (no leading keyword)
      // Postcondition:
      //    Returns false if to be kept, or string if to be corrected
      // Uses:
      //    .util.gtin.format()
      // 2013-06-21 PerfektesChaos@de.wikipedia
      return  WSTM.util.gtin.format( adjust, "EAN" );
   };   // .util.code.ean()



   WSTM.util.code.gnd  =  function ( adjust ) {
      // Check GND code
      // Precondition:
      //    adjust  -- GND code (no leading keyword)
      // Postcondition:
      //    Returns false if valid, or true if invalid
      // Uses:
      //    .util.dnb.failure()
      // 2016-06-19 PerfektesChaos@de.wikipedia
      return  WSTM.util.dnb.failure( adjust, "GND", 8, false );
   };   // .util.code.gnd()



   WSTM.util.code.gtin  =  function ( adjust ) {
      // Check GTIN code
      // Precondition:
      //    adjust  -- GTIN code (no leading keyword)
      // Postcondition:
      //    Returns false if to be kept, or string if to be corrected
      // Uses:
      //    .util.gtin.format()
      // 2013-06-21 PerfektesChaos@de.wikipedia
      return  WSTM.util.gtin.format( adjust, "GTIN" );
   };   // .util.code.gtin()



   WSTM.util.code.isbn  =  function ( adjust, accept ) {
      // Format ISBN code
      // Precondition:
      //    adjust  -- ISBN code (no leading keyword)
      //    accept  -- 10, 13, false or omitted
      // Uses:
      //    .util.isbn.format()
      // Postcondition:
      //    Returns  array[2]
      //             [0] number  of characters successfully consumed
      //                         at least 10, some more for hyphens etc.
      //                         [1] string  reformatted ISBN:
      //                                     insert hyphens etc.
      //                                     spaces replaced by hyphens
      //                                     x->X
      //                                     hyphens inserted
      //                                             before checknumber
      //                                             at ISBN-13
      //                             false   no formatting necessary
      //                 false   adjust is invalid sequence
      //                         [1] error code -1,1...12
      // 2012-12-22 PerfektesChaos@de.wikipedia
      return  WSTM.util.isbn.format( adjust,
                                     (accept ? accept : false) );
   };   // .util.code.isbn()



   WSTM.util.code.issn  =  function ( adjust ) {
      // Format ISSN code
      // Precondition:
      //    adjust  -- ISSN code (no leading keyword)
      // Postcondition:
      //    Returns false if to be kept, or string if to be corrected
      // Uses:
      //    .util.issn.format()
      // 2013-06-02 PerfektesChaos@de.wikipedia
      return  WSTM.util.issn.format( adjust );
   };   // .util.code.issn()



   WSTM.util.code.lang  =  function ( adjust ) {
      // Check ISO 639 code
      // Precondition:
      //    adjust  -- lang code
      // Postcondition:
      //    Returns false if valid,
      //            string if to be adjusted,
      //            or Array with error info [1]
      // Uses:
      //    >< .util.code.re.baselang
      //    .str.trim()
      //    .util.isO_639_1()
      //    .str.capitalize()
      // 2021-10-26 PerfektesChaos@de.wikipedia
      var r      =  WSTM.str.trim( adjust ),
          parts  =  r.split( "-" ),
          s;
      r  =  parts[ 0 ].toLowerCase();
      switch ( r.length ) {
          case 2 :
             if ( ! WSTM.util.isO_639_1( r ) ) {
                r  =  false;
             }
             break;
          case 3 :
             if ( typeof WSTM.util.code.re.baselang  !==  "object" ) {
                WSTM.util.code.re.baselang  =  new RegExp( "^[a-z]+$" );
             }
             if ( ! WSTM.util.code.re.baselang.test( r ) ) {
                r  =  false;
             }
             break;
          default :
             r  =  false;
      }   // switch r.length
      if ( r ) {
         if ( parts.length > 1 ) {
            if ( parts.length === 2 ) {
               s  =  parts[ 1 ];
               if ( typeof WSTM.util.code.re.baselang  !==  "object" ) {
                  WSTM.util.code.re.baselang  =
                                                new RegExp( "^[a-z]+$" );
               }
               if ( WSTM.util.code.re.baselang.test( r ) ) {
                  switch ( s.length ) {
                     case 2 :
                        s  =  s.toUpperCase();
                        break;
                     case 4 :
                        s  =  WSTM.str.capitalize( s );
                        break;
                     default :
                        s  =  false;
                  }   // switch s.length
               } else {
                  s  =  false;
               }
               if ( s ) {
                  r  =  r + "-" + s;
               } else {
                  r  =  [ adjust, "Invalid; bad subset ID" ];
               }
            } else {
               r  =  [ adjust, "Invalid; too many hyphens" ];
            }
         }
         if ( r === adjust ) {
            r  =  false;
         }
      } else {
         r  =  [ adjust, "Invalid; bad ID" ];
      }
      return  r;
   };   // .util.code.lang()



   WSTM.util.code.lccn  =  function ( adjust, apply ) {
      // Check LCCN code
      // Precondition:
      //    adjust  -- LCCN code (no leading keyword)
      //    apply   -- '/' or '-' or false
      // Postcondition:
      //    Returns false if valid,
      //            string if to be adjusted,
      //            or Array with error info [1]
      // Uses:
      //    .util.lccn.format()
      // 2013-06-27 PerfektesChaos@de.wikipedia
      return  WSTM.util.lccn.format( adjust, apply );
   };   // .util.code.lccn()



   WSTM.util.code.pmc  =  function ( adjust ) {
      // Check PMC code
      // Precondition:
      //    adjust  -- PMC code (trimmed, no leading keyword)
      // Postcondition:
      //    Returns false if valid, or true if invalid
      // Uses:
      //    >< .util.code.re.pmc
      // 2021-10-26 PerfektesChaos@de.wikipedia
      if ( typeof WSTM.util.code.re.pmc  !==  "object" ) {
         WSTM.util.code.re.pmc  =  new RegExp( "^[1-9][0-9]{4,9}$" );
      }
      return  ( ! WSTM.util.code.re.pmc.test( adjust ) );
   };   // .util.code.pmc()



   WSTM.util.code.pmid  =  function ( adjust ) {
      // Check PMID code
      // Precondition:
      //    adjust  -- PMID code (trimmed, no leading keyword)
      // Postcondition:
      //    Returns false if valid, or true if invalid
      // Uses:
      //    >< .util.code.re.pmid
      // 2021-10-26 PerfektesChaos@de.wikipedia
      if ( typeof WSTM.util.code.re.pmid  !==  "object" ) {
         WSTM.util.code.re.pmid  =  new RegExp( "^[1-9]([0-9]{1,9})?$" );
      }
      return  ( ! WSTM.util.code.re.pmid.test( adjust ) );
   };   // .util.code.pmid()



   WSTM.util.code.urn  =  function ( adjust ) {
      // Check URN code
      // Precondition:
      //    adjust  -- URN code (URI)
      // Postcondition:
      //    Returns false if valid, or true if invalid
      // Uses:
      //    .util.urn.failure()
      // 2013-06-21 PerfektesChaos@de.wikipedia
      return  WSTM.util.urn.failure( adjust );
   };   // .util.code.urn()



   WSTM.util.code.viaf  =  function ( adjust ) {
      // Check VIAF code
      // Precondition:
      //    adjust  -- VIAF code (trimmed, no leading keyword)
      // Postcondition:
      //    Returns false if valid, or true if invalid
      // Uses:
      //    >< .util.code.re.viaf
      // 2021-10-26 PerfektesChaos@de.wikipedia
      if ( typeof WSTM.util.code.re.viaf  !==  "object" ) {
         WSTM.util.code.re.viaf  =  new RegExp( "^[1-9][0-9]{3,13}$" );
      }
      return  ( ! WSTM.util.code.re.viaf.test( adjust ) );
   };   // .util.code.viaf()



   WSTM.util.code.zdb  =  function ( adjust ) {
      // Check ZDB code
      // Precondition:
      //    adjust  -- ZDB code (no leading keyword)
      // Postcondition:
      //    Returns false if valid, or true if invalid
      // Uses:
      //    .util.dnb.failure()
      // 2016-06-19 PerfektesChaos@de.wikipedia
      return  WSTM.util.dnb.failure( adjust, "ZDB", 4, true );
      //          {{ZDB|94467-1}}   {{ZDB|1372-9}}
   };   // .util.code.zdb()



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



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



mw.libs.WikiSyntaxTextMod.bb.dnb  =  function (WSTM) {
   // DNB family (DNB, GND, ZDB) code syntax analysis
   // Public:
   //    .util.dnb.failure()
   // Uses:
   //    .util.code.fetch()
   //    .errors.found()
   // 2013-06-23 PerfektesChaos@de.wikipedia
   "use strict";
   WSTM.util.fiatObjects( WSTM.util,  "dnb" );



   WSTM.util.dnb.failure  =  function ( attempt, about, amount, alt ) {
      // Is DNB code invalid?
      // Precondition:
      //    attempt  -- DNB code (no leading keyword)
      //    about    -- keyword
      //    amount   -- minimum length of core
      //    alt      -- hyphen required
      // Postcondition:
      //    Returns false if valid, or true/string/number if invalid
      // Uses:
      //    >< .util.re.dnbX
      //    .util.code.fetch()
      //    .util.dnb.faith()
      // 2021-10-26 PerfektesChaos@de.wikipedia
      var j    =  attempt.indexOf( "/" ),
          dnb,
          s,
          r;
      if ( j > 0 ) {
         s  =  attempt.substr( 0, j );
      } else {
         s  =  attempt;
      }
      dnb  =  WSTM.util.code.fetch( s, 11, true, about );
      if ( dnb ) {
         j = dnb.length;
         if ( amount  &&  j <= amount ) {
            r  =  amount;
         }
         if ( ! r   &&   typeof alt  ===  "boolean" ) {
            if ( attempt.indexOf( "-" ) < 0 ) {
               r  =  alt;
            } else {
               r  =  ( ! alt );
            }
         }
         if ( ! r  &&  j <= 8 ) {
            if ( typeof WSTM.util.re.dnbX  !==  "object" ) {
               WSTM.util.re.dnbX  =
                               new RegExp( "^[1-9][0-9]{3,6}-[0-9xX]$" );
            }
            if ( WSTM.util.re.dnbX.test( s ) ) {
               r = ( ( 11 - this.faith( dnb ) )  %  11
                                                     !==  dnb[ j - 1 ] );
               j = false;
            } else {
               r = true;
            }
         }
         if ( ! r  &&  j  &&  ! alt ) {
            r = ( this.faith( dnb )  !==  dnb[ j - 1 ] );
         }
      } else {
         r = true;
      }
      return  r;
   };   // .util.dnb.failure()



   WSTM.util.dnb.faith  =  function ( assert ) {
      // Compute DNB family (DNB, GND, ZDB) check digit
      // Precondition:
      //    assert  -- Array with digits
      // Postcondition:
      //    Returns   0...9
      // 2013-06-23 PerfektesChaos@de.wikipedia
      var n  =  assert.length,
          k  =  n,
          r  =  0,
          i;
      n--;
      for ( i = 0;  i < n;  i++ ) {
         r  =  r  +  k * assert[ i ];
         k  =  k - 1;
      }   // for i
      r  =  ( 11  -  r % 11 )   %   11;
      return  r;
   };   // .util.dnb.faith()



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



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




mw.libs.WikiSyntaxTextMod.bb.doi  =  function (WSTM) {
   // DOI syntax analysis, code correction and formatting
   // Public:
   //    .util.doi.format()
   // Uses:
   //    .util.code.fetch()
   //    .errors.found()
   // 2013-06-27 PerfektesChaos@de.wikipedia
   "use strict";
   WSTM.util.fiatObjects( WSTM.util,  "doi" );



   WSTM.util.doi.failure  =  function ( attempt ) {
      // Is DOI invalid?
      // Precondition:
      //    attempt  -- identifier (trimmed)
      // Postcondition:
      //    Returns false if valid,
      //            string if to be adjusted,
      //            or Array with error info [1]
      // Uses:
      //    .util.doi.format()
      //    .str.decodeXML()
      // 2013-06-27 PerfektesChaos@de.wikipedia
      var r  =  this.format(attempt, false),
          s;
      if ( r ) {
         s  =  attempt.replace( /&(#x200[9A-F]|lrm|rlm|zwn?j);/, "" );
         if ( s !== attempt ) {
            r  =  s;
         }
      }
      return  r;
   };   //    .util.doi.failure()



   WSTM.util.doi.format  =  function (adjust, allow) {
      // DOI syntax analysis, error message
      // Precondition:
      //    adjust  -- identifier (trimmed)
      //    allow   -- permit Wikisyntax characters;  else interwiki link
      // Postcondition:
      //    Returns false if valid, or Array with error info [1]
      // Uses:
      //    >< .util.doi.re.*
      //    .str.decodeXML()
      // 2017-07-18 PerfektesChaos@de.wikipedia
      var r  =  false,
          i, s;
      if ( adjust.substr( 0, 3 ) === "10." ) {
         s  =  adjust.substr( 3 );
         i  =  s.indexOf( "/" );
         if ( i > 3 ) {
            if ( typeof this.re  !==  "object" ) {
               this.re  =  { };
               this.re.org  =  new RegExp( "^[1-9][0-9]{3,7}$", "" );
               this.re.doi  =  "-0-9/A-Z.a-z()_;,:";
               this.re.iw   =  new RegExp( "^["
                                              + this.re.doi + "&#]{3,}$",
                                           "" );
               this.re.doi  =  new RegExp( "^" + "[/0-9.A-Za-z(<]"
                                               + "(?:[" + this.re.doi
                                                       + "<>]+|\\[|\\])+"
                                              + "[0-9A-Za-z#+)]$",
                                           "" );
            }
            if ( this.re.org.test( s.substr( 0, i ) ) ) {
               s  =  s.substr( i + 1 );
               if ( ! allow ) {
                  if ( ! this.re.iw.test( s ) ) {
                     r  =  "invalid character in ID: " + adjust;
                  }
               }
               if ( ! r ) {
                  s  =  WSTM.str.decodeXML( s );
                  if ( ! this.re.doi.test( s ) ) {
                     r  =  "bad selector '" + s + "'";
                  }
               }
            } else {
               r  =  "bad number '"  +  s.substr( 0, i )  +  "'";
            }
         } else {
            r  =  "missing '/'";
         }
      } else {
         r  =  "leading '10.' missing";
      }
      return  ( r  ?  [ false, r ]  :  false );
   };   // .util.doi.format()



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



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



mw.libs.WikiSyntaxTextMod.bb.gtin  =  function (WSTM) {
   // GTIN (EAN) syntax analysis, code correction and formatting
   // Public:
   //    .util.gtin.format()
   // Uses:
   //    .util.fiatObjects()
   //    .util.code.fetch()
   //    .errors.found()
   // 2013-06-23 PerfektesChaos@de.wikipedia
   "use strict";
   WSTM.util.fiatObjects( WSTM.util,  "gtin" );



   WSTM.util.gtin.faith  =  function ( assert ) {
      // Compute GTIN check digit
      // Precondition:
      //    assert  -- Array with digits
      // Postcondition:
      //    Returns   0...9
      // 2013-06-23 PerfektesChaos@de.wikipedia
      var lead  =  true,
          r     =  0,
          i,
          k;
      for ( i = 0;  i < 12;  i++ ) {
         k   =  assert[i];
         r  +=  k;
         if ( lead ) {   // odd
            lead  =  false;
         } else {   // even
            r     +=  k + k;
            lead   =  true;
         }
      }   // for i
      r  =  ( 10  -  r % 10 )   %   10;
      return  r;
   };   // .util.gtin.faith()



   WSTM.util.gtin.fashion  =  function (acquired) {
      // Format GTIN code
      // Precondition:
      //    acquired  -- Array with digits
      // 2013-06-23 PerfektesChaos@de.wikipedia
      var r  =  "",
          i;
      for (i = 0;  i < 4;  i++) {
         r  =  r + String.fromCharCode(acquired[i]+48);
      }   // for i
      r  =  r + "-";
      for (i = 4;  i < 12;  i++) {
         r  =  r + String.fromCharCode(acquired[i]+48);
      }   // for i
      r  =  r + "-" + String.fromCharCode(acquired[12]+48);
      return  r;
   };   // .util.gtin.faith()



   WSTM.util.gtin.format  =  function (attempt, about) {
      // Format GTIN code
      // Precondition:
      //    attempt  -- GTIN code (no leading keyword)
      //    about    -- keyword
      // Postcondition:
      //    Returns false if valid, or string if to be corrected
      // Uses:
      //    .util.code.fetch()
      //    .util.gtin.faith()
      //    .str.trim()
      //    .util.gtin.fashion()
      //    .errors.found()
      // 2013-06-23 PerfektesChaos@de.wikipedia
      var r  =  WSTM.util.code.fetch( attempt, 13, false, "GTIN" );
      if ( r ) {
         if ( r.length === 13 ) {
            if ( this.faith( r ) === r[ 12 ] ) {
               if ( attempt.indexOf("-") > 0 ) {
                  r  =  WSTM.str.trim( attempt );
                  if ( r === attempt ) {
                     r  =  false;
                  }
               } else {
                  r  =  this.fashion(r);
               }
            } else {
               r  =  false;
               WSTM.errors.found( "badCodeCheckdig",
                                  false,
                                  about + ": " + attempt );
            }
         } else {
            r  =  false;
            WSTM.errors.found( "badCodeDigitcount",
                               false,
                               about + ": " + attempt );
         }
      }
      return  r;
   };   // .util.gtin.format()



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



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



mw.libs.WikiSyntaxTextMod.bb.isbn  =  function (WSTM) {
   // ISBN syntax analysis, code correction and formatting
   // Public:
   //    .util.isbn.factory()
   //    .util.isbn.format()
   // Uses:
   //    >  .str.sticks
   //     < .util.isbn.grouping
   //    .util.fiatObjects()
   //    .util.gtin.faith()
   //    .errors.found()
   //    .str.substrEnd()
   // 2016-03-20 PerfektesChaos@de.wikipedia
   "use strict";
   WSTM.util.fiatObjects(WSTM.util,  "isbn");
   WSTM.util.isbn.grouping   =  false;   // segmentation data



   WSTM.util.isbn.factory  =  function (attribute) {
      // Make regexp string for ISBN detection
      // Precondition:
      //    attribute  -- URLs are excluded from detection
      // Postcondition:
      //    Returns string for RegExp
      //                [1]  prolog
      //                     preceding non-whitespace
      //                [2]  "ISBN"
      //        6 10 14 [3]  10 | 13
      //              4 [4]  '=' assignment, if any
      //             15 [5]  I-S-B-N
      //             17 [6]  epilog
      // Uses:
      //    >  .str.sticks
      // Requires: JavaScript 1.5   RegExp non-capturing parenthese
      // 2013-09-26 PerfektesChaos@de.wikipedia
      return  "(^|"  +  (attribute ? "\\W"
                                   : "[ \n]")  +  ")"  +             // 1
              "(ISBN)" +                                             // 2
              "(?:" +
                 "(?:[" + WSTM.str.sticks + " ]?" +
                    "(10|13):?" +                                    // 3
                 ")?)" +
              " *" +
              "(?::? *|&nbsp;|&#160;|" +
                 "(=)" +                                             // 4
                 ")?" +
              " *[" + WSTM.str.sticks + "]?" +
              "([0-9]" +
                  "(?:[" + WSTM.str.sticks + " .0-9]|&nbsp;|&#160;)+" +
                     "[0-9X])" +                                     // 5
              "([ -.]*[^" + WSTM.str.sticks + ". 0-9X]|\\.? *$)";    // 6
   };   // .util.isbn.factory()



   WSTM.util.isbn.faith  =  function ( attempt, amount ) {
      // Compute ISBN check digit
      // Precondition:
      //    attempt -- string with digits and hyphens without last digit
      //    amount  -- 10 or 13
      // Postcondition:
      //    Returns   0...9, 40 for X, if attempt is valid;  else < 0
      //              -1  attempt is empty
      //              -2  illegal char
      //              -3  invalid length
      // Uses:
      //    .util.gtin.faith()
      // 2013-06-23 PerfektesChaos@de.wikipedia
      var d  =  new Array( amount ),
          k  =  0,
          n  =  attempt.length,
          r  =  -1,
          c,
          i;
      for ( i = 0;  i < n;  i++ ) {
         c  =  attempt.charCodeAt( i );
         if ( c >= 48  &&  c <= 57 ) {
            d[ k ]  =  c - 48;
            k++;
         } else if ( c !== 32  &&  c !== 45 ) {   // space hyphen
            r  =  -2;
            i  =  n + 1;
         }
      }   // for i
      if ( i === n ) {
         if ( amount === 13 ) {   // 13
            if ( k === 12 ) {
               r  =  WSTM.util.gtin.faith( d );
            } else {
               r  =  -3;
            }
         } else {   // 10
            if ( k === 9 ) {
               k  =  0;
               for ( i = 0;  i < 9;  i++ ) {
                  k  +=  ( i + 1 )  *  d[ i ];
               }   // for i
               r  =  k % 11;
               if ( r === 10 ) {
                  r  =  40;   // X(88d) - 48
               }
            } else {
               r  =  -3;
            }
         }
      }   // regular
      return  r;
   };   // .util.isbn.faith()



   WSTM.util.isbn.fault  =  function ( alert, about, another ) {
      // Manage detected error
      // Precondition:
      //    alert    -- identifier of error message
      //    about    -- additional information as found, or false
      //                plain wikitext; will be HTML-escaped later
      //    another  -- error function other than WSTM built-in
      //                called with: another(alert, about)
      // Postcondition:
      //    Environment application package has been notified
      // Uses:
      //    .errors.found()
      // 2012-10-02 PerfektesChaos@de.wikipedia
      if ( typeof another  ===  "function" ) {
         another.call( null, alert, about );
      } else {
         WSTM.errors.found( alert, false, about );
      }
   };   // .util.isbn.fault()



   WSTM.util.isbn.flip  =  function ( adjust, another ) {
      // Find ISBN counterpart: ISBN-10 for ISBN-13, ISBN-13 for ISBN-10
      // Precondition:
      //    adjust  -- string, should contain ISBN, may be formatted
      //    another  -- error function other than WSTM built-in
      // Postcondition:
      //    Returns formatted counterpart of adjust, or false
      // Uses:
      //    .util.isbn.format()
      //    .util.isbn.faith()
      // 2013-11-06 PerfektesChaos@de.wikipedia
      var g  =  this.format( adjust, false, another ),
          r  =  false,
          n, s;
      if ( typeof g[ 0 ]  ===  "number" ) {
         s  =  ( g[ 1 ] ? g[ 1 ] : adjust ).replace( /-/g, "" );
         n  =  s.length;
         s  =  s.substr( 0,  n - 1 );
         if ( n === 10 ) {
            n  =  13;
            s  =  "978" + s;
         } else {
            n  =  10;
            s  =  s.substr( 3 );
         }
         n  =  this.faith( s, n );
         if ( n >= 0 ) {
            s  =  s   +   ( n === 40  ?  "X"  :  n );
            g  =  this.format( s, false, false );
            r  =  g[ 1 ];
         }
      }
      return  r;
   };   // .util.isbn.flip()



   WSTM.util.isbn.fold  =  function ( ahead, area, adjust ) {
      // Divide ISBN substring, separate publisher and title numbers
      // Precondition:
      //    ahead   -- true: bookland 979;  false: 978 or none
      //    area    -- numeric group (0, 3, 99999 etc.)
      //    adjust  -- string with publisher and title numbers
      //               digits and hyphens only
      // Postcondition:
      //    Returns modified area+adjust, or false
      // Uses:
      //    >  .util.isbn.grouping
      // 2022-01-30 PerfektesChaos@de.wikipedia
      var f   =  this.grouping[ ( ahead ? 1 : 0 ) ],
          id  =  area,
          j   =  adjust.indexOf( "-" ),
          r   =  false,
          s   =  adjust,
          d,
          g,
          i,
          n,
          k,
          m;
      if ( j < 0 ) {
         j  =  false;
      } else {
         if ( ! j ) {
            s  =  adjust.substr( 1 );
            j  =  false;
         } else {
            s  =  s.substr( 0, j )  +  s.substr( j + 1 );
         }   // leading hyphen
         k  =  s.indexOf( "-" );
         while ( k >= 0 ) {
            s  =  s.substr( 0, k )  +  s.substr( k + 1 );
            k  =  s.indexOf( "-" );
            j  =  false;
         }   // while k
      }   // one hyphen
      if ( f ) {
         n  =  f.length;
         for ( i = 0;  i < n;  i++ ) {
            g  =  f[ i ];
            m  =  g[ 0 ];
            if ( m === area ) {
               f  =  false;
               break;   // for i
            }
         }   // for i
         if ( f ) {
            s  =  area + s;
            for ( i = 0;  i < n;  i++ ) {
               g  =  f[ i ];
               m  =  g[ 0 ];
               if ( m < 10 ) {
                  k  =  1;
               } else if ( m < 100 ) {
                  k  =  2;
               } else if ( m < 1000 ) {
                  k  =  3;
               } else if ( m < 10000 ) {
                  k  =  4;
               } else {
                  k  =  5;
               }
               if ( m  ===  parseInt( s.substr( 0, k ),  10 ) ) {
                  id  =  m;
                  s   =  s.substr( k );
                  f   =  false;
                  break;   // for i
               }
            }   // for i
         }
         if ( ! f ) {
            n  =  g.length;
            for ( i = 1;  i < n;  i++ ) {
               f  =  g[ i ];   // certain length
               k  =  parseInt( s.substr( 0, f[ 0 ] ),  10 );
               for ( m = 1;  m < f.length;  m++ ) {
                  d  =  f[ m ];
                  if ( k >= d[ 0 ]  &&  k <= d[ 1 ] ) {
                     r  =  d[ 2 ];
                     n  =  -1;
                     break;   // for m
                  }   // match
               }   // for m
            }   // for i
         }   // group match
      }   // bookland
      if ( r ) {
         if ( j ) {
            if ( j === r  &&  id === area ) {
               r  =  false;
            }   // unchanged
         }   // one hyphen found
         if ( r ) {
            g  =  s.substr( r );
            r  =  id  +  "-"  +  s.substr( 0, r );
            if ( g ) {
               r  =  r + "-" + g;
            }
         }   // hyphen modified
      }   // publisher identified
      return  r;
   };   // .util.isbn.fold()



   WSTM.util.isbn.format  =  function (adjust, ask, another) {
      // Parse ISBN string, reformat / standardize if necessary
      // Precondition:
      //    adjust   -- string, containing possible ISBN
      //    ask      -- 10:    require ISBN-10
      //                13:    require ISBN-13
      //                false: no type required
      //    another  -- error function other than WSTM built-in
      // Postcondition:
      //    Returns  array[2]
      //             [0] number  of characters successfully consumed
      //                         at least 10, some more for hyphens etc.
      //                         [1] string  reformatted ISBN:
      //                                     insert hyphens etc.
      //                                     spaces replaced by hyphens
      //                                     x->X
      //                                     hyphens inserted
      //                                             before checknumber
      //                                             at ISBN-13
      //                             false   no formatting necessary
      //                 false   adjust is invalid sequence
      //                         [1] error code -1,1...12
      // Uses:
      //    >  .util.isbn.grouping
      //    .util.isbn.fault()
      //    .util.isbn.faith()
      //    .str.substrEnd()
      //    .util.isbn.furnish()
      //    .util.isbn.fold()
      // Requires: JavaScript 1.3   charCodeAt()   fromCharCode()
      // 2022-01-30 PerfektesChaos@de.wikipedia
      var chain   =  false,
          i       =  0,
          impact  =  0,
          last    =  false,
          lazy    =  false,
          loop    =  true,
          max     =  ( ask ? ask : 13 ),
          n       =  adjust.length,
          naked   =  0,
          r       =  [ false, false ],
          shift   =  "",
          scope   =  "",
          c,
          j,
          lead,
          lean,
          slang,
          swap;
      // Universelle Error-Funktion     impact-Nr.->msgName + s
      while ( loop ) {
         c     =  adjust.charCodeAt(i);
         lead  =  ( c >= 48  &&  c <= 57 );
         if ( lead ) {
            if ( last ) {
               impact  =  1;   // digit after 'X'
               this.fault( "badISBNdigitAfterX",
                           adjust.substr(0,  i + 1),
                           another );
            }
         } else {
            switch ( c ) {
               case   32 :   // space
               case   46 :   // dot
               case  173 :   // shy
               case 8208 :   // hyphen
               case 8209 :   // nb-hyphen
               case 8210 :   // figure dash
               case 8211 :   // ndash
               case 8212 :   // mdash
               case 8213 :   // horizontal bar
               case 8259 :   // hyphen bullet
               case 8722 :   // minus
               case 9472 :   // box drawings light horizontal
               case   38 :   // '&'
                  lazy  =  true;   // fall-through
               case   45 :   // hyphen
                  if ( c === 38 ) {
                     swap  =  adjust.substr( i, 6 );
                     if ( swap === "&nbsp;"  ||
                          swap === "&#160;"  ||
                          swap === "&#xA0;"  ||
                          swap === "&#xa0;" ) {
                        i  +=  5;
                     } else {
                        loop  =  false;
                     }
                  }
                  if ( chain ) {
                     if ( naked < max ) {
                        shift  =  shift + "-";
                     }
                     chain  =  false;
                  } else if ( naked === max ) {
                     if ( c === 45 ) {
                        impact  =  2;   // hyphen after last digit
                        this.fault( "badISBNhyphenAfterEnd",
                                    adjust.substr( 0,  i + 1 ),
                                    another );
                     } else if ( ! lazy ) {
                        loop  =  false;
                     }
                  }
                  break;
               case   88 :   // X
               case  120 :   // x
                  if ( last ) {
                     impact  =  3;   // multiple 'X'
                     this.fault("badISBNmultipleX",
                                adjust.substr(0,  i + 1),
                                another);
                  } else {
                     last  =  true;
                     if (ask) {
                        lead  =  (naked  ===  ask - 1);
                     } else {
                        lead  =  (naked === 9);
                     }
                     if (lead) {
                        c  =  88;
                     } else {
                        impact  =  4;   // 'X' at bad position
                        this.fault("badISBNXbadPosition",
                                   adjust.substr(0,  i + 1),
                                   another);
                      }
                  }
                  break;
               default :
                  loop  =  false;
                  break;
            }   // switch c
         }   // no digit
         if ( lead ) {
            if ( ! impact ) {
               if ( naked === max ) {
                  impact  =  5;   // too many digits
                  this.fault( "badISBNtooManyDigits1",
                              adjust.substr( 0,  i + 1 ),
                              another );
               } else {
                  c  =  String.fromCharCode( c );
                  naked++;
                  shift  =  shift + c;
                  scope  =  scope + c;
                  chain  =  true;
               }   // loop
            }   // valid
         }   // lead
         if ( impact > 0 ) {
            loop  =  false;
         }   // invalid
         if ( loop ) {
            i++;
            loop  =  ( i < n );
         }   // loop
      }   // while loop
      if ( ! impact ) {
         if ( ask ) {
            if ( naked !== ask ) {
               impact  =  6;   // too many digits
               this.fault( "badISBNtooManyDigits2",
                           adjust.substr( 0,  i + 1 ),
                           another );
            }
         } else if ( naked !== 10  &&  naked !== 13 ) {
            impact  =  7;   // bad number of digits
            this.fault("badISBNcountingDigits",
                       "[" + naked + "] "
                       +   adjust.substr( 0,  i + 1 ),
                       another);
         }   // check length
         if ( ! impact ) {
            if ( naked === 13 ) {
               j  =  shift.indexOf( "-" );
               while ( j > 0  &&  j < 3 ) {
                  shift  =  shift.substr( 0, j )
                            +  shift.substr( j + 1 );
                  j      =  shift.indexOf( "-" );
               }   // while "-"
               c  =  shift.substr( 0, 3 );
               if ( c !== "978"  &&  c !== "979" ) {
                  impact  =  8;   // bad bookland (EAN) in ISBN-13
                  this.fault( "badISBN13bookland",
                              adjust.substr( 0,  i + 1 ),
                              another );
               } else if ( shift.substr( 3, 1 )  !==  "-" ) {
                  shift  =  shift.substr( 0, 3 )
                            +  "-"  +  shift.substr( 3 );
               }
            }
         } else if (naked < 5) {   // too short
            impact  =  -1;
         }
      }   // basically valid
      if ( ! impact ) {
         lean  =  ( naked === 13 );
         if ( lean ) {
            lead  =  ( shift.charCodeAt( 2 )  ===  57 );   // 97*9*
         } else {
            lead  =  false;
         }
         j  =  shift.length;
         n  =  j;
         j--;
         if ( shift.charCodeAt( j ) === 45 ) {   // '-'
            n--;
            j--;
            shift  =  shift.substr( 0, n );
         }
         c  =  this.faith( shift.substr( 0, j ),  naked );
         if ( c < 0 ) {
            impact  =  8 - c;   // invalid checkdigit
            switch ( c ) {
               case -1 :
                  shift  =  "badISBNcheckdigEmpty";
                  break;
               case -2 :
                  shift  =  "badISBNcheckdigChar";
                  break;
               case -3 :
                  shift  =  "badISBNcheckdigLength";
                  break;
            }   // switch faith
            this.fault( shift,   adjust.substr( 0,  i + 1 ),   another );
         } else if ( c   !==   shift.charCodeAt( j )  -  48 ) {
            impact  =  12;   // wrong checkdigit
            this.fault( "badISBNcheckdigWrong",
                        adjust.substr(0,  i + 1),
                        another );
         }
      }
      if ( ! impact ) {
         c  =  WSTM.str.substrEnd( shift, 1 );
         if ( lean ) {
            if ( shift.substr( 3, 1 )  !==  "-" ) {
               shift  =  shift.substr( 0, 3 )
                         +  "-"  +  shift.substr( 3 );
               n++;
            }
         }
         if ( shift.substr( n - 2,  1 )   !==   "-" ) {
            shift  =  shift.substr( 0,  n - 1 )   +   "-"   +   c;
         }
         slang  =  shift.substr( ( lean ? 4 : 0 ) );
         slang  =  slang.substr( 0,  slang.length - 2 );
         j      =  slang.indexOf( "-" );
         while (j > 0) {
            slang  =  slang.substr(0, j)  +  slang.substr(j + 1);
            j      =  slang.indexOf("-");
         }   // while "-"
         n  =  1;
         c  =  Number( slang.substr( 0, 1 ) );
         if ( c === 1 ) {
            if ( lead   &&
                 slang.substr( 1, 1 )  ===  "0" ) {   // 979-10 fr
               n  =  2;
               c  =  10;
               //
            }
         } else if ( c === 6 ) {
            n  =  -1;
            c  =  false;
         } else if ( c >= 8 ) {
            n  =  2;
            c  =  Number( slang.substr( 0, n ) );
            if ( c > 94 ) {
               n  =  3;
               c  =  Number( slang.substr( 0, n ) );
               if ( c > 989 ) {
                  n  =  4;
                  c  =  Number( slang.substr( 0, n ) );
                  if ( c > 9989 ) {
                     n  =  5;  // ERROR
                     c  =  Number( slang.substr( 0, n ) );
                  }
               }
            }
         }
         if ( n > 0 ) {
            swap  =  slang.substr( n );
            if ( lean ) {   // bookland
               scope   =  shift.substr( 0, 3 )  +  "-";
               n      +=  4;
            } else {
               scope  =  "";
            }
            if ( ! this.grouping ) {
               this.furnish();
            }
            swap  =  this.fold( lead, c, swap );
            if ( swap ) {
               shift  =  scope  +  swap  +  WSTM.str.substrEnd(shift, 2);
            } else {   // not separated
               if ( scope + c + "-"  !==  shift.substr( 0, n ) ) {
                  if ( shift.charCodeAt( n ) === 45 ) {   // '-'
                     n++;
                  }   // already present
                  shift  =  scope  +  c  +  "-"  +  shift.substr( n );
               }
            }
         }
         r[ 0 ]  =  i;
         if ( shift  !==  adjust.substr( 0, i ) ) {
            r[ 1 ]  =  shift;
         }
      } else {
         r[ 1 ]  =  impact;
      }   // result
      return  r;
   };   // .util.isbn.format()



   WSTM.util.isbn.furnish  =  function () {
      // Define ISBN separation between publisher and title numbers
      // Postcondition:
      //    Global variable was set
      // Uses:
      //     < .util.isbn.grouping
      // 2022-01-30 PerfektesChaos@de.wikipedia
      this.grouping  =  [   // Commemorate LISP
         [   // 978 or none
            [  0,   // en
              [2, [ 0, 19, 2],
                  [20, 69, 3],
                  [70, 84, 4],
                  [85, 89, 5],
                  [90, 94, 6],
                  [95, 99, 7]   ]
              ],
            [  1,   // en
              [2, [ 0,  9, 2],
                  [10, 39, 3],
                  [40, 54, 4],
                  [55, 85, 5]   ],
              [4, [8600, 8697, 5],
                  [8698, 9989, 6],
                  [9990, 9999, 7]   ]
              ],
            [  2,   // fr
              [2, [ 0, 19, 2],
                  [20, 34, 3],
                  [35, 39, 5],
                  [40, 69, 3],
                  [70, 83, 4],
                  [84, 89, 5],
                  [90, 94, 6],
                  [95, 99, 7]   ]
              ],
            [  3,   // de
              [2, [ 0,  0, 2],
                  [ 5, 19, 2],
                  [20, 69, 3],
                  [70, 84, 4],
                  [85, 89, 5],
                  [90, 94, 6],
                  [96, 96, 5],
                  [97, 98, 7],
                  [99, 99, 5]   ],
              [3, [ 34,  36, 4],
                  [ 37,  39, 5],
                  [950, 953, 7],
                  [954, 969, 5]   ]
              ],
            [  4,   // ja
              [2, [ 0, 19, 2],
                  [20, 69, 3],
                  [70, 84, 4],
                  [85, 89, 5],
                  [90, 94, 6],
                  [95, 99, 7]   ]
              ],
            [  5,   // ru/SU
              [2, [ 0, 19, 2],
                  [20, 41, 3],
                  [45, 69, 3],
                  [70, 84, 4],
                  [85, 89, 5],
                  [90, 90, 6],
                  [91, 91, 5],
                  [92, 92, 4],
                  [93, 94, 5],
                  [96, 97, 7],
                  [98, 98, 5]   ],
              [3, [420, 420, 3],
                  [421, 429, 4],
                  [430, 430, 3],
                  [431, 439, 4],
                  [440, 440, 3],
                  [441, 449, 4],
                  [990, 990, 7],
                  [991, 999, 4]   ],
              [4, [9500, 9500, 7],
                  [9501, 9599, 4]   ]
              ],
            [  7,   // cn
              [2, [ 0,  9, 2],
                  [10, 49, 3],
                  [50, 79, 4],
                  [80, 89, 5],
                  [90, 99, 6]   ]
              ],
            [ 80,   // cz sk
              [2, [ 0, 19, 2],
                  [20, 69, 3],
                  [70, 84, 4],
                  [85, 89, 5],
                  [90, 99, 6]   ]
              ],
            [ 81,   // in
              [2, [ 0, 19, 2],
                  [20, 69, 3],
                  [70, 84, 4],
                  [85, 89, 5],
                  [90, 99, 6]   ]
              ],
            [ 82,   // no
              [2, [ 0, 19, 2],
                  [20, 69, 3],
                  [70, 89, 4],
                  [90, 98, 5],
                  [99, 99, 6]   ]
              ],
            [ 83,   // pl
              [2, [ 0, 19, 2],
                  [20, 59, 3],
                  [60, 69, 5],
                  [70, 84, 4],
                  [90, 99, 6]   ]
              ],
            [ 84,   // es
              [2, [ 0, 14, 2],
                  [15, 19, 5],
                  [20, 69, 3],
                  [70, 84, 4],
                  [85, 89, 5],
                  [90, 91, 4],
                  [93, 94, 6],
                  [95, 96, 5],
                  [97, 99, 4]   ],
              [3, [920, 923, 6],
                  [924, 929, 5]   ]
              ],
            [ 85,   // br
              [2, [ 0, 19, 2],
                  [20, 59, 3],
                  [60, 69, 5],
                  [70, 84, 4],
                  [85, 89, 5],
                  [90, 98, 6],
                  [98, 99, 5]   ]
              ],
            [ 86,   // rs me
              [2, [ 0, 29, 2],
                  [30, 59, 3],
                  [60, 79, 4],
                  [80, 89, 5],
                  [90, 99, 6]   ]
              ],
            [ 87,   // dk
              [2, [ 0, 29, 2],
                  [40, 64, 3],
                  [70, 79, 4],
                  [85, 94, 5],
                  [97, 99, 6]   ]
              ],
            [ 88,   // it
              [2, [ 0, 19, 2],
                  [20, 59, 3],
                  [60, 84, 4],
                  [85, 89, 5],
                  [90, 94, 6],
                  [95, 99, 5]   ]
              ],
            [ 89,   // kr
              [2, [ 0, 24, 2],
                  [25, 54, 3],
                  [55, 84, 4],
                  [85, 94, 5],
                  [95, 99, 6]   ]
              ],
            [ 90,   // nl
              [2, [ 0, 19, 2],
                  [20, 49, 3],
                  [50, 69, 4],
                  [70, 79, 5],
                  [80, 84, 6],
                  [85, 89, 4],
                  [90, 90, 2],
                  [91, 93, 6],
                  [94, 94, 2],
                  [95, 99, 6]   ]
              ],
            [ 91,   // se
              [2, [ 0,  1, 1],
                  [20, 49, 2],
                  [50, 64, 3],
                  [70, 79, 4],
                  [85, 94, 5],
                  [97, 99, 6]   ]
              ],
            [ 92,   // int
              [2, [ 0,  5, 1],
                  [60, 79, 2],
                  [80, 89, 3],
                  [90, 94, 4],
                  [95, 98, 5],
                  [99, 99, 6]   ]
              ],
           // 93       in
            [ 94,   // nl
              [1, [0, 5, 3],
                  [6, 8, 4],
                  [9, 9, 5]   ]
              ],
            [600,   // ir
              [2, [ 0,  9, 2],
                  [10, 49, 3],
                  [50, 89, 4],
                  [90, 99, 5]   ]
             ],
            [601,   // kz
              [2, [ 0, 19, 2],
                  [20, 69, 3],
                  [70, 79, 4],
                  [80, 84, 5],
                  [85, 99, 2]   ]
              ],
            [602,   // id
              [2, [ 0, 19, 2],
                  [20, 79, 3],
                  [80, 94, 4],
                  [95, 99, 5]   ]
              ],
            [603,   // sa
              [2, [ 0,  4, 2],
                  [50, 79, 3],
                  [80, 89, 4],
                  [90, 99, 5]   ]
              ],
            [604,   // vn
              [2, [ 0,  4, 1],
                  [50, 89, 2],
                  [90, 97, 3],
                  [98, 99, 4]   ]
              ],
            [605,   // tr
              [2, [ 0,  9, 2],
                  [10, 39, 3],
                  [40, 59, 4],
                  [60, 89, 5]   ]
              ],
            [950,   // ar
              [2, [ 0, 49, 2],
                  [50, 89, 3],
                  [90, 98, 4],
                  [99, 99, 5]   ]
              ],
            [951,   // fi
              [2, [ 0,  1, 1],
                  [20, 54, 2],
                  [55, 88, 3],
                  [89, 94, 4],
                  [95, 99, 5]   ]
              ],
            [952,   // fi
              [2, [ 0, 19, 2],
                  [20, 49, 3],
                  [50, 59, 4],
                  [60, 65, 2],
                  [66, 66, 4],
                  [67, 69, 5],
                  [70, 79, 4],
                  [80, 94, 2],
                  [95, 98, 4],
                  [99, 99, 5]   ]
              ],
            [953,   // hr
              [2, [ 0,  0, 1],
                  [10, 14, 2],
                  [15, 54, 3],
                  [55, 59, 5],
                  [60, 94, 4],
                  [95, 99, 5]   ]
              ],
            [954,   // bg
              [2, [ 0, 20, 2],
                  [30, 79, 3],
                  [80, 89, 4],
                  [90, 92, 5],
                  [93, 99, 4]   ]
              ],
            [955,   // lk
              [2, [ 0,  0, 1],
                  [10, 19, 4],
                  [20, 54, 2],
                  [55, 79, 3],
                  [80, 94, 4],
                  [95, 99, 5]   ]
              ],
            [956,   // cl
              [2, [ 0, 19, 2],
                  [20, 69, 3],
                  [70, 99, 4]   ]
              ],
            [957,   // tw
              [2, [ 0,  2, 2],
                  [ 3,  4, 4],
                  [ 5, 19, 2],
                  [20, 20, 4],
                  [21, 27, 2],
                  [28, 30, 5],
                  [31, 43, 2],
                  [44, 81, 3],
                  [82, 96, 4],
                  [97, 99, 5]   ]
              ],
            [958,   // co
              [2, [ 0, 59, 2],
                  [60, 79, 3],
                  [80, 94, 4],
                  [95, 99, 5]   ]
              ],
            [959,   // cu
              [2, [ 0, 19, 2],
                  [20, 69, 3],
                  [70, 84, 4]   ]
              ],
            [960,   // gr
              [2, [ 0, 19, 2],
                  [20, 65, 3],
                  [66, 68, 4],
                  [69, 69, 3],
                  [70, 84, 4],
                  [85, 92, 5],
                  [93, 93, 2],
                  [94, 97, 4],
                  [98, 99, 5]   ]
              ],
            [961,   // si
              [2, [ 0, 19, 2],
                  [20, 59, 3],
                  [60, 89, 4],
                  [90, 99, 5]   ]
              ],
            [962,   // hk
              [2, [ 0, 19, 2],
                  [20, 69, 3],
                  [70, 84, 4],
                  [85, 86, 5],
                  [87, 89, 4],
                  [90, 99, 3]   ]
              ],
            [963,   // hu
              [2, [ 0, 19, 2],
                  [20, 69, 3],
                  [70, 84, 4],
                  [85, 89, 5],
                  [90, 99, 4]   ]
              ],
            [964,   // ir
              [2, [ 0, 14, 2],
                  [15, 24, 3],
                  [25, 29, 4],
                  [30, 54, 3],
                  [55, 89, 4],
                  [90, 96, 5],
                  [97, 98, 3],
                  [99, 99, 4]   ]
              ],
            [965,   // il
              [2, [ 0, 19, 2],
                  [20, 59, 3],
                  [70, 79, 4],
                  [90, 99, 5]   ]
              ],
            [966,   // ua
              [2, [ 0, 19, 2],
                  [20, 29, 4],
                  [30, 69, 3],
                  [70, 89, 4],
                  [90, 99, 5]   ]
              ],
            [967,   // my
              [2, [ 0, 29, 2],
                  [30, 49, 3],
                  [50, 59, 4],
                  [60, 89, 2],
                  [90, 98, 4]   ],
              [3, [990, 989, 4],
                  [999, 999, 5]   ]
              ],
            [968,   // mx
              [2, [ 0, 39, 2],
                  [40, 49, 3],
                  [50, 79, 4],
                  [80, 89, 5],
                  [90, 99, 4]   ]
              ],
            [969,   // pk
              [2, [ 0,  1, 1],
                  [20, 39, 2],
                  [40, 79, 3],
                  [80, 99, 4]   ]
              ],
            [970,   // mx
              [2, [ 0, 59, 2],
                  [60, 89, 3],
                  [90, 90, 4],
                  [91, 96, 5],
                  [97, 99, 4]   ]
              ],
            [971,   // ph
              [2, [ 0,  1, 3],
                  [ 2,  2, 2],
                  [ 3,  5, 4],
                  [ 6, 49, 2],
                  [50, 84, 3],
                  [85, 90, 4],
                  [91, 99, 5]   ]
              ],
            [972,   // pt
              [2, [ 0,  1, 1],
                  [20, 54, 2],
                  [55, 79, 3],
                  [80, 94, 4],
                  [95, 99, 5]   ]
              ],
            [973,   // ro
              [2, [ 0,  0, 1],
                  [10, 16, 3],
                  [17, 19, 4],
                  [20, 54, 2],
                  [55, 75, 3],
                  [76, 84, 4],
                  [85, 88, 5],
                  [89, 94, 4],
                  [95, 99, 5]   ]
              ],
            [974,   // th
              [2, [ 0, 19, 2],
                  [20, 69, 3],
                  [70, 84, 4],
                  [85, 94, 5],
                  [95, 99, 4]   ]
              ],
            [975,   // tr
              [2, [ 0,  0, 5],
                  [ 1, 24, 2],
                  [25, 59, 3],
                  [60, 91, 4],
                  [92, 98, 5],
                  [99, 99, 3]   ]
              ],
            [976,   // Caribbean Community
              [2, [ 0, 30, 1],
                  [40, 59, 2],
                  [60, 79, 3],
                  [80, 94, 4],
                  [95, 99, 5]   ]
              ],
            [977,   // eg
              [2, [ 0, 19, 2],
                  [20, 49, 3],
                  [50, 69, 4],
                  [70, 99, 3]   ]
              ],
            [978,   // ng
              [2, [ 0, 19, 3],
                  [20, 29, 4],
                  [30, 79, 5],
                  [80, 89, 4],
                  [90, 99, 3]   ]
              ],
            [979,   // id
              [2, [ 0,  9, 3],
                  [10, 14, 4],
                  [15, 19, 5],
                  [20, 29, 2],
                  [30, 39, 4],
                  [40, 79, 4],
                  [95, 99, 5]   ]
              ],
            [980,   // ve
              [2, [ 0, 19, 2],
                  [20, 59, 3],
                  [60, 99, 4]   ]
              ],
            [981,   // sg
              [2, [ 0, 19, 2],
                  [20, 29, 3],
                  [30, 99, 4]   ]
              ],
            [982,   // South Pacific
              [2, [ 0,  9, 2],
                  [10, 69, 3],
                  [70, 89, 2],
                  [90, 99, 4]   ]
              ],
            [983,   // my
              [2, [ 0,  1, 2],
                  [ 2, 19, 3],
                  [20, 39, 4],
                  [40, 44, 5],
                  [45, 79, 2],
                  [80, 89, 3],
                  [90, 98, 4],
                  [99, 99, 5]   ]
              ],
            [984,   // bd
              [2, [ 0, 39, 2],
                  [40, 79, 3],
                  [80, 89, 4],
                  [90, 99, 5]   ]
              ],
            [985,   // by
              [2, [ 0, 39, 2],
                  [40, 59, 3],
                  [60, 89, 4],
                  [90, 99, 5]   ]
              ],
            [986,   // tw
              [2, [ 0, 11, 2],
                  [12, 55, 3],
                  [56, 79, 4],
                  [80, 99, 5]   ]
              ],
            [987,   // ar
              [2, [ 0,  9, 2],
                  [10, 19, 4],
                  [20, 29, 5],
                  [30, 49, 2],
                  [50, 89, 3],
                  [90, 94, 4],
                  [95, 99, 5]   ]
              ],
            [988,   // hk
              [2, [ 0, 16, 2],
                  [17, 19, 5],
                  [20, 79, 3],
                  [80, 96, 4],
                  [97, 99, 5]   ]
              ],
            [989,   // pt
              [2, [ 0, 19, 1],
                  [20, 54, 2],
                  [55, 79, 3],
                  [80, 94, 4],
                  [95, 99, 5]   ]
              ],
            [9937,   // np
              [2, [ 0, 29, 1],
                  [30, 49, 2],
                  [50, 79, 3],
                  [80, 99, 4]   ]
              ],
            [9938,   // tn
              [2, [ 0, 79, 2],
                  [80, 94, 3],
                  [95, 99, 4]   ]
              ],
            [9939,   // am
              [2, [ 0, 49, 1],
                  [50, 79, 2],
                  [80, 89, 3],
                  [90, 99, 4]   ]
              ],
            [9940,   // me
              [2, [ 0, 19, 1],
                  [20, 49, 2],
                  [50, 89, 3],
                  [90, 99, 4]   ]
              ],
            [9941,   // ge
              [2, [ 0,  9, 1],
                  [10, 39, 2],
                  [40, 89, 3],
                  [90, 99, 4]   ]
              ],
            [9942,   // ec
              [3, [  0, 899, 2],
                  [900, 994, 3],
                  [995, 999, 4]   ]
              ],
            [9943,   // uz
              [2, [ 0, 29, 2],
                  [30, 39, 3],
                  [40, 99, 4]   ]
              ],
            [9944,   // tr
              [2, [ 0, 29, 2],
                  [30, 49, 3],
                  [50, 59, 4],
                  [60, 89, 2],
                  [90, 99, 3]   ]
              ],
            [9945,   // do
              [2, [ 0,  0, 2],
                  [ 1,  7, 3],
                  [ 8, 39, 2],
                  [40, 56, 3],
                  [57, 57, 2],
                  [58, 84, 3],
                  [85, 99, 4]   ]
              ],
            [9946,   // kp
              [2, [ 0, 19, 1],
                  [20, 39, 2],
                  [40, 89, 3],
                  [90, 99, 4]   ]
              ],
            [9947,   // dz
              [2, [ 0, 19, 1],
                  [20, 79, 2],
                  [80, 99, 3]   ]
              ],
            [9948,   // ae
              [2, [ 0, 39, 2],
                  [40, 84, 3],
                  [85, 99, 4]   ]
              ],
            [9949,   // ee
              [2, [ 0,  9, 1],
                  [10, 39, 2],
                  [40, 89, 3],
                  [90, 99, 4]   ]
              ],
            [9950,   // ps
              [2, [ 0, 29, 2],
                  [30, 84, 3],
                  [85, 99, 4]   ]
              ],
            [9951,   // Kosova
              [2, [ 0, 29, 2],
                  [30, 84, 3],
                  [85, 99, 4]   ]
              ],
            [9952,   // az
              [2, [ 0, 19, 1],
                  [20, 39, 2],
                  [40, 79, 3],
                  [80, 99, 4]   ]
              ],
            [9953,   // lb
              [2, [ 0,  9, 1],
                  [10, 39, 2],
                  [40, 59, 3],
                  [60, 89, 2],
                  [90, 99, 4]   ]
              ],
            [9954,   // ma
              [2, [ 0, 19, 1],
                  [20, 39, 2],
                  [40, 79, 3],
                  [80, 99, 4]   ]
              ],
            [9955,   // lt
              [2, [ 0, 39, 2],
                  [40, 92, 3],
                  [93, 99, 4]   ]
              ],
            [9956,   // cm
              [2, [ 0,  9, 1],
                  [10, 39, 2],
                  [40, 89, 3],
                  [90, 99, 4]   ]
              ],
            [9957,   // jo
              [2, [ 0, 39, 2],
                  [40, 69, 3],
                  [70, 84, 2],
                  [85, 99, 4]   ]
              ],
            [9958,   // ba
              [2, [ 0,  9, 1],
                  [10, 49, 2],
                  [50, 89, 3],
                  [90, 99, 4]   ]
              ],
            [9959,   // ly
              [2, [ 0, 19, 1],
                  [20, 79, 2],
                  [80, 94, 3],
                  [95, 99, 4]   ]
              ],
            [9960,   // sa
              [2, [ 0, 59, 2],
                  [60, 89, 3],
                  [90, 99, 4]   ]
              ],
            [9961,   // dz
              [2, [ 0, 29, 1],
                  [30, 69, 2],
                  [70, 94, 3],
                  [95, 99, 4]   ]
              ],
            [9962,   // pa
              [2, [ 0, 54, 2],
                  [55, 55, 4],
                  [56, 59, 2],
                  [60, 84, 3],
                  [85, 99, 4]   ]
              ],
            [9963,   // cy
              [2, [ 0, 29, 1],
                  [30, 54, 2],
                  [55, 74, 3],
                  [75, 99, 4]   ]
              ],
            [9964,   // gh
              [2, [ 0, 69, 2],
                  [70, 94, 3],
                  [95, 99, 4]   ]
              ],
            [9965,   // kz
              [2, [ 0, 39, 2],
                  [40, 89, 3],
                  [90, 99, 4]   ]
              ],
            [9966,   // ke
              [2, [ 0, 69, 2],
                  [70, 74, 4],
                  [75, 95, 3],
                  [96, 99, 4]   ]
              ],
            [9967,   // kg
              [2, [ 0, 39, 2],
                  [40, 89, 3],
                  [90, 99, 4]   ]
              ],
            [9968,   // cr
              [2, [ 0, 49, 2],
                  [50, 93, 3],
                  [94, 99, 4]   ]
              ],
            [9970,   // ug
              [2, [ 0, 39, 2],
                  [40, 89, 3],
                  [90, 99, 4]   ]
              ],
            [9971,   // sg
              [2, [ 0, 59, 1],
                  [60, 89, 2],
                  [90, 98, 3],
                  [99, 99, 4]   ]
              ],
            [9972,   // pe
              [2, [ 0,  9, 2],
                  [10, 19, 1],
                  [20, 24, 3],
                  [25, 29, 4],
                  [30, 59, 2],
                  [60, 89, 3],
                  [90, 99, 4]   ]
              ],
            [9973,   // tn
              [2, [ 0,  5, 2],
                  [ 6,  8, 3],
                  [ 9,  9, 4],
                  [10, 69, 2],
                  [70, 96, 3],
                  [97, 99, 4]   ]
              ],
            [9974,   // ug
              [2, [ 0, 29, 1],
                  [30, 54, 2],
                  [55, 74, 3],
                  [75, 94, 4],
                  [95, 99, 2]   ]
              ],
            [9975,   // md
              [2, [ 0,  0, 1],
                  [10, 39, 3],
                  [40, 44, 4],
                  [45, 89, 2],
                  [90, 94, 3],
                  [95, 99, 4]   ]
              ],
            [9976,   // tz
              [2, [ 0, 50, 1],
                  [60, 89, 2],
                  [90, 98, 3],
                  [99, 99, 4]   ]
              ],
            [9977,   // cr
              [2, [ 0, 89, 2],
                  [90, 98, 3],
                  [99, 99, 4]   ]
              ],
            [9978,   // ec
              [2, [ 0, 29, 2],
                  [30, 39, 3],
                  [40, 94, 2],
                  [95, 98, 3],
                  [99, 99, 4]   ]
              ],
            [9979,   // is
              [2, [ 0, 49, 1],
                  [50, 64, 2],
                  [65, 65, 3],
                  [66, 75, 2],
                  [76, 89, 3],
                  [90, 99, 4]   ]
              ],
            [9980,   // pg
              [2, [ 0, 30, 1],
                  [40, 89, 2],
                  [90, 98, 3],
                  [90, 99, 4]   ]
              ],
            [9981,   // ma
              [2, [ 0,  9, 2],
                  [10, 15, 3],
                  [16, 19, 2],
                  [20, 79, 2],
                  [80, 94, 3],
                  [95, 99, 4]   ]
              ],
            [9982,   // zm
              [2, [ 0, 79, 2],
                  [80, 98, 3],
                  [99, 99, 4]   ]
              ],
            [9983,   // gm
              [2, [80, 94, 2],
                  [95, 98, 3],
                  [99, 99, 4]   ]
              ],
            [9984,   // lv
              [2, [ 0, 49, 2],
                  [50, 79, 3],
                  [90, 99, 4]   ]
              ],
            [9985,   // ee
              [2, [ 0, 49, 1],
                  [50, 79, 2],
                  [80, 89, 3],
                  [90, 99, 4]   ]
              ],
            [9986,   // lt
              [2, [ 0, 39, 2],
                  [40, 89, 3],
                  [90, 93, 4],
                  [94, 96, 3],
                  [97, 99, 2]   ]
              ],
            [9987,   // tz
              [2, [ 0, 39, 2],
                  [40, 87, 3],
                  [88, 99, 4]   ]
              ],
            [9988,   // gh
              [2, [ 0, 29, 1],
                  [30, 54, 2],
                  [55, 74, 3],
                  [75, 99, 4]   ]
              ],
            [9989,   // mk
              [2, [ 0,  0, 1],
                  [10, 19, 3],
                  [20, 29, 4],
                  [60, 94, 3],
                  [95, 99, 4]   ]
              ],
            [99901,   // bh
              [2, [ 0, 49, 2],
                  [50, 79, 3],
                  [80, 99, 2]   ]
              ],
          // 99902,   // ga   no ranges fixed yet
            [99903,   // mu
              [2, [ 0, 19, 1],
                  [20, 89, 2],
                  [90, 99, 3]   ]
              ],
            [99904,   // an
              [2, [ 0, 59, 1],
                  [60, 89, 2],
                  [90, 99, 3]   ]
              ],
            [99905,   // bo
              [2, [ 0, 39, 1],
                  [40, 79, 2],
                  [80, 99, 3]   ]
              ],
            [99906,   // kw
              [2, [ 0, 29, 1],
                  [30, 59, 2],
                  [60, 69, 2],
                  [70, 89, 2],
                  [90, 99, 1]   ]
              ],
            [99908,   // mw
              [2, [ 0,  0, 1],
                  [10, 89, 2],
                  [90, 99, 3]   ]
              ],
            [99909,   // mt
              [2, [ 0, 39, 1],
                  [40, 94, 2],
                  [95, 99, 3]   ]
              ],
            [99910,   // sl
              [2, [ 0, 29, 1],
                  [30, 89, 2],
                  [90, 99, 3]   ]
              ],
            [99911,   // ls
              [2, [ 0, 59, 2],
                  [60, 99, 3]   ]
              ],
            [99912,   // bw
              [2, [ 0, 39, 1],
                  [40, 59, 3],
                  [60, 89, 2],
                  [90, 99, 3]   ]
              ],
            [99913,   // ad
              [3, [  0, 299, 1],
                  [439, 350, 2],
                  [600, 604, 3]   ]
              ],
            [99914,   // sr
              [2, [ 0, 49, 1],
                  [50, 89, 2],
                  [90, 94, 3]   ]
              ],
            [99915,   // mv
              [2, [ 0, 49, 1],
                  [50, 79, 2],
                  [80, 99, 3]   ]
              ],
            [99916,   // na
              [2, [ 0, 29, 1],
                  [30, 69, 2],
                  [70, 99, 3]   ]
              ],
            [99917,   // bn
              [2, [ 0, 29, 1],
                  [30, 89, 2],
                  [90, 99, 3]   ]
              ],
            [99918,   // fo
              [2, [ 0, 39, 1],
                  [40, 79, 2],
                  [80, 99, 3]   ]
              ],
            [99919,   // bj
              [2, [ 0, 29, 1],
                  [40, 69, 2],
                  [90, 99, 3]   ]
              ],
            [99920,   // ad
              [2, [ 0, 49, 1],
                  [50, 89, 2],
                  [90, 99, 3]   ]
              ],
            [99921,   // qa
              [2, [ 0,  9, 1],
                  [20, 69, 2],
                  [70, 79, 3],
                  [80, 89, 1],
                  [90, 99, 2]   ]
              ],
            [99922,   // gt
              [2, [ 0, 39, 1],
                  [40, 69, 2],
                  [70, 99, 3]   ]
              ],
            [99923,   // sv
              [2, [ 0, 19, 1],
                  [20, 79, 2],
                  [80, 99, 3]   ]
              ],
            [99924,   // ni
              [2, [ 0, 29, 1],
                  [30, 79, 2],
                  [80, 99, 3]   ]
              ],
            [99925,   // py
              [2, [ 0, 39, 1],
                  [40, 79, 2],
                  [80, 99, 3]   ]
              ],
            [99926,   // hn
              [2, [ 0,  9, 1],
                  [10, 59, 2],
                  [60, 99, 3]   ]
              ],
            [99927,   // al
              [2, [ 0, 29, 1],
                  [30, 59, 2],
                  [60, 99, 3]   ]
              ],
            [99928,   // ge
              [2, [ 0,  9, 1],
                  [10, 79, 2],
                  [80, 99, 3]   ]
              ],
            [99929,   // mn
              [2, [ 0, 49, 1],
                  [50, 79, 2],
                  [80, 99, 3]   ]
              ],
            [99930,   // am
              [2, [ 0, 49, 1],
                  [50, 79, 2],
                  [80, 99, 3]   ]
              ],
            [99931,   // sc
              [2, [ 0, 49, 1],
                  [50, 79, 2],
                  [80, 99, 3]   ]
              ],
            [99932,   // mt
              [2, [ 0,  9, 1],
                  [10, 59, 2],
                  [60, 69, 3],
                  [70, 79, 1],
                  [80, 99, 2]   ]
              ],
            [99933,   // np
              [2, [ 0, 29, 1],
                  [30, 59, 2],
                  [60, 99, 3]   ]
              ],
            [99934,   // do
              [2, [ 0, 19, 1],
                  [20, 79, 2],
                  [80, 99, 3]   ]
              ],
            [99935,   // ht
              [2, [ 0, 29, 1],
                  [30, 59, 2],
                  [60, 69, 3],
                  [70, 89, 1],
                  [90, 99, 2]   ]
              ],
            [99936,   // bt
              [2, [ 0,  9, 1],
                  [10, 59, 2],
                  [60, 99, 3]   ]
              ],
            [99937,   // mo
              [2, [ 0, 19, 1],
                  [20, 59, 2],
                  [60, 99, 3]   ]
              ],
            [99938,   // Srpska
              [2, [ 0, 19, 1],
                  [20, 59, 2],
                  [60, 69, 3],
                  [90, 99, 2]   ]
              ],
            [99939,   // gt
              [2, [ 0, 59, 1],
                  [60, 89, 2],
                  [90, 99, 3]   ]
              ],
            [99940,   // ge
              [2, [ 0,  9, 1],
                  [10, 69, 2],
                  [70, 99, 3]   ]
              ],
            [99941,   // am
              [2, [ 0, 29, 1],
                  [30, 79, 2],
                  [80, 99, 3]   ]
              ],
            [99942,   // sd
              [2, [ 0, 49, 1],
                  [50, 79, 2],
                  [80, 99, 3]   ]
              ],
            [99943,   // al
              [2, [ 0, 29, 1],
                  [30, 59, 2],
                  [60, 99, 3]   ]
              ],
            [99944,   // et
              [2, [ 0, 49, 1],
                  [50, 79, 2],
                  [80, 99, 3]   ]
              ],
            [99945,   // na
              [2, [ 0, 59, 1],
                  [60, 89, 2],
                  [90, 99, 3]   ]
              ],
            [99946,   // np
              [2, [ 0, 29, 1],
                  [30, 59, 2],
                  [60, 99, 3]   ]
              ],
            [99947,   // tj
              [2, [ 0, 29, 1],
                  [30, 69, 2],
                  [70, 99, 3]   ]
              ],
            [99948,   // er
              [2, [ 0, 49, 1],
                  [50, 79, 2],
                  [80, 99, 3]   ]
              ],
            [99949,   // mu
              [2, [ 0, 19, 1],
                  [20, 89, 2],
                  [90, 99, 3]   ]
              ],
            [99950,   // kh
              [2, [ 0, 49, 1],
                  [50, 79, 2],
                  [80, 99, 3]   ]
              ],
          // 99951,   // cg   no ranges fixed yet
            [99952,   // ml
              [2, [ 0, 49, 1],
                  [50, 79, 2],
                  [80, 99, 3]   ]
              ],
            [99953,   // py
              [2, [ 0, 29, 1],
                  [30, 79, 2],
                  [80, 99, 3]   ]
              ],
            [99954,   // bo
              [2, [ 0, 29, 1],
                  [30, 69, 2],
                  [70, 99, 3]   ]
              ],
            [99955,   // Srpska
              [2, [ 0, 19, 1],
                  [20, 59, 2],
                  [60, 89, 3],
                  [90, 99, 2]   ]
              ],
            [99956,   // al
              [2, [ 0, 59, 2],
                  [60, 99, 3]   ]
              ]
                  ],
         [   // 979
            [ 0,
              [1, [0, 9, 8]   ]
              ],
            [ 2,
              [1, [0, 9, 8]   ]
              ],
            [ 3,
              [1, [0, 9, 8]   ]
              ],
            [ 4,
              [1, [0, 9, 8]   ]
              ],
            [ 5,
              [1, [0, 9, 8]   ]
              ],
            [ 6,
              [1, [0, 9, 8]   ]
              ],
            [ 7,
              [1, [0, 9, 8]   ]
              ],
            [ 8,   // USA
              [2, [ 0, 19, 8],
                  [20, 21, 3],
                  [22, 39, 8],
                  [40, 79, 4]   ],
              [3, [800, 884, 8],
                  [885, 899, 5],
                  [900, 984, 8],
                  [985, 986, 7],
                  [987, 999, 8]   ]
              ],
            [ 9,
              [1, [ 0, 9, 8]   ]
              ],
            [ 10,   // fr
              [2, [ 0, 19, 2],
                  [20, 69, 3],
                  [70, 89, 4]   ],
              [3, [900, 975, 5],
                  [976, 999, 6]   ]
              ],
            [ 11,   // ROK
              [2, [ 0, 24, 2],
                  [25, 54, 3],
                  [55, 84, 4],
                  [85, 94, 5],
                  [95, 99, 6]   ]
              ],
            [ 12,   // ITA
              [2, [ 0, 19, 7],
                  [20, 29, 3]   ],
              [3, [300, 544, 7],
                  [545, 599, 4],
                  [600, 799, 7],
                  [800, 849, 5],
                  [850, 999, 7]   ]
              ],
            [ 13,
              [1, [0, 9, 7]   ]
              ],
            [ 14,
              [1, [0, 9, 7]   ]
              ],
            [ 15,
              [1, [0, 9, 7]   ]
              ],
            [ 16,
              [1, [0, 9, 7]   ]
              ],
            [ 17,
              [1, [0, 9, 7]   ]
              ],
            [ 18,
              [1, [0, 9, 7]   ]
              ],
            [ 19,
              [1, [0, 9, 7]   ]
              ]
                  ]
                ];   // .util.isbn.grouping
   };   // .util.isbn.furnish()



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



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



mw.libs.WikiSyntaxTextMod.bb.issn  =  function (WSTM) {
   // ISSN syntax analysis, code correction and formatting
   // Public:
   //    .util.issn.format()
   // Uses:
   //    .util.fiatObjects()
   //    .errors.found()
   // 2013-06-27 PerfektesChaos@de.wikipedia
   "use strict";
   WSTM.util.fiatObjects(WSTM.util,  "issn");



   WSTM.util.issn.faith  =  function (acquired) {
      // Compute and compare ISSN check digit (4-4)
      // Precondition:
      //    acquired  -- Array(8) with digits 0...9, or 10 at [7]
      // Postcondition:
      //    Returns  true if valid
      // 2013-08-03 PerfektesChaos@de.wikipedia
      var k  =  0,
          i;
      for (i = 0;  i < 7;  i++) {
         k  +=  acquired[i]  *  (8 - i);
      }   // for i
      k  =  (11  -  k % 11)   %   11;
      return  (k === acquired[7]);
   };   // .util.issn.faith()



   WSTM.util.issn.fashion  =  function (acquired) {
      // Format ISSN digits for 8 or 13
      // Precondition:
      //    acquired  -- Array(8) with digits 0...9, or 10 at [7]
      // Postcondition:
      //    Returns  true if valid
      // Requires: JavaScript 1.3   fromCharCode()
      // 2013-06-20 PerfektesChaos@de.wikipedia
      var i,
          n  =  acquired.length,
          r;
      if ( n === 8 ) {
         r  =  "";
         for ( i = 0;  i < 4;  i++ ) {
            r  =  r + String.fromCharCode( acquired[i] + 48 );
         }   // for i
         r  =  r + "-";
         for ( i = 4;  i < 7;  i++ ) {
            r  =  r + String.fromCharCode( acquired[i] + 48 );
         }   // for i
         if ( acquired[7] === 10 ) {
            r  =  r + "X";
         } else {
            r  =  r + String.fromCharCode( acquired[7] + 48 );
         }
      } else if ( n === 13 ) {
         r  =  "977-";
         for ( i = 3;  i < 10;  i++ ) {
            r  =  r + String.fromCharCode( acquired[i] + 48 );
         }   // for i
         r  =  r + "-";
         for ( i = 10;  i < 12;  i++ ) {
            r  =  r + String.fromCharCode( acquired[i] + 48 );
         }   // for i
         r  =  r + "-" + String.fromCharCode( acquired[12] + 48 );
      }
      return  r;
   };   // .util.issn.fashion()



   WSTM.util.issn.fetch  =  function ( attempt ) {
      // Convert presumable ISSN code into Array
      // Precondition:
      //    attempt  -- ISSN code (no leading keyword)
      // Postcondition:
      //    Returns Array with digits 0...9, or 10 at last position
      // Uses:
      //    .util.code.fetch()
      // Requires: JavaScript 1.3   charCodeAt()   fromCharCode()
      // 2013-06-23 PerfektesChaos@de.wikipedia
      var n  =  attempt.length,
          m,
          r;
      if ( n >= 13   &&   attempt.substr( 0, 3 ) ===  "977" ) {   // EAN
         m  =  13;
      } else {
         m  =  8;
      }
      r  =  WSTM.util.code.fetch( attempt, m, 8, "ISSN" );
      return  r;
   };   // .util.issn.fetch()



   WSTM.util.issn.format  =  function (adjust) {
      // Format ISSN code
      // Precondition:
      //    adjust  -- ISSN code (no leading keyword)
      // Postcondition:
      //    Returns false if valid, or string if to be corrected
      // Uses:
      //    .util.issn.fetch()
      //    .util.issn.faith()
      //    .util.gtin.faith()
      // 2013-06-23 PerfektesChaos@de.wikipedia
      var issn  =  this.fetch( adjust ),
          r     =  false,
          n;
      if ( issn ) {
         n  =  issn.length;
         if ( n === 8  ||  n === 13 ) {
            if ( n === 8 ) {
               if ( ! this.faith( issn ) ) {
                  WSTM.errors.found( "badISSNcheckdig", false, adjust );
                  issn  =  false;
               }
            } else if ( WSTM.util.gtin.faith( issn ) !== issn[ 12 ] ) {
               issn  =  false;
               WSTM.errors.found( "badISSNcheckdig", false, adjust );
            }
            if (issn) {
               r  =  this.fashion(issn);
               if (r === adjust) {
                  r  =  false;
               }
            }
         } else {
            WSTM.errors.found("badISSNstrange", false, adjust);
         }
      }
      return  r;
   };   // .util.issn.format()



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



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



mw.libs.WikiSyntaxTextMod.bb.lccn  =  function (WSTM) {
   // LCCN syntax analysis, code correction and formatting
   // Public:
   //    .util.lccn.format()
   // Uses:
   //    .util.fiatObjects()
   // 2013-06-27 PerfektesChaos@de.wikipedia
   "use strict";
   WSTM.util.fiatObjects( WSTM.util,  "lccn" );



   WSTM.util.lccn.format  =  function (attempt, apply) {
      // Check LCCN code
      // Precondition:
      //    attempt  -- LCCN code (no leading keyword)
      //    apply   -- '/' or '-' (true='-') or false
      // Postcondition:
      //    Returns false if valid,
      //            Array with
      //                  [0] string if to be adjusted, or false
      //                  [1] error info (could be false)
      // Uses:
      //    >< .util.urn.re.*
      // 2015-03-25 PerfektesChaos@de.wikipedia
      // a{1,2}9{2|4}9{1,6}
      // n79022889 -> n/79/22889 -> n79-22889
      // nr00001027 -> nr/00/1027
      // xx2001000555 -> xx/2001/555
      // yyyy>2000
      var r  =  false,
          d, got, j, s, small;
      if ( typeof this.re  !==  "object" ) {
         this.re          =  { };
         this.re.pre      =  new RegExp( "^ *([A-Za-z]{1,3})?"
                                         + "([/0-9])"
                                         + "(.+[^ \n])[ \n]*$",
                                         "" );
         this.re.year     =  new RegExp( "^([0-9][0-9])"
                                         + "([0-9][0-9])"
                                         + "([0-9]*)$",
                                         "" );
         this.re.yearser  =  new RegExp( "^(([0-9][0-9])|(20[0-9][0-9]))"
                                         + "([/-])"
                                         + "(.+)",
                                         "" );
      }
      if ( attempt ) {
         got =  this.re.pre.exec( attempt );
         if ( got ) {
            s  =  got[ 1 ];
            if (s) {
               small  =  s.toLowerCase();
               if (s !== small) {
                  r  =  small + got[ 2 ] + got[ 3 ];
               }
            } else {
               small  =  false;
            }
            if ( got[2] === "/" ) {
               got  =  this.re.yearser.exec( got[ 3 ] );
               if ( got ) {
                  if (got[ 4 ] !== "/") {
                     got  =  false;
                  }
               }
               if ( got ) {
                  j  =  got[ 3 ];
               } else {
                  r  =  [ r, "invalid slash segmentation" ];
               }
            } else {
               s    =  got[ 2 ] + got[ 3 ];
               got  =  this.re.yearser.exec(s);
               if ( got ) {
                  j  =  ( got[4] === "-"  ?  got[3]  :  false );
               } else {
                  got =  this.re.year.exec(s);
                  if (got) {
                     if (got[1] === "20") {
                        j       =  got[1] + got[2];
                        got[5]  =  got[3];
                     } else {
                        j       =  got[1];
                        got[5]  =  got[2] + got[3];
                     }
                  }
               }
            }
         } else {
            r  =  [ false, "invalid prefix" ];
         }
         if ( j   &&   typeof r  !==  "object" ) {
            d  =  j.length;
            if ( d !== 2  &&  d !== 4 ) {
               r  =  false;
            } else if ( apply === "/" ) {
               r  =  ( small  ?  small + "/"  :  "" )
                     + j + "/" + got[ 5 ];
            } else if ( apply === "-"  ||  apply === true ) {
               r  =  ( small ? small : "" )  +  j  +  "-"  +  got[ 5 ];
            } else {
               r  =  ( small ? small : "" )  +  j  +  got[ 5 ];
            }
            if ( r ) {
               j  =  parseInt( j, 10 );
               if ( j > 2000 ) {
                  d  =  new Date();
                  if ( j > d.getFullYear() ) {
                     r  =  false;
                  }
               } else if ( j > 100 ) {
                  r  =  false;
               }
            }
            if ( ! r ) {
               r  =  [ r,  "invalid year: " + j ];
            }
         }
         if ( typeof r  ===  "string" ) {
            r  =  [ r, false ];
         }
      }
      return  r;
   };   // .util.lccn.format()



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



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



mw.libs.WikiSyntaxTextMod.bb.urn  =  function (WSTM) {
   // URN syntax analysis, code correction and formatting
   // Public:
   //    .util.urn.failure()
   // Uses:
   //    .util.fiatObjects()
   // 2013-06-27 PerfektesChaos@de.wikipedia
   "use strict";
   WSTM.util.fiatObjects( WSTM.util,  "urn" );



   WSTM.util.urn.sns  =    ":3gpp:cablelabs:cgi:clei:dgiwg:dvb:ebu:epc"
                         + ":epcglobal:example:fdc:fipa:geant:ietf:iptc"
                         + ":isan:isbn:iso:issn:ivis:lex:liberty:mace"
                         + ":mpeg:nbn:nena:newsml:nfc:nzl:oasis:ogc:ogf"
                         + ":oid:oipf:oma:pin:publicid:s1000d:schac"
                         + ":service:smpte:swift:tva:uci:ucode:uuid"
                         + ":web3d:xmlorg:xmpp:";



   WSTM.util.urn.failure  =  function (attempt) {
      // Is URN URI invalid?
      // Precondition:
      //    attempt  -- URN
      // Postcondition:
      //    Returns false if valid,
      //            string if to be adjusted,
      //            or Array with error info [1]
      // Uses:
      //    >  .util.urn.sns
      //    >< .util.urn.re.*
      //    .util.isEscValid()
      // 2013-06-27 PerfektesChaos@de.wikipedia
      var r  =  false,
          crash, got, small, space, subject, swap;
      if ( typeof this.re  !==  "object" ) {
         this.re          =  { };
         this.re.chr  =  new RegExp( "([^-A-Za-z0-9()+,.:=@;$_!*'%].*)$",
                                     "" );
         this.re.org  =  new RegExp( "^ *"
                                     + "(urn:)"
                                     + "([A-Za-z0-9]+:)?"
                                     + "(.*[^ \n])"
                                     + "[ \n]*",
                                     "i" );
      }
      if ( attempt ) {
         got  =  this.re.org.exec( attempt );
         if ( got ) {
            space  =  got[2];
            if ( space ) {
               space  =  space.toLowerCase();
               if (this.sns.indexOf(":" + space)  >=  0) {
                  small    =  "urn:" + space;
                  subject  =  got[3];
                  swap     =  WSTM.util.isEscValid(subject);
                  crash    =  this.re.chr.exec(subject);
                  if (crash) {
                     r  =  [ false,  "bad character: " + crash[1]];
                  } else if (swap) {
                     r  =  [ false,  "bad escaping: " + swap];
                  } else if (got[1] + got[2]  !==  small) {
                     r  =  small + subject;
                  }
               } else {
                  r  =  [ false, "unknown namespace" ];
               }
            } else {
               r  =  [ false, "missing namespace" ];
            }
         } else {
            r  =  [ false, "invalid scheme (urn:)" ];
         }
      }
      return  r;
   };   // .util.urn.failure()



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



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



mw.libs.WikiSyntaxTextMod.bb.regexp  =  function ( WSTM ) {
   // Support for user defined regexp
   // Public:
   //    .util.regexp.fiat()
   //    .util.regexp.flag()
   // Uses:
   //    .util.fiatObjects()
   // 2012-05-26 PerfektesChaos@de.wikipedia
   "use strict";
   WSTM.util.fiatObjects( WSTM.util,  "regexp" );



   WSTM.util.regexp.fault  =  function ( attempt ) {
      // Guess whether attempt is a RegExp object
      // Precondition:
      //    attempt  -- thing to be tested
      // Postcondition:
      //    Return  string with error info, or false if appears to be RE
      // 2012-11-15 PerfektesChaos@de.wikipedia
      var r  =  false;
      if ( attempt ) {
         if ( typeof attempt  ===  "object" ) {
            if ( typeof attempt.ignoreCase  !==  "boolean" ) {
               r  =  "Object not RegExp";
            }
         } else {
            r  =  "RegExp definition not object";
         }
      } else {
         r  =  "Empty RegExp definition (" + attempt + ")";
      }
      return  r;
   };   // .util.regexp.fault()



   WSTM.util.regexp.fiat  =  function ( attempt, adjust, alert ) {
      // Safe creation of RegExp from regexp string
      // Precondition:
      //    attempt  -- pattern string to be tested
      //    adjust   -- optional string: flags
      //    alert    -- optional location for immediate error message
      // Postcondition:
      //    Returns RegExp object if no error detected,  or
      //            in case of error
      //            string with error message and data, if not alert,  or
      //            false if message displayed
      // Uses:
      //    .util.regexp.fault()
      //    .lang.text.fetch()
      //    .main.fault()
      // 2013-05-28 PerfektesChaos@de.wikipedia
      var r   =  false,
          s   =  false,
          lt, sf;
      switch ( typeof attempt ) {
         case "string":
            if ( attempt ) {
               lt  =  ( typeof adjust  ===  "string" );
               sf  =  ( lt ? adjust : "" );
               try {
                  r  =  new RegExp( attempt, sf );
               } catch ( err ) {
                  s  =  err + "\n" + attempt;
                  if ( adjust ) {
                     s  =  s + "\nflags: " + adjust;
                  }
               }   // try-catch
            } else {
               s  =  "Empty string";
            }
            break;
         case "object":
            s  =  this.fault( attempt );
            if ( ! s ) {
               r  =  attempt;
            }
            break;
         default:
            s  =  "Invalid type";
      }   // switch typeof attempt
      if ( s ) {
         if ( alert ) {
            WSTM.main.fault( WSTM.lang.text.fetch( "BadRegExp" ) + s,
                             alert );
            r  =  false;
         } else {
            r  =  s;
         }
      }
      return  r;
   };   // .util.regexp.fiat()



   WSTM.util.regexp.flag  =  function (attempt, apply, about) {
      // Is attempt a well-formed regexp string?
      // Precondition:
      //    attempt  -- flag string to be tested, or false
      //    apply    -- default flags
      //    about    -- user info
      // Postcondition:
      //    Return value  --  flag string
      // Versioning:
      //    'm' flag applied
      //        available for JavaScript = 1.5+
      //        required by:  IE 8   for  "^...$" line matches
      //    'y' proprietary flag applied
      // Uses:
      //    .lang.text.fetch()
      //    .main.fault()
      // 2012-05-26 PerfektesChaos@de.wikipedia
      var r  =  apply,
          l,
          s;
      if ( attempt ) {
         l  =  ( typeof attempt  ===  "string");
         if ( l ) {
            l  =  (attempt.search(/[^gGiImMyY]/) < 0);
            if ( l ) {
               s  =  attempt.toLowerCase();
               if ( s.indexOf( "g" ) < 0 ) {
                  if ( r.indexOf( "g" ) >= 0 ) {
                     r  =  r.replace( /g/, "" );
                  }
               }   // not global
               if ( s.indexOf( "i" ) >= 0 ) {
                  r  =  r + "i";
               }   // ignoreCase
               if ( s.indexOf( "y" ) >= 0 ) {
                  r  =  r + "y";
               }
            }
         }
         if ( ! l ) {
            WSTM.main.fault( WSTM.lang.text.fetch( "BadRegExpFlag" )
                             + " " + attempt,
                             about );
         }
      }
      return  r;
   };   // .util.regexp.flag()



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



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



mw.libs.WikiSyntaxTextMod.bb.translate  =  function (WSTM) {
   // String translation map
   // Public:
   //    .util.translate.factory()
   //    .util.translate.()
   //    .util.translate.flip()
   //    .util.translate.further()
   // Uses:
   //    .util.fiatObjects()
   // 2012-05-27 PerfektesChaos@de.wikipedia
   "use strict";
   WSTM.util.fiatObjects( WSTM.util,  "translate" );



   WSTM.util.translate.factory  =  function ( adjust, about ) {
      // Fast definition of replacements (internal)
      // Precondition:
      //    adjust  -- array of mappings
      //               Each mapping is an array of strings.
      //               It is either  [re, rp]  or  [re, rp, flag].
      //               re   -- regular expression string
      //               rp   -- replacement string or function
      //               flag -- RegExp-Flag; Standard is "g"
      //                       alternatively: "gi", "i", ""
      //                       (g for global, i for ignoreCase)
      //    about   -- context (variable name)
      // Postcondition:
      //    Returns array of mappings.
      //    Each mapping is an array [RE, rp].
      //                             RE -- RegExp object
      //                             rp -- replacement string (unchanged)
      // Uses:
      //    .main.fault()
      // Requires: JavaScript 1.2
      // 2012-05-27 PerfektesChaos@de.wikipedia
      var n  =  adjust.length,
          r  =  new Array(n),
          e, f, i, m, s;
      for ( i = 0;  i < n;  i++ ) {
         m  =  adjust[i];
         f  =  ( m.length < 3  ?  "g"
                               :  m[ 2 ] );
         s  =  m[ 0 ];
         try {
            e  =  new RegExp( s, f );
         } catch ( err ) {
            WSTM.main.fault( "RegExp error:\n"
                             + err + "\n"
                             + s + "\nin " + about + "[" + i + "]",
                             false );
            r.splice( i, 1 );
            i--;
            break;
         }   // try-catch
         r[ i ]  =  [ e,  m[ 1 ] ];
      }   // for i
      return  r;
   };   // .util.translate.factory()



   WSTM.util.translate.fiat  =  function ( assign, apply, about ) {
      // Transfer user defined pair of regexp string and replacement
      // Precondition:
      //    assign  -- array of strings  [re, rp, flags]  to be evaluated
      //                                 re  -- may be string or RegExp
      //                                        if string than flags
      //    apply   -- default flags
      //    about   -- user info
      // Postcondition:
      //    Return value  --  false if not applicable
      //                      array[2] with RegExp and replacement
      // Uses:
      //    .util.isArray()
      //    .util.regexp.flag()
      //    .util.regexp.fault()
      //    .main.fault()
      // 2012-11-15 PerfektesChaos@de.wikipedia
      var r    =  false,
          bug,
          s,
          sf,
          sh,
          sr;
      if ( WSTM.util.isArray( assign ) ) {
         if ( assign.length > 1 ) {
            bug  =  false;
            sh   =  assign[ 1 ];
            s    =  typeof sh;
            if ( s === "string"  ||  s === "function" ) {
               sr  =  assign[ 0 ];
               if ( sr === false  ||  sr === true  ||  sr === "" ) {
                  sr  =  "^.*$";
               }
               switch ( typeof sr ) {
                  case "string":
                     if ( assign.length < 3 ) {
                        sf  =  apply;
                     } else {
                        sf  =  WSTM.util.regexp.flag( assign[ 2 ],
                                                      apply,
                                                      about );
                     }
                     try {
                        r  =  [ new RegExp( sr, sf ),  sh ];
                     } catch (err) {
                        bug  = err + "\n" + sr;
                        if ( typeof sf  ===  "string") {
                           bug  =  bug + "\nflags:  " + sf;
                        }   // adjust provided
                        bug  =  [ "BadRegExp", bug ];
                     }   // try-catch
                     break;
                  case "object":
                     bug  =  WSTM.util.regexp.fault(sr);
                     if ( bug ) {
                        bug  =  [ bug, false ];
                     } else {
                        r  =  [ sr, sh ];
                     }
                     break;
               }   // switch typeof assign[0]
            } else {
               bug  =  [ "IsNotStringOrFunction", sh ];
            }
            if ( bug ) {
               WSTM.main.fault( WSTM.lang.text.fetch( bug[ 0 ] ),
                                bug[ 1 ] );
            }
         }
      }
      return  r;
   };   // .util.translate.fiat()



   WSTM.util.translate.flip  =  function ( adjust, apply ) {
      // Modify string by multiple replacement
      // Precondition:
      //    adjust  -- string to be modified
      //    apply   -- array of mappings
      //               Each mapping is an array  [RE, rp].
      //               RE  -- RegExp object
      //               rp  -- replacement string
      // Postcondition:
      //    Returns modified string, even unchanged.
      // Requires: JavaScript 1.2   replace()
      // 2012-05-27 PerfektesChaos@de.wikipedia
      var n  =  apply.length,
          r  =  adjust,
          i,
          s,
          t,
          x;
      for ( i = 0;  i < n;  i++ ) {
         t  =  apply[i];
         x  =  t[1];
         s  =  typeof x;
         if ( s === "string" ) {
            r  =  r.replace(t[0], x);
         } else if ( s === "function" ) {
            r  =  r.replace( t[ 0 ],  x( 1, i, 0, r ) );
         }
      }   // for i
      return  r;
   };   // .util.translate.flip()



   WSTM.util.translate.further  =  function (add, all, adhere, already) {
      // Definition of additional replacements by user
      // Precondition:
      //    add      -- array of mappings to be added
      //                Each mapping is an array of strings.
      //                For details see  this.factory()
      //    all      -- accumulated array of mappings
      //                false if empty (internally created)
      //                extended if not empty and valid array of mappings
      //    adhere   -- User visible name of add (optional string)
      //    already  -- optional
      //                User is an expert now, mapping already checked
      // Postcondition:
      //    Return value  -- all has been extended
      //                     (created RE objects instead if re strings)
      //                     if successful and input data valid,
      //                     false if error detected
      // Remark:
      //    Function can be called several times;
      //    mappings will cumulate in order of applying.
      // Versioning:
      //    'm' flag applied
      //        available for JavaScript = 1.5+
      //        required by:  IE 8   for  "^...$" line matches
      //    'y' proprietary flag applied
      // Uses:
      //    .util.isArray()
      //    .lang.text.fetch()
      //    .util.regexp.flag()
      //    .util.regexp.fiat()
      //    .main.fault()
      // Requires: JavaScript 1.3   charCodeAt()
      // 2012-07-15 PerfektesChaos@de.wikipedia
      var s        =  false,
          story    =  ( typeof adhere  ===  "string"
                                                    ?  adhere
                                                    :  "'add.further'" ),
          wstmTXT  =  WSTM.lang.text.fetch,
          c, e, f, i, j, k, learnt, n, source, x;
      if ( WSTM.util.isArray( add ) ) {
         learnt  =  ( already ? true : false );
         n       =  add.length;
         if ( ! all ) {   // new
            k    =  0;
            all  =  new Array(n);
         } else {   // expand
            k    =  all.length;
            all  =  all.concat( new Array( n ) );
         }   // all
         for ( i = 0;  i < n;  i++ ) {
            e  =  add[i];
            if ( WSTM.util.isArray( e ) ) {
               c  =  e.length;
               if ( learnt ) {   // no debug
                  if ( c > 2 ) {
                     x  =  e[ 2 ];
                  } else {
                     c  =  2;
                  }
               } else {
                  source  =  story + " #" + ( i+1 ) + " ";
                  if ( c < 2 ) {
                     s  =  source
                           + wstmTXT( "Not" )
                           + " min. Array(2)";
                     break;
                  } else if ( typeof e[0]  !==  "string" ) {
                     s  =  "regexp in " + source
                           + wstmTXT( "IsNotAString" );
                     break;
                  } else if ( typeof e[1]  !==  "string"  &&
                              typeof e[1]  !==  "function" ) {
                     s  =  wstmTXT( "ReplacementIn" )
                           + " " + source
                           + wstmTXT( "IsNotStringOrFunction" );
                     break;
                  } else if ( c > 4 ) {
                     s  =  source
                           + wstmTXT( "HasMoreThan4Elements" );
                     break;
                  } else if ( c > 2 ) {
                     x  =  e[ 2 ];
                     if ( typeof x  ===  "string") {
                        x  =  x.toLowerCase();
                        for ( j = x.length - 1;  j >= 0;  j-- ) {
                           switch (x.charCodeAt(j)) {
                           case 103 :   // g
                           case 105 :   // i
                           case 109 :   // m
                           case 121 :   // y
                              break;
                           default :
                              s  =  "flag '" + x[j] + "' in " + source
                                    + wstmTXT("Invalid")
                                    + ":  '" + e[2] + "'";
                              break;
                           }   // switch charCodeAt
                        }   // for j--
                     } else {
                        if ( c > 3 ) {
                           if ( x  &&
                                x !== null  &&
                                x !== undefined ) {
                              s  =  "flag in " + source
                                    + wstmTXT( "IsNotAString" );
                              break;
                           }   // skip empty element, leave flag default
                        }   // may be ', ,'
                        c  =  2;
                     }    // e[2] flag
                  }
               }   // debug array
               if ( ! s ) {
                  f  =  ( c > 2  ?  x  :  "gm" );   // JS=1.5+  *  IE8
                  if ( learnt ) {   // no debug
                     x  =  new RegExp( e[ 0 ], f );
                  } else {
                     x  =  WSTM.util.regexp.fiat( e[ 0 ], f, false );
                     if ( typeof x  ===  "string") {
                        s  =  "RegExp error:\n" + x + "\nin "
                              + story + " #" + (i+1);
                        all.splice( k, 1 );
                        break;   // for i
                     }   // error detected
                  }   // debug regexp
                  all[k]  =  [ x, e[ 1 ] ];
                  k++;
               }
            } else {
               s  =  source + wstmTXT( "IsNotAnArray" );
               break;
            }   // m
         }   // for i
      } else {
         s  =  story + wstmTXT( "IsNotAnArray" );
      }   // add
      if ( s ) {
         WSTM.main.fault( s, false );
      }   // s
      return  ( s ? false : all );
   };   // .util.translate.further()



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



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



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




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

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