Die Dokumentation für dieses Modul kann unter Modul:Sort/cellNum/Doku erstellt werden
local Sort = { suite = "Sort", sub = "cellNum", serial = "2020-11-12", item = 88370026, globals = { Cell = 90144855, FormatNum = 15709679 } } --[=[ Sort/cellNum support table cells with numerical content and number formatting ]=] local Failsafe = Sort local GlobalMod = Sort Sort.digits = { { 0x30 }, { 0x0660, "Arab" }, { 0x06F0, "Arab" }, { 0x07C0, "Nkoo" }, { 0x0966, "Deva" }, { 0x09E6, "Beng" }, { 0x0A66, "Guru" }, { 0x0AE6, "Gujr" }, { 0x0B66, "Orya" }, { 0x0BE6, "Taml" }, { 0x0C66, "Telu" }, { 0x0CE6, "Knda" }, { 0x0D66, "Mlym" }, { 0x0DE6, "Sinh" }, { 0x0E50, "Thai" }, { 0x0ED0, "Laoo" }, { 0x0F20, "Tibt" }, { 0x102E, "Copt" }, { 0x1040, "Mymr" }, { 0x1369, "Ethi" }, { 0x17E0, "Khmr" }, { 0x1810, "Mong" }, { 0x1946, "Limb" }, { 0x19D0, "Talu" }, { 0x1A80, "Lana" }, { 0x1A90, "Lana" }, { 0x1B50, "Bali" }, { 0x1BB0, "Sund" }, { 0x1C40, "Lepc" }, { 0x1C50, "Olck" }, { 0xA620, "Vaii" }, { 0xA8D0, "Saur" }, { 0xA900, "Kali" }, { 0xA9D0, "Java" }, --{ 0xA9F0, "" }, MYANMAR TAI LAING { 0xAA50, "Cham" }, { 0xABF0, "Mtei" }, { 0xFF10 }, -- FULLWIDTH { 0x1104A, "Osma" }, { 0x110D3, "Rohg" }, --{ 0x110E6, "" }, RUMI { 0x11106, "Brah" }, { 0x1110F, "Sora" }, { 0x11113, "Cakm" }, { 0x1111D, "Shrd" }, { 0x1112F, "Sind" }, { 0x11145, "Newa" }, { 0x1114D, "Tirh" }, { 0x11165, "Modi" }, { 0x1116C, "Takr" }, { 0x11173, "Ahom" }, { 0x1118E, "Wara" }, { 0x111C5, "Bhks" }, { 0x111D5, "Gonm" }, { 0x111DA, "Gong" }, { 0x116A6, "Mroo" }, { 0x116B5, "Hmng" }, { 0x116E8, "Medf" }, { 0x11E14, "Hmnp" }, { 0x11E2F, "Wcho" }, { 0x11E8C, "Mend" }, { 0x11E95, "Adlm" }, { 0x1D7F6 }, -- MATHEMATICAL MONOSPACE { 0xE0030 } -- Tags } Sort.heading = { [0x2D] = 45, -- - [0x2212] = 45, -- - [0x2B] = 43, -- + [0xFF0B] = 43, -- + [0xFF0D] = 45 -- - } Sort.mpz = -0.5 Sort.prefix = { [0x003C] = -5, [0x003E] = 5, [0x00B1] = true, [0x2248] = false, [0x2264] = -2, [0x2265] = 2 } Sort.supreme = mw.ustring.char( 8734 ) -- infinit local foreignModule = function ( access, advanced, append, alt, alert ) -- Fetch global module -- Precondition: -- access -- string, with name of base module -- advanced -- true, for require(); else mw.loadData() -- append -- string, with subpage part, if any; or false -- alt -- number, of wikidata item of root; or false -- alert -- true, for throwing error on data problem -- Postcondition: -- Returns whatever, probably table -- 2020-01-01 local storage = access local finer = function () if append then storage = string.format( "%s/%s", storage, append ) end end local fun, lucky, r, suited if advanced then fun = require else fun = mw.loadData end GlobalMod.globalModules = GlobalMod.globalModules or { } suited = GlobalMod.globalModules[ access ] if not suited then finer() lucky, r = pcall( fun, "Module:" .. storage ) end if not lucky then if not suited and type( alt ) == "number" and alt > 0 then suited = string.format( "Q%d", alt ) suited = mw.wikibase.getSitelink( suited ) GlobalMod.globalModules[ access ] = suited or true end if type( suited ) == "string" then storage = suited finer() lucky, r = pcall( fun, storage ) end if not lucky and alert then error( "Missing or invalid page: " .. storage ) end end return r end -- foreignModule() local fetch = function ( access, advanced, append ) -- Fetch global library -- Precondition: -- access -- string|false, with name of base module -- advanced -- true, for require(); else mw.loadData() -- append -- string, with subpage part, if any; or false local store, sub, suite if access then suite = access store = access sub = append else suite = Sort.suite if append then sub = append:lower() store = append else store = "Sorter" end end if type( Sort[ store ] ) == "nil" then local bib = foreignModule( suite, advanced, sub, Sort.globals[ store ], not access ) if bib and type( bib[ suite ] ) == "function" then Sort[ store ] = bib[ suite ]() elseif advanced then error( tostring( bib ) ) else Sort[ store ] = bib end end return Sort[ store ] end -- fetch() local factory = function ( ask ) -- Ensure config data -- Precondition: -- assign -- string|nil, particular query -- Postcondition: -- config data available -- Returns elements for "*", 10, 1000, fractpart local r if not ask then Sort.minus = Sort.minus or mw.ustring.char( 0x2212 ) elseif ask == "sep" then if not Sort.sepDec then local seek = "%d(%p?)(%d?%d?456)(%p)7" local s Sort.contLang = Sort.contLang or mw.language.getContentLanguage() s = Sort.contLang:formatNum( 123456.7 ) Sort.sepGroup, s, Sort.sepDec = mw.ustring.match( s, seek ) Sort.sepDec = Sort.sepDec or "." Sort.keyDec = mw.ustring.codepoint( Sort.sepDec, 1, 1 ) if s then Sort.nGroup = #s end if Sort.sepDec == "." then Sort.seekDec = "%%." else Sort.seekDec = Sort.sepDec end if Sort.sepGroup and Sort.sepGroup ~= "" then if Sort.sepGroup == "." then Sort.seekGroup = "%." else Sort.seekGroup = Sort.sepGroup end Sort.separated = string.format( "%s%%d%%d%%d%s", Sort.seekGroup, Sort.seekGroup ) end end elseif ask == "dec" then if not Sort.spanDec then if Sort.sepDec == "." then Sort.spanDec = "." else local e = mw.html.create( "span" ) :addClass( "numericFormat-dec" ) :node( mw.html.create( "span" ) :wikitext( "." ) ) Sort.spanDec = tostring( e ) end end elseif ask == "minus" then if not Sort.spanMinus then local e = mw.html.create( "span" ) :addClass( "numericFormat-minus" ) :node( mw.html.create( "span" ) :wikitext( "-" ) ) Sort.spanMinus = tostring( e ) end elseif ask == 1000 then r = mw.html.create( "span" ) :addClass( "numericFormat-1000" ) elseif ask == "fractpart" then r = mw.html.create( "span" ) :addClass( "numericFormat-fractpart" ) elseif ask == "*" then r = mw.html.create( "span" ) :addClass( "numericFormat-multiply" ) elseif ask == 10 then r = mw.html.create( "span" ) :addClass( "numericFormat-10" ) -- ::before { content: "10"; } end return r end -- factory() local feeder = function ( access ) -- Retrieve first TemplateStyles transclusion -- Precondition: -- access -- string, TemplateStyles ID local ts = Sort[ access ] local r if ts and not ts.loaded then local s = type( ts.origin ) local src ts.loaded = true if s == "string" then src = ts.origin elseif s == "table" then src = ts.origin.prefixedText end if src then Sort.frame = Sort.frame or mw.getCurrentFrame() r = Sort.frame:extensionTag( "templatestyles", nil, { src = src } ) end end return r or "" end -- feeder() local fine = function ( about ) -- Equip number with styled special characters -- Precondition: -- about -- table, parameters of base number -- .show -- string, digits -- .low -- boolean, heading minus -- .sign -- string, heading sign -- .sub -- string, decimal fraction -- .long -- boolean, grouping possible -- Postcondition: -- Returns updated entire presentation local r if about.long then factory( "sep" ) local n = mw.ustring.len( about.show ) local k = n - Sort.nGroup + 1 local i, m, e, s r = mw.ustring.sub( about.show, k ) n = k - Sort.nGroup for j = n, -1, - Sort.nGroup do if j > 0 then i = j else i = 1 end m = j + Sort.nGroup - 1 s = mw.ustring.sub( about.show, i, m ) e = factory( 1000 ):wikitext( s ) r = tostring( e ) .. r end -- for j end r = r or about.show or about.scream if about.low then factory( "minus" ) r = Sort.spanMinus .. r elseif about.sign then r = about.sign .. r end if about.sub then local s = about.sub factory( "sep" ) factory( "dec" ) r = r .. Sort.spanDec if Sort.nGroup then local n = mw.ustring.len( s ) if n > Sort.nGroup + 2 then local k = 0 local m = n - Sort.nGroup local e, sg for j = 1, m, Sort.nGroup do sg = mw.ustring.sub( about.sub, j, j + Sort.nGroup - 1 ) e = factory( "fractpart" ):wikitext( sg ) r = r .. tostring( e ) k = k + Sort.nGroup end -- for j s = s:sub( k + 1, n ) end end r = r .. s end return feeder( "cssNum" ) .. r end -- fine() local fined = function ( all, assign ) -- Append styled number -- Precondition: -- all -- string, formatted entire presentation -- assign -- table, exponent -- .show -- string, digits -- .low -- boolean, < 0 -- Postcondition: -- Returns -- 1. string, updated entire presentation -- 2. string, styled number local r1 = all local r2 = assign.show if assign.low then if Sort.cssNum then factory( "minus" ) r2 = Sort.spanMinus .. r2 r1 = feeder( "cssNum" ) .. r1 else factory() r2 = Sort.minus .. r2 end end return r1, r2 end -- fined() local finest = function ( args, ahead ) -- Append styled decimal power -- Precondition: -- args -- table, parameters -- .exp -- table, exponent -- ahead -- string, formatted presentation -- Postcondition: -- Returns expanded presentation local r = string.format( "%s%s%s", feeder( "cssNum" ), feeder( "cssNumExp" ), ahead ) local em = factory( "*" ) local ep = factory( 10 ) local s r, s = fined( r, args.exp ) em:wikitext( "e" ) ep:node( mw.html.create( "sup" ) :wikitext( s ) ) s = Sort.Cell.feature( args, "color" ) or "#000000" em:css( "background-color", s ) r = string.format( "%s%s%s", r, tostring( em ), tostring( ep ) ) return r end -- finest() local flat = function ( assign, after, adjust ) -- Parse decimal number -- Precondition: -- assign -- string, number to be parsed -- after -- boolean, decimal separator expected -- adjust -- number|boolean|nil, cheat sort figure -- Postcondition: -- Returns table, with analysis -- .long -- >= 1000 etc. -- .low -- < 0 -- .sign -- minus, plus -- .show -- leading digits, scripting -- .sub -- decimal fragment digits, scripting -- .sort -- signed ASCII sort text -- .script -- script code -- .scream -- error text local r = { } local s = assign local k, init local face = function () local j if init == 45 then j = 8722 else j = init end return mw.ustring.char( j ) end -- face() factory( "sep" ) if s:find( "&", 1, true ) then s = mw.text.decode( s ) :gsub( " ", mw.ustring.char( 0x2009 ) ) end s = mw.ustring.gsub( s, "%s", "" ) k = mw.ustring.codepoint( s, 1, 1 ) if k then init = Sort.heading[ k ] if init then if mw.ustring.len( s ) > 1 then s = mw.ustring.sub( s, 2 ) k = mw.ustring.codepoint( s, 1, 1 ) r.low = ( init == 45 ) else k = 0x30 s = "0" end end else k = 0x30 s = "0" end if after then local m = mw.ustring.find( s, Sort.sepGroup, 1, true ) local dig, j0, j9, n if m and Sort.separated and mw.ustring.match( s, Sort.separated ) then s = mw.ustring.gsub( s, Sort.seekGroup, "" ) end for i = 1, #Sort.digits do dig = Sort.digits[ i ] j0 = dig[ 1 ] j9 = j0 + 9 if k >= j0 and k <= j9 then r.script = dig[ 2 ] n = mw.ustring.len( s ) break -- for i elseif k < j0 then break -- for i end end -- for i if n then m = 0 for i = 1, n do if k == j0 then m = i if i < n then k = mw.ustring.codepoint( s, i + 1, i + 1 ) end else break -- for i end end -- for i if m > 0 then s = mw.ustring.sub( s, m + 1 ) n = n - m end m = 0 for i = 1, n do if k == Sort.keyDec or k == 46 then k = false break -- for i elseif k >= j0 and k <= j9 then r.sort = string.format( "%s%c", r.sort or "", k - j0 + 48 ) if i < n then k = mw.ustring.codepoint( s, i + 1, i + 1 ) end m = i end end -- for i if m > 0 then r.long = ( m > Sort.nGroup ) r.sort = r.sort or "0" r.show = mw.ustring.sub( s, 1, m ) if not k then m = m + 1 s = mw.ustring.sub( s, m + 1 ) end n = n - m else r.show = mw.ustring.char( j0 ) r.sort = "0" if not k then s = mw.ustring.sub( s, 2 ) n = n - 1 end end if r.low and r.sort ~= "0" then r.sort = "-" .. r.sort end if n > 0 then if k then r.scream = s else r.sort = r.sort .. Sort.sepDec k = mw.ustring.codepoint( s, 1, 1 ) for i = 1, n do if k and k >= j0 and k <= j9 then r.sort = string.format( "%s%c", r.sort, k - j0 + 48 ) if i < n then k = mw.ustring.codepoint( s, i + 1, i + 1 ) end else k = false end end -- for i if k then r.sub = s else r.scream = s r.show = false end end end if adjust then if adjust == true then -- plus/minus r.sort = "0" elseif r.sort then k = tonumber( r.sort ) if k then local m = k * 0.0000000001 if m < 0 then m = -m end k = k + m * adjust r.sort = tostring( k ) end end end else r.scream = assign end if init and not r.scream then r.sign = face() end else k = tonumber( s ) if k and k >= 0 then k = math.floor( k ) r.show = tostring( k ) r.sort = r.show if init then r.sign = face() if init == 45 then r.sort = "-" .. r.sort end end else r.scream = assign end end return r end -- flat() local fore = function ( args ) -- Create and merge sort attribute -- Precondition: -- args -- table, parameters -- .n -- table, for base number -- .sort -- string|nil -- .exp -- table|nil, for exponent -- amount -- number, for base -- Postcondition: -- attributes extended local s = args.n.sort or "0" if args.exp and args.exp.sort then s = string.format( "%sE%s", s, args.exp.sort ) end Sort.Cell.faced( args, s ) end -- fore() local format = function ( args ) -- Format visible number -- Precondition: -- args -- table, parameters -- .pad -- number|false, for padding -- .pre -- string|false, for prefix -- .n -- table, for base -- .low -- boolean, < 0 -- .sign -- minus, plus -- .show -- leading digits -- .sub -- decimal fragment digits -- .script -- script code -- .suffix -- string|false, extending base -- .exp -- table|false, for exponent -- .post -- string|false, for postfix -- .round -- number|false, for rounding -- .cell -- boolean, enfoce sort value -- Postcondition: -- Returns string local r = args.n.show or args.n.scream local e, move, s, shift if args.pad and args.pad < 0 then move = args.pad + mw.ustring.len( args.n.show ) if args.n.sign then move = move + 1 end if move < 0 then move = move + 1 end if args.pre and move then move = move + mw.ustring.len( args.pre ) + 1 end end if move then if move < 0 then if not Sort.shift then if Sort.Cell.following() then Sort.shift = "left" else Sort.shift = "right" end Sort.shift = "padding-" .. Sort.shift end Sort.Cell.feature( args, Sort.shift, string.format( "%.2fem", Sort.mpz * move ) ) end elseif args.pad then move = args.pad if args.n.sub then move = move - mw.ustring.len( args.n.sub ) - 1 if args.suffix then move = move - mw.ustring.len( args.suffix ) end else move = move + 0.5 end if args.post then move = move - mw.ustring.len( args.post ) - 1 end if move > 0 then shift = string.rep( "0", move ) e = mw.html.create( "span" ) :css( "visibility", "hidden" ) :wikitext( shift ) shift = tostring( e ) end end if args.n.low or args.n.long or args.n.sub then r = fine( args.n ) end if args.suffix then r = r .. args.suffix end if args.exp then if Sort.cssNumExp then r = finest( args, r ) else Sort.stick = Sort.stick or mw.ustring.char( 0xB7 ) r, s = fined( r, args.exp ) e = mw.html.create( "sup" ) :wikitext( s ) r = string.format( "%s%s10%s", r, Sort.stick, tostring( e ) ) end end if args.pre or args.n.long or args.n.sub or args.exp or args.post or args.n.script then if args.pre then r = string.format( "%s %s", args.pre, r ) end if args.post then r = string.format( "%s %s", r, args.post ) end e = mw.html.create( "span" ) :css( "white-space", "nowrap" ) :wikitext( r ) if ( args.pre or args.post ) and not Sort.Cell.following() then e:attr( "dir", "ltr" ) end if args.n.script then e:attr( "lang", "und-" .. args.n.script ) end r = tostring( e ) end if shift then r = r .. shift end if args.pad or args.pre or ( args.cell and ( args.n.low or args.n.sign or args.n.sub or args.n.long or args.suffix or args.exp or args.n.script ) ) then fore( args ) end return r end -- format() local front = function ( analyse ) -- Interprete heading text in front of number -- Parameter: -- analyse -- string, with probably prefixed number -- Postcondition: -- Returns -- 1. string|nil -- prefix -- 2. string|nil -- remaining text, hopefully number -- 3. number|nil -- weight, cheat sort figure local i, r1, r2, r3 local s = analyse if s:find( "&", 1, true ) then s = mw.text.decode( s ) if s:find( "&", 1, true ) then local html = { lt = 0x003C, gt = 0x003E, plusmn = 0x00B1, asymp = 0x2248, le = 0x2264, ge = 0x2265 } for k, v in pairs( html ) do s = s:gsub( string.format( "&%s;", k ), mw.ustring.char( v ) ) end -- for k, v end end i = mw.ustring.codepoint( s, 1, 1 ) for k, v in pairs( Sort.prefix ) do if k == i then r1 = mw.ustring.char( k ) r2 = mw.text.trim( mw.ustring.sub( s, 2 ) ) r3 = v break -- for k, v end end -- for k, v if not r1 then local Value = fetch( "Text", false, "value" ) if Value and type( Value.prefix ) == "table" then for k, v in pairs( Value.prefix ) do i = mw.ustring.len( k ) if k == mw.ustring.sub( s, 1, i ) then r1 = k r2 = mw.text.trim( mw.ustring.sub( s, i + 1 ) ) r3 = v break -- for k, v end end -- for k, v end end return r1, r2, r3 end -- front() local furnish = function ( args ) -- Execute task -- Parameter: -- args -- table, parameters -- Postcondition: -- Returns string, or expands .cell -- Throws error on failure local r fetch( false, true, "Cell" ) if type( args ) == "table" then local present = Sort.Cell.first( args ) local s = type( args.exp ) if s == "string" then Sort.Cell.fair( args, "exp", present ) elseif s == "number" then present.exp = args.exp end Sort.Cell.fair( args, "pre", present ) s = type( args.n ) if s == "string" then s = mw.text.trim( args.n ) if s == Sort.supreme then present.infinit = 1 elseif mw.ustring.len( s ) == 2 and mw.ustring.codepoint( s, 2, 2 ) == 8734 then local m = mw.ustring.codepoint( s, 1, 1 ) if m == 45 or m == 8722 then present.infinit = -1 elseif m == 43 then present.infinit = 1 end end if not present.infinit then if not present.exp then local i = s:find( "%d[.,]?[eE]%-?%d+$" ) if i then local split = s:sub( i + 2 ):upper() if split:sub( 1, 1 ) == "E" then split = split:sub( 2 ) end present.exp = split s = s:sub( 1, i ) end end present.n = flat( s, true ) if present.n.scream and not present.pre then local move present.pre, s, move = front( s ) if present.pre then present.n = flat( s, true, move ) end end end elseif s == "number" then local k = args.n present.n = { low = ( k < 0 ), sort = tostring( k ) } present.n.show = present.n.sort if present.n.low then present.n.show = present.n.show:sub( 2 ) end k = present.n.show:find( ".", 1, true ) if k then present.n.sub = present.n.show:sub( k + 1 ) k = k - 1 present.n.show = present.n.show:sub( 1, k ) else k = mw.ustring.len( present.n.show ) end present.n.long = ( k > Sort.nGroup ) end if present.n or present.infinit then if present.n then local lazy s = type( present.exp ) if s == "string" then present.exp = flat( present.exp ) elseif s == "number" then local k = present.exp present.exp = { low = ( k < 0 ) } if present.exp.low then k = -1 * k end k = math.floor( k ) present.exp.show = tostring( k ) if k > 0 then present.exp.sort = present.exp.show if present.exp.low then present.exp.sort = "-" .. present.exp.sort end end end s = type( args.lazy ) if s == "string" then lazy = ( args.lazy == "1" ) elseif s == "" then lazy = args.lazy end if lazy then fore( present ) else Sort.Cell.fair( args, "suffix", present ) s = type( args.pad ) if s == "string" then present.pad = tonumber( args.pad ) elseif s == "number" then present.pad = args.pad end if present.pad and present.pad == 0 then present.pad = false end Sort.Cell.fair( args, "post", present ) if not present.n.low then s = type( args.plus ) if s == "string" then if args.plus == "1" or args.plus == "+" then present.n.sign = "+" end elseif s == "boolean" then present.n.sign = "+" end end if args.cssNum and not Sort.cssNum then Sort.cssNum = { } Sort.cssNum.origin = args.cssNum end if args.cssNumExp and not Sort.cssNumExp then Sort.cssNumExp = { } Sort.cssNumExp.origin = args.cssNumExp end r = format( present ) end else present.n = { sort = "9999999" } if present.infinit < 0 then present.n.sort = "-" .. present.n.sort end present.exp = { sort = "301" } fore( present ) end r = Sort.Cell.finalize( present, r ) else Sort.Cell.fault( "???", args ) end else error( "'args' is not a table" ) end return r end -- furnish() Sort.f = function ( args ) -- Create table cell start -- Parameter: -- args -- table, parameters -- .pad -- number|string, for padding -- .pre -- string, for prefix -- .plus -- boolean|string, for plus sign -- .n -- number|string, for base -- .suffix -- string, extending base -- .exp -- number|string, for exponent -- .post -- string, for postfix -- .round -- number|string, for rounding -- .lazy -- string|boolean, mute -- .cell -- string|boolean|table, enforce sort -- .rowspan -- number|string, for cell attribute -- .colspan -- number|string, for cell attribute -- .class -- string, for cell attribute -- .style -- string|table, for cell attribute -- .id -- string, for cell attribute -- .cssNum -- string|title, for templatestyles -- .cssNumExp -- string|title, for templatestyles -- .cat -- string|nil, for error category -- .frame -- table, if present -- Postcondition: -- Returns string, or expands .cell, or nil local lucky, r = pcall( furnish, args ) if not lucky then local e = mw.html.create( "span" ) :addClass( "error" ) :wikitext( "Module:Sort/cell * " .. r ) if type( args.cell ) == "table" and type( args.cell.wikitext ) == "function" then args.cell:node( e ) else r = tostring( e ) end end return r end -- Sort.f() Sort.furnish = function () -- Retrieve list of project prefixes -- Postcondition: -- Returns string -- with wikitext list local r, Value for k, v in pairs( Sort.prefix ) do if r then r = r .. "\n" else r = "" end r = string.format( "%s* %s", r, mw.ustring.char( k ) ) end -- for k, v Value = fetch( "Text", false, "value" ) if Value and type( Value.prefix ) == "table" then for k, v in pairs( Value.prefix ) do r = string.format( "%s\n* %s", r, k ) end -- for k, v end return r end -- Sort.furnish() Failsafe.failsafe = function ( atleast ) -- Retrieve versioning and check for compliance -- Precondition: -- atleast -- string, with required version or "wikidata" or "~" -- or false -- Postcondition: -- Returns string -- with queried version, also if problem -- false -- if appropriate -- 2019-10-15 local last = ( atleast == "~" ) local since = atleast local r if last or since == "wikidata" then local item = Failsafe.item since = false if type( item ) == "number" and item > 0 then local entity = mw.wikibase.getEntity( string.format( "Q%d", item ) ) if type( entity ) == "table" then local seek = Failsafe.serialProperty or "P348" local vsn = entity:formatPropertyValues( seek ) if type( vsn ) == "table" and type( vsn.value ) == "string" and vsn.value ~= "" then if last and vsn.value == Failsafe.serial then r = false else r = vsn.value end end end end end if type( r ) == "nil" then if not since or since <= Failsafe.serial then r = Failsafe.serial else r = false end end return r end -- Failsafe.failsafe() -- Export local p = { } p.f = function ( frame ) -- Template call Sort.frame = frame return Sort.f( frame.args ) or "" end -- p.f p.furnish = function () return Sort.furnish() end -- p.f p.failsafe = function ( frame ) -- Versioning interface local s = type( frame ) local since if s == "table" then since = frame.args[ 1 ] elseif s == "string" then since = frame end if since then since = mw.text.trim( since ) if since == "" then since = false end end return Failsafe.failsafe( since ) or "" end -- p.failsafe p.Sort = function () -- Module interface return Sort end return p