Module:Navseasoncats/மணல்தொட்டி


About

{{Navseasoncats}} is intended to be a minimal-input, near-universal template for navigating most sequential categories.

Recognized category types
TypeExample categoryBC(E)?Example output
Decade2010கள்கிமு
  • 16-ஆம்
  • 17-ஆம்
  • 18-ஆம்
  • 19-ஆம்
  • 20-ஆம்
  • 21-ஆம்
  • 22-ஆம்
  • 23-ஆம்
  • 24-ஆம்
  • 25-ஆம்
  • 26-ஆம்
Ordinal (Decade)1970கள் படைப்புகள்கிமு
  • 15-ஆம்
  • 16-ஆம்
  • 17-ஆம்
  • 18-ஆம்
  • 19-ஆம்
  • 20-ஆம்
  • 21-ஆம்
  • 22-ஆம்
  • 23-ஆம்
  • 24-ஆம்
  • 25-ஆம்
Decade1530களில் இந்தியாகிமு
Year (|skip-gaps=yes)1880
Ordinal (Year)2019 இல் இந்தியாகிமு
Ordinal (நூற்றாண்டு)பதினான்காம் நூற்றாண்டுகிமு
Ordinal (temporal)12-ஆம் நூற்றாண்டு நபர்கள்கிமு
  • 7-ஆம்
  • 8-ஆம்
  • 9-ஆம்
  • 10-ஆம்
  • 11-ஆம்
  • 12-ஆம்
  • 13-ஆம்
  • 14-ஆம்
  • 15-ஆம்
  • 16-ஆம்
  • 17-ஆம்
Ordinal (temporal)16 ஆம் நூற்றாண்டு நபர்கள்கிமு
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
Ordinal (numeric)9வது மக்களவை உறுப்பினர்கள்Error! Function find_var can't find the variable text in category "9வது மக்களவை உறுப்பினர்கள்".***Navseasoncats failed to generate navbox***

Searching behavior

Most multi-year seasons/office terms/numerical ranges are acceptable, as long as the season duration/term length/range size is <= 10, and the gap between seasons is <= 6. For series exceeding either of these criteria, see/use {{Irregular navseasoncats}}.

The length of each season is automatically determined from the originating category name, up to and including 10 years. MOS:DATERANGE compliance is preferred, but some deviation is allowed and tracked for regular series with seasons > 1 year long. {{Category redirect}}s are followed, and tracked for either MOS contravention (to be corrected) or for navigational aid (no error). The gap size between successive seasons is also automatically determined, up to and including 5 years, and defaults to 0 (e.g. 1995–961996–97).

Automatically condensed years are supported for presidential categories only (but can be easily expanded as needed), for gaps up to and including 5 years, and defaults to 1. To skip gaps of up to 25 years in any year categories, use |skip-gaps=yes.

Limitations

Numerical limitations & AD/BC/E
  • Season/office term categories do not work for any years BC, which will be hidden, because no working examples were found.
  • Decade categories recognize BC, but not BCE, because no working examples were found.
  • Ordinal & numeral words do not work above the ninety-ninth & ninety-nine, because no working examples were found.
Condensation
  • Automatically condensed Olympics display is not supported due to peculiarities; use {{Winter Olympics by year category navigation}}, etc., instead.
  • Automatically condensed years are supported for presidential categories only, due to their consistency; use |skip-gaps=yes as desired elsewhere.
Work-arounds
  • Base-name changes: create at least 2 logically numbered {{R from category navigation}} (1 forward & 1 backward), to join both related series.
  • Unaccounted-for name+number conventions: where a fixed number is part of the prefix text, e.g. Chapter 11 bankruptcies, a non-breaking space may force the template to work. See this fix, where {{title year}} skipped over 11 as part of a word rather than a discrete number. (This has been accounted for and is no longer required in this example.)
  • General: for large, permanent gaps between successive categories, use {{Succeeding category}}, {{Preceding category}}, {{Category pair}}, as needed, in addition to {{Navseasoncats}} on both sides, or in the middle, of the gap. Even if {{Navseasoncats}} is isolated, it has the benefit of confirming the absence of nearby categories to the reader or maintainer.
    Permanent gaps, where there is confirmed to be an absence of data, and not just a current, yet to be filled, gap on Wikipedia.
  • Wikipedia:Categories for discussion/Log/2019 June 8#Category:Northern Ireland MLAs 2016–17
  • Wikipedia:Categories for discussion/Log/2019 May 29#Category:MEPs 1952–58
  • Wikipedia:Categories for discussion/Log/2019 April 19#Category:Aircraft piston engines 1900–1909

Usage

Typical usage
Specify a minimum and/or maximum year to display
To skip gaps in year categories
To not automatically follow {{Category redirect}}s
Exceptional cases

Testing & debugging

To test the output of the template on a particular category name, use the |testcase= parameter, and |testcasegap= if necessary:

  • {{Navseasoncats |testcase=1770s in the Province of Quebec (1763–1791) |min=1760}}

Lua error in Module:Navseasoncats at line 2065: attempt to perform arithmetic on local 'decade' (a nil value).

  • {{Navseasoncats |testcase=1770s in the Province of Quebec (1763–1791) |max=1970s}}

Lua error in Module:Navseasoncats at line 2065: attempt to perform arithmetic on local 'decade' (a nil value).
To see all links produced and/or tested, and what effect each has on their display, use |list-all-links=yes:

  • {{Navseasoncats |testcase=Nations at the 2013 World Athletics Championships |min=2008 |skip-gaps=yes |list-all-links=yes}}
  1. Category:Nations at the 2006 World Athletics Championships (2006) (2006)
  2. Category:Nations at the 2007 World Athletics Championships (2007) (2007)
  3. Category:Nations at the 2008 World Athletics Championships (2008)
  4. Category:Nations at the 2008–2009 World Athletics Championships (2008–2009) (tried; not displayed)
  5. Category:Nations at the 2008–09 World Athletics Championships (2008–09) (tried; not displayed)
  6. Category:Nations at the 2009 World Athletics Championships → Category:Nations at the 2009 World Championships in Athletics (2009)
  7. Category:Nations at the 2011 World Athletics Championships → Category:Nations at the 2011 World Championships in Athletics (2011)
  8. Category:Nations at the 2015 World Athletics Championships → Category:Nations at the 2015 World Championships in Athletics (2015)
  9. Category:Nations at the 2017 World Athletics Championships → Category:Nations at the 2017 World Championships in Athletics (2017)
  10. Category:Nations at the 2019 World Athletics Championships (2019)
  11. Category:Nations at the 2020 World Athletics Championships (2020)
  12. Category:Nations at the 2020–2021 World Athletics Championships (2020–2021) (tried; not displayed)
  13. Category:Nations at the 2020–21 World Athletics Championships (2020–21) (tried; not displayed)
  14. Category:Nations at the 2021 World Athletics Championships (2021)
  15. Category:Nations at the 2021–2022 World Athletics Championships (2021–2022) (tried; not displayed)
  16. Category:Nations at the 2021–22 World Athletics Championships (2021–22) (tried; not displayed)
  • All possible element types are shown above (blue, red/grey, hidden, and redirect), and would otherwise display as:
  • 2006
  • 2007
  • 2008
  • 2009
  • 2011
  • 2013
  • 2015
  • 2017
  • 2019
  • 2020
  • 2021

Tracking categories

Purge this page to update the totals

If the template encounters an issue, it displays an error message and/or places the category into one or more of the following tracking categories:

Maintenance required

  • பகுப்பு:Navseasoncats failed to generate navbox (2)
  • பகுப்பு:Navseasoncats redirection error (0)
  • பகுப்பு:Navseasoncats range abbreviated (MOS) (0)
  • பகுப்பு:Navseasoncats range redirected (MOS) (0)
  • பகுப்பு:Navseasoncats range ends (blank, MOS) (0)
  • பகுப்பு:Navseasoncats range not using en dash (0)
  • பகுப்பு:Navseasoncats in mainspace (0)

Maintenance possible

  • பகுப்பு:Navseasoncats isolated (103)
  • பகுப்பு:Navseasoncats default season gap size (0)
  • பகுப்பு:Navseasoncats using cat parameter (0)
  • பகுப்பு:Navseasoncats using testcase parameter (0)
  • பகுப்பு:Navseasoncats using unknown parameter (0)

Module maintenance possible

  • பகுப்பு:Navseasoncats year redirected (other) (0)
  • பகுப்பு:Navseasoncats range redirected (other) (0)

Tracking only

  • பகுப்பு:Navseasoncats range redirected (base change) (0)
  • பகுப்பு:Navseasoncats range redirected (var change) (0)
  • பகுப்பு:Navseasoncats range redirected (end) (0)
  • பகுப்பு:Navseasoncats range gaps (0)
  • பகுப்பு:Navseasoncats range irregular (0)
  • பகுப்பு:Navseasoncats range irregular, 0-length (0)
  • பகுப்பு:Navseasoncats range ends (present) (0)
  • பகுப்பு:Navseasoncats TV season redirected (0)
  • பகுப்பு:Navseasoncats decade redirected (0)
  • பகுப்பு:Navseasoncats year redirected (base change) (0)
  • பகுப்பு:Navseasoncats year redirected (var change) (0)
  • பகுப்பு:Navseasoncats roman numeral redirected (0)
  • பகுப்பு:Navseasoncats nordinal redirected (0)
  • பகுப்பு:Navseasoncats wordinal redirected (0)
  • பகுப்பு:Navseasoncats using skip-gaps parameter (540)
  • பகுப்பு:Navseasoncats year and range (0)
  • பகுப்பு:Navseasoncats year and decade (795)
  • பகுப்பு:Navseasoncats decade and century (13)

See also



