Jump to content

User:PerfektesChaos/js/citoidWikitext/opus/d.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.
/// User:PerfektesChaos/js/citoidWikitext/opus.js
// Postprocess citoid results under content aspects
/// 2019-11-22 PerfektesChaos@de.wikipedia
// ResourceLoader:  compatible;
//    dependencies: --
/// Fingerprint: #0#0#
/// @license: CC-by-sa/4.0 GPLv3
/// <nowiki>
/* global window: false                                                */
/* jshint forin: false,
          bitwise:true, curly:true, eqeqeq:true, latedef:true,
          laxbreak:true,
          nocomma:true, strict:true, undef:true, unused:true           */



( function ( mw ) {
   "use strict";
   var Version   = -4.4,
       Signature = "citoidWikitext",
       Sub       = "opus",
       OPUS      = { hdl: { } },
       UTIL      = { },
       XPORT     = { opus: { } },
       CITWT;


   function facilitated() {
      // Mark sub-module as ready
      // Uses:
      //    >  Signature
      //    >  Sub
      //    >  Version
      //    >  XPORT
      //     < CITWT
      //     < .signature
      //     < .vsn
      //     < .type
      //    mw.loader.getState()
      //    mw.loader.state()
      //    mw.hook()
      // 2018-08-24 PerfektesChaos@de.wikipedia
      var sign      = "ext.gadget." + Signature,
          sub       = "/" + Sub,
          signature = sign + sub,
          s         = mw.loader.getState( signature ),
          e, o, rls;
      if ( s !== "loaded"  &&  s !== "ready" ) {
         rls = { };
         rls[ signature ] = "loaded";
         mw.loader.state( rls );
         if ( typeof mw.libs[ Signature ]  !==  "object"   ||
              !      mw.libs[ Signature ] ) {
            mw.libs[ Signature ] = { };
         }
         CITWT = mw.libs[ Signature ];
         CITWT.signature = sign;
         if ( typeof CITWT.vsn  ===  "string" ) {
            CITWT.vsn = CITWT.vsn + " ";
         } else {
            CITWT.vsn = "";
         }
         CITWT.vsn  = CITWT.vsn + Sub.substr( 0, 1 ) + ":" + Version;
         CITWT.type = Signature;
         if ( typeof CITWT[ Sub ]  !==  "object"   ||
              !      CITWT[ Sub ] ) {
            CITWT[ Sub ] = { };
         }
         e = XPORT[ Sub ];
         o = CITWT[ Sub ];
         for ( s in e ) {
            o[ s ] = e[ s ];
         }   // for s in e
         rls[ signature ] = "ready";
         mw.loader.state( rls );
         mw.hook( Signature + sub + ".ready" ).fire( CITWT );
      }
   }   // facilitated()



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



   OPUS.hdl.supreme = "|com|gov|info|net|org|at|ch|de|is|";
   if ( typeof OPUS.re  !==  "object" ) {
      OPUS.re  =  { };
   }



   OPUS.hdl.factory = function () {
      // Build set of domain handlers
      // Uses:
      //    this
      //    >< OPUS.hdl.supreme
      //     < OPUS.hdl.recover
      //     < OPUS.hdl.*.*
      // 2016-04-11 PerfektesChaos@de.wikipedia
      var tld = this.supreme.split( "|" ),
          i;
      this.supreme = false;
      for ( i = 0;  i < tld.length;  i++ ) {
         this[ tld[ i ] ] = { };
      }   // for i
      this.recover = new RegExp( "^\\w+://(?:[^./]+\\.)*"
                                 + "([^./]+)"
                                 + "(?:\\.(ac|co|gv|or))?"
                                 + "\\.(\\w+)"
                                 + "(?::[0-9]+)?/" );


      this.dtNatBib = function ( answer ) {
         // 2016-04-11 PerfektesChaos@de.wikipedia
         var splash = "Katalog der Deutschen Nationalbibliothek",
             got, i, re;
         if ( typeof answer.title  ===  "string" ) {
            i = answer.title.indexOf( ":" );
            if ( i > 0   &&
                 typeof answer.publisher  !==  "string" ) {
               answer.publisher = answer.title.substr( i + 1 )
                                              .replace( /^\s+/, "" );
               answer.title     = answer.title.substr( 0, i )
                                              .replace( /\s+$/, "" );
            }
            if ( typeof answer.publisher  ===  "string" ) {
               re  = /^(.+)[,.]\s*([0-9].+)Aufl(?:\.|age)$/;
               got = re.exec( answer.publisher );
               if ( got   &&   typeof answer.edition  !==  "string" ) {
                  answer.edition   = got[ 2 ];
                  answer.publisher = got[ 1 ];
               }
               re  = /^(.+),\s*((?:20|1[0-9])[0-9][0-9])$/;
               got = re.exec( answer.publisher );
               if ( got   &&   typeof answer.date  !==  "string" ) {
                  answer.date      = got[ 2 ];
                  answer.publisher = got[ 1 ];
               }
            }
            re  = /^(.+)\s+-\s+(.+)$/;
            got = re.exec( answer.title );
            if ( got   &&   typeof answer.place  !==  "string" ) {
               answer.place = got[ 2 ];
               answer.title = got[ 1 ];
            } else if ( answer.title.indexOf( splash ) >= 0 ) {
               answer.title = "?";
            }
         }
         answer.domain           = "dnb.de";
         answer.publicationTitle = false;
      };   // OPUS.hdl.dtNatBib()


      this.googleBooks = function ( answer ) {
         var got;
         if ( typeof answer.volume  !==  "string" ) {
            got = /&pg=RA(\d+)&/.exec( answer.url + "&" );
            if ( got ) {
               answer.volume = got[ 1 ];
            }
         }
         if ( typeof answer.pages  !==  "string" ) {
            got = /&pg=PA(\d+)&/.exec( answer.url + "&" );
            if ( got ) {
               answer.pages = got[ 1 ];
            }
         }
      };   // OPUS.hdl.googleBooks()


      this.com.google = function ( answer ) {
         if ( answer.url.indexOf( "//books.google.com/" )  >  0 ) {
            OPUS.hdl.googleBooks( answer );
         }
      };   // OPUS.hdl.com.google()


      this.com.springer = function ( answer ) {
         // 2016-11-21 PerfektesChaos@de.wikipedia
         var s = "//link.springer.com/article/";
         i = answer.url.indexOf( s );
         if ( i > 0   &&
              typeof answer.DOI  ===  "string"   &&
              answer.url.substr( i + s.length ).replace( /%2F/ig, "/" )
                                                      ===  answer.DOI ) {
            answer.url = false;
         }
      };   // OPUS.hdl.com.springer()


      this.gov.loc = function ( answer ) {
         // 2018-07-28 PerfektesChaos@de.wikipedia
         var s;
         if ( typeof answer.title  ===  "string" ) {
            if ( answer.title.indexOf( "No Connections Available" ) >= 0
                 &&   typeof answer.date  !==  "string" ) {
               for ( s in answer ) {
                  answer[ s ] = false;
               }   // for s in answer
            }
            if ( answer.title ) {
               if ( typeof this.reLOC !==  "object" ) {
                  this.reLOC = " *L"
                               + "(?:C|ibrary of Congress)"
                               + " Online Catalog *"
                               + "(?:- "
                                     + "(?:Browse"
                                       + "|Item Information"
                                         + "(?: \\(Full Record\\))?"
                                     + " *)?"

                               + " *)?";
                  this.reLOC = new RegExp( this.reLOC );
               }
               answer.title = answer.title.replace( this.reLOC, " " );
               if ( answer.title  ===  " " ) {
                  answer.title = false;
               }
            }
         }
         if ( typeof answer.publicationTitle  ===  "string"   &&
              answer.publicationTitle  ===  "catalog.loc.gov" ) {
            answer.publicationTitle = false;
            answer.websiteTitle     = false;
         }
      };   // OPUS.hdl.gov.loc()


      this.gov.nih = function ( answer ) {
         // 2017-05-17 PerfektesChaos@de.wikipedia
         var got, i, s;
         if ( typeof answer.url  ===  "string" ) {
            i = answer.url.indexOf( "ncbi.nlm.nih.gov/" );
            if ( i > 0 ) {
               s = answer.url.substr( i + 17 );
               i = s.indexOf( "pubmed/" );
               if ( ! i ) {
                  if ( typeof answer.PMCID  ===  "string" ) {
                     answer.PMC = answer.PMCID;
                  }
                  s   = s.substr( i + 7 );
                  got = /^(\d+)(?:[\/?].*)?$/.exec( s );
                  if ( got ) {
                     answer.PMID = got[ 1 ];
                     answer.url  = false;
                  }
               } else {
                  i = s.indexOf( "pmc/articles/PMC" );
                  if ( ! i ) {
                     s   = s.substr( i + 16 );
                     got = /^(\d+)(?:[\/?].*)?$/.exec( s );
                     if ( got ) {
                        answer.PMC = got[ 1 ];
                        answer.url = false;
                     }
                  }
               }
            }
         }
         if ( typeof answer.PMC  ===  "string" ) {
            answer.PMC = answer.PMC.replace( /^PMC\s*/, "" );
            answer.PMCID = answer.PMC;
         }
      };   // OPUS.hdl.gov.nih()


      this.info[ "d-nb" ] = function ( answer ) {
         answer.itemType = "book";
         OPUS.hdl.dtNatBib( answer );
      };   // OPUS.hdl.info.d-nb()


      this.net.faz = function ( answer, ask ) {
         // 2019-11-06 PerfektesChaos@de.wikipedia
         var s;
         if ( typeof answer.url  ===  "string"   &&
              answer.url.length < 35   &&
              typeof ask.url  ===  "object"   &&
              typeof ask.url.length  ===  "number"   &&
              typeof ask.url[ 0 ]  ===  "object"   &&
              typeof ask.url[ 0 ].length  ===  "number"   &&
              typeof ask.url[ 0 ][ 0 ]  ===  "string"   &&
              ask.url[ 0 ][ 0 ].length > 50 ) {
            answer.url = ask.url[ 0 ][ 0 ];
         }
         answer.editors          = false;
         answer.ISSN             = false;
         answer.websiteTitle     = false;
         answer.publicationTitle = "Frankfurter Allgemeine Zeitung";
         if ( typeof answer.authors  ===  "string" ) {
            s = answer.authors.toLowerCase();
            if ( s === "faz.net"  ||
                 s.indexOf( "frankfurter allgemeine zeitung" ) >= 0 ) {
               answer.authors = false;
            }
         } else if ( typeof answer.authors  ===  "object"   &&
                     typeof answer.authors.length  ===  "number"   &&
                     typeof answer.authors[ 0 ]  ===  "object"   &&
                     typeof answer.authors[ 0 ].given  ===  "string"
                     &&     answer.authors[ 0 ].given.indexOf(
                                       answer.publicationTitle ) >= 0 ) {
            answer.authors = false;
         }
      };   // OPUS.hdl.net.faz()


      this.org.archive = function ( answer ) {
         // 2017-02-07 PerfektesChaos@de.wikipedia
         var got, re;
         if ( typeof answer.url  ===  "string" ) {
            re  = /^https?:\/\/web\.archive\.org\/web\/[0-9]+\/((?:https?|ftp):\/\/.+)$/;
            got = re.exec( answer.url );
            if ( got ) {
               answer.archive  = answer.url;
               answer.url      = decodeURIComponent( got[ 1 ] );
               answer.itemType = "webpage";
               OPUS.hdl.format( answer, "archive.org" );
            }
         }
      };   // OPUS.hdl.org.archive()


      this.org.doi = function ( answer ) {
         // 2015-06-10 PerfektesChaos@de.wikipedia
         var got, re;
         if ( typeof answer.url  ===  "string" ) {
            re  = /^https?:\/\/dx\.doi\.org\/(10\..+)$/;
            got = re.exec( answer.url );
            if ( got ) {
               answer.DOI = decodeURIComponent( got[ 1 ] );
               answer.url = false;
            }
         }
      };   // OPUS.hdl.org.doi()


      this.org.worldcat = function ( answer ) {
         // 2016-04-11 PerfektesChaos@de.wikipedia
         var got, s;
         if ( typeof this.reWC  !==  "object" ) {
            this.reWC        = { };
            s                = " *\\[(.+ .+)\\] *$";
            this.reWC.author = new RegExp( s );
            s                = "'isbn:\\d{9,12}.'$";
            this.reWC.isbn   = new RegExp( s );
            s                = " *\\[worldcat\\.org\\] *";
            this.reWC.org    = new RegExp( s, "i" );
            s                = "^(.+) *\\(.+, *([12]\\d\\d\\d)\\) *$";
            this.reWC.yyyy   = new RegExp( s );
         }
         if ( typeof answer.title  ===  "string" ) {
            answer.title = answer.title.replace( this.reWC.org, "" );
            got          = this.reWC.yyyy.exec( answer.title );
            if ( got ) {
               answer.title = got[ 1 ];
               answer.year  = got[ 2 ];
            }
            if ( this.reWC.isbn.test( answer.title ) ) {
               answer.title = "?";
            }
         }
         s = "abstract";
         if ( typeof answer[ s ]  ===  "string"   &&
              typeof answer.creators  !==  "object" ) {
            got = this.reWC.author.exec( answer[ s ] );
            if ( got ) {
               answer.authors = [ { extra: got[ 1 ] } ];
            }
         }
         answer.publicationTitle = false;
         answer.websiteTitle     = false;
      };   // OPUS.hdl.org.worldcat()


      this.de["bsz-bw"] = function ( answer ) {
         if ( typeof answer.title  ===  "string"   &&
              !  answer.title.indexOf( "SWB Online-Katalog" ) ) {
            answer.title = false;
         }
         if ( typeof answer.publicationTitle  ===  "string"   &&
              answer.publicationTitle.indexOf( "swb.bsz-bw.de" ) >= 0 ) {
            answer.publicationTitle = false;
         }
         answer.itemType     = "book";
         answer.websiteTitle = false;
      };   // OPUS.hdl.de.bsz-bw()


      this.de.dnb = function ( answer ) {
         OPUS.hdl.dtNatBib( answer );
      };   // OPUS.hdl.de.dnb()


      this.de.google = function ( answer ) {
         if ( answer.url.indexOf( "//books.google.de/" )  >  0 ) {
            OPUS.hdl.googleBooks( answer );
         }
      };   // OPUS.hdl.de.google()


      this.de.google = function ( answer ) {
         if ( answer.url.indexOf( "//books.google.de/" )  >  0 ) {
            OPUS.hdl.googleBooks( answer );
         }
      };   // OPUS.hdl.de.google()


      this.de[ "nbn-resolving" ] = function ( answer ) {
         // 2015-06-24 PerfektesChaos@de.wikipedia
         var s = "//nbn-resolving.de/urn:";
         i = answer.url.indexOf( s );
         if ( i > 0 ) {
            answer.URN = answer.url.substr( i + s.length );
         }
      };   // OPUS.hdl.de.nbn-resolving.de()


      this.de.spiegel = function ( answer ) {
         // 2016-05-01 PerfektesChaos@de.wikipedia
         var got, re;
         if ( answer.url.indexOf( "spiegel.de/spiegel/print/" )  >  0 ) {
            answer.publicationTitle = "Der Spiegel";
            answer.itemType         = "magazineArticle";
            answer.url              = answer.url.replace( /\/\/m\./,
                                                          "//www." );
            if ( typeof answer.title  ===  "string" ) {
               re  = /^(.+)\b([0-5]?\d)\/((?:19|20)\d\d)$/;
               got = re.exec( answer.title );
               if ( got ) {
                  answer.issue = got[ 2 ];
                  answer.year  = got[ 3 ];
                  answer.title = got[ 1 ];
               }
               re           = new RegExp( " *-? +DER SPIEGEL *$", "i" );
               answer.title = answer.title.replace( re, "" );
            }
            if ( typeof answer.issue  !==  "string"   &&
                 typeof answer.volume  ===  "string"   &&
                 /^[0-5]?\d$/.test( answer.volume ) ) {
               answer.issue = answer.volume;
            }
            if ( answer.authors ) {
               got = answer.authors[ 0 ];
               if ( typeof got.family  ===  "string"   &&
                    got.family  ===  "Germany" ) {
                  got.family = false;
               }
               if ( typeof got.given  ===  "string"   &&
                    got.given  ===  "SPIEGEL" ) {
                  got.given = false;
               }
               if ( ! ( typeof got.family  ===  "string"   ||
                        typeof got.given  ===  "string" ) ) {
                  answer.authors = false;
               }
            }
         } else {
            answer.publicationTitle = "Spiegel Online";
            answer.itemType         = "webpage";
         }
      };   // OPUS.hdl.de.spiegel()


      this.de.welt = function ( answer ) {
         var s = answer.url;
         if ( s.indexOf( "welt.de/print/" )  >  0   ||
              s.indexOf( "welt.de/welt_print/" )  >  0 ) {
            answer.publicationTitle = "Die Welt";
            answer.itemType         = "newspaperArticle";
         } else {
            answer.publicationTitle = "Welt Online";
            answer.itemType         = "webpage";
         }
      };   // OPUS.hdl.de.welt()


      this.de.zeit = function ( answer ) {
         var re  = /zeit\/.de\/([12][901]\d\d)\/([0-5]\d)\//,
             got = re.exec( answer.url );
         if ( got ) {
            answer.publicationTitle = "Die Zeit";
            answer.itemType         = "journalArticle";
            answer.issue            = got[ 2 ];
            answer.year             = got[ 1 ];
         } else {
            answer.publicationTitle = "Zeit Online";
            answer.itemType         = "webpage";
         }
      };   // OPUS.hdl.de.zeit()


      this.is.archive = function ( answer ) {
         // 2017-02-07 PerfektesChaos@de.wikipedia
         var got, re;
         if ( typeof answer.url  ===  "string" ) {
            re  = /^https?:\/\/archive\.is\/[0-9]+\/((?:https?|ftp):\/\/.+)$/;
            got = re.exec( answer.url );
            if ( got ) {
               answer.archive  = answer.url;
               answer.url      = decodeURIComponent( got[ 1 ] );
               answer.itemType = "webpage";
               OPUS.hdl.format( answer, "archive.is" );
            }
         }
      };   // OPUS.hdl.is.archive()
   };   // OPUS.hdl.factory()



   OPUS.hdl.format = function ( answer, again, ask ) {
      // Postprocess and adapt citoid server answer by URL
      // Precondition:
      //    answer  -- citoid server result
      //    again   -- avoid self-recursive: tld2.tld
      //    ask     -- original query
      // Postcondition:
      //    Modifies answer, if appropriate
      // Uses:
      //    this
      //    >  OPUS.hdl.supreme
      //    >< OPUS.hdl.recover
      //    OPUS.hdl.factory()
      //    OPUS.hdl.*.*()
      // 2019-11-06 PerfektesChaos@de.wikipedia
      var got, slot, sub, sup, superior, tld, tld2;
      if ( this.supreme ) {
         this.factory();
      }
      if ( typeof answer.url  ===  "string" ) {
         got = this.recover.exec( answer.url );
         if ( got ) {
            sub      = got[ 1 ];
            slot     = got[ 2 ];
            sup      = got[ 3 ];
            superior = sub  +  ( slot  ?  "." + slot  :  "" )
                            +  "."  +  sup;
            if ( typeof this[ sup ]  ===  "object"
                 &&   again !== superior ) {
               tld = this[ sup ];
               if ( slot ) {
                  if ( typeof tld[ slot ]  ===  "object" ) {
                     tld2 = tld[ slot ];
                  }
               } else {
                  tld2 = tld;
               }
               if ( tld2  &&  typeof tld2[ sub ]  ===  "function" ) {
                  tld2[ sub ]( answer, ask );
               }
            }
            if ( typeof answer.domain  !==  "string" ) {
               answer.domain = superior;
            }
         }
      }
   };   // OPUS.hdl.format()



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



   OPUS.complete = { issued: "date",
                     doi:    "DOI",
                     lang:   "language",
                     pmid:   "PMID" };
   if ( typeof OPUS.re  !==  "object" ) {
      OPUS.re  =  { };
   }
   OPUS.dateMonS     = false;
   OPUS.reDateMY     = false;
   OPUS.reDateUS     = false;
   OPUS.sLangNam     = false;



   OPUS.fair = function ( adjust ) {
      // Capitalize entire fully upcased title
      // Precondition:
      //    adjust  -- citoid server result
      // Postcondition:
      //    Modifies adjust, if appropriate
      // Uses:
      // 2015-05-01 PerfektesChaos@de.wikipedia
      var i, s, words;
      if ( typeof adjust.title  ===  "string"
           &&   adjust.title  ===  adjust.title.toUpperCase()
           &&   adjust.title.indexOf( " " )  >  0 ) {
         words = adjust.title.split( " " );
         for ( i = 0;  i < words.length;  i++ ) {
            s = words[ i ].toLowerCase();
            if ( s.length > 3 ) {
               s = s.substr( 0, 1 ).toUpperCase()  +  s.substr( 1 );
            }
            words[ i ] = s;
         }   // for i
         adjust.title = words.join( " " );
      }
   };   // OPUS.fair()



   OPUS.feather = function ( answer, access, add ) {
      // Transform person lists of Arrays into object
      //    answer  -- citoid server result
      //    access  -- string, with component to exploit
      //    add     -- string, with component to be extended
      // Postcondition:
      //    Extend answer, if detected
      // Uses:
      //    >  OPUS.re.terminator
      // 2019-11-22 PerfektesChaos@de.wikipedia
      var e, got, i, k, o, s;
      if ( typeof answer[ access ]  ===  "object"   &&
           typeof answer[ add ]  !==  "object" ) {
         got = answer[ access ];
         if ( got   &&   typeof got.length  ===  "number"
                         &&     got.length ) {
            for ( i = 0;  i < got.length;  i++ ) {
               e = got[ i ];
               if ( typeof e  ===  "object"
                    &&     e   &&
                    typeof e.length  ===  "number"
                    &&     e.length ) {
                  o = false;
                  if ( typeof e[ 0 ]  ===  "string"
                       &&     e[ 0 ] ) {
                     s = e[ 0 ];
                     k = s.length;
                     if ( s.substr( k - 1 ) === "," ) {
                        o = { family: s.substr( 0, k - 1 ).trim() };
                     } else {
                        o = { given: s };
                     }
                  }
                  if ( e.length > 1   &&
                       typeof e[ 1 ]  ===  "string"
                       &&     e[ 1 ] ) {
                     s = e[ 1 ];
                     if ( s.indexOf( "..." ) < 0 ) {
                        s = s.replace( OPUS.re.terminator, "" )
                             .trim();
                     }
                     if ( s ) {
                        if ( o ) {
                           if ( typeof o.family  ===  "string" ) {
                              o.given = s;
                           } else {
                              o.family = s;
                           }
                        } else {
                           o = { family: s };
                        }
                     }
                  }
                  if ( o ) {
                     if ( typeof answer[ add ]  ===  "object"
                          &&     answer[ add ]   &&
                          typeof answer[ add ].length  ===  "number" ) {
                        answer[ add ].push( o );
                     } else {
                        answer[ add ] = [ o ];
                        answer[ access ] = false;
                     }
                  }
               }
            }   // for i
         }
      }
   };   // OPUS.feather()



   OPUS.feathers = function ( answer ) {
      // Transform person lists into Arrays
      // Precondition:
      //    answer  -- citoid server result
      // Postcondition:
      //    Modifies answer, adding components authors, editors etc.
      // Uses:
      //    >  OPUS.re
      //    >< OPUS.re.terminator
      //    OPUS.feather()
      // 2019-11-22 PerfektesChaos@de.wikipedia
      var e, groups, i, p, s, shift, story, sub, trsl;
      if ( typeof OPUS.re.terminator  ===  "undefined" ) {
         OPUS.re.terminator  =  new RegExp( "[,;.]$" );
      }
      if ( typeof answer.creators  ===  "object" ) {
         groups = { contributor:  "contributors",
                    editor:       "editors",
                    seriesEditor: "seriesEditors",
                    translator:   "translators" };
         trsl   = { creatorType: "type",
                    lastName:    "family",
                    firstName:   "given",
                    name:        "name" };
         for ( i = 0;  i < answer.creators.length;  i++ ) {
            p = answer.creators[ i ];
            if ( typeof p.creatorType  ===  "string" ) {
               sub = p.creatorType;
               if ( typeof groups[ p.creatorType ]  ===  "string" ) {
                  sub = groups[ p.creatorType ];
               } else {
                  sub = "authors";
               }
            } else {
               sub = "authors";
            }
            e = { };
            for ( s in p ) {
               story = p[ s ].replace( OPUS.reTerminator, "" );
               if ( typeof trsl[ s ]  ===  "string" ) {
                  shift      = trsl[ s ];
                  e[ shift ] = story;
               } else {
                  if ( typeof e.extra  ===  "string" ) {
                     e.extra = e.extra + "; " + story;
                  } else {
                     e.extra = story;
                  }
               }
            }   // for s in p
            if ( typeof answer[ sub ]  !==  "object" ) {
               answer[ sub ] = [ ];
            }
            answer[ sub ].push( e );
         }   // for i
      }
      if ( typeof answer.authors  !==  "object" ) {
         answer.authors = false;
      }
      OPUS.feather( answer, "author", "authors" );
      OPUS.feather( answer, "contributor", "contributors" );
   };   // OPUS.feathers()



   OPUS.fiat = function ( answer ) {
      // Create empty citoid server object
      // Precondition:
      //    answer  -- citoid server result pattern
      // Postcondition:
      //    Returns initialized citoid answer
      // Uses:
      //    OPUS.fair()
      // 2015-06-25 PerfektesChaos@de.wikipedia
      var r = { };
      if ( typeof answer.title  ===  "string" ) {
         r.title = answer.title;
      } else if ( typeof answer.publicationTitle  ===  "string" ) {
         r.title = answer.publicationTitle;
         answer.publicationTitle = false;
      } else if ( typeof answer.websiteTitle  ===  "string" ) {
         r.title = answer.websiteTitle;
         answer.websiteTitle = false;
      } else {
         r.title = false;
      }
      OPUS.fair( r );
      return r;
   };   // OPUS.fiat()



   OPUS.fiddle = function ( assembly ) {
      // Improve ISBN
      // Precondition:
      //    assembly  -- combined result
      //    mw.libs.isbnLib has been loaded
      // Postcondition:
      //    Modifies assembly, if appropriate
      // Uses:
      //    >  CITWT.isbnLib
      //    .isbnLib.format()
      // 2017-05-17 PerfektesChaos@de.wikipedia
      var fault, got, i, j, n, re, s1, s2;
      switch ( typeof assembly.ISBN ) {
         case "string":
            assembly.ISBN = [ assembly.ISBN ];
            break;
         case "object":
            break;
         default:
            if ( typeof assembly.isbn  ===  "string" ) {
               assembly.ISBN = [ assembly.isbn ];
            } else {
               assembly.ISBN = false;
            }
      }   // switch typeof assembly.ISBN
      if ( assembly.ISBN ) {
         // OCLC 271018568 2015-06
         assembly.itemType = "book";
         re                = /^(?:978)?(\d{9})[0-9xX]$/;
         for ( i = 0;  i < assembly.ISBN.length;  i++ ) {
            if ( typeof assembly.ISBN[ i ]  ===  "string" ) {
               s1 = assembly.ISBN[ i ].replace( /-/g, "" );
               n  = s1.length;
               if ( n !== 10  &&  n !== 13 ) {
                  if ( n > 20  &&  s1.indexOf( " " )  >  9 ) {
                     got = s1.split( /[^0-9xX]+/ );
                     for ( j = 0;  j < got.length;  j++ ) {
                        assembly.ISBN.push( got[ j ] );
                     }   // for j
                  }
                  s1 = false;
               }
               if ( s1   &&   !  re.test( s1 ) ) {
                  s1 = false;
               }
               if ( s1 ) {
                  assembly.ISBN[ i ] = s1;
               } else {
                  assembly.ISBN.splice( i, 1 );
                  i--;
               }
            }
         }   // for i
         if ( ! assembly.ISBN.length ) {
            assembly.ISBN = false;
         }
      }
      if ( assembly.ISBN ) {
         if ( assembly.ISBN.length === 2   &&
              typeof assembly.year  ===  "number" ) {
            s1 = assembly.ISBN[ 0 ];
            s2 = assembly.ISBN[ 1 ];
            if ( s1.replace( re, "$1" )  ===  s2.replace( re, "$1" ) ) {
               n = assembly.year;
               if ( ( s1.length < s2.length   &&   n <  2007 )    ||
                      s1.length > s2.length   &&   n >= 2007 ) {
                  got = 0;
               } else {
                  got = 1;
               }
               assembly.ISBN = [ assembly.ISBN[ got ] ];
            }
         }
         if ( typeof CITWT.isbnLib  ===  "object" ) {
            fault = function ( abandon, alert, about ) {
               assembly.title = "**** Bad ISBN " + alert + " ****";
               if ( about ) {
                  assembly.title = assembly.title + " " + about;
               }
            };
            got = CITWT.isbnLib.format( assembly.ISBN[ 0 ], true );
            if ( got[ 0 ] ) {
               if ( got[ 1 ] ) {
                  assembly.ISBN[ 0 ] = got[ 1 ];
               }
               assembly[ "ISBN-type" ]    = got[ 0 ];
               assembly[ "ISBN-invalid" ] = false;
            } else {
               assembly[ "ISBN-invalid" ] = true;
            }
         }
      }
   };   // OPUS.fiddle()



   OPUS.finish = function ( ask, assembly ) {
      // Last improvements, guess missing data
      // Precondition:
      //    ask       -- object with basic citoid query
      //    assembly  -- combined result
      // Postcondition:
      //    Modifies assembly, if appropriate
      // Uses:
      //    >  OPUS.complete
      //    OPUS.focus()
      //    OPUS.foreign()
      //    OPUS.fiddle()
      //    OPUS.fix()
      // 2017-06-11 PerfektesChaos@de.wikipedia
      var scheme, second;
      if ( typeof ask.scheme  ===  "string" ) {
         scheme = ask.scheme;
         if ( typeof ask[ scheme ]  ===  "string" ) {
            second = scheme.toUpperCase();
            if ( typeof assembly[ second ]  !==  "string" ) {
               assembly[ second ] = ask[ scheme ];
            }
            if ( second === "DOI" ) {
               assembly.url = false;
            }
         }
      }
      for ( second in OPUS.complete ) {
         scheme = OPUS.complete[ second ];
         if ( typeof assembly[ second ]  ===  "string"   &&
              typeof assembly[ scheme ]  !==  "string" ) {
            assembly[ scheme ] = assembly[ second ];
         }
      }   // for second in OPUS.complete
      if ( typeof assembly.date  !==  "string"   &&
           typeof assembly.issued  ===  "string" ) {
         assembly.date = assembly.issued;
      }
      OPUS.fix( assembly );
      OPUS.focus( assembly );
      if ( typeof assembly.year  !==  "string"   &&
           typeof assembly.date  ===  "string" ) {
         if ( /^\d\d\d\d\b/.test( assembly.date ) ) {
            assembly.date = assembly.date.substr( 0, 4 );
            assembly.year = assembly.date;
         } else if ( /^\[\d\d\d\d\]/.test( assembly.date ) ) {
            assembly.date = assembly.date.substr( 1, 4 );
            assembly.year = assembly.date;
         }
      }
      if ( typeof assembly.year  ===  "string" ) {
         assembly.year = parseInt( assembly.year, 10 );
      } else if ( typeof assembly.year  !==  "number" ) {
         assembly.year = false;
      }
      OPUS.foreign( assembly );
      OPUS.fiddle( assembly );
   };   // OPUS.finish()



   OPUS.fix = function ( assembly ) {
      // Fix minor syntax issues
      // Precondition:
      //    assembly  -- object, with result
      // Postcondition:
      //    Modifies assembly, if appropriate
      // Uses:
      //    >  OPUS.re
      //    >< OPUS.re.nbsp
      //    >< OPUS.re.space
      //    >< OPUS.re.trimR
      //    UTIL.flat()
      // 2019-11-22 PerfektesChaos@de.wikipedia
      var e, s;
      if ( typeof OPUS.re.nbsp  ===  "undefined" ) {
         s              = String.fromCharCode( 91, 9, 160, 93 );
         OPUS.re.nbsp   = new RegExp( s, "g" );
         OPUS.re.pipe   = new RegExp( "\\|", "g" );
         OPUS.re.space  = new RegExp( "\\s\\s+", "g" );
         OPUS.re.trimR  = new RegExp( " $" );
      }
      for ( s in assembly ) {
         e = assembly[ s ];
         if ( typeof e  ===  "string" ) {
            e             = UTIL.flat( e );
            e             = e.replace( OPUS.re.nbsp, " " )
                             .replace( OPUS.re.pipe, "&#124;" )
                             .replace( OPUS.re.space, " " )
                             .replace( OPUS.re.trimR, "" );
            assembly[ s ] = e;
         }
      }   // for s in assembly
   };   // OPUS.fix()



   OPUS.focus = function ( assembly ) {
      // Improve date format
      // Precondition:
      //    assembly  -- combined result
      // Postcondition:
      //    Modifies assembly, if appropriate
      // Uses:
      //    >< OPUS.reDateUS
      //    >< OPUS.reDateMY
      //    >< OPUS.dateMonS
      // 2015-06-09 PerfektesChaos@de.wikipedia
      var got, m, s;
      if ( typeof assembly.date  ===  "string"   &&
           /[a-z]/i.test( assembly.date ) ) {
         if ( ! OPUS.reDateUS ) {
            OPUS.reDateUS = new RegExp(  "^([a-z]+) +"
                                        + "([0-3]?\\d), *"
                                        + "((?:20|1\\d)\\d\\d)$",
                                        "i" );
            // "Jul 16, 2009"
            OPUS.reDateMY = new RegExp(  "^([a-z]+) +"
                                        + "((?:20|1\\d)\\d\\d)$",
                                        "i" );
            // "Apr 2003"
         }
         got = OPUS.reDateUS.exec( assembly.date );
         if ( got ) {
            got = { dd:   got[ 2 ],
                    mon:  got[ 1 ],
                    yyyy: got[ 3 ] };
         } else {
            got = OPUS.reDateMY.exec( assembly.date );
            if ( got ) {
               got = { dd:   false,
                       mon:  got[ 1 ],
                       yyyy: got[ 2 ] };
            }
         }
         if ( got ) {
            if ( ! OPUS.dateMonS ) {
               OPUS.dateMonS = { jan:  1,
                                 feb:  2,
                                 mar:  3,
                                 apr:  4,
                                 may:  5,
                                 jun:  6,
                                 jul:  7,
                                 aug:  8,
                                 sep:  9,
                                 oct: 10,
                                 nov: 11,
                                 dec: 12 };
            }
            s = got.mon.substr( 0, 3 ).toLowerCase();
            if ( typeof OPUS.dateMonS[ s ]  ===  "number" ) {
               m             = OPUS.dateMonS[ s ];
               assembly.date = got.yyyy + "-" +
                               ( m < 10  ?  "0" + m  :  m );
               if ( got.dd ) {
                  assembly.date = assembly.date
                                  + ( got.dd.length === 1  ?  "-0"
                                                           :  "-" )
                                  + got.dd;
               }
            }
         }
      }
   };   // OPUS.focus()



   OPUS.fold = function ( assembly, answer ) {
      // Merge multiple results into single object
      // Precondition:
      //    assembly  -- combined result
      //    answer    -- citoid server result
      // Postcondition:
      //    Modifies assembly, if appropriate
      // 2015-05-01 PerfektesChaos@de.wikipedia
      var learn, second, plus;
      for ( second in answer ) {
         plus = answer[ second ];
         if ( plus ) {
            learn = true;
            switch ( typeof assembly[ second ] ) {
               case "string":
                  if ( typeof plus  ===  "string" ) {
                     learn = ( plus.length
                               >  assembly[ second ].length );
                  }
                  break;
               case "object":
                  if ( typeof plus  ===  "object" ) {
                     learn = ( plus.length
                               >  assembly[ second ].length );
                  }
                  break;
            }   // switch typeof assembly[ second ]
            if ( learn ) {
               assembly[ second ] = plus;
            }
         }
      }   // for second in answer
   };   // OPUS.fold()



   OPUS.foreign = function ( assembly ) {
      // Improve language format
      // Precondition:
      //    assembly  -- combined result
      // Postcondition:
      //    Modifies assembly, if appropriate
      // Uses:
      //    >< OPUS.sLangNam
      // 2015-10-29 PerfektesChaos@de.wikipedia
      var s;
      if ( typeof assembly.language  ===  "string"   &&
           assembly.language.length > 3 ) {
         if ( ! OPUS.sLangNam ) {
            OPUS.sLangNam = { abkhazian:        "ab",
                              afar:             "aa",
                              afrikaans:        "af",
                              albanian:         "sq",
                              amharic:          "am",
                              arabic:           "ar",
                              armenian:         "hy",
                              assamese:         "as",
                              aymara:           "ay",
                              azerbaijani:      "az",
                              bashkir:          "ba",
                              basque:           "eu",
                              bengali:          "bn",
                              bhutani:          "dz",
                              bihari:           "bh",
                              bislama:          "bi",
                              breton:           "br",
                              bulgarian:        "bg",
                              burmese:          "my",
                              byelorussian:     "be",
                              cambodian:        "km",
                              catalan:          "ca",
                              chinese:          "zh",
                              corsican:         "co",
                              croatian:         "hr",
                              czech:            "cs",
                              danish:           "da",
                              dutch:            "nl",
                              english:          "en",
                              eng:              "en",
                              "british english":  "en-gb",
                              "american english": "en-us",
                              "en-uk":          "en-gb",
                              esperanto:        "eo",
                              estonian:         "et",
                              faeroese:         "fo",
                              fiji:             "fj",
                              finnish:          "fi",
                              french:           "fr",
                              frisian:          "fy",
                              galician:         "gl",
                              georgian:         "ka",
                              ger:              "de",
                              german:           "de",
                              greek:            "el",
                              greenlandic:      "kl",
                              guarani:          "gn",
                              gujarati:         "gu",
                              hausa:            "ha",
                              hebrew:           "he",
                              hindi:            "hi",
                              hungarian:        "hu",
                              icelandic:        "is",
                              indonesian:       "id",
                              interlingua:      "ia",
                              interlingue:      "ie",
                              inuktitut:        "iu",
                              inupiak:          "ik",
                              irish:            "ga",
                              italian:          "it",
                              japanese:         "ja",
                              javanese:         "jw",
                              kannada:          "kn",
                              kashmiri:         "ks",
                              kazakh:           "kk",
                              kinyarwanda:      "rw",
                              kirghiz:          "ky",
                              kirundi:          "rn",
                              korean:           "ko",
                              kurdish:          "ku",
                              laothian:         "lo",
                              latin:            "la",
                              latvian:          "lv",
                              lettish:          "lv",
                              lingala:          "ln",
                              lithuanian:       "lt",
                              macedonian:       "mk",
                              malagasy:         "mg",
                              malay:            "ms",
                              malayalam:        "ml",
                              maltese:          "mt",
                              maori:            "mi",
                              marathi:          "mr",
                              moldavian:        "mo",
                              mongolian:        "mn",
                              nauru:            "na",
                              nederlands:       "nl",
                              nepali:           "ne",
                              norwegian:        "no",
                              occitan:          "oc",
                              oriya:            "or",
                              oromo:            "om",
                              pashto:           "ps",
                              persian:          "fa",
                              polish:           "pl",
                              portuguese:       "pt",
                              punjabi:          "pa",
                              pushto:           "ps",
                              quechua:          "qu",
                              "rhaeto-romance": "rm",
                              romanian:         "ro",
                              russian:          "ru",
                              samoan:           "sm",
                              sangro:           "sg",
                              sanskrit:         "sa",
                              "scots gaelic":   "gd",
                              serbian:          "sr",
                              "serbo-croatian": "sh",
                              sesotho:          "st",
                              setswana:         "tn",
                              shona:            "sn",
                              sindhi:           "sd",
                              singhalese:       "si",
                              siswati:          "ss",
                              slovak:           "sk",
                              slovenian:        "sl",
                              somali:           "so",
                              spanish:          "es",
                              sundanese:        "su",
                              swahili:          "sw",
                              swedish:          "sv",
                              tagalog:          "tl",
                              tajik:            "tg",
                              tamil:            "ta",
                              tatar:            "tt",
                              telugu:           "te",
                              thai:             "th",
                              tibetan:          "bo",
                              tigrinya:         "ti",
                              tonga:            "to",
                              tsonga:           "ts",
                              turkish:          "tr",
                              turkmen:          "tk",
                              uigur:            "ug",
                              ukrainian:        "uk",
                              urdu:             "ur",
                              uzbek:            "uz",
                              vietnamese:       "vi",
                              volapuk:          "vo",
                              welsh:            "cy",
                              wolof:            "wo",
                              xhosa:            "xh",
                              yiddish:          "yi",
                              yoruba:           "yo",
                              zulu:             "zu" };
         }
         s = assembly.language.toLowerCase();
         if ( typeof OPUS.sLangNam[ s ]  ===  "string" ) {
            assembly.language = OPUS.sLangNam[ s ];
         }
      }
   };   // OPUS.foreign()



   OPUS.format = function ( answer, ask ) {
      // Postprocess and adapt citoid server answer by URL
      // Precondition:
      //    answer  -- citoid server result
      //    ask     -- original query
      // Postcondition:
      //    Returns and modifies answer, if appropriate
      // Uses:
      //    OPUS.feathers()
      //    OPUS.hdl.format()
      //    OPUS.fair()
      // 2019-11-06 PerfektesChaos@de.wikipedia
      OPUS.feathers( answer );
      OPUS.hdl.format( answer, false, ask );
      OPUS.fair( answer );
      return answer;
   };   // OPUS.format()



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



   UTIL.remover  = false;
   UTIL.combiner = false;


   UTIL.flat = function ( adjust ) {
      // Remove undesired characters from string
      // Precondition:
      //    adjust  -- string
      // Postcondition:
      //    Returns string
      // Uses:
      //    >< UTIL.combiner
      //    >< UTIL.relaxer
      //    >< UTIL.remover
      // Note: These character codes will break plain JS code.
      // 2019-11-22 PerfektesChaos@de.wikipedia
      var r = adjust,
          c, combi, escape, i, k, re, relax, remove, s;
      if ( ! UTIL.combiner ) {
         combi  = { 0x0300: { 0x41: 0x00C0,
                              0x45: 0x00C8,
                              0x49: 0x00CC,
                              0x4E: 0x01F8,
                              0x4F: 0x00D2,
                              0x55: 0x00D9,
                              0x61: 0x00E0,
                              0x65: 0x00E8,
                              0x69: 0x00EC,
                              0x6E: 0x01F9,
                              0x6F: 0x00F2,
                              0x75: 0x00F9 },
                    0x0301: { 0x41: 0x00C1,
                              0x43: 0x0106,
                              0x45: 0x00C9,
                              0x49: 0x00CD,
                              0x4C: 0x0139,
                              0x4E: 0x0143,
                              0x4F: 0x00D3,
                              0x52: 0x0154,
                              0x53: 0x015A,
                              0x55: 0x00DA,
                              0x59: 0x00DD,
                              0x5A: 0x0179,
                              0x61: 0x00E1,
                              0x63: 0x0107,
                              0x65: 0x00E9,
                              0x69: 0x00ED,
                              0x6C: 0x013A,
                              0x6E: 0x0144,
                              0x6F: 0x00F3,
                              0x72: 0x0155,
                              0x73: 0x015B,
                              0x75: 0x00FA,
                              0x79: 0x00FD,
                              0x7A: 0x017A },
                    0x0302: { 0x41: 0x00C2,
                              0x43: 0x0108,
                              0x45: 0x00CA,
                              0x47: 0x011C,
                              0x48: 0x0124,
                              0x49: 0x00CE,
                              0x4A: 0x0134,
                              0x4F: 0x00D4,
                              0x53: 0x015C,
                              0x55: 0x00DB,
                              0x57: 0x0174,
                              0x59: 0x0176,
                              0x61: 0x00E2,
                              0x63: 0x0109,
                              0x65: 0x00EA,
                              0x67: 0x011D,
                              0x68: 0x0125,
                              0x69: 0x00EE,
                              0x6A: 0x0135,
                              0x6F: 0x00F4,
                              0x73: 0x015D,
                              0x75: 0x00FB,
                              0x77: 0x0175,
                              0x79: 0x0177 },
                    0x0303: { 0x41: 0x00C3,
                              0x49: 0x0128,
                              0x4E: 0x00D1,
                              0x4F: 0x00D5,
                              0x55: 0x0168,
                              0x61: 0x00E3,
                              0x69: 0x0129,
                              0x6E: 0x00F1,
                              0x6F: 0x00F5,
                              0x75: 0x0169 },
                    0x0307: { 0x41: 0x0226,
                              0x43: 0x010A,
                              0x45: 0x0116,
                              0x47: 0x0120,
                              0x49: 0x0130,
                              0x4F: 0x022E,
                              0x5A: 0x017B,
                              0x61: 0x0227,
                              0x63: 0x010B,
                              0x65: 0x0117,
                              0x67: 0x0121,
                              0x6F: 0x022F,
                              0x7A: 0x017C },
                    0x0308: { 0x41: 0x00C4,
                              0x45: 0x00CB,
                              0x49: 0x00CF,
                              0x4F: 0x00D6,
                              0x55: 0x00DC,
                              0x59: 0x0178,
                              0x61: 0x00E4,
                              0x65: 0x00EB,
                              0x69: 0x00EF,
                              0x6F: 0x00F6,
                              0x75: 0x00FC,
                              0x79: 0x00FF },
                    0x030A: { 0x41: 0x00C5,
                              0x55: 0x016E,
                              0x61: 0x00E5,
                              0x75: 0x016F },
                    0x030B: { 0x4F: 0x0150,
                              0x55: 0x0170,
                              0x6F: 0x0151,
                              0x75: 0x0171 }
                    };
         escape = [ 60, 62, 91, 93, 123, 124, 125 ];
         relax  = [ 10, 13, 8232, 8233 ];
         remove = [ 8206, 8207,
                    8234, 8235, 8236, 8237, 8238,
                    8287, 8288,
                    8298, 8299, 8300, 8301, 8302, 8303 ];
         UTIL.combiner = { };
         for ( i in combi ) {
            UTIL.combiner[ String.fromCharCode( i ) ] = combi[ i ];
         }   // for i in combi
         UTIL.escape = [ ];
         for ( i = 0;  i < escape.length;  i++ ) {
            UTIL.escape.push( String.fromCharCode( escape[ i ] ) );
         }   // for i
         UTIL.relaxer = [ ];
         for ( i = 0;  i < relax.length;  i++ ) {
            UTIL.relaxer.push( String.fromCharCode( relax[ i ] ) );
         }   // for i
         UTIL.remover = [ ];
         for ( i = 0;  i < remove.length;  i++ ) {
            UTIL.remover.push( String.fromCharCode( remove[ i ] ) );
         }   // for i
      }
      for ( i in UTIL.combiner ) {
         if ( r.indexOf( i )  >  0 ) {
            combi = UTIL.combiner[ i ];
            for ( c in combi ) {
               re = new RegExp( String.fromCharCode( c )  +  i,   "g" );
               r  = r.replace( re,  String.fromCharCode( combi[ c ] ) );
            }   // for c in combi
         }
      }   // for i in UTIL.combiner
      for ( i = 0;  i < UTIL.relaxer.length;  i++ ) {
         if ( r.indexOf( UTIL.relaxer[ i ] )  >=  0 ) {
            re = new RegExp( UTIL.relaxer[ i ], "g" );
            r  = r.replace( re, " " );
         }
      }   // for i
      for ( i = 0;  i < UTIL.remover.length;  i++ ) {
         if ( r.indexOf( UTIL.remover[ i ] )  >=  0 ) {
            re = new RegExp( UTIL.remover[ i ], "g" );
            r  = r.replace( re, "" );
         }
      }   // for i
      for ( i = 0;  i < UTIL.escape.length;  i++ ) {
         c = UTIL.escape[ i ];
         if ( r.indexOf( c )  >=  0 ) {
            k  = c.charCodeAt( 0 );
            re = c;
            if ( k >= 91 ) {
               re = "\\" + re;
            }
            re = new RegExp( re, "g" );
            s  = "&#" + k + ";";
            r  = r.replace( re, s );
         }
      }   // for i
      return r;
   };   // UTIL.flat()



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



   XPORT.opus.fetch = function ( assembly, access, adjoin, action ) {
      // Retrieve string value from query result
      // Precondition:
      //    assembly  -- object, with query result
      //    access    -- string, with component name
      //    adjoin    -- string, with separator for Array concatenation
      //    action    -- function, with handler for object as item
      //                     ( item object, component name, item number )
      // Postcondition:
      //    Returns string, or false
      // 2018-07-14 PerfektesChaos@de.wikipedia
      var e, g, i, r;
      switch ( typeof assembly[ access ] ) {
         case "string":
            r = assembly[ access ];
            break;
         case "number":
            r = "" + assembly[ access ];
            break;
         case "object":
            g = assembly[ access ];
            if ( g  &&
                 typeof adjoin  ===  "string"  &&
                 typeof g.length  ===  "number"
                 &&     g.length ) {
               for ( i = 0;  i < g.length;  i++ ) {
                  switch ( typeof g[ i ] ) {
                     case "string":
                        e = g[ i ];
                        break;
                     case "number":
                        e = "" + g[ i ];
                        break;
                     case "object":
                        if ( typeof action  ===  "function" ) {
                           e = action( g[ i ], access, i );
                           break;
                        }   // fall through
                     default:
                        e = false;
                  }   // switch typeof
                  if ( typeof e  ===  "string" ) {
                     if ( r ) {
                        r = r + adjoin;
                     }
                     r = r + e;
                  } else {
                     e = false;
                     break;   // for i
                  }
               }   // for i
               if ( ! e ) {
                  r = false;
               }
            }   // fall through
         default:
            r = false;
      }   // switch typeof assembly[ access ]
      return r;
   };   // XPORT.opus.fetch()



   XPORT.opus.figures = function ( apply ) {
      // Format list of comma-separated hyphen-joined number ranges
      // Precondition:
      //    apply  -- string, or not
      // 2015-05-01 PerfektesChaos@de.wikipedia
      var r = apply,
          e, g, i, nb, ne, s;
      if ( typeof apply  ===  "string"   &&
           apply.indexOf( "-" )  >  0 ) {
         e = apply.split( "," );
         for ( i = 0;  i < e.length;  i++ ) {
            s = e[ i ].replace( /^\s+/, "" )
                      .replace( /\s+$/, "" );
            g = /^(\d+)-(\d+)$/.exec( s );
            if ( g ) {
               nb = parseInt( g[ 1 ], 10 );
               ne = parseInt( g[ 2 ], 10 );
               if ( nb < ne ) {
                  s = nb + String.fromCharCode( 8211 ) + ne;
               }
            }
            e[ i ] = s;
         }   // for i
         e.join( ", " );
      }
      return r;
   };   // XPORT.opus.figures()



   XPORT.opus.fork = function ( array ) {
      // Duplicate template definition Array
      // Precondition:
      //    array  -- Array with basic citoid query
      // Postcondition:
      //    Returns deeper clone
      // 2015-05-01 PerfektesChaos@de.wikipedia
      var r = [ array[ 0 ] ],
          e, i;
      for ( i = 1;  i < array.length;  i++ ) {
         e = array[ i ];
         r.push( [ e[ 0 ], e[ 1 ] ] );
      }   // for i
      return r;
   };   // XPORT.opus.fork()



   XPORT.opus.format = function ( assembly ) {
      // Guess URL content type, like PDF
      // Precondition:
      //    assembly  -- object, with citoid server result
      // Postcondition:
      //    Returns string, or false
      // 2015-05-01 PerfektesChaos@de.wikipedia
      var r = false;
      if ( typeof assembly.url  ===  "string" ) {
         if ( /\bPDF\b/i.test( assembly.url ) ) {
            r = "PDF";
         }
      }
      return r;
   };   // XPORT.opus.format()



   XPORT.opus.freeze = function ( amount ) {
      // Retrieve ISO 8601 string of current date and time
      // Precondition:
      //    amount  -- Number of digits; 10: date
      // Postcondition:
      //    Returns string of length amount
      // Uses:
      //    >< OPUS.date
      //    >< OPUS.stamp
      // 2015-05-01 PerfektesChaos@de.wikipedia
      function iso8601( local ) {
         var n = ( amount ? amount : 19 ),
             k, r;
         function f( a ) {
            return ( local ? "get" : "getUTC" )  +  a;
         }
         r = OPUS.date[ f( "FullYear" ) ]()  +  "";
         if ( n >= 7 ) {
            r = r + "-";
            k = OPUS.date[ f( "Month" ) ]()  +  1;
            if ( k < 10 ) {
                r = r + "0";
            }
            r = r + k;
            if ( n >= 10 ) {
               r = r + "-";
               k = OPUS.date[ f( "Date" ) ]();
               if ( k < 10 ) {
                  r = r + "0";
               }
               r = r + k;
               if ( n >= 13 ) {
                  r = r + " ";
                  k = OPUS.date[ f( "Hours" ) ]();
                  if ( k < 10 ) {
                     r = r + "0";
                  }
                  r = r + k;
                  if ( n >= 16 ) {
                     r = r + ":";
                     k = OPUS.date[ f( "Minutes" ) ]();
                     if ( k < 10 ) {
                        r = r + "0";
                     }
                     r = r + k;
                     if ( n >= 19 ) {
                        r = r + ":";
                        k = OPUS.date[ f( "Seconds" ) ]();
                        if ( k < 10 ) {
                           r = r + "0";
                        }
                        r = r + k;
                     }
                  }
               }
            }
         }
         return r;
      }   // iso8601()
      if ( typeof OPUS.date  !==  "object" ) {
         OPUS.date = new Date();
      }
      if ( typeof OPUS.stamp  ===  "string"
           &&   OPUS.stamp.length < amount ) {
         OPUS.stamp = false;
      }
      if ( typeof OPUS.stamp  !==  "string" ) {
         OPUS.stamp = iso8601( true );
      }
      return OPUS.stamp.substr( 0, amount );
   };   // XPORT.opus.freeze()



   XPORT.opus.fruit  = function ( array, appearance ) {
      // Merge template definition
      // Precondition:
      //    array       -- Array, with template parameters
      //    appearance  -- number, with indentation
      //                   >= 0  -- line break
      //                   > 0   -- number of indentation spaces
      // Postcondition:
      //    Returns string, empty or with transclusion text
      // 2017-02-07 PerfektesChaos@de.wikipedia
      var e, i, lot, r, s, sep, sp;
      switch ( typeof array ) {
         case "object":
            e = array[ 0 ];
            r = "{{" + e[ 0 ];
            if ( appearance < 0  ||  ! e[ 1 ] ) {
               sep = "|";
               sp  = "";
               if ( appearance < 0 ) {
                  for ( i = appearance;  i;  i++ ) {
                     sep =  " " + sep;
                  }   // for i
               }
               lot = false;
            } else {
               sep = "\n";
               lot = e[ 1 ];
               sp  = ( e[ 3 ] ? " " : "" );
               for ( i = 0;  i < appearance;  i++ ) {
                  sep = sep + " ";
               }   // for i
               sep = sep + "|";
            }
            for ( i = 1;  i < array.length;  i++ ) {
               e = array[ i ];
               if ( e ) {
                  // currently no unnamed parameters expected,
                  // but might be supported by e[0]=false
                  s = e[ 2 ];
                  if ( s || e[ 1 ] || lot ) {
                     r = r  +
                         sep + e[ 0 ] + sp + "=" + sp +
                         ( s ? s : "" );
                  }
               }
            }   // for i
            r = r + "}}";
            break;
         case "string":
            r = array;
            break;
         default:
            r = "";
      }   // switch typeof array
      return r;
   };   // XPORT.opus.fruit()



   XPORT.opus.fire = function ( ask, answers ) {
      // Transform and merge multiple citoid results
      // Precondition:
      //    ask      -- object with basic citoid query
      //    answers  -- Array of citoid server results
      // Postcondition:
      //    Returns Array of results
      // Uses:
      //    >  Signature
      //    OPUS.fiat()
      //    OPUS.format()
      //    OPUS.fold()
      //    OPUS.finish()
      // Remark: Used as event handler -- 'this' is not XPORT
      // 2019-11-06 PerfektesChaos@de.wikipedia
      var i,
          r = [ OPUS.format( answers[ 0 ], ask ) ];
      if ( answers.length > 1 ) {
         r[ 0 ] = OPUS.fiat( r[ 0 ] );
         for ( i = 0;  i < answers.length;  i++ ) {
            r.push( OPUS.format( answers[ i ], ask ) );
         }   // for i
         for ( i = 1;  i < r.length;  i++ ) {
            OPUS.fold( r[ 0 ], r[ i ] );
         }   // for i
      }
      if ( ! r[ 0 ].title ) {
         r[ 0 ].title = Signature + " * NO TITLE PROVIDED";
      }
      if ( typeof ask.subtle  ===  "string"   &&
           answers.length === 1   &&
           r[ 0 ].url ) {
         r[ 0 ].url = r[ 0 ].url + "#" + ask.subtle;
      }
      OPUS.finish( ask, r[ 0 ] );
      return r;
   };   // XPORT.opus.fire()



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

/// EOF </nowiki>   citoidWikitext/opus/d.js