Module:Internet Archive
--[[ 
 
 For functions related to Internet Archive
 
 Notes: 
 
 1. Internet Archive runs Elasticsearch search engine as of 4 Nov 2015 
 
 2. Program flowchart:
 
    Break name down into number of words
      Build a base URL based on number of words (1,2,3,4,5+), use of sopt=t switch, and availability of birth-death dates
        If any words contain extended-ascii characters
          append extra code for wildcards based on sopt=t or w         
    return finished URL
 
 3. URL length should not exceed 2000 characters or it will break certain popular browsers
 
 4. Wildcard (*) replacements should be avoided in the first letter of the first word, and with any single-letter words
   
 5. Changing search formulations will have impacts on existing uses of the template and off-line tools which are optimized for these search recipes. 
   
 ]]
 
 local p = {}
 
 --[[ 
 
 For Template:Internet Archive author
 
 ]]
 function p.author(frame)
 
   local pframe = frame:getParent()
   local args = pframe.args
 
   local tname = &quot;Internet Archive author&quot;                       -- name of calling template. Change if template rename.
   
   local name = nil                                              -- article name (default: current page name)
   dname = nil                                                   -- display name (default: current page name)
   local sname = nil                                             -- search name (default: current page name)
   local sopt = nil                                              -- search options (default: nil)
   byabout = &quot;ஆக்கங்கள்&quot;
   tagline = &quot;[[இணைய ஆவணகம்|இணைய ஆவணகத்தில்]]&quot;
   urlhead = &quot;//archive.org/search.php?query=&quot;
   mydate = &quot;&quot;                                                   -- birth-death date
                                                  
   --- Determine name
   name = trimArg(args.name)                                     -- When using template outside main article space, the 'name' parameter is required (not optional)
   if not name then
     name = mw.title.getCurrentTitle().text
   end
   dname = mw.ustring.gsub(name,'%s+%([^%(]-%)$', '')            -- Remove the final disambig parentheses
   sname = dname
   if trimArg(args.sname) then                                       
     sname = trimArg(args.sname)
   end
   if trimArg(args.dname) then
     dname = trimArg(args.dname)
   end
  
   --- Determine search option
   sopt = trimArg(args.sopt)
   if sopt then
     sopt =  mw.ustring.lower(sopt)
     if sopt == &quot;tight&quot; then sopt = &quot;t&quot; end
     if sopt == &quot;tightx&quot; then sopt = &quot;tx&quot; end
     if sopt == &quot;wild&quot; then sopt = &quot;w&quot; end
     if sopt ~= &quot;t&quot; and sopt ~= &quot;tx&quot; and sopt ~= &quot;w&quot; then sopt = &quot;unknown&quot;  end
   end
 
   --- Determine tagline
   if trimArg(args.coda) then
     tagline = tagline .. &quot; &quot; .. trimArg(args.coda)
   end
 
   --- Custom search. Do early to avoid unnecessary processing. 
   if trimArg(args.search) then
     local search = p.ia_url_encode(trimArg(args.search))
     return &quot;[&quot; .. urlhead .. search .. &quot; &quot; .. byabout .. &quot; &quot; .. dname .. &quot;] &quot; .. tagline
   end
 
   -- Determine media string
   media = p.mediaTypes(args.media)
   if media == &quot;&quot; then
     mediaopen = &quot;%28&quot; -- added a default mediatype Dec 2015 see p.mediaTypes()
   else
     mediaopen = &quot;%28&quot;
   end
 
   -- Determine date of birth and death 
   local temp = mw.text.split(p.bdDate(args.birth, args.death, name), &quot; &quot;)
   local birth = temp[1]
   local death = temp[2]
   if birth == &quot;Error&quot; or death == &quot;Error&quot; then
     return &quot;Error in [[:Template:&quot;..tname..&quot;]]: [[&quot; ..name.. &quot;]] doesn't exist.&quot;
   end
 
   --- Split sname into words and count words
   local N = mw.text.split(sname, &quot; &quot;)
   local l, count = mw.ustring.gsub(sname, &quot;%S+&quot;, &quot;&quot;)
   if count == 0 then
     return &quot;Error in [[:Template:&quot;..tname..&quot;]]: Zero-word name.&quot;
   end 
 
   --- Date string
   if birth ~= &quot;none&quot; and death ~= &quot;none&quot; then
     if p.ia_extendedascii(N[count]) == 1 then
       mydate = &quot;%20OR%20%28%22&quot;..birth..&quot;-&quot;..death..&quot;%22%20AND%20%28%22&quot;..p.urlX(N[count])..&quot;%22%20OR%20&quot;..p.urlX(p.ia_deaccent(N[count]))..&quot;%29%29&quot;
     else
       mydate = &quot;%20OR%20%28%22&quot;..birth..&quot;-&quot;..death..&quot;%22%20AND%20&quot;..p.urlX(N[count])..&quot;%29&quot;
     end
   end
 
   --- wild string
   wild = &quot;%29&quot;           
   if sopt == &quot;w&quot; and p.ia_extendedascii(sname) == 1 then
     if p.wildcheck(N, count) == 1 then    
       myurl = p.wildfix(N, count)
       return p.IArender()
     end
     if count &lt; 3 or count &gt; 3 then
       -- (first last)
       wild = &quot;%20OR%20%28&quot; .. p.ia_url_encode(p.ia_extendedascii2wildcard(sname)) .. &quot;%29%29&quot;
     end
     if count == 3 then
       -- (first last)
       wild = &quot;%20OR%20%28&quot; .. p.ia_url_encode(p.ia_extendedascii2wildcard(N[1])) .. &quot;%20&quot; .. p.ia_url_encode(p.ia_extendedascii2wildcard(N[3])) .. &quot;%29%29&quot;
     end
   end
  
   --[[ 
 
       Format URL
 
   ]]
 
     if count == 1 then 
 
       myurl = p.oneWord(sname)
  
       if sopt == &quot;t&quot; and p.ia_extendedascii(sname) == 1 then
         local plainname = p.ia_deaccent(sname)       
         local A1 = &quot;%20OR%20%22&quot;..p.urlX(plainname)
         myurl = myurl .. A1 .. &quot;%22&quot;
         return p.IArender()
       end
 
       return p.IArender()
     
     end
 
     if count == 2 then
  
       myurl = p.twoWords(N, sopt)
     
       if sopt == &quot;t&quot; and p.ia_extendedascii(sname) == 1 then
         local plainname = p.ia_deaccent(sname)
         local PN = mw.text.split(plainname, &quot; &quot;) 
         -- Last, First
         local A1 = &quot;%20OR%20%22&quot;..p.urlX(PN[2])..&quot;%2C%20&quot;..p.urlX(PN[1])
         -- First Last
         local A2 = &quot;%22%20OR%20%22&quot;..p.urlX(PN[1])..&quot;%20&quot;..p.urlX(PN[2])
         myurl = myurl .. A1 .. A2 .. &quot;%22&quot;
         return p.IArender()
       end
 
       return p.IArender()
 
     end
 
     if count == 3 then
 
       myurl = p.threeWords(N, sopt)
 
       if sopt == &quot;t&quot; and p.ia_extendedascii(sname) == 1 then
         local plainname = p.ia_deaccent(sname)
         local PN = mw.text.split(plainname, &quot; &quot;) 
         local FIRST  = p.urlX(PN[1])
         local MIDDLE = p.urlX(PN[2])
         local LAST   = p.urlX(PN[3])
         local firstinitialp  = p.urlX( p.firstLetter(PN[1]) )
         local middleinitialp  = p.urlX( p.firstLetter(PN[2]) )
         -- First Middle Last
         local A1 = &quot;%20OR%20%22&quot;..FIRST..&quot;%20&quot;..MIDDLE..&quot;%20&quot;..LAST
         -- Last, First Middle
         local A2 = &quot;%22%20OR%20%22&quot;..LAST..&quot;%2C%20&quot;..FIRST..&quot;%20&quot;..MIDDLE
         -- Last, First M.
         local A3 = &quot;%22%20OR%20%22&quot;..LAST..&quot;%2C%20&quot;..FIRST..&quot;%20&quot;..middleinitialp..&quot;%2E&quot;
         -- Last, F. M.
         local A4 = &quot;%22%20OR%20%22&quot;..LAST..&quot;%2C%20&quot;..firstinitialp..&quot;.%20&quot;..middleinitialp..&quot;%2E&quot;
         local ALL = A1 .. A2 .. A3 .. A4 .. &quot;%22&quot;
         myurl = myurl .. ALL
         return p.IArender()
       end
 
       return p.IArender()
 
     end
 
     if count == 4 then
 
       myurl = p.fourWords(N, sopt)
 
       if sopt == &quot;t&quot; and p.ia_extendedascii(sname) == 1 then
         local plainname = p.ia_deaccent(sname)
         local PN = mw.text.split(plainname, &quot; &quot;) 
         local FIRST  = p.urlX(PN[1])
         local SECOND = p.urlX(PN[2])
         local THIRD  = p.urlX(PN[3])
         local LAST   = p.urlX(PN[4])
         local firstinitialp  = p.urlX( p.firstLetter(PN[1]) )
         local secondinitialp  = p.urlX( p.firstLetter(PN[2]) )
         local thirdinitialp  = p.urlX( p.firstLetter(PN[3]) )
         -- Last, First Second Third
         local A1 = &quot;%20OR%20%22&quot;..LAST..&quot;%2C%20&quot;..FIRST..&quot;%20&quot;..SECOND..&quot;%20&quot;..THIRD
         -- First Second Third Last
         local A2 = &quot;%22%20OR%20%22&quot;..FIRST..&quot;%20&quot;..SECOND..&quot;%20&quot;..THIRD..&quot;%20&quot;..LAST
         -- Last, F. S. T.
         local A3 = &quot;%22%20OR%20%22&quot;..LAST..&quot;%2C%20&quot;..firstinitialp..&quot;%2E%20&quot;..secondinitialp..&quot;%2E%20&quot;..thirdinitialp..&quot;%2E&quot;
         local ALL = A1 .. A2 .. A3 .. &quot;%22&quot;
         myurl = myurl .. ALL 
         return p.IArender()
       end 
 
       return p.IArender()
 
     end
 
     if count &gt; 4 then
 
       myurl = &quot;&quot;
 
       if sopt == &quot;w&quot; and p.ia_extendedascii(sname) == 1 then
         myurl = &quot;%28&quot;
       end
 
       myurl = myurl .. &quot;%28&quot; .. p.ia_url_encode(sname) 
 
       if sopt == &quot;w&quot; and p.ia_extendedascii(sname) == 1 then
         myurl = myurl .. &quot;%29&quot;
       end
  
       if sopt == &quot;t&quot; and p.ia_extendedascii(sname) == 1 then
         local plainname = p.ia_deaccent(sname)       
         local A1 = &quot;%29%20OR%20%28&quot;..p.ia_url_encode(plainname)
         myurl = myurl .. A1 
         return p.IArender()
       end
 
       return p.IArender()
 
     end
 
   return &quot;Unknown error (1). Please check documentation for [[Template:&quot;..tname..&quot;]]&quot;
 
 end
 
 -- Build final output and render
 function p.IArender() 
 
    return &quot;[&quot; .. urlhead .. mediaopen .. myurl .. wild .. mydate .. media .. &quot; &quot; .. byabout .. &quot; &quot; .. dname .. &quot;] &quot; .. tagline
 
 end
 
 function p.oneWord(sname)
 
       local nameurl = p.ia_url_encode(sname)
       local A1 = &quot;%28subject%3A%22&quot;..nameurl
       local A2 = &quot;%22%20OR%20creator%3A%22&quot;..nameurl
       local A3 = &quot;%22%20OR%20description%3A%22&quot;..nameurl
       local A4 = &quot;%22%20OR%20title%3A%22&quot;..nameurl
       return A1 .. A2 .. A3 .. A4 .. &quot;%22&quot;
 end
 
 function p.twoWords(N, sopt)
       local FIRST  = p.urlX(N[1])
       local LAST   = p.urlX(N[2])
       local firstinitial  = p.urlX( p.firstLetter(N[1]) )
 
       -- Last, First
       local S1 = &quot;%28subject%3A%22&quot;..LAST..&quot;%2C%20&quot;..FIRST
       -- First Last
       local S2 = &quot;%22%20OR%20subject%3A%22&quot;..FIRST..&quot;%20&quot;..LAST
       local SALL = S1..S2
       -- Last, First
       local C1 = &quot;%22%20OR%20creator%3A%22&quot;..LAST..&quot;%2C%20&quot;..FIRST
       -- First Last
       local C2 = &quot;%22%20OR%20creator%3A%22&quot;..FIRST..&quot;%20&quot;..LAST
       local CALL = C1..C2
       -- First Last
       local T1 = &quot;%22%20OR%20title%3A%22&quot;..FIRST..&quot;%20&quot;..LAST
       local TALL = T1
       -- Last, First
       local D1 = &quot;%22%20OR%20description%3A%22&quot;..LAST..&quot;%2C%20&quot;..FIRST
       -- First Last
       local D2 = &quot;%22%20OR%20description%3A%22&quot;..FIRST..&quot;%20&quot;..LAST
       local DALL = D1..D2
 
       if sopt == &quot;t&quot; or sopt == &quot;tx&quot; then
         return SALL .. CALL .. TALL .. DALL .. &quot;%22&quot;
       else
         -- Last, F.
         local C3 = &quot;%22%20OR%20creator%3A%22&quot;..LAST..&quot;%2C%20&quot;..firstinitial..&quot;%2E&quot;
         local CALL = CALL..C3
         return SALL .. CALL .. TALL .. DALL .. &quot;%22&quot;
       end
 
 end
 
 function p.threeWords(N, sopt)
       -- CAUTION: The following is near the max 2000 character URL limit for most browsers when using long names 
       --          such as &quot;René-Nicolas Dufriche Desgenettes&quot;. 
 
       local FIRST  = p.urlX(N[1])
       local MIDDLE = p.urlX(N[2])
       local LAST   = p.urlX(N[3])
       local firstinitial  = p.urlX( p.firstLetter(N[1]) )
       local middleinitial = p.urlX( p.firstLetter(N[2]) )
 
       -- Last, First Middle
       local S1 = &quot;%28subject%3A%22&quot;..LAST..&quot;%2C%20&quot;..FIRST..&quot;%20&quot;..MIDDLE
       -- Last, First M.
       local S2 = &quot;%22%20OR%20subject%3A%22&quot;..LAST..&quot;%2C%20&quot;..FIRST..&quot;%20&quot;..middleinitial..&quot;%2E&quot;
       -- Last, F. M.
       local S3 = &quot;%22%20OR%20subject%3A%22&quot;..LAST..&quot;%2C%20&quot;..firstinitial..&quot;%2E%20&quot;..middleinitial..&quot;%2E&quot;
       -- First Middle Last
       local S4 = &quot;%22%20OR%20subject%3A%22&quot;..FIRST..&quot;%20&quot;..MIDDLE..&quot;%20&quot;..LAST
       -- First M. Last
       local S5 = &quot;%22%20OR%20subject%3A%22&quot;..FIRST..&quot;%20&quot;..middleinitial..&quot;%2E%20&quot;..LAST
       -- F. M. Last
       local S6 = &quot;%22%20OR%20subject%3A%22&quot;..firstinitial..&quot;%2E%20&quot;..middleinitial..&quot;%2E%20&quot;..LAST
       local SALL = S1..S2..S3..S4..S5..S6
       -- First Middle Last
       local C1 = &quot;%22%20OR%20creator%3A%22&quot;..FIRST..&quot;%20&quot;..MIDDLE..&quot;%20&quot;..LAST
       -- First M. Last
       local C2 = &quot;%22%20OR%20creator%3A%22&quot;..FIRST..&quot;%20&quot;..middleinitial..&quot;%2E%20&quot;..LAST
       -- F. M. Last
       local C3 = &quot;%22%20OR%20creator%3A%22&quot;..firstinitial..&quot;%2E%20&quot;..middleinitial..&quot;%2E%20&quot;..LAST
       -- F. Middle Last
       local C4 = &quot;%22%20OR%20creator%3A%22&quot;..firstinitial..&quot;%2E%20&quot;..MIDDLE..&quot;%20&quot;..LAST
       -- Last, First Middle
       local C5 = &quot;%22%20OR%20creator%3A%22&quot;..LAST..&quot;%2C%20&quot;..FIRST..&quot;%20&quot;..MIDDLE
       -- Last, First M.
       local C6 = &quot;%22%20OR%20creator%3A%22&quot;..LAST..&quot;%2C%20&quot;..FIRST..&quot;%20&quot;..middleinitial..&quot;%2E&quot;
       -- Last, F. M.
       local C7 = &quot;%22%20OR%20creator%3A%22&quot;..LAST..&quot;%2C%20&quot;..firstinitial..&quot;%2E%20&quot;..middleinitial..&quot;%2E&quot;
       -- Last, F. M.
       local C8 = &quot;%22%20OR%20creator%3A%22&quot;..LAST..&quot;%2C%20&quot;..firstinitial..&quot;%2E%20&quot;..MIDDLE
       local CALL = C1..C2..C3..C4..C5..C6..C7..C8
       -- First Middle Last
       local T1 = &quot;%22%20OR%20title%3A%22&quot;..FIRST..&quot;%20&quot;..MIDDLE..&quot;%20&quot;..LAST
       -- First M. Last
       local T2 = &quot;%22%20OR%20title%3A%22&quot;..FIRST..&quot;%20&quot;..middleinitial..&quot;%2E%20&quot;..LAST
       -- F. M. Last
       local T3 = &quot;%22%20OR%20title%3A%22&quot;..firstinitial..&quot;%2E%20&quot;..middleinitial..&quot;%2E%20&quot;..LAST
       local TALL = T1..T2..T3
       -- First Middle Last
       local D1 = &quot;%22%20OR%20description%3A%22&quot;..FIRST..&quot;%20&quot;..MIDDLE..&quot;%20&quot;..LAST
       -- First M. Last
       local D2 = &quot;%22%20OR%20description%3A%22&quot;..FIRST..&quot;%20&quot;..middleinitial..&quot;%2E%20&quot;..LAST
       -- F. M. Last
       local D3 = &quot;%22%20OR%20description%3A%22&quot;..firstinitial..&quot;%2E%20&quot;..middleinitial..&quot;%2E%20&quot;..LAST
       -- Last, First Middle
       local D4 = &quot;%22%20OR%20description%3A%22&quot;..LAST..&quot;%2C%20&quot;..FIRST..&quot;%20&quot;..MIDDLE
       -- Last, First M.
       local D5 = &quot;%22%20OR%20description%3A%22&quot;..LAST..&quot;%2C%20&quot;..FIRST..&quot;%20&quot;..middleinitial..&quot;%2E&quot;
       local DALL = D1..D2..D3..D4..D5
 
       if sopt == &quot;t&quot; or sopt == &quot;tx&quot; then
         return SALL .. CALL .. TALL .. DALL .. &quot;%22&quot;
       else
         -- Last, First
         local S7 = &quot;%22%20OR%20subject%3A%22&quot;..LAST..&quot;%2C%20&quot;..FIRST
         -- First Last
         local S8 = &quot;%22%20OR%20subject%3A%22&quot;..FIRST..&quot;%20&quot;..LAST
         local SALL = SALL..S7..S8
         -- First Last
         local C9 = &quot;%22%20OR%20creator%3A%22&quot;..FIRST..&quot;%20&quot;..LAST
         -- Last, First
         local C10 = &quot;%22%20OR%20creator%3A%22&quot;..LAST..&quot;%2C%20&quot;..FIRST
         local CALL = CALL..C9..C10
         -- First Last
         local T4 = &quot;%22%20OR%20title%3A%22&quot;..FIRST..&quot;%20&quot;..LAST
         local TALL = TALL..T4
         -- First Last
         local D6 = &quot;%22%20OR%20description%3A%22&quot;..FIRST..&quot;%20&quot;..LAST
         -- Last, First
         local D7 = &quot;%22%20OR%20description%3A%22&quot;..LAST..&quot;%2C%20&quot;..FIRST
         local DALL = DALL..D6..D7
 
         return SALL .. CALL .. TALL .. DALL .. &quot;%22&quot;
       end
 end
 
 function p.fourWords(N, sopt)
 
       local FIRST  = p.urlX(N[1])
       local SECOND = p.urlX(N[2])
       local THIRD  = p.urlX(N[3])
       local LAST   = p.urlX(N[4])
 
       local firstinitial  = p.firstLetter(N[1])
       local secondinitial  = p.firstLetter(N[2])
       local thirdinitial = p.firstLetter(N[3])
 
       if sopt == &quot;t&quot; or sopt == &quot;tx&quot; then
         -- Last, First Second Third
         local S1 = &quot;%28subject%3A%22&quot;..LAST..&quot;%2C%20&quot;..FIRST..&quot;%20&quot;..SECOND..&quot;%20&quot;..THIRD
         -- First Second Third Last
         local S2 = &quot;%22%20OR%20subject%3A%22&quot;..FIRST..&quot;%20&quot;..SECOND..&quot;%20&quot;..THIRD..&quot;%20&quot;..LAST
         -- Last, First Second Third
         local C1 = &quot;%22%20OR%20creator%3A%22&quot;..LAST..&quot;%2C%20&quot;..FIRST..&quot;%20&quot;..SECOND..&quot;%20&quot;..THIRD
         -- First Second Third Last
         local C2 = &quot;%22%20OR%20creator%3A%22&quot;..FIRST..&quot;%20&quot;..SECOND..&quot;%20&quot;..THIRD..&quot;%20&quot;..LAST
         -- First Second Third Last
         local T1 = &quot;%22%20OR%20title%3A%22&quot;..FIRST..&quot;%20&quot;..SECOND..&quot;%20&quot;..THIRD..&quot;%20&quot;..LAST
         -- First Second Third Last
         local D1 = &quot;%22%20OR%20description%3A%22&quot;..FIRST..&quot;%20&quot;..SECOND..&quot;%20&quot;..THIRD..&quot;%20&quot;..LAST
 
         return S1..S2..C1..C2..T1..D1..&quot;%22&quot;
       end
 
       -- Last, First Second Third
       local S1 = &quot;%28subject%3A%22&quot;..LAST..&quot;%2C%20&quot;..FIRST..&quot;%20&quot;..SECOND..&quot;%20&quot;..THIRD
       -- First Second Third Last
       local S2 = &quot;%22%20OR%20subject%3A%22&quot;..FIRST..&quot;%20&quot;..SECOND..&quot;%20&quot;..THIRD..&quot;%20&quot;..LAST
       -- Last, First Second Third
       local C1 = &quot;%22%20OR%20creator%3A%22&quot;..LAST..&quot;%2C%20&quot;..FIRST..&quot;%20&quot;..SECOND..&quot;%20&quot;..THIRD
       -- First Second Third Last
       local C2 = &quot;%22%20OR%20creator%3A%22&quot;..FIRST..&quot;%20&quot;..SECOND..&quot;%20&quot;..THIRD..&quot;%20&quot;..LAST
       -- Last, F. S. T.
       local C3 = &quot;%22%20OR%20creator%3A%22&quot;..LAST..&quot;%2C%20&quot;..firstinitial..&quot;%2E%20&quot;..secondinitial..&quot;%2E%20&quot;..thirdinitial..&quot;%2E&quot;
       -- First Second Third Last
       local T1 = &quot;%22%20OR%20title%3A%22&quot;..FIRST..&quot;%20&quot;..SECOND..&quot;%20&quot;..THIRD..&quot;%20&quot;..LAST
       -- First Second Third Last
       local D1 = &quot;%22%20OR%20description%3A%22&quot;..FIRST..&quot;%20&quot;..SECOND..&quot;%20&quot;..THIRD..&quot;%20&quot;..LAST
 
       return S1..S2..C1..C2..C3..T1..D1..&quot;%22&quot;
 
 end
 
 -- ElasticSearch speed/resource problems if first letter of first word is &quot;*&quot; wildcard ie. accented letter
 --  Build special search in these cases.
 --  https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html#_wildcards
 function p.wildfix(N, count)
 
   --- Split along &quot;-&quot; and use only first word ie. John-Taylor-Smith becomes John
   local NF = mw.text.split(N[1], &quot;-&quot;)
   local NL = mw.text.split(N[count], &quot;-&quot;)
 
   -- ..but use full name for 1-word names
   if count == 1 then
     NF[1] = N[1]
     NL[1] = N[1]
   end
   
   -- ((Fïrst OR First) AND (Lást OR Last))
   return &quot;%28%28%22&quot; .. NF[1] .. &quot;%22%20OR%20&quot; .. p.ia_deaccent(NF[1]) .. &quot;%29%20AND%20%28%22&quot; .. NL[1] .. &quot;%22%20OR%20&quot; .. p.ia_deaccent(NL[1]) .. &quot;%29&quot;
 
 end
 
 -- Return 1 if the first letter of first word, or any single-letter word, is extended ascii
 function p.wildcheck(N, count)      
   local i = 0
 
   -- first letter of first word is extended ascii
   if N[1]:byte(1) &lt; 32 or N[1]:byte(1) &gt; 126 then return 1 end
 
   -- any single-letter word that is composed of only extended ascii
   while i &lt; count do
     i = i + 1
     if N[i]:len() == 1 then
       if N[i]:byte(1) &lt; 32 or N[i]:byte(1) &gt; 126 then return 1 end
     end
   end
   return 0
 end
 
 function trimArg(arg)
   if arg == &quot;&quot; or arg == nil then
     return nil
   else
     return mw.text.trim(arg)
   end
 end
 
 function p.mediaTypes(argsmedia)
 
   -- Added a default mediatype Dec 2015 due to too many false positives in the software mediatype, caused by birth-death dates catching numbers in source codes
   local media = &quot;-mediatype:software&quot;
 
   if argsmedia ~=&quot;&quot; and argsmedia ~=nil then
     local medialist = mw.text.split(mw.text.trim(argsmedia), &quot; &quot;)
     local al, acount = mw.ustring.gsub(mw.text.trim(argsmedia), &quot;%S+&quot;, &quot;&quot;)
     local i = 0
     repeat -- the following could be condensed but repetitive for clarity 
       i = i + 1
       if(mw.ustring.lower(medialist[i]) == &quot;text&quot; or mw.ustring.lower(medialist[i]) == &quot;texts&quot;) then
         media = media .. p.ia_url_encode(&quot; OR mediatype:texts&quot;)         
       end
       if(mw.ustring.lower(medialist[i]) == &quot;audio&quot;) then
         media = media .. p.ia_url_encode(&quot; OR mediatype:audio&quot;)
       end
       if(mw.ustring.lower(medialist[i]) == &quot;video&quot;) then
         media = media .. p.ia_url_encode(&quot; OR mediatype:video&quot;)
       end
     until i == acount
   end
 
   media = &quot;%29%20AND%20%28&quot; .. media .. &quot;%29&quot;
 
   return media
 
 end
 
 -- Alt way to get b/d dates via getContent()
 function p.bdDateAlt(argsbirth, argsdeath, name)
 
     local pagetext = nil
     local birth = &quot;none&quot;
     local death = &quot;none&quot;
 
     -- Load the page
     local t = mw.title.new(name)
     if(t.exists) then
       pagetext = t:getContent()
     end
     if pagetext == nil then 
       return &quot;Error&quot;     
     end
  
     -- Remove false positives
     pagetext = mw.ustring.gsub( mw.ustring.gsub(pagetext, &quot;&lt;!--.---&gt;&quot;, &quot;&quot;), &quot;&lt;nowiki&gt;.-&lt;/nowiki&gt;&quot;, &quot;&quot;)
  
     -- &quot;Category:1900 births&quot; 
     if argsbirth == &quot;&quot; or argsbirth == nil then
       local birthcheck = mw.ustring.match(pagetext, &quot;%[%[%s-[Cc]ategory:%s-%d+%.?%d*%s-births%s-%]%]&quot; )
       if birthcheck ~= nil then
         birth = mw.ustring.match(birthcheck, &quot;%d+%.?%d*&quot;)
       else
         birth = &quot;none&quot;
       end
     else
       birth = mw.text.trim(argsbirth)
     end
 
     -- &quot;Category:2000 deaths&quot; 
     if argsdeath == &quot;&quot; or argsdeath == nil then
       local deathcheck = mw.ustring.match(pagetext, &quot;%[%[%s-[Cc]ategory:%s-%d+%.?%d*%s-deaths%s-%]%]&quot; )
       if deathcheck ~= nil then
         death = mw.ustring.match(deathcheck, &quot;%d+%.?%d*&quot;)
       else
         death = &quot;none&quot;
       end
     else
       death = mw.text.trim(argsdeath)
     end
 
     return birth .. &quot; &quot; .. death
 
 end
 
 -- Get b/d dates via Wikidata.
 -- ‎ 
 function p.bdDate(argsbirth, argsdeath, name)
 
   local pagetext = nil
   local birth = &quot;none&quot;
   local death = &quot;none&quot;
 
   
   entity = mw.wikibase.getEntityObject()
   if not entity or not entity.claims then 
     -- Alternative if template not on a page in mainspace. This is needed since Wikidata can only be retrieved
     -- for the article where the template is located.
     return p.bdDateAlt(argsbirth, argsdeath, name)
   end
 
   -- Note: The below uses formatPropertyValues() to get and format the date from Wikidata.
   --       For an alternative method, see sandbox revision dated 5:58 am, 15 October 2014
   if argsbirth == &quot;&quot; or argsbirth == nil then
     local birthtable = entity:formatPropertyValues( 'P569' )
     local birthsplit = mw.text.split(birthtable[&quot;value&quot;], &quot; &quot;)
     local l, count = mw.ustring.gsub(birthtable[&quot;value&quot;], &quot;%S+&quot;, &quot;&quot;)
     if count &gt; 0 then
       if string.find(birthsplit[count], &quot;^%d&quot;) then
         birth = birthsplit[count]
       elseif string.find(birthsplit[count], &quot;BCE&quot;) then
         birth = birthsplit[count - 1]
       elseif string.find(birthsplit[count], &quot;BC&quot;) then
         birth = birthsplit[count - 1]
       elseif string.find(birthsplit[count], &quot;AD&quot;) then
         birth = birthsplit[count - 1]
       end
     end
   else
     birth = mw.text.trim(argsbirth)
   end
 
   if argsdeath == &quot;&quot; or argsdeath == nil then
     local deathtable = entity:formatPropertyValues( 'P570' )
     local deathsplit = mw.text.split(deathtable[&quot;value&quot;], &quot; &quot;)
     local l, count = mw.ustring.gsub(deathtable[&quot;value&quot;], &quot;%S+&quot;, &quot;&quot;)
     if count &gt; 0 then
       if string.find(deathsplit[count], &quot;^%d&quot;) then
         death = deathsplit[count]
       elseif string.find(deathsplit[count], &quot;BCE&quot;) then
         death = deathsplit[count - 1]
       elseif string.find(deathsplit[count], &quot;BC&quot;) then
         death = deathsplit[count - 1]
       elseif string.find(deathsplit[count], &quot;AD&quot;) then
         death = deathsplit[count - 1]
       end
     end
   else
     death = mw.text.trim(argsdeath)
   end
 
   if birth == &quot;none&quot; and death == &quot;none&quot; then 
     -- Alternative if Wikidata is missing data
     -- return p.bdDateAlt(name)
     return birth .. &quot; &quot; .. death
   else
     return birth .. &quot; &quot; .. death
   end
 
 end
 
 --- URL-encode special characters
 --- Note: this function was added later to deal with &quot;&amp;&quot; characters instead of using p.ia_url_encode since 
 ---       that may break existing instances of the template.
 function p.urlX(str)
   if (str) then
     str = mw.ustring.gsub (str, &quot;&amp;&quot;, &quot;%%26&quot;)
   end
   return str
 end
 
 --- URL-encode a string
 --- http://lua-users.org/wiki/StringRecipes
 ---
 function p.ia_url_encode(str)
   if (str) then
     str = mw.ustring.gsub (str, &quot;\n&quot;, &quot;\r\n&quot;)
     str = mw.ustring.gsub (str, &quot;([^%w %-%_%.%~])&quot;,
         function (c) return mw.ustring.format (&quot;%%%02X&quot;, string.byte(c)) end)
     str = mw.ustring.gsub (str, &quot; &quot;, &quot;+&quot;)
   end
   return str	
 end
 
 -- Does str contain extended ascii? 1 = yes
 function p.ia_extendedascii(str)
     for i = 1, str:len() do
       if (str:byte(i) &gt;= 32 and str:byte(i) &lt;= 126) and str:byte(i) ~= 39 then -- 39 = &quot;'&quot; 
         --do nothing
       else
         return 1
       end
     end
     return 0
 end
 
 -- UTF-8 aware replacement for string.sub() which doesn't support UTF-8.
 -- Note: Using instead of mw.ustring.sub() which I suspect(?) might be cause of intermittent error, and faster here for first-letter job.
 -- Source: prapin @ Stack Overflow http://stackoverflow.com/questions/13235091/extract-the-first-letter-of-a-utf-8-string-with-lua
 function p.firstLetter(str)
   return str:match(&quot;[%z\1-\127\194-\244][\128-\191]*&quot;)
 end
 
 
 -- Replace all extended ascii characters with wildcard '*'
 -- Replace &quot;-&quot; with &lt;space&gt; eg. Pierre-Jean -&gt; Pierre Jean
 function p.ia_extendedascii2wildcard(str)
     local s = &quot;&quot;
     local j = 0
     local k = 0    
     for i = 1, str:len() do
       k = str:byte(i)
       if k &gt;= 32 and k &lt;= 126 then
 -- For list of Lucene special characters needing to be escaped: 
 -- http://lucene.apache.org/core/4_10_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#Escaping_Special_Characters
 -- We only worry about - (45) and &quot; (34) since the others are unlikely to appear in a proper name.
 -- Also ' (39) since it is sometimes the extended character ’
         if k == 34 or k == 39 then 
           s = s .. &quot;*&quot; 
         elseif k == 45 then
           s = s .. &quot; &quot;
         else
           s = s .. str:sub(i,i)
         end
       else
         if j == 1 then
           s = s .. &quot;*&quot;
           j = 2
         end
         if j == 0 then j = 1 end
         if j == 2 then j = 0 end
       end
     end
     return s
 end
 
 -- Replace accented letters with non-accented equivalent letters
 -- Note: this is not a complete list of all possible accented letters. It is 
 --       all of the accented letters found in the first 10,000 names using 
 --       the Internet Archive author template.
 function p.ia_deaccent(str)
     local s = str
 
     s = mw.ustring.gsub(s, &quot;á&quot;, &quot;a&quot;)
     s = mw.ustring.gsub(s, &quot;a︡&quot;, &quot;a&quot;)
     s = mw.ustring.gsub(s, &quot;Á&quot;, &quot;A&quot;)
     s = mw.ustring.gsub(s, &quot;ă&quot;, &quot;a&quot;)
     s = mw.ustring.gsub(s, &quot;â&quot;, &quot;a&quot;)
     s = mw.ustring.gsub(s, &quot;æ&quot;, &quot;ae&quot;)
     s = mw.ustring.gsub(s, &quot;Æ&quot;, &quot;AE&quot;)
     s = mw.ustring.gsub(s, &quot;à&quot;, &quot;a&quot;)
     s = mw.ustring.gsub(s, &quot;ā&quot;, &quot;a&quot;)
     s = mw.ustring.gsub(s, &quot;Ā&quot;, &quot;A&quot;)
     s = mw.ustring.gsub(s, &quot;ą&quot;, &quot;a&quot;)
     s = mw.ustring.gsub(s, &quot;å&quot;, &quot;a&quot;)
     s = mw.ustring.gsub(s, &quot;Å&quot;, &quot;A&quot;)
     s = mw.ustring.gsub(s, &quot;ã&quot;, &quot;a&quot;)
     s = mw.ustring.gsub(s, &quot;ä&quot;, &quot;a&quot;)
     s = mw.ustring.gsub(s, &quot;Ä&quot;, &quot;A&quot;)
     s = mw.ustring.gsub(s, &quot;β&quot;, &quot;B&quot;)
     s = mw.ustring.gsub(s, &quot;ć&quot;, &quot;c&quot;)
     s = mw.ustring.gsub(s, &quot;č&quot;, &quot;c&quot;)
     s = mw.ustring.gsub(s, &quot;Č&quot;, &quot;C&quot;)
     s = mw.ustring.gsub(s, &quot;ç&quot;, &quot;c&quot;)
     s = mw.ustring.gsub(s, &quot;Ç&quot;, &quot;C&quot;)
     s = mw.ustring.gsub(s, &quot;ĉ&quot;, &quot;c&quot;)
     s = mw.ustring.gsub(s, &quot;ď&quot;, &quot;d&quot;)
     s = mw.ustring.gsub(s, &quot;đ&quot;, &quot;d&quot;)
     s = mw.ustring.gsub(s, &quot;é&quot;, &quot;e&quot;)
     s = mw.ustring.gsub(s, &quot;É&quot;, &quot;E&quot;)
     s = mw.ustring.gsub(s, &quot;ě&quot;, &quot;e&quot;)
     s = mw.ustring.gsub(s, &quot;ê&quot;, &quot;e&quot;)
     s = mw.ustring.gsub(s, &quot;è&quot;, &quot;e&quot;)
     s = mw.ustring.gsub(s, &quot;È&quot;, &quot;E&quot;)
     s = mw.ustring.gsub(s, &quot;ε&quot;, &quot;e&quot;)
     s = mw.ustring.gsub(s, &quot;ē&quot;, &quot;e&quot;)
     s = mw.ustring.gsub(s, &quot;Ē&quot;, &quot;E&quot;)
     s = mw.ustring.gsub(s, &quot;ę&quot;, &quot;e&quot;)
     s = mw.ustring.gsub(s, &quot;ð&quot;, &quot;e&quot;)
     s = mw.ustring.gsub(s, &quot;ë&quot;, &quot;e&quot;)
     s = mw.ustring.gsub(s, &quot;Ë&quot;, &quot;E&quot;)
     s = mw.ustring.gsub(s, &quot;γ&quot;, &quot;Y&quot;)
     s = mw.ustring.gsub(s, &quot;ħ&quot;, &quot;h&quot;)
     s = mw.ustring.gsub(s, &quot;i︠a︡&quot;, &quot;ia&quot;)
     s = mw.ustring.gsub(s, &quot;í&quot;, &quot;i&quot;)
     s = mw.ustring.gsub(s, &quot;i︠&quot;, &quot;i&quot;)
     s = mw.ustring.gsub(s, &quot;ĭ&quot;, &quot;i&quot;)
     s = mw.ustring.gsub(s, &quot;Í&quot;, &quot;I&quot;)
     s = mw.ustring.gsub(s, &quot;î&quot;, &quot;i&quot;)
     s = mw.ustring.gsub(s, &quot;Î&quot;, &quot;I&quot;)
     s = mw.ustring.gsub(s, &quot;ì&quot;, &quot;i&quot;)
     s = mw.ustring.gsub(s, &quot;ī&quot;, &quot;i&quot;)
     s = mw.ustring.gsub(s, &quot;ł&quot;, &quot;i&quot;)
     s = mw.ustring.gsub(s, &quot;ï&quot;, &quot;i&quot;)
     s = mw.ustring.gsub(s, &quot;Ï&quot;, &quot;I&quot;)
     s = mw.ustring.gsub(s, &quot;ĺ&quot;, &quot;I&quot;)
     s = mw.ustring.gsub(s, &quot;Ĺ&quot;, &quot;L&quot;)
     s = mw.ustring.gsub(s, &quot;μ&quot;, &quot;u&quot;)
     s = mw.ustring.gsub(s, &quot;µ&quot;, &quot;u&quot;)
     s = mw.ustring.gsub(s, &quot;ń&quot;, &quot;n&quot;)
     s = mw.ustring.gsub(s, &quot;ň&quot;, &quot;n&quot;)
     s = mw.ustring.gsub(s, &quot;ņ&quot;, &quot;n&quot;)
     s = mw.ustring.gsub(s, &quot;ñ&quot;, &quot;n&quot;)
     s = mw.ustring.gsub(s, &quot;Ñ&quot;, &quot;N&quot;)
     s = mw.ustring.gsub(s, &quot;ó&quot;, &quot;o&quot;)
     s = mw.ustring.gsub(s, &quot;Ó&quot;, &quot;O&quot;)
     s = mw.ustring.gsub(s, &quot;ô&quot;, &quot;o&quot;)
     s = mw.ustring.gsub(s, &quot;œ&quot;, &quot;oe&quot;)
     s = mw.ustring.gsub(s, &quot;ò&quot;, &quot;o&quot;)
     s = mw.ustring.gsub(s, &quot;ō&quot;, &quot;o&quot;)
     s = mw.ustring.gsub(s, &quot;ø&quot;, &quot;o&quot;)
     s = mw.ustring.gsub(s, &quot;Ø&quot;, &quot;o&quot;)
     s = mw.ustring.gsub(s, &quot;õ&quot;, &quot;o&quot;)
     s = mw.ustring.gsub(s, &quot;ö&quot;, &quot;o&quot;)
     s = mw.ustring.gsub(s, &quot;ő&quot;, &quot;o&quot;)
     s = mw.ustring.gsub(s, &quot;Ö&quot;, &quot;O&quot;)
     s = mw.ustring.gsub(s, &quot;φ&quot;, &quot;o&quot;)
     s = mw.ustring.gsub(s, &quot;ŕ&quot;, &quot;r&quot;)
     s = mw.ustring.gsub(s, &quot;ř&quot;, &quot;r&quot;)
     s = mw.ustring.gsub(s, &quot;Ř&quot;, &quot;R&quot;)
     s = mw.ustring.gsub(s, &quot;ß&quot;, &quot;ss&quot;)
     s = mw.ustring.gsub(s, &quot;ś&quot;, &quot;s&quot;)
     s = mw.ustring.gsub(s, &quot;Ś&quot;, &quot;S&quot;)
     s = mw.ustring.gsub(s, &quot;š&quot;, &quot;s&quot;)
     s = mw.ustring.gsub(s, &quot;ṣ&quot;, &quot;s&quot;)
     s = mw.ustring.gsub(s, &quot;Š&quot;, &quot;S&quot;)
     s = mw.ustring.gsub(s, &quot;ş&quot;, &quot;s&quot;)
     s = mw.ustring.gsub(s, &quot;Ş&quot;, &quot;S&quot;)
     s = mw.ustring.gsub(s, &quot;ŝ&quot;, &quot;s&quot;)
     s = mw.ustring.gsub(s, &quot;σ&quot;, &quot;s&quot;)
     s = mw.ustring.gsub(s, &quot;ť&quot;, &quot;t&quot;)
     s = mw.ustring.gsub(s, &quot;ţ&quot;, &quot;t&quot;)
     s = mw.ustring.gsub(s, &quot;τ&quot;, &quot;t&quot;)
     s = mw.ustring.gsub(s, &quot;þ&quot;, &quot;p&quot;)
     s = mw.ustring.gsub(s, &quot;Þ&quot;, &quot;p&quot;)
     s = mw.ustring.gsub(s, &quot;ú&quot;, &quot;u&quot;)
     s = mw.ustring.gsub(s, &quot;Ú&quot;, &quot;U&quot;)
     s = mw.ustring.gsub(s, &quot;û&quot;, &quot;u&quot;)
     s = mw.ustring.gsub(s, &quot;ù&quot;, &quot;u&quot;)
     s = mw.ustring.gsub(s, &quot;ū&quot;, &quot;u&quot;)
     s = mw.ustring.gsub(s, &quot;ů&quot;, &quot;u&quot;)
     s = mw.ustring.gsub(s, &quot;ü&quot;, &quot;u&quot;)
     s = mw.ustring.gsub(s, &quot;Ü&quot;, &quot;U&quot;)
     s = mw.ustring.gsub(s, &quot;ŵ&quot;, &quot;w&quot;)
     s = mw.ustring.gsub(s, &quot;ý&quot;, &quot;y&quot;)
     s = mw.ustring.gsub(s, &quot;ŷ&quot;, &quot;y&quot;)
     s = mw.ustring.gsub(s, &quot;¥&quot;, &quot;y&quot;)
     s = mw.ustring.gsub(s, &quot;ÿ&quot;, &quot;y&quot;)
     s = mw.ustring.gsub(s, &quot;Ÿ&quot;, &quot;Y&quot;)
     s = mw.ustring.gsub(s, &quot;ź&quot;, &quot;z&quot;)
     s = mw.ustring.gsub(s, &quot;Ž&quot;, &quot;Z&quot;)
     s = mw.ustring.gsub(s, &quot;ž&quot;, &quot;z&quot;)
     s = mw.ustring.gsub(s, &quot;ż&quot;, &quot;z&quot;)
     s = mw.ustring.gsub(s, &quot;Ż&quot;, &quot;Z&quot;)
 
     return s
 
 end