local p = {}--[[==========================================================================]]--[[                                Globals                                   ]]--[[==========================================================================]]local currtitle = mw.title.getCurrentTitle()local nexistingcats = 0local errors = ''local testcasecolon = ''local testcases = string.match(currtitle.subpageText, '^testcases')if    testcases then testcasecolon = ':' endlocal navborder = truelocal followRs = truelocal skipgaps = falselocal listall = falselocal tlistall = {}local tlistallbwd = {}local tlistallfwd = {}local ttrackingcats = { --when reindexing, Ctrl+H 'trackcat(13,' & 'ttrackingcats[16]''', -- [1] placeholder for [[Category:Navseasoncats using cat parameter]]'', -- [2] placeholder for [[Category:Navseasoncats using testcase parameter]]'', -- [3] placeholder for [[Category:Navseasoncats using unknown parameter]]'', -- [4] placeholder for [[Category:Navseasoncats range not using en dash]]'', -- [5] placeholder for [[Category:Navseasoncats range abbreviated (MOS)]]'', -- [6] placeholder for [[Category:Navseasoncats range redirected (base change)]]'', -- [7] placeholder for [[Category:Navseasoncats range redirected (var change)]] --new'', -- [8] placeholder for [[Category:Navseasoncats range redirected (end)]]'', -- [9] placeholder for [[Category:Navseasoncats range redirected (MOS)]]'', --[10] placeholder for [[Category:Navseasoncats range redirected (other)]]'', --[11] placeholder for [[Category:Navseasoncats range gaps]]'', --[12] placeholder for [[Category:Navseasoncats range irregular]]'', --[13] placeholder for [[Category:Navseasoncats range irregular, 0-length]]'', --[14] placeholder for [[Category:Navseasoncats range ends (present)]]'', --[15] placeholder for [[Category:Navseasoncats range ends (blank, MOS)]]'', --[16] placeholder for [[Category:Navseasoncats isolated]]'', --[17] placeholder for [[Category:Navseasoncats default season gap size]]'', --[18] placeholder for [[Category:Navseasoncats decade redirected]]'', --[19] placeholder for [[Category:Navseasoncats year redirected (base change)]]'', --[20] placeholder for [[Category:Navseasoncats year redirected (var change)]]'', --[21] placeholder for [[Category:Navseasoncats year redirected (other)]]'', --[22] placeholder for [[Category:Navseasoncats roman numeral redirected]]'', --[23] placeholder for [[Category:Navseasoncats nordinal redirected]]'', --[24] placeholder for [[Category:Navseasoncats wordinal redirected]]'', --[25] placeholder for [[Category:Navseasoncats TV season redirected]]'', --[26] placeholder for [[Category:Navseasoncats using skip-gaps parameter]]'', --[27] placeholder for [[Category:Navseasoncats year and range]]'', --[28] placeholder for [[Category:Navseasoncats year and decade]]'', --[29] placeholder for [[Category:Navseasoncats decade and century]]'', --[30] placeholder for [[Category:Navseasoncats in mainspace]]'', --[31] placeholder for [[Category:Navseasoncats redirection error]]}local avoidself =  (not string.match(currtitle.text, 'Navseasoncats with') andnot string.match(currtitle.text, 'Navseasoncats.*/doc') andnot string.match(currtitle.text, 'Navseasoncats.*/sandbox') andcurrtitle.text ~= 'Navseasoncats' andcurrtitle.nsText ~= 'User_talk' andcurrtitle.nsText ~= 'Template_talk' and(currtitle.nsText ~= 'Template' or testcases)) --avoid nested transclusion errors (i.e. {{Infilmdecade}})--[[==========================================================================]]--[[                      Utility & category functions                        ]]--[[==========================================================================]]--Determine if a category exists (in a function for easier localization).local function catexists( title )return mw.title.new( title, 'Category' ).existsend--Error message handling.function p.errorclass( msg )return mw.text.tag( 'span', {class='error mw-ext-cite-error'}, '<b>Error!</b> '..string.gsub(msg, '&#', '&amp;#') )end--Failure handling.function p.failedcat( errors, sortkey )if avoidself thenreturn (errors or '')..'&#42;&#42;&#42;Navseasoncats failed to generate navbox***'..   '[['..testcasecolon..'Category:Navseasoncats failed to generate navbox|'..(sortkey or 'O')..']]\n'endreturn ''end--Tracking cat handling.--key: 15 (when reindexing ttrackingcats{}, Ctrl+H 'trackcat(13,' & 'ttrackingcats[16]')--cat: 'Navseasoncats isolated'; '' to remove--Used by main, all nav_*(), & several utility functions.local function trackcat( key, cat )if avoidself and key and cat thenif cat ~= '' thenttrackingcats[key] = '[['..testcasecolon..'Category:'..cat..']]'elsettrackingcats[key] = ''endendreturnend--Check for unknown parameters.--Used by main only.local function checkforunknownparams( tbl )local knownparams = {['min'] = 'min',['max'] = 'max',['cat'] = 'cat',['testcase'] = 'testcase',['testcasegap'] = 'testcasegap',['skip-gaps'] = 'skip-gaps',['list-all-links'] = 'list-all-links',['follow-redirects'] = 'follow-redirects',}for k, _ in pairs (tbl) doif knownparams[k] == nil thentrackcat(3, 'Navseasoncats using unknown parameter')breakendendend--Check for nav_*() navigational isolation (not necessarily an error).--Used by all nav_*().local function isolatedcat()if nexistingcats == 0 thentrackcat(16, 'Navseasoncats isolated')endend--Returns the target of {{Category redirect}}, if it exists, else returns the original cat.--{{Title year}}, etc., if found, are evaluated.--Used by catlinkfollowr(), and so indirectly by all nav_*().local function rtarget( frame, cat )local catcontent = mw.title.new( cat or '', 'Category' ):getContent()if string.match( catcontent or '', '{{ *[Cc]at' ) then --prelim testlocal regex = {--the following 11 pages (6 condensed) redirect to [[Template:Category redirect]], in descending order, as of 9/2022:'{{ *[Cc]ate?g?o?r?y?[ _]*[rR]edirect',--505+312+243+1 transclusions'{{ *[Cc]atr',--21'{{ *[Cc]at[ _]*[rR]edir',--5+3'{{ *[Cc]at[ _]*[rR]ed',--3+2'{{ *[Cc]at[ _]*[mM]ove',--1'{{ *[Cc]ategory[ _]*[mM]ove',--0}for _, v in pairs (regex) dolocal rtarget = mw.ustring.match( catcontent, v..'%s*|%s*([^|}]+)' )if rtarget thenif string.match(rtarget, '{{') then --{{Title year}}, etc., exists; evaluatelocal regex_ty = '%s*|%s*([^{}]*{{([^{|}]+)}}[^{}]-)%s*}}' --eval null-param templates only; expanded if/as neededlocal rtarget_orig, ty = mw.ustring.match( catcontent, v..regex_ty )if rtarget_orig thenlocal ty_eval = frame:expandTemplate{ title = ty, args = { page = cat } } --frame:newChild doesn't work, use 'page' param insteadlocal rtarget_eval = mw.ustring.gsub(rtarget_orig, '{{%s*'..ty..'%s*}}', ty_eval )return rtarget_evalelse --sub-parameters present; track & return defaulttrackcat(31, 'Navseasoncats redirection error')endendrtarget = mw.ustring.gsub(rtarget, '^1%s*=%s*', '')rtarget = string.gsub(rtarget, '^[Cc]ategory:', '')return rtargetendend --forend --ifreturn catend--Similar to {{LinkCatIfExists2}}: make a piped link to a category, if it exists;--if it doesn't exist, just display the greyed link title without linking.--Follows {{Category redirect}}s.--Returns {--['cat'] = cat,--['catexists'] = true,--['rtarget'] = <#R target>,--['navelement'] = <#R target navelement>,--['displaytext'] = displaytext,--  } if #R followed;--returns {--['cat'] = cat,--['catexists'] = <true|false>,--['rtarget'] = nil,--['navelement'] = <cat navelement>,--['displaytext'] = displaytext,--  } otherwise.--Used by all nav_*().local function catlinkfollowr( frame, cat, displaytext, displayend )cat         = mw.text.trim(cat or '')displaytext = mw.text.trim(displaytext or '')displayend  = displayend or false --bool flag to override displaytext IIF the cat/target is terminal (e.g. "2021–present" or "2021–")local grey = '#888'local disp = catif displaytext ~= '' then --use 'displaytext' parameter if presentdisp = mw.ustring.gsub(displaytext, '%s+%(.+$', ''); --strip any trailing disambiguatorendlocal link, nilorRlocal exists = catexists(cat)if exists thennexistingcats = nexistingcats + 1if followRs thenlocal R = rtarget(frame, cat) --find & follow #Rif R ~= cat then --#R followednilorR = Rendif displayend thenlocal y, hyph, ending = mw.ustring.match(R, '^.-(%d+)([–-])(.*)$')if ending == 'present' thendisp = y..hyph..endingelseif ending == '' thendisp = y..hyph..'<span style="visibility:hidden">'..y..'</span>' --hidden y to match spacingendendlink = '[[:Category:'..R..'|'..disp..']]'elselink = '[[:Category:'..cat..'|'..disp..']]'endelselink = '<span style="color:'..grey..'">'..disp..'</span>'endif listall thenif nilorR then --#R followedtable.insert( tlistall, '[[:Category:'..cat..']] → '..'[[:Category:'..nilorR..']] ('..link..')' )else --no #Rtable.insert( tlistall, '[[:Category:'..cat..']] ('..link..')' )endendreturn {['cat'] = cat,['catexists'] = exists,['rtarget'] = nilorR,['navelement'] = link,['displaytext'] = disp,}end--Returns a numbered list of all {{Category redirect}}s followed by catlinkfollowr() -> rtarget().--For a nav_hyphen() cat, also returns a formatted list of all cats searched for & found, & all loop indices.--Used by all nav_*().local function listalllinks()local nl = '\n# 'local out = ''if currtitle.nsText == 'Category' thenerrors = p.errorclass('The <b><code>|list-all-links=yes</code></b> parameter/utility '..'should not be saved in category space, only previewed.')out = p.failedcat(errors, 'Z')endlocal bwd, fwd = '', ''if tlistallbwd[1] thenbwd = '\n\nbackward search:\n# '..table.concat(tlistallbwd, nl)endif tlistallfwd[1] thenfwd = '\n\nforward search:\n# '..table.concat(tlistallfwd, nl)endif tlistall[1] thenreturn out..nl..table.concat(tlistall, nl)..bwd..fwdelsereturn out..nl..'No links found!?'..bwd..fwdendend--Returns the difference b/w 2 ints separated by endash|hyphen, nil if error.--Used by nav_hyphen() only.local function find_duration( cat )local from, to = mw.ustring.match(cat, '(%d+)[–-](%d+)')if from and to thenif to == '00' then return nil end --doesn't follow MOS:DATERANGEif (#from == 4) and (#to == 2) then             --1900-01to = string.match(from, '(%d%d)%d%d')..to   --1900-1901elseif (#from == 2) and (#to == 4) then         --  01-1902from = string.match(to, '(%d%d)%d%d')..from --1901-1902endreturn (tonumber(to) - tonumber(from))endreturn 0end--Returns the ending of a terminal cat, and sets the appropriate tracking cat, else nil.--Used by nav_hyphen() only.local function find_terminaltxt( cat )local terminaltxt = nilif mw.ustring.match(cat, '%d+[–-]present$') thenterminaltxt = 'present'trackcat(14, 'Navseasoncats range ends (present)')elseif mw.ustring.match(cat, '%d+[–-]$') thenterminaltxt = ''trackcat(15, 'Navseasoncats range ends (blank, MOS)')endreturn terminaltxtend--Returns an unsigned string of the 1-4 digit decade ending in "0", else nil.--Used by nav_decade() only.local function sterilizedec( decade )if decade == nil or decade == '' thenreturn nilendlocal dec = string.match(decade, '^[-%+]?(%d?%d?%d?0)$') orstring.match(decade, '^[-%+]?(%d?%d?%d?0)%D')if dec thenreturn decelse--fix 2-4 digit decadelocal decade_fixed234 = string.match(decade, '^[-%+]?(%d%d?%d?)%d$') orstring.match(decade, '^[-%+]?(%d%d?%d?)%d%D')if decade_fixed234 thenreturn decade_fixed234..'0'end--fix 1-digit decadelocal decade_fixed1   = string.match(decade, '^[-%+]?(%d)$') orstring.match(decade, '^[-%+]?(%d)%D')if decade_fixed1 thenreturn '0'end--unfixablereturn nilendend--Check for nav_hyphen default gap size + isolatedcat() (not necessarily an error).--Used by nav_hyphen() only.local function defaultgapcat( bool )if bool and nexistingcats == 0 then--using "nexistingcats > 0" isn't as useful, since the default gap size obviously workedtrackcat(17, 'Navseasoncats default season gap size')endend--12 -> 12th, etc.--Used by nav_nordinal() & nav_wordinal().function p.addord( i )if tonumber(i) thenlocal s = tostring(i)local tens = string.match(s, '1%d$')if    tens then return s..'th' endlocal  ones = string.match(s, '%d$')if     ones == '1' then return s..'st'elseif ones == '2' then return s..'nd'elseif ones == '3' then return s..'rd' endreturn s..'th'endreturn iend--Returns the properly formatted central nav element.--Expects an integer i, and a catlinkfollowr() table.--Used by nav_decade() & nav_ordinal() only.local function navcenter( i, catlink )if i == 0 then --center nav elementif navborder == true thenreturn '*<b>'..catlink.displaytext..'</b>\n'elsereturn '*<b>'..catlink.navelement..'</b>\n'endelsereturn '*'..catlink.navelement..'\n'endend--Return conditionally aligned stacked navs.--Used by main only.local function nav1nav2( nav1, nav2 )if avoidself thenlocal forcealign = '<div style="display:block !important; max-width: calc(100% - 25em);">'return forcealign..'\n'..nav1..'\n'..nav2..'\n</div>'elsereturn nav1..'\n'..nav2endend--[[==========================================================================]]--[[                  Formerly separated templates/modules                    ]]--[[==========================================================================]]--[[==========================={{  nav_hyphen  }}=============================]]local function nav_hyphen( frame, start, hyph, finish, firstpart, lastpart, minseas, maxseas, testgap )--Expects a PAGENAME of the form "Some sequential 2015–16 example cat", where--start     = 2015--hyph      = –--finish    = 16 (sequential years can be abbreviated, but others should be full year, e.g. "2001–2005")--firstpart = Some sequential--lastpart  = example cat--minseas   = 1800 ('min' starting season shown; optional; defaults to -9999)--maxseas   = 2000 ('max' starting season shown; optional; defaults to 9999; 2000 will show 2000-01)--testgap   = 0 (testcasegap parameter for easier testing; optional)--sterilize startif string.match(start or '', '^%d%d?%d?%d?$') == nil then --1-4 digits, AD onlylocal start_fixed = mw.ustring.match(start or '', '^%s*(%d%d?%d?%d?)%D')if start_fixed thenstart = start_fixedelseerrors = p.errorclass('Function nav_hyphen can\'t recognize the number "'..(start or '')..'" '..  'in the first part of the "season" that was passed to it. '..  'For e.g. "2015–16", "2015" is expected via "|2015|–|16|".')return p.failedcat(errors, 'H')endendlocal nstart = tonumber(start)--en dash checkif hyph ~= '–' thentrackcat(4, 'Navseasoncats range not using en dash') --nav still processable, but trackend--sterilize finish & check for weird parentslocal tgaps   = {} --table of gap sizes found b/w terms    { [<gap size found>]    = 1 }local ttlens  = {} --table of term lengths found w/i terms { [<term length found>] = 1 }local tirregs = {} --table of ir/regular-term-length cats' "from"s & "to"s foundlocal regularparent = trueif (finish == -1) or --"Members of the Scottish Parliament 2021–present"   (finish == 0) --"Members of the Scottish Parliament 2021–"thenregularparent = falseif maxseas == nil or maxseas == '' thenmaxseas = start --hide subsequent rangesendif finish == -1 then trackcat(14, 'Navseasoncats range ends (present)')else trackcat(15, 'Navseasoncats range ends (blank, MOS)') endelseif (start == finish) and   (ttrackingcats[16] ~= '') --nav_year found isolated; check for surrounding hyphenated terms (e.g. UK MPs 1974)thentrackcat(16, '') --reset for another check latertrackcat(13, 'Navseasoncats range irregular, 0-length')ttlens[0] = 1 --calc ttlens for std cases belowregularparent = 'isolated'endif (string.match(finish or '', '^%d+$') == nil) and   (string.match(finish or '', '^%-%d+$') == nil)thenlocal finish_fixed = mw.ustring.match(finish or '', '^%s*(%d%d?%d?%d?)%D')if finish_fixed thenfinish = finish_fixedelseerrors = p.errorclass('Function nav_hyphen can\'t recognize "'..(finish or '')..'" '..  'in the second part of the "season" that was passed to it. '..  'For e.g. "2015–16", "16" is expected via "|2015|–|16|".')return p.failedcat(errors, 'I')endelseif string.len(finish) >= 5 thenerrors = p.errorclass('The second part of the season passed to function nav_hyphen should only be four or fewer digits, not "'..(finish or '')..'". '..  'See [[MOS:DATERANGE]] for details.')return p.failedcat(errors, 'J')endendlocal nfinish = tonumber(finish)--save sterilized parent range for easier lookup latertirregs['from0'] = nstarttirregs['to0']   = nfinish--sterilize min/maxlocal nminseas_default = -9999local nmaxseas_default =  9999local nminseas = tonumber(minseas) or nminseas_default --same behavior as nav_yearlocal nmaxseas = tonumber(maxseas) or nmaxseas_default --same behavior as nav_yearif nminseas > nstart then nminseas = nstart endif nmaxseas < nstart then nmaxseas = nstart endlocal lspace = ' ' --assume a leading space (most common)local tspace = ' ' --assume a trailing space (most common)if string.match(firstpart, '%($') then lspace = '' end --DNE for "Madrid city councillors (2007–2011)"-type catsif string.match(lastpart,  '^%)') then tspace = '' end --DNE for "Madrid city councillors (2007–2011)"-type cats--calculate term length/intRAseason size & finishing yearlocal term_limit = 10local t = 1while t <= term_limit and regularparent == true dolocal nish = nstart + t --use switchADBC to flip this sign to work for years BC, if/when the time comesif (nish == nfinish) or (string.match(nish, '%d?%d$') == finish) thenttlens[t] = 1breakendif t == term_limit thenerrors = p.errorclass('Function nav_hyphen can\'t determine a reasonable term length for "'..start..hyph..finish..'".')return p.failedcat(errors, 'K')endt = t + 1end--apply MOS:DATERANGE to parentlocal lenstart = string.len(start)local lenfinish = string.len(finish)if lenstart == 4 and regularparent == true then --"2001–..."if t == 1 then --"2001–02" & "2001–2002" both allowedif lenfinish ~= 2 and lenfinish ~= 4 thenerrors = p.errorclass('The second part of the season passed to function nav_hyphen should be two or four digits, not "'..finish..'".')return p.failedcat(errors, 'L')endelse --"2001–2005" is required for t > 1; track "2001–05"; anything else = errorif lenfinish == 2 thentrackcat(5, 'Navseasoncats range abbreviated (MOS)')elseif lenfinish ~= 4 thenerrors = p.errorclass('The second part of the season passed to function nav_hyphen should be four digits, not "'..finish..'".')return p.failedcat(errors, 'M')endendif finish == '00' then --full year required regardless of term lengthtrackcat(5, 'Navseasoncats range abbreviated (MOS)')endend--calculate intERseason gap sizelocal hgap_default     = 0 --assume & start at the most common case: 2001–02 -> 2002–03, etc.local hgap_limit_reg   = 6 --less expensive per-increment (inc x 4)local hgap_limit_irreg = 6 --more expensive per-increment (inc x 23: inc x (k_bwd + k_fwd) = inc x (12 + 11))local hgap_success = falselocal hgap = hgap_defaultwhile hgap <= hgap_limit_reg and regularparent == true do --verifylocal prevseason2 = firstpart..lspace..(nstart-t-hgap)..hyph..string.match(nstart-hgap, '%d?%d$')    ..tspace..lastpartlocal nextseason2 = firstpart..lspace..(nstart+t+hgap)..hyph..string.match(nstart+2*t+hgap, '%d?%d$')..tspace..lastpartlocal prevseason4 = firstpart..lspace..(nstart-t-hgap)..hyph..(nstart-hgap)    ..tspace..lastpartlocal nextseason4 = firstpart..lspace..(nstart+t+hgap)..hyph..(nstart+2*t+hgap)..tspace..lastpartif t == 1 then --test abbreviated range first, then full range, to be frugal with expensive functionsif catexists(prevseason2) or --use 'or', in case we're at the edge of the cat structure,   catexists(nextseason2) or --or we hit a "–00"/"–2000" situation on one side   catexists(prevseason4) or   catexists(nextseason4)thenhgap_success = truebreakendelseif t > 1 then --test full range first, then abbreviated range, to be frugal with expensive functionsif catexists(prevseason4) or --use 'or', in case we're at the edge of the cat structure,   catexists(nextseason4) or --or we hit a "–00"/"–2000" situation on one side   catexists(prevseason2) or   catexists(nextseason2)thenhgap_success = truebreakendendhgap = hgap + 1endif hgap_success == false thenhgap = tonumber(testgap) or hgap_default --tracked via defaultgapcat()end--preliminary scan to determine ir/regular spacing of nearby cats;--to limit expensive function calls, MOS:DATERANGE-violating cats are ignored;--an irregular-term-length series should follow "YYYY..hyph..YYYY" throughoutif hgap <= hgap_limit_reg then --also to isolate temp vars--find # of nav-visible ir/regular-term-length catslocal bwanchor = nstart       --backward anchor/common yearlocal fwanchor = bwanchor + t --forward anchor/common yearif regularparent == 'isolated' thenfwanchor = bwanchorendlocal spangreen = '[<span style="color:green">j, g, k = ' --used for/when debugging via list-all-links=yeslocal spanblue = '<span style="color:blue">'local spanred = ' (<span style="color:red">'local span = '</span>'local lastg = nil --to check for run-on searcheslocal lastk = nil --to check for run-on searcheslocal endfound = false --switch used to stop searching forwardlocal iirregs = 0 --index of tirregs[] for j < 0, since search starts from parentlocal j = -3 --index of tirregs[] for j > 0 & pseudo nav positionwhile j <= 3 doif j < 0 then --search backward from parentlocal gbreak = false --switch used to break out of g-looplocal g = 0 --gap sizewhile g <= hgap_limit_irreg dolocal k = 0 --term length: 0 = "0-length", 1+ = normalwhile k <= term_limit dolocal from = bwanchor - k - glocal to   = bwanchor - glocal full = mw.text.trim( firstpart..lspace..from..hyph..to..tspace..lastpart )if k == 0 thenif regularparent ~= 'isolated' then --+restrict to g == 0 if repeating year problems ariseto = '0-length'full = mw.text.trim( firstpart..lspace..from..tspace..lastpart )if catlinkfollowr( frame, full ).rtarget ~= nil then --#R followedtable.insert( tlistallbwd, spangreen..j..', '..g..', '..k..span..'] '..full..spanred..'#R ignored'..span..')' )full, to = '', '' --don't use/follow 0-length cat #Rs from nav_hyphen(); otherwise gets messyendendendif (k >= 1) or  --the normal case; only continue k = 0 if 0-length found   (to == '0-length') --ghetto "continue" (thx Lua) to avoid expensive searches for "UK MPs 1974-1974", etc.thentable.insert( tlistallbwd, spangreen..j..', '..g..', '..k..span..'] '..full )if (k == 1) and   (g == 0 or g == 1) and   (catexists(full) == false)then --allow bare-bones MOS:DATERANGE alternation, in case we're on a 0|1-gap, 1-year term serieslocal to2 = string.match(to, '%d%d$')if to2 and to2 ~= '00' then --and not at a century transition (i.e. 1999–2000)to = to2full = mw.text.trim( firstpart..lspace..from..hyph..to..tspace..lastpart )table.insert( tlistallbwd, spangreen..j..', '..g..', '..k..span..'] '..full )endendif catexists(full) thenif to == '0-length' thentrackcat(13, 'Navseasoncats range irregular, 0-length')endtlistallbwd[#tlistallbwd] = spanblue..tlistallbwd[#tlistallbwd]..span..' (found)'ttlens[ find_duration(full) ] = 1tgaps[g] = 1iirregs = iirregs + 1tirregs['from-'..iirregs] = fromtirregs['to-'..iirregs] = tobwanchor = from --ratchet downif to ~= '0-length' thengbreak = truebreakelseg = 0 --soft-reset g, to keep stepping thru kj = j + 1 --save, but keep searching thru kif j > 3 then --lest we keep searching & finding 0-length cats ("MEPs for the Republic of Ireland 1973" & down)gbreak = truebreakendendendend --ghetto "continue"k = k + 1lastk = kend --while kif gbreak == true then break endg = g + 1lastg = gend --while gend --if j < 0if j > 0 and endfound == false then --search forward from parentlocal gbreak = false --switch used to break out of g-looplocal g = 0 --gap sizewhile g <= hgap_limit_irreg dolocal k = -2 --term length: -2 = "0-length", -1 = "2020–present", 0 = "2020–", 1+ = normalwhile k <= term_limit dolocal from = fwanchor + glocal to4  = fwanchor + k + g--override carefullylocal to2  = nil--last 2 digits of to4, IIF existsif k == -1 then to4 = 'present'--see if end-cat exists (present)elseif k == 0 then to4 = '' end--see if end-cat exists (blank)local full = mw.text.trim( firstpart..lspace..from..hyph..to4..tspace..lastpart )if k == -2 thenif regularparent ~= 'isolated' then --+restrict to g == 0 if repeating year problems ariseto4 = '0-length' --see if 0-length cat existsfull = mw.text.trim( firstpart..lspace..from..tspace..lastpart )if catlinkfollowr( frame, full ).rtarget ~= nil then --#R followedtable.insert( tlistallfwd, spangreen..j..', '..g..', '..k..span..'] '..full..spanred..'#R ignored'..span..')' )full, to4 = '', '' --don't use/follow 0-length cat #Rs from nav_hyphen(); otherwise gets messyendendendif (k >= -1) or   --only continue k = -2 if 0-length found   (to4 == '0-length') --ghetto "continue" (thx Lua) to avoid expensive searches for "UK MPs 1974-1974", etc.thentable.insert( tlistallfwd, spangreen..j..', '..g..', '..k..span..'] '..full )if (k == 1) and   (g == 0 or g == 1) and   (catexists(full) == false)then --allow bare-bones MOS:DATERANGE alternation, in case we're on a 0|1-gap, 1-year term seriesto2 = string.match(to4, '%d%d$')if to2 and to2 ~= '00' then --and not at a century transition (i.e. 1999–2000)full = mw.text.trim( firstpart..lspace..from..hyph..to2..tspace..lastpart )table.insert( tlistallfwd, spangreen..j..', '..g..', '..k..span..'] '..full )endendif catexists(full) thenif to4 == '0-length' thenif rtarget(frame, full) == full then --only use 0-length cats that don't #Rtrackcat(13, 'Navseasoncats range irregular, 0-length')endendtirregs['from'..j] = fromtirregs['to'..j] = (to2 or to4)if (k == -1) or (k == 0) thenendfound = true --tentativeelse --k == { -2, > 0 }tlistallfwd[#tlistallfwd] = spanblue..tlistallfwd[#tlistallfwd]..span..' (found)'ttlens[ find_duration(full) ] = 1tgaps[g] = 1endfound = falseif to4 ~= '0-length' then --k > 0fwanchor = to4 --ratchet upgbreak = truebreak --only break on k > 0 b/c old end-cat #Rs still exist like "Members of the Scottish Parliament 2011–"else --k == -2j = j + 1 --save, but keep searching k's, in case "1974" → "1974-1979"if j > 3 then --lest we keep searching & finding 0-length cats ("2018 CONCACAF Champions League" & up)gbreak = truebreakendendendendend --ghetto "continue"k = k + 1lastk = kend --while kif gbreak == true then break endg = g + 1lastg = gend --while gend --if j > 0if (lastg == (hgap_limit_irreg + 1)) and   (lastk == (term_limit + 1))then --search exhaustedif j < 0 then j = 0 --bwd search exhausted; continue fwdelseif j > 0 then break end --fwd search exhaustedendj = j + 1end --while j <= 3end --if hgap <= hgap_limit_reg--begin navhyphenlocal navh = '{| class="toccolours hlist" style="text-align: center; margin: auto;"\n'..'|\n'local terminalcat = false --switch used to hide future catslocal terminaltxt = nillocal i = -3 --nav positionwhile i <= 3 dolocal from = nstart + i*(t+hgap) --the logical, but not necessarily correct, 'from'if tirregs['from'..i] then from = tonumber(tirregs['from'..i]) end --prefer irregular term tablelocal from2 = string.match(from, '%d?%d$')local to = tostring(from+t)--the logical, naive range, butif tirregs['to'..i] then--prefer irregular term tableto = tirregs['to'..i]elseif regularparent == false and tirregs and i > 0 thento = tirregs['to-1']--special treatment for parent terminal cats, since they have no natural 'to'endlocal to2 = string.match(to, '%d?%d$')local tofinal = (to2 or '')    --assume t=1 and abbreviated 'to' (the most common case)if t > 1 or                    --per MOS:DATERANGE (e.g. 1999-2004)  (from2 - (to2 or from2)) > 0 --century transition exception (e.g. 1999–2000)thentofinal = (to or '')       --default to the MOS-correct format, in case no fallbacks foundendif to == '0-length' thentofinal = toend--check existance of 4-digit, MOS-correct range, with abbreviation fallbackif tofinal ~= '0-length' thenif t > 1 and string.len(from) == 4 then --e.g. 1999-2004--determine which link exists (full or abbr)local full = firstpart..lspace..from..hyph..tofinal..tspace..lastpartif not catexists(full) thenlocal abbr = firstpart..lspace..from..hyph..to2..tspace..lastpartif catexists(abbr) thentofinal = (to2 or '') --rv to MOS-incorrect format; if full AND abbr DNE, then tofinal is still in its MOS-correct formatendendelseif t == 1 then --full-year consecutive ranges are also allowedlocal abbr = firstpart..lspace..from..hyph..tofinal..tspace..lastpart --assume tofinal is in abbr formatif not catexists(abbr) and tofinal ~= to thenlocal full = firstpart..lspace..from..hyph..to..tspace..lastpartif catexists(full) thentofinal = (to or '') --if abbr AND full DNE, then tofinal is still in its abbr format (unless it's a century transition)endendendend--populate navhif i ~= 0 then --left/right navhlocal orig = firstpart..lspace..from..hyph..tofinal..tspace..lastpartlocal disp = from..hyph..tofinalif tofinal == '0-length' thenorig = firstpart..lspace..from..tspace..lastpartdisp = fromendlocal catlink = catlinkfollowr(frame, orig, disp, true) --force terminal cat displayif terminalcat == false thenterminaltxt = find_terminaltxt( disp ) --also sets tracking catsterminalcat = (terminaltxt ~= nil)endif catlink.rtarget and avoidself then --a {{Category redirect}} was followed, figure out why--determine new term length & gap sizettlens[ find_duration( catlink.rtarget ) ] = 1if i > -3 thenlocal lastto = tirregs['to'..(i-1)]if lastto == nil thenlocal lastfrom = nstart + (i-1)*(t+hgap)lastto = lastfrom+t --use last logical 'from' to calc lasttoendif lastto thenlocal gapcat = lastto..'-'..from --dummy cat to calc withlocal gap = find_duration(gapcat) or -1--in case of nil,tgaps[ gap ] = 1--tgaps[-1] is ignoredendend--display/tracking handlinglocal base_regex = '%d+[–-]%d+'local origbase = mw.ustring.gsub(orig, base_regex, '')local rtarbase, rtarbase_success = mw.ustring.gsub(catlink.rtarget, base_regex, '')if rtarbase_success == 0 thenlocal base_regex_lax = '%d%d%d%d' --in case rtarget is a year catrtarbase, rtarbase_success = mw.ustring.gsub(catlink.rtarget, base_regex_lax, '')endlocal terminal_regex = '%d+[–-]'..(terminaltxt or '')..'$' --more manual ORs bc Lua regex suxif mw.ustring.match(orig, terminal_regex) thenorigbase = mw.ustring.gsub(orig, terminal_regex, '')endif mw.ustring.match(catlink.rtarget, terminal_regex) then--finagle/overload terminalcat type to set nmaxseas on 1st occurence onlyif terminalcat == false then terminalcat = 1 endlocal dummy = find_terminaltxt( catlink.rtarget ) --also sets tracking catsrtarbase = mw.ustring.gsub(catlink.rtarget, terminal_regex, '')endorigbase = mw.text.trim(origbase)rtarbase = mw.text.trim(rtarbase)if origbase ~= rtarbase thentrackcat(6, 'Navseasoncats range redirected (base change)')elseif terminalcat == 1 thentrackcat(8, 'Navseasoncats range redirected (end)')else --origbase == rtarbaselocal all4s_regex = '%d%d%d%d[–-]%d%d%d%d'local orig_all4s = mw.ustring.match(orig, all4s_regex)local rtar_all4s = mw.ustring.match(catlink.rtarget, all4s_regex)if orig_all4s and rtar_all4s thentrackcat(10, 'Navseasoncats range redirected (other)')elselocal year_regex1 = '%d%d%d%d$'local year_regex2 = '%d%d%d%d[%s%)]'local year_rtar = mw.ustring.match(catlink.rtarget, year_regex1) or  mw.ustring.match(catlink.rtarget, year_regex2)if orig_all4s and year_rtar thentrackcat(7, 'Navseasoncats range redirected (var change)')elsetrackcat(9, 'Navseasoncats range redirected (MOS)')endendendendif terminalcat then --true or 1if type(terminalcat) ~= 'boolean' then nmaxseas = from end --only want to do this onceterminalcat = true --done finagling/overloadingendif (from >= 0) and (nminseas <= from) and (from <= nmaxseas) thennavh = navh..'*'..catlink.navelement..'\n'if terminalcat then nmaxseas = nminseas_default end --prevent display of future rangeselselocal hidden = '<span style="visibility:hidden">'..disp..'</span>'navh = navh..'*'..hidden..'\n'if listall thentlistall[#tlistall] = tlistall[#tlistall]..' ('..hidden..')'endendelse --center navhif finish == -1 then finish = 'present'elseif finish == 0 then finish = '<span style="visibility:hidden">'..start..'</span>' endlocal disp = start..hyph..finishif regularparent == 'isolated' then disp = start endnavh = navh..'*<b>'..disp..'</b>\n'endi = i + 1end--tracking cats & finalizeif avoidself thenlocal igaps  = 0 --# of diff gap sizes > 0 foundlocal itlens = 0 --# of diff term lengths foundfor s = 1, hgap_limit_reg do --must loop; #tgaps, #ttlens unreliableigaps = igaps + (tgaps[s] or 0)endfor s = 0, term_limit doitlens = itlens + (ttlens[s] or 0)endif igaps  > 0 then trackcat(11, 'Navseasoncats range gaps') endif itlens > 1 and ttrackingcats[13] == '' then --avoid duplication in "Navseasoncats range irregular, 0-length"trackcat(12, 'Navseasoncats range irregular')endendisolatedcat()defaultgapcat(not hgap_success)if listall thenreturn listalllinks()elsereturn navh..'|}'endend--[[=========================={{  nav_tvseason  }}============================]]local function nav_tvseason( frame, firstpart, tv, lastpart, maximumtv )--Expects a PAGENAME of the form "Futurama (season 1) episodes", where--firstpart = Futurama (season--tv        = 1--lastpart  = ) episodes--maximumtv = 7 ('max' tv season parameter; optional; defaults to 9999)tv = tonumber(tv)if tv == nil thenerrors = p.errorclass('Function nav_tvseason can\'t recognize the TV season number sent to its 2nd parameter.')return p.failedcat(errors, 'T')endlocal maxtv = tonumber(maximumtv) or 9999 --allow +/- qualifierif maxtv < tv then maxtv = tv end --input error; maxtv should be >= parent--begin navtvseasonlocal navt = '{| class="toccolours hlist" style="text-align: center; margin: auto;"\n'..'|\n'local i = -5 --nav positionwhile i <= 5 dolocal t = tv + iif i ~= 0 then --left/right navtlocal catlink = catlinkfollowr( frame, firstpart..' '..t..lastpart, t )if (t >= 1 and t <= maxtv) then --hardcode mintvif catlink.rtarget then --a {{Category redirect}} was followedtrackcat(25, 'Navseasoncats TV season redirected')endnavt = navt..'*'..catlink.navelement..'\n'elselocal hidden = '<span style="visibility:hidden">'..'0'..'</span>' --'0' to maintain dot spacingnavt = navt..'*'..hidden..'\n'if listall thentlistall[#tlistall] = tlistall[#tlistall]..' ('..hidden..')'endendelse --center navtnavt = navt..'*<b>'..tv..'</b>\n'endi = i + 1endisolatedcat()if listall thenreturn listalllinks()elsereturn navt..'|}'endend--[[==========================={{  nav_decade  }}=============================]]local function nav_decade( frame, firstpart, decade, lastpart, mindecade, maxdecade )--Expects a PAGENAME of the form "Some sequential 2000 example cat", where--firstpart = Some sequential--decade    = 2000--lastpart  = example cat--mindecade = 1800 ('min' decade parameter; optional; defaults to -9999)--maxdecade = 2020 ('max' decade parameter; optional; defaults to 9999)--sterilize declocal dec = sterilizedec(decade)if dec == nil thenerrors = p.errorclass('Function nav_decade was sent "'..(decade or '')..'" as its 2nd parameter, '..'but expects a 1 to 4-digit year ending in "0".')return p.failedcat(errors, 'D')endlocal ndec = tonumber(dec)--sterilize mindecade & determine AD/BClocal mindefault = '-9999'local mindec = sterilizedec(mindecade) --returns a tostring(unsigned int), or nilif mindec thenif string.match(mindecade, '-%d') or   string.match(mindecade, 'BC')thenmindec = '-'..mindec --better +/-0 behavior with strings (0-initialized int == "-0" string...)endelseif mindec == nil and mindecade and mindecade ~= '' thenerrors = p.errorclass('Function nav_decade was sent "'..(mindecade or '')..'" as its 4th parameter, '..'but expects a 1 to 4-digit year ending in "0", the earliest decade to be shown.')return p.failedcat(errors, 'E')else --mindec == nilmindec = mindefault --tonumber() later, after error checksend--sterilize maxdecade & determine AD/BClocal maxdefault = '9999'local maxdec = sterilizedec(maxdecade) --returns a tostring(unsigned int), or nil + errorif maxdec thenif string.match(maxdecade, '-%d') or   string.match(maxdecade, 'BC')then                     --better +/-0 behavior with strings (0-initialized int == "-0" string...),maxdec = '-'..maxdec --but a "-0" string -> tonumber() -> tostring() = "-0",end                      --and a  "0" string -> tonumber() -> tostring() =  "0"elseif maxdec == nil and maxdecade and maxdecade ~= '' thenerrors = p.errorclass('Function nav_decade was sent "'..(maxdecade or '')..'" as its 5th parameter, '..'but expects a 1 to 4-digit year ending in "0", the highest decade to be shown.')return p.failedcat(errors, 'F')else --maxdec == nilmaxdec = maxdefaultendlocal tspace = ' ' --assume trailing space for "1950s in X"-type catsif string.match(lastpart, '^-') then tspace = '' end --DNE for "1970s-related"-type cats--AD/BC switches & varslocal parentBC = string.match(lastpart, '^BC') --following the "0s BC" convention for all years BClastpart = mw.ustring.gsub(lastpart, '^BC%s*', '') --handle BC separately; AD never used--TODO?: handle BCE, but only if it exists in the wildlocal dec0to40AD = (ndec >= 0 and ndec <= 40 and not parentBC) --special behavior in this rangelocal switchADBC = 1                 --  1=AD parentif parentBC then switchADBC = -1 end -- -1=BC parent; possibly adjusted laterlocal BCdisp = ''local D = -math.huge --secondary switch & iterator for AD/BC transition--check non-default min/max more carefullyif mindec ~= mindefault thenif tonumber(mindec) > ndec*switchADBC thenmindec = tostring(ndec*switchADBC) --input error; mindec should be <= parentendendif maxdec ~= maxdefault thenif tonumber(maxdec) < ndec*switchADBC thenmaxdec = tostring(ndec*switchADBC) --input error; maxdec should be >= parentendendlocal nmindec = tonumber(mindec) --similar behavior to nav_year & nav_nordinallocal nmaxdec = tonumber(maxdec) --similar behavior to nav_nordinal--begin navdecadelocal bnb = '' --border/no borderif navborder == false then --for Navseasoncats year and decadebnb = ' border-style: none; background-color: transparent;'endlocal navd = '{| class="toccolours hlist" style="text-align: center; margin: auto;'..bnb..'"\n'..'|\n'local i = -50 --nav position x 10while i <= 50 dolocal d = ndec + i*switchADBClocal BC = ''BCdisp = ''if dec0to40AD thenif D < -10 thend = math.abs(d + 10) --b/c 2 "0s" decades exist: "0s BC" & "0s" (AD)BC = 'BC 'if d == 0 thenD = -10 --track 1st d = 0 use (BC)endelseif D >= -10 thenD = D + 10 --now iterate from 0s ADd = D      --2nd d = 0 useendelseif parentBC thenif switchADBC == -1 then --parentBC looking at the BC side (the common case)BC = 'BC 'if d == 0 then     --prepare to switch to the AD side on the next iterationswitchADBC = 1 --1st d = 0 use (BC)D = -10        --prependelseif switchADBC == 1 then --switched to the AD sideD = D + 10 --now iterate from 0s ADd = D      --2nd d = 0 use (on first use)endendif BC ~= '' and ndec <= 50 thenBCdisp = ' BC' --show BC for all BC decades whenever a "0s" is displayed on the navend--determine target catlocal disp = d..'s'..BCdisplocal catlink = catlinkfollowr( frame, firstpart..' '..d..'s'..tspace..BC..lastpart, disp )if catlink.rtarget then --a {{Category redirect}} was followedtrackcat(18, 'Navseasoncats decade redirected')end--populate left/right navdlocal shown = navcenter(i, catlink)local hidden = '<span style="visibility:hidden">'..disp..'</span>'local dsign = d --use d for display & dsign for logicif BC ~= '' then dsign = -dsign endif (nmindec <= dsign) and (dsign <= nmaxdec) thenif dsign == 0 and (nmindec == 0 or nmaxdec == 0) then --distinguish b/w -0 (BC) & 0 (AD)--"zoom in" on +/- 0 and turn dsign/min/max temporarily into +/- 1 for easier processinglocal zsign, zmin, zmax = 1, nmindec, nmaxdecif BC ~= '' then zsign = -1 endif     mindec == '-0' then zmin = -1elseif mindec ==  '0' then zmin =  1 endif     maxdec == '-0' then zmax = -1elseif maxdec ==  '0' then zmax =  1 endif (zmin <= zsign) and (zsign <= zmax) thennavd = navd..shownhidden = nilelsenavd = navd..'*'..hidden..'\n'endelsenavd = navd..shown --the common casehidden = nilendelsenavd = navd..'*'..hidden..'\n'endif listall and hidden thentlistall[#tlistall] = tlistall[#tlistall]..' ('..hidden..')'endi = i + 10endisolatedcat()if listall thenreturn listalllinks()elsereturn navd..'|}'endend--[[============================{{  nav_year  }}==============================]]local function nav_year( frame, firstpart, year, lastpart, minimumyear, maximumyear )--Expects a PAGENAME of the form "Some sequential 1760 example cat", where--firstpart   = Some sequential--year        = 1760--lastpart    = example cat--minimumyear = 1758 ('min' year parameter; optional)--maximumyear = 1800 ('max' year parameter; optional)local minyear_default = -9999local maxyear_default =  9999year = tonumber(year) or tonumber(mw.ustring.match(year or '', '^%s*(%d*)'))local minyear = tonumber(string.match(minimumyear or '', '-?%d+')) or minyear_default --allow +/- qualifierlocal maxyear = tonumber(string.match(maximumyear or '', '-?%d+')) or maxyear_default --allow +/- qualifierif string.match(minimumyear or '', 'BC') then minyear = -math.abs(minyear) end --allow BC qualifier (AD otherwise assumed)if string.match(maximumyear or '', 'BC') then maxyear = -math.abs(maxyear) end --allow BC qualifier (AD otherwise assumed)if year == nil thenerrors = p.errorclass('Function nav_year can\'t recognize the year sent to its 2nd parameter.')return p.failedcat(errors, 'Y')end--AD/BC switches & varslocal yearBCElastparts = { --needed for parent = AD 1-5, when the BC/E format is unknown--"BCE" removed to match both AD & BCE cats; easier & faster than multiple string.match()s['example_Hebrew people_example'] = 'BCE', --example entry format; add to & adjust as needed}local parentAD = string.match(firstpart, 'AD$')  --following the "AD 1" convention from AD 1 to AD 10local parentBC = string.match(lastpart, '^BCE?') --following the "1 BC" convention for all years BCfirstpart = mw.ustring.gsub(firstpart, '%s*AD$', '') --handle AD/BC separately for easier & faster accountinglastpart  = mw.ustring.gsub(lastpart,  '^BCE?%s*', '')local BCe = parentBC or yearBCElastparts[lastpart] or 'BC' --"BC" defaultlocal year1to10 = (year >= 1 and year <= 10)local year1to10ADBC = year1to10 and (parentBC or parentAD) --special behavior 1-10 for low-# non-year serieslocal year1to15AD = (year >= 1 and year <= 15 and not parentBC) --special behavior 1-15 for AD/BC displaylocal switchADBC = 1                 --  1=AD parentif parentBC then switchADBC = -1 end -- -1=BC parent; possibly adjusted laterlocal Y = 0 --secondary iterator for AD-on-a-BC-parentif minyear > year*switchADBC then minyear = year*switchADBC end --input error; minyear should be <= parentif maxyear < year*switchADBC then maxyear = year*switchADBC end --input error; maxyear should be >= parentlocal lspace = ' ' --leading space before year, after firstpartif string.match(firstpart, '[%-VW]$') thenlspace = '' --e.g. "Straight-8 engines"endlocal tspace = ' ' --trailing space after year, before lastpartif string.match(lastpart, '^-') thentspace = '' --e.g. "2018-related timelines"end--determine interyear gap size to condense special category types, if possiblelocal ygapdefault = 1 --assume/start at the most common case: 2001, 2002, etc.local ygap = ygapdefaultif string.match(lastpart, 'presidential') thenlocal ygap1, ygap2 = ygapdefault, ygapdefault --need to determine previous & next year gaps indepedentlylocal ygap1_success, ygap2_success = false, falselocal prevseason = nilwhile ygap1 <= 5 do --Czech Republic, Poland, Sri Lanka, etc. have 5-year termsprevseason = firstpart..lspace..(year-ygap1)..tspace..lastpartif catexists(prevseason) thenygap1_success = truebreakendygap1 = ygap1 + 1endlocal nextseason = nilwhile ygap2 <= 5 do --Czech Republic, Poland, Sri Lanka, etc. have 5-year termsnextseason = firstpart..lspace..(year+ygap2)..tspace..lastpartif catexists(nextseason) thenygap2_success = truebreakendygap2 = ygap2 + 1endif ygap1_success and ygap2_success thenif ygap1 == ygap2 then ygap = ygap1 endelseif ygap1_success then  ygap = ygap1elseif ygap2_success then  ygap = ygap2endend--skip non-existing years, if requestedlocal ynogaps = {} --populate with existing years in the range, at most, [year - (skipgaps_limit * 5), year + (skipgaps_limit * 5)]local skipgaps_limit = 25if skipgaps thenif minyear == minyear_default thenminyear = 0 --automatically set minyear to 0, as AD/BC not supported anywayendif (year > 70) or --add support for AD/BC (<= AD 10) if/when needed   (minyear >= 0 and --must be a non-year series like "AC with 0 elements"   not parentAD and not parentBC)thenlocal yskipped = {} --track skipped y's to avoid double-checkinglocal cat, found, Yeary --populate nav element queue outwards positively from the parentlocal Year = year --to save/ratchet progressionlocal i = 1while i <= 5 dolocal y = 1while y <= skipgaps_limit dofound = falseYeary = Year + yif yskipped[Yeary] == nil thenyskipped[Yeary] = Yearycat = firstpart..lspace..Yeary..tspace..lastpartfound = catexists(cat)if found then break endendy = y + 1endif found then Year = Yearyelse          Year = Year + 1 endynogaps[i] =  Yeari = i + 1endynogaps[0] = year --the parent--populate nav element queue outwards negatively from the parentYear = year --reset ratcheti = -1while i >= -5 dolocal y = -1while y >= -skipgaps_limit dofound = falseYeary = Year + yif yskipped[Yeary] == nil thenyskipped[Yeary] = Yearycat = firstpart..lspace..Yeary..tspace..lastpartfound = catexists(cat)if found then break endendy = y - 1endif found then Year = Yearyelse          Year = Year - 1 endynogaps[i] =  Yeari = i - 1endelseskipgaps = false --AD/BC not supportedendend--begin navyearslocal navy = '{| class="toccolours hlist" style="text-align: center; margin: auto;"\n'..'|\n'local ylocal i = -5 --nav positionwhile i <= 5 doif skipgaps theny = ynogaps[i]elsey = year + i*ygap*switchADBCendlocal BCdisp = ''if i ~= 0 then --left/right navylocal AD = ''local BC = ''if year1to15AD and not   (year1to10 and not year1to10ADBC) --don't AD/BC 1-10's if parents don't contain AD/BCthenif year >= 11 then --parent = AD 11-15if y <= 10 then --prepend AD on y = 1-10 cats only, per existing catsAD = 'AD 'endelseif year >= 1 then --parent = AD 1-10if y <= 0 thenBC = BCe..' 'y = math.abs(y - 1) --skip y = 0 (DNE)elseif y >= 1 and y <= 10 then --prepend AD on y = 1-10 cats only, per existing catsAD = 'AD 'endendelseif parentBC thenif switchADBC == -1 then --displayed y is in the BC regimeif y >= 1 then     --the common caseBC = BCe..' 'elseif y == 0 then --switch from BC to AD regimeswitchADBC = 1endendif switchADBC == 1 then --displayed y is now in the AD regimeY = Y + 1 --skip y = 0 (DNE)y = Y     --easiest solution: start another iterator for these AD y's displayed on a BC year parentAD = 'AD 'endendif BC ~= '' and year <= 5 then --only show 'BC' for parent years <= 5: saves room, easier to read,BCdisp = ' '..BCe          --and 6 is the first/last nav year that doesn't need a disambiguator;end                            --the center/parent year will always show BC, so no need to show it another 10x--populate left/right navylocal ysign = y --use y for display & ysign for logiclocal disp = y..BCdispif BC ~= '' then ysign = -ysign endlocal firsttry = firstpart..lspace..AD..y..tspace..BC..lastpartif (minyear <= ysign) and (ysign <= maxyear) thenlocal catlinkAD = catlinkfollowr( frame, firsttry, disp ) --try ADlocal catlink = catlinkAD --tentative winnerif AD ~= '' then --for "ACArt with 5 suppressed elements"-type catslocal catlinkNoAD = catlinkfollowr( frame, firstpart..lspace..y..tspace..BC..lastpart, disp ) --try !ADif catlinkNoAD.catexists == true thencatlink = catlinkNoAD --usurpelseif listall thentlistall[#tlistall] = tlistall[#tlistall]..' (tried; not displayed)'endendif (AD..BC == '') and (catlink.catexists == false) and (y >= 1000) then --!ADBC & DNE; 4-digit only, to be frugal--try basic hyphenated cats: 1-year, endash, MOS-correct only, no #Rslocal yHyph_4 = y..'–'..(y+1) --try 2010–2011 type catslocal catlinkHyph_4 = catlinkfollowr( frame, firstpart..lspace..yHyph_4..tspace..BC..lastpart, yHyph_4 )if catlinkHyph_4.catexists and catlinkHyph_4.rtarget == nil then --exists & no #Rscatlink = catlinkHyph_4 --usurptrackcat(27, 'Navseasoncats year and range')elseif listall thentlistall[#tlistall] = tlistall[#tlistall]..' (tried; not displayed)'endlocal yHyph_2 = y..'–'..string.match(y+1, '%d%d$') --try 2010–11 type catslocal catlinkHyph_2 = catlinkfollowr( frame, firstpart..lspace..yHyph_2..tspace..BC..lastpart, yHyph_2 )if catlinkHyph_2.catexists and catlinkHyph_2.rtarget == nil then --exists & no #Rscatlink = catlinkHyph_2 --usurptrackcat(27, 'Navseasoncats year and range')elseif listall thentlistall[#tlistall] = tlistall[#tlistall]..' (tried; not displayed)'endendendif catlink.rtarget then --#R followed; determine whylocal r = catlink.rtargetlocal c = catlink.catlocal regex_year  = '%d%d%d%d[–-]?%d?%d?%d?%d?' --prioritize year/range stripping, e.g. for "2006 Super 14 season"local regex_hyph  = '%d%d%d%d[–-]%d+'local regex_num   = '%d+' --strip any number otherwiselocal regex_final = nil   --best choice goes hereif mw.ustring.match(r, regex_year) and mw.ustring.match(c, regex_year) thenregex_final = regex_yearelseif mw.ustring.match(r, regex_num) and mw.ustring.match(c, regex_num) thenregex_final = regex_numendif regex_final thenlocal r_base = mw.ustring.gsub(r, regex_final, '')local c_base = mw.ustring.gsub(c, regex_final, '')if r_base ~= c_base thentrackcat(19, 'Navseasoncats year redirected (base change)') --acceptable #R targetelseif mw.ustring.match(r, regex_hyph) thentrackcat(20, 'Navseasoncats year redirected (var change)') --e.g. "2008 in Scottish women's football" to "2008–09"elsetrackcat(21, 'Navseasoncats year redirected (other)') --exceptions go hereendelsetrackcat(20, 'Navseasoncats year redirected (var change)') --e.g. "V2 engines" to "V-twin engines"endendnavy = navy..'*'..catlink.navelement..'\n'else --OOB vs min/maxlocal hidden = '<span style="visibility:hidden">'..disp..'</span>'navy = navy..'*'..hidden..'\n'if listall thenlocal dummy = catlinkfollowr( frame, firsttry, disp )tlistall[#tlistall] = tlistall[#tlistall]..' ('..hidden..')'endendelse --center navyif parentBC then BCdisp = ' '..BCe endnavy = navy..'*<b>'..year..BCdisp..'</b>\n'endi = i + 1endisolatedcat()if listall thenreturn listalllinks()elsereturn navy..'|}'endend--[[==========================={{  nav_roman  }}==============================]]local function nav_roman( frame, firstpart, roman, lastpart, minimumrom, maximumrom )local toarabic = require('Module:ConvertNumeric').roman_to_numerallocal toroman  = require('Module:Roman').main--sterilize/convert rom/numlocal num = tonumber(toarabic(roman))local rom = toroman({ [1] = num })if num == nil or rom == nil then --out of range or some other errorerrors = p.errorclass('Function nav_roman can\'t recognize one or more of "'..(num or 'nil')..'" & "'..(rom or 'nil')..'" in category "'..firstpart..' '..roman..' '..lastpart..'".')return p.failedcat(errors, 'R')end--sterilize min/maxlocal minrom = tonumber(minimumrom or '') or tonumber(toarabic(minimumrom or ''))local maxrom = tonumber(maximumrom or '') or tonumber(toarabic(maximumrom or ''))if minrom < 1 then minrom = 1 end    --toarabic() returns -1 on errorif maxrom < 1 then maxrom = 9999 end --toarabic() returns -1 on errorif minrom > num then minrom = num endif maxrom < num then maxrom = num end--begin navromanlocal navr = '{| class="toccolours hlist" style="text-align: center; margin: auto;"\n'..'|\n'local i = -5 --nav positionwhile i <= 5 dolocal n = num + iif n >= 1 thenlocal r = toroman({ [1] = n })if i ~= 0 then --left/right navrlocal catlink = catlinkfollowr( frame, firstpart..' '..r..' '..lastpart, r )if minrom <= n and n <= maxrom thenif catlink.rtarget then --a {{Category redirect}} was followedtrackcat(22, 'Navseasoncats roman numeral redirected')endnavr = navr..'*'..catlink.navelement..'\n'elselocal hidden = '<span style="visibility:hidden">'..r..'</span>'navr = navr..'*'..hidden..'\n'if listall thentlistall[#tlistall] = tlistall[#tlistall]..' ('..hidden..')'endendelse --center navrnavr = navr..'*<b>'..r..'</b>\n'endelsenavr = navr..'*<span style="visibility:hidden">'..'I'..'</span>\n'endi = i + 1endisolatedcat()if listall thenreturn listalllinks()elsereturn navr..'|}'endend--[[=========================={{  nav_nordinal  }}============================]]local function nav_nordinal( frame, firstpart, ord, lastpart, minimumord, maximumord )local nord = tonumber(ord)local minord = tonumber(string.match(minimumord or '', '(-?%d+)[snrt]?[tdh]?')) or -9999 --allow full ord & +/- qualifierlocal maxord = tonumber(string.match(maximumord or '', '(-?%d+)[snrt]?[tdh]?')) or  9999 --allow full ord & +/- qualifierif string.match(minimumord or '', 'BC') then minord = -math.abs(minord) end --allow BC qualifier (AD otherwise assumed)if string.match(maximumord or '', 'BC') then maxord = -math.abs(maxord) end --allow BC qualifier (AD otherwise assumed)local temporal = string.match(lastpart, 'century') or string.match(lastpart, 'millennium')local tspace = ' ' --assume a trailing space after ordinalif string.match(lastpart, '^-') then tspace = '' end --DNE for "19th-century"-type cats--AD/BC switches & varslocal ordBCElastparts = { --needed for parent = AD 1-5, when the BC/E format is unknown--lists the lastpart of valid BCE cats--"BCE" removed to match both AD & BCE cats; easier & faster than multiple string.match()s['-century Hebrew people'] = 'BCE', --WP:CFD/Log/2016 June 21#Category:11th-century BC Hebrew people['-century Jews']          = 'BCE', --co-nominated['-century Judaism']       = 'BCE', --co-nominated['-century rabbis']        = 'BCE', --co-nominated['-century High Priests of Israel'] = 'BCE',}local parentBC = mw.ustring.match(lastpart, '%s(BCE?)')       --"1st-century BC" formatlocal lastpartNoBC = mw.ustring.gsub(lastpart, '%sBCE?', '')  --easier than splitting lastpart up in 2; AD never usedlocal BCe = parentBC or ordBCElastparts[lastpartNoBC] or 'BC' --"BC" defaultlocal switchADBC = 1                 --  1=AD parentif parentBC then switchADBC = -1 end -- -1=BC parent; possibly adjusted laterlocal O = 0 --secondary iterator for AD-on-a-BC-parentif not temporal and minord < 1 then minord = 1 end --nothing before "1st parliament", etc.if minord > nord*switchADBC then minord = nord*switchADBC end --input error; minord should be <= parentif maxord < nord*switchADBC then maxord = nord*switchADBC end --input error; maxord should be >= parent--begin navnordinallocal bnb = '' --border/no borderif navborder == false then --for Navseasoncats decade and centurybnb = ' border-style: none; background-color: transparent;'endlocal navo = '{| class="toccolours hlist" style="text-align: center; margin: auto;'..bnb..'"\n'..'|\n'local i = -5 --nav positionwhile i <= 5 dolocal o = nord + i*switchADBClocal BC = ''local BCdisp = ''if parentBC thenif switchADBC == -1 then --parentBC looking at the BC sideif o >= 1 then     --the common caseBC = ' '..BCeelseif o == 0 then --switch to the AD sideBC = ''switchADBC = 1endendif switchADBC == 1 then --displayed o is now in the AD regimeO = O + 1 --skip o = 0 (DNE)o = O     --easiest solution: start another iterator for these AD o's displayed on a BC year parentendelseif o <= 0 then --parentAD looking at BC sideBC = ' '..BCeo = math.abs(o - 1) --skip o = 0 (DNE)endif BC ~= '' and nord <= 5 then --only show 'BC' for parent ords <= 5: saves room, easier to read,BCdisp = ' '..BCe          --and 6 is the first/last nav ord that doesn't need a disambiguator;end                            --the center/parent ord will always show BC, so no need to show it another 10x--populate left/right navolocal oth = p.addord(o)local osign = o --use o for display & osign for logicif BC ~= '' then osign = -osign endlocal hidden = '<span style="visibility:hidden">'..oth..'</span>'if temporal then --e.g. "3rd-century BC"local lastpart = lastpartNoBC --lest we recursively add multiple "BC"sif BC ~= '' thenlastpart = string.gsub(lastpart, temporal, temporal..BC) --replace BC if neededendlocal catlink = catlinkfollowr( frame, firstpart..' '..oth..tspace..lastpart, oth..BCdisp )if (minord <= osign) and (osign <= maxord) thenif catlink.rtarget then --a {{Category redirect}} was followedtrackcat(23, 'Navseasoncats nordinal redirected')endnavo = navo..navcenter(i, catlink)elsenavo = navo..'*'..hidden..'\n'if listall thentlistall[#tlistall] = tlistall[#tlistall]..' ('..hidden..')'endendelseif BC == '' and minord <= osign and osign <= maxord then --e.g. >= "1st parliament"local catlink = catlinkfollowr( frame, firstpart..' '..oth..tspace..lastpart, oth )if catlink.rtarget then --a {{Category redirect}} was followedtrackcat(23, 'Navseasoncats nordinal redirected')endnavo = navo..navcenter(i, catlink)else --either out-of-range (hide), or non-temporal + BC = something might be wrong (2nd X parliament BC?); handle exceptions if/as they arisenavo = navo..'*'..hidden..'\n'endi = i + 1endisolatedcat()if listall thenreturn listalllinks()elsereturn navo..'|}'endend--[[========================={{  nav_wordinal  }}=============================]]local function nav_wordinal( frame, firstpart, word, lastpart, minimumword, maximumword, ordinal, frame )--Module:ConvertNumeric.numeral_to_english() flags:--   ordinal == 'on': 'second' is output instead of 'two'--   ordinal ~= 'on': 'two' is output instead of 'second'local ord2eng = require('Module:ConvertNumeric').numeral_to_englishlocal eng2ord = require('Module:ConvertNumeric').english_to_ordinallocal th = 'th'if ordinal ~= 'on' thenth = ''eng2ord = require('Module:ConvertNumeric').english_to_numeralendlocal sc = string.match(word, '^%u') --sentence-case checklocal lc = string.lower(word) --operate on/with lc, and restore any sc laterlocal nord = eng2ord(lc)local case = nilif sc then case = 'U' endlocal lspace = ' ' --assume a leading space (most common)local tspace = ' ' --assume a trailing space (most common)if string.match(firstpart, '[%-%(]$') then lspace = '' end --DNE for "Straight-eight engines"-type catsif string.match(lastpart, '^[%-%)]' ) then tspace = '' end --DNE for "Nine-cylinder engines"-type cats--sterilize min/maxlocal minword = 1local maxword = 99if minimumword thenlocal num = tonumber(minimumword)if num and 0 < num and num < maxword thenminword = numelselocal ord = eng2ord(minimumword)if 0 < ord and ord < maxword thenminword = ordendendendif maximumword thenlocal num = tonumber(maximumword)if num and 0 < num and num < maxword thenmaxword = numelselocal ord = eng2ord(maximumword)if 0 < ord and ord < maxword thenmaxword = ordendendendif minword > nord then minword = nord endif maxword < nord then maxword = nord end--begin navwordinallocal navw = '{| class="toccolours hlist" style="text-align: center; margin: auto;"\n'..'|\n'local i = -5 --nav positionwhile i <= 5 dolocal n = nord + iif n >= 1 thenlocal nth = p.addord(n)if ordinal ~= 'on' then nth = n endif i ~= 0 then --left/right navwlocal frame_args = frame:newChild{ args = { n, ord = ordinal, case = case } } --easier to do this than modify Module:ConvertNumericlocal w = ord2eng( frame_args )local catlink = catlinkfollowr( frame, firstpart..lspace..w..tspace..lastpart, nth )if minword <= n and n <= maxword thenif catlink.rtarget then --a {{Category redirect}} was followedtrackcat(24, 'Navseasoncats wordinal redirected')endnavw = navw..'*'..catlink.navelement..'\n'elselocal hidden = '<span style="visibility:hidden">'..nth..'</span>'navw = navw..'*'..hidden..'\n'if listall thentlistall[#tlistall] = tlistall[#tlistall]..' ('..hidden..')'endendelse --center navwnavw = navw..'*<b>'..nth..'</b>\n'endelsenavw = navw..'*<span style="visibility:hidden">'..'0'..th..'</span>\n'endi = i + 1endisolatedcat()if listall thenreturn listalllinks()elsereturn navw..'|}'endend--[[==========================={{  find_var  }}===============================]]local function find_var( pn )--Extracts the variable text (e.g. 2015, 2015–16, 2000s, 3rd, III, etc.) from a string,--and returns { ['vtype'] = <'year'|'season'|etc.>, <v> = <2015|2015–16|etc.> }local pagename = currtitle.textif pn and pn ~= '' thenpagename = pnendlocal cpagename = 'Category:'..pagename --limited-Lua-regex workaroundlocal d_season = mw.ustring.match(cpagename, ':(%d+s).+%(%d+[–-]%d+%)') --i.e. "1760s in the Province of Quebec (1763–1791)"local y_season = mw.ustring.match(cpagename, ':(%d+) .+%(%d+[–-]%d+%)') --i.e. "1763 establishments in the Province of Quebec (1763–1791)"local e_season = mw.ustring.match(cpagename, '%s(%d+[–-])$') or --irreg; ending unknown, e.g. "Members of the Scottish Parliament 2021–" mw.ustring.match(cpagename, '%s(%d+[–-]present)$') --e.g. "UK MPs 2019–present"local season   = mw.ustring.match(cpagename, '[:%s%(](%d+[–-]%d+)[%)%s]') or --split in 2 b/c you can't frontier '$'/eos? mw.ustring.match(cpagename, '[:%s](%d+[–-]%d+)$')local tvseason = mw.ustring.match(cpagename, 'season (%d+)') or mw.ustring.match(cpagename, 'series (%d+)')local nordinal = mw.ustring.match(cpagename, '[:%s](%d+[snrt][tdh])[-%s]') or mw.ustring.match(cpagename, '[:%s](%d+[snrt][tdh])$')local decade   = mw.ustring.match(cpagename, '[:%s](%d+s)[%s-]') or mw.ustring.match(cpagename, '[:%s](%d+s)$')local year     = mw.ustring.match(cpagename, '[:%s](%d%d%d%d)%s') or --prioritize 4-digit years mw.ustring.match(cpagename, '[:%s](%d%d%d%d)$') or mw.ustring.match(cpagename, '[:%s](%d+)%s') or mw.ustring.match(cpagename, '[:%s](%d+)$') or --expand/combine exceptions below as needed mw.ustring.match(cpagename, '[:%s](%d+)-related') or mw.ustring.match(cpagename, '[:%s](%d+)-cylinder') or mw.ustring.match(cpagename, '[:%-VW](%d+)%s') --e.g. "Straight-8 engines"local roman    = mw.ustring.match(cpagename, '%s([IVXLCDM]+)%s')local found    = d_season or y_season or e_season or season or tvseason or nordinal or decade or year or romanif found thenif string.match(found, '%d%d%d%d%d') == nil then--return in order of decreasing complexity/least chance for duplicationif nordinal and season --i.e. "18th-century establishments in the Province of Quebec (1763–1791)"then return { ['vtype'] = 'nordinal', ['v'] = nordinal } endif d_season then return { ['vtype'] = 'decade',   ['v'] = d_season } endif y_season then return { ['vtype'] = 'year',     ['v'] = y_season } endif e_season then return { ['vtype'] = 'ending',   ['v'] = e_season } endif season   then return { ['vtype'] = 'season',   ['v'] = season   } endif tvseason then return { ['vtype'] = 'tvseason', ['v'] = tvseason } endif nordinal then return { ['vtype'] = 'nordinal', ['v'] = nordinal } endif decade   then return { ['vtype'] = 'decade',   ['v'] = decade   } endif year     then return { ['vtype'] = 'year',     ['v'] = year     } endif roman    then return { ['vtype'] = 'roman',    ['v'] = roman    } endendelse--try wordinals ('zeroth' to 'ninety-ninth' only)local eng2ord = require('Module:ConvertNumeric').english_to_ordinallocal split = mw.text.split(pagename, ' ')for i=1, #split doif eng2ord(split[i]) > -1 thenreturn { ['vtype'] = 'wordinal', ['v'] = split[i] }endend--try English numerics ('one'/'single' to 'ninety-nine' only)local eng2num = require('Module:ConvertNumeric').english_to_numerallocal split = mw.text.split(pagename, '[%s%-]') --e.g. "Nine-cylinder engines"for i=1, #split doif eng2num(split[i]) > -1 thenreturn { ['vtype'] = 'enumeric', ['v'] = split[i] }endendenderrors = p.errorclass('Function find_var can\'t find the variable text in category "'..pagename..'".')return { ['vtype'] = 'error', ['v'] = p.failedcat(errors, 'V') }end--[[==========================================================================]]--[[                                  Main                                    ]]--[[==========================================================================]]function p.navseasoncats( frame )--arg checks & handlinglocal args = frame:getParent().argscheckforunknownparams(args)       --for template argscheckforunknownparams(frame.args) --for #invoke'd argslocal cat  = args['cat']                --'testcase' alias for catspacelocal list = args['list-all-links']     --debugging utility to output all links & followed #Rslocal follow = args['follow-redirects'] --default 'yes'local testcase    = args['testcase']local testcasegap = args['testcasegap']local minimum = args['min']local maximum = args['max']local skip_gaps = args['skip-gaps']--apply argslocal pagename = testcase or cat or currtitle.textlocal testcaseindent = ''if testcasecolon == ':' then testcaseindent = '\n::' endif follow and follow == 'no' then followRs = false endif list and list == 'yes' then listall = true endif skip_gaps and skip_gaps == 'yes' thenskipgaps = truetrackcat(26, 'Navseasoncats using skip-gaps parameter')end--ns checksif currtitle.nsText == 'Category' thenif cat and cat ~= '' thentrackcat(1, 'Navseasoncats using cat parameter')endif testcase and testcase ~= '' thentrackcat(2, 'Navseasoncats using testcase parameter')endelseif currtitle.nsText == '' thentrackcat(30, 'Navseasoncats in mainspace')end--find the variable parts of pagenamelocal findvar = find_var(pagename)if findvar.vtype == 'error' then --basic format error checking in find_var()return findvar.v..table.concat(ttrackingcats)endlocal start = string.match(findvar.v, '^%d+')--the rest is staticlocal findvar_escaped = string.gsub( findvar.v, '%-', '%%%-')local firstpart, lastpart = string.match(pagename, '^(.-)'..findvar_escaped..'(.*)$')if findvar.vtype == 'tvseason' then --double check for cases like '30 Rock (season 3) episodes'firstpart, lastpart = string.match(pagename, '^(.-season )'..findvar_escaped..'(.*)$')if firstpart == nil thenfirstpart, lastpart = string.match(pagename, '^(.-series )'..findvar_escaped..'(.*)$')endendfirstpart = mw.text.trim(firstpart or '')lastpart  = mw.text.trim(lastpart or '')--call the appropriate nav function, in order of decreasing popularityif findvar.vtype == 'year' then     --e.g. "500", "2001"; nav_year..nav_decade; ~75% of catslocal nav1 = nav_year( frame, firstpart, start, lastpart, minimum, maximum )..testcaseindent..table.concat(ttrackingcats)local dec = math.floor(findvar.v/10)local decadecat = nillocal firstpart_dec = firstpartif firstpart_dec ~= '' thenfirstpart_dec = firstpart_dec..' the'elseif firstpart_dec == 'AD' and dec <= 1 thenfirstpart_dec = ''if dec == 0 then dec = '' endendlocal decade = dec..'0s 'decadecat = mw.text.trim( firstpart_dec..' '..decade..lastpart )local exists = catexists(decadecat)if exists thennavborder = falsetrackcat(28, 'Navseasoncats year and decade')local nav2 = nav_decade( frame, firstpart_dec, decade, lastpart, minimum, maximum )..testcaseindent..table.concat(ttrackingcats)return nav1nav2( nav1, nav2 )elseif ttrackingcats[16] ~= '' then --nav_year isolated; check nav_hyphen (e.g. UK MPs 1974, Moldovan MPs 2009, etc.)local hyphen = '–'local finish = startlocal nav2 = nav_hyphen( frame, start, hyphen, finish, firstpart, lastpart, minimum, maximum, testcasegap )..testcaseindent..table.concat(ttrackingcats)if ttrackingcats[16] ~= '' then return nav1 --still isolated; rv to nav_yearelse return nav2 endelse --regular nav_yearreturn nav1endelseif findvar.vtype == 'decade' then   --e.g. "0s", "2010s"; nav_decade..nav_nordinal; ~12% of catslocal nav1 = nav_decade( frame, firstpart, start, lastpart, minimum, maximum )..testcaseindent..table.concat(ttrackingcats)local decade = tonumber(string.match(findvar.v, '^(%d+)s'))local century = math.floor( ((decade-1)/100) + 1 ) --from {{CENTURY}}if century == 0 then century = 1 end --no 0th centuryif string.match(decade, '00$') thencentury = century + 1 --'2000' is in the 20th, but the rest of the 2000s is in the 21stendlocal clastpart = ' century '..lastpartlocal centurycat = mw.text.trim( firstpart..' '..p.addord(century)..clastpart )local exists = catexists(centurycat)if not exists then --check for hyphenated centuryclastpart = '-century '..lastpartcenturycat = mw.text.trim( firstpart..' '..p.addord(century)..clastpart )exists = catexists(centurycat)endif exists thennavborder = falsetrackcat(29, 'Navseasoncats decade and century')local nav2 = nav_nordinal( frame, firstpart, century, clastpart, minimum, maximum )..testcaseindent..table.concat(ttrackingcats)return nav1nav2( nav1, nav2 )elsereturn nav1endelseif findvar.vtype == 'nordinal' then --e.g. "1st", "99th"; ~7.5% of catsreturn nav_nordinal( frame, firstpart, start, lastpart, minimum, maximum )..testcaseindent..table.concat(ttrackingcats)elseif findvar.vtype == 'season' then   --e.g. "1–4", "1999–2000", "2001–02", "2001–2002", "2005–2010", etc.; ~5.25%local hyphen, finish = mw.ustring.match(findvar.v, '%d([–-])(%d+)') --ascii 150 & 45 (ndash & keyboard hyphen); mw req'dreturn nav_hyphen( frame, start, hyphen, finish, firstpart, lastpart, minimum, maximum, testcasegap )..testcaseindent..table.concat(ttrackingcats)elseif findvar.vtype == 'tvseason' then --e.g. "1", "15" but preceded with "season" or "series"; <1% of catsreturn nav_tvseason( frame, firstpart, start, lastpart, maximum )..testcaseindent..table.concat(ttrackingcats) --"minimum" defaults to 1elseif findvar.vtype == 'wordinal' then --e.g. "first", "ninety-ninth"; <<1% of catslocal ordinal = 'on'return nav_wordinal( frame, firstpart, findvar.v, lastpart, minimum, maximum, ordinal, frame )..testcaseindent..table.concat(ttrackingcats)elseif findvar.vtype == 'enumeric' then --e.g. "one", "ninety-nine"; <<1% of catslocal ordinal = 'off'return nav_wordinal( frame, firstpart, findvar.v, lastpart, minimum, maximum, ordinal, frame )..testcaseindent..table.concat(ttrackingcats)elseif findvar.vtype == 'roman' then    --e.g. "I", "XXVIII"; <<1% of catsreturn nav_roman( frame, firstpart, findvar.v, lastpart, minimum, maximum )..testcaseindent..table.concat(ttrackingcats)elseif findvar.vtype == 'ending' then   --e.g. "2021–" (irregular; ending unknown); <<<1% of catslocal hyphen, finish = mw.ustring.match(findvar.v, '%d([–-])present$'), -1 --ascii 150 & 45 (ndash & keyboard hyphen); mw req'dif hyphen == nil thenhyphen, finish = mw.ustring.match(findvar.v, '%d([–-])$'), 0 --0/-1 are hardcoded switches for nav_hyphen()endreturn nav_hyphen( frame, start, hyphen, finish, firstpart, lastpart, minimum, maximum, testcasegap )..testcaseindent..table.concat(ttrackingcats)else                                 --malformederrors = p.errorclass('Failed to determine the appropriate nav function from malformed season "'..findvar.v..'". ')return p.failedcat(errors, 'N')..table.concat(ttrackingcats)endendreturn p
"https:https://www.search.com.vn/wiki/index.php?lang=ta&q=Module:Navseasoncats/மணல்தொட்டி&oldid=3532532" இலிருந்து மீள்விக்கப்பட்டது
🔥 Top keywords: தியாகத் திருநாள்சிறப்பு:Searchமுதற் பக்கம்சுப்பிரமணிய பாரதிபாரதிதாசன்தமிழ்வாஞ்சிநாதன்ஐம்பெருங் காப்பியங்கள்ஐம்பூதங்கள்வெ. இராமலிங்கம் பிள்ளைஎட்டுத்தொகைதமிழ்நாட்டின் மாவட்டங்கள்பெண் தமிழ்ப் பெயர்கள்திருக்குறள்காமராசர்பதினெண் கீழ்க்கணக்குதமிழ்த் திரைப்படங்களின் பட்டியல் (ஆண்டு வரிசை)கடையெழு வள்ளல்கள்திருவள்ளுவர்சிலப்பதிகாரம்சிறப்பு:RecentChangesதமிழ்ப் பழமொழிகளின் பட்டியல்பாரிஐஞ்சிறு காப்பியங்கள்ஆ. ப. ஜெ. அப்துல் கலாம்தம்பி ராமையாதமிழ்நாடுகண்ணதாசன்பெயர்வாரியாக தனிமங்களின் பட்டியல்மரபுச்சொற்கள்பத்துப்பாட்டுவிநாயகர் அகவல்தஞ்சைப் பெருவுடையார் கோயில்பதினெண்மேற்கணக்குபஞ்சபூதத் தலங்கள்முருகன்சுற்றுச்சூழல் பாதுகாப்புதொல்காப்பியம்பீப்பாய்