<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.limswiki.org/index.php?action=history&amp;feed=atom&amp;title=Module%3AArchive_list</id>
	<title>Module:Archive list - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://www.limswiki.org/index.php?action=history&amp;feed=atom&amp;title=Module%3AArchive_list"/>
	<link rel="alternate" type="text/html" href="https://www.limswiki.org/index.php?title=Module:Archive_list&amp;action=history"/>
	<updated>2026-04-05T19:43:13Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.36.1</generator>
	<entry>
		<id>https://www.limswiki.org/index.php?title=Module:Archive_list&amp;diff=13230&amp;oldid=prev</id>
		<title>Shawndouglas: Created as needed.</title>
		<link rel="alternate" type="text/html" href="https://www.limswiki.org/index.php?title=Module:Archive_list&amp;diff=13230&amp;oldid=prev"/>
		<updated>2013-10-31T17:04:37Z</updated>

		<summary type="html">&lt;p&gt;Created as needed.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;-- This module implements {{archive list}} in Lua, and adds a few&lt;br /&gt;
-- new features.&lt;br /&gt;
&lt;br /&gt;
-- Process a numeric argument to make sure it is a positive&lt;br /&gt;
-- integer.&lt;br /&gt;
local function processNumArg( num )&lt;br /&gt;
    if num then&lt;br /&gt;
        num = tonumber( num )&lt;br /&gt;
        if type( num ) == 'number' then&lt;br /&gt;
            num = math.floor( num )&lt;br /&gt;
            if num &amp;gt;= 0 then&lt;br /&gt;
                return num&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Checks whether a page exists, going through pcall&lt;br /&gt;
-- in case we are over the expensive function limit.&lt;br /&gt;
local function checkPageExists( title )&lt;br /&gt;
    if not title then&lt;br /&gt;
        error('No title passed to checkArchiveExists', 2)&lt;br /&gt;
    end&lt;br /&gt;
    local noError, titleObject = pcall(mw.title.new, title)&lt;br /&gt;
    if not noError then&lt;br /&gt;
        -- If we are over the expensive function limit then assume&lt;br /&gt;
        -- that the page doesn't exist.&lt;br /&gt;
        return false&lt;br /&gt;
    else&lt;br /&gt;
        if titleObject then&lt;br /&gt;
            return titleObject.exists&lt;br /&gt;
        else&lt;br /&gt;
            return false -- Return false if given a bad title.&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Checks every nth archive to see if it exists, and returns the&lt;br /&gt;
-- number of the first archive that doesn't exist. It is&lt;br /&gt;
-- necessary to do this in batches because each check is an&lt;br /&gt;
-- expensive function call, and we want to avoid making too many&lt;br /&gt;
-- of them so as not to go over the expensive function limit.&lt;br /&gt;
local function checkArchives( prefix, n, start )&lt;br /&gt;
    local i = start&lt;br /&gt;
    local exists = true&lt;br /&gt;
    while exists do&lt;br /&gt;
        exists = checkPageExists( prefix .. tostring( i ) )&lt;br /&gt;
        if exists then&lt;br /&gt;
            i = i + n&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return i&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Return the biggest archive number, using checkArchives()&lt;br /&gt;
-- and starting in intervals of 1000. This should get us a&lt;br /&gt;
-- maximum of 500,000 possible archives before we hit the&lt;br /&gt;
-- expensive function limit.&lt;br /&gt;
local function getBiggestArchiveNum( prefix, max )&lt;br /&gt;
    -- Return the value for max if it is specified.&lt;br /&gt;
    max = processNumArg( max )&lt;br /&gt;
    if max then&lt;br /&gt;
        return max&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    -- Otherwise, detect the largest archive number.&lt;br /&gt;
    local check1000 = checkArchives( prefix, 1000, 1 )&lt;br /&gt;
    if check1000 == 1 then&lt;br /&gt;
        return 0 -- Return 0 if no archives were found.&lt;br /&gt;
    end&lt;br /&gt;
    local check200 = checkArchives( prefix, 200, check1000 - 1000 )&lt;br /&gt;
    local check50 = checkArchives( prefix, 50, check200 - 200 )&lt;br /&gt;
    local check10 = checkArchives( prefix, 10, check50 - 50 )&lt;br /&gt;
    local check1 = checkArchives( prefix, 1, check10 - 10 )&lt;br /&gt;
    -- check1 is the first page that doesn't exist, so we want to&lt;br /&gt;
    -- subtract it by one to find the biggest existing archive.&lt;br /&gt;
    return check1 - 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the archive link prefix (the title of the archive pages&lt;br /&gt;
-- minus the number).&lt;br /&gt;
local function getPrefix( root, prefix, prefixSpace )&lt;br /&gt;
    local ret = root or mw.title.getCurrentTitle().prefixedText&lt;br /&gt;
    ret = ret .. '/'&lt;br /&gt;
    if prefix then&lt;br /&gt;
        ret = ret .. prefix&lt;br /&gt;
        if prefixSpace == 'yes' then&lt;br /&gt;
            ret = ret .. ' '&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        ret = ret .. 'Archive '&lt;br /&gt;
    end&lt;br /&gt;
    return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the number of archives to put on one line. Set to&lt;br /&gt;
-- math.huge if there should be no line breaks.&lt;br /&gt;
local function getLineNum( links, nobr )&lt;br /&gt;
    local linksToNum = tonumber( links )&lt;br /&gt;
    local lineNum&lt;br /&gt;
    if nobr == 'yes' or (links and not linksToNum) then&lt;br /&gt;
        lineNum = math.huge&lt;br /&gt;
    -- If links is a number, process it. Negative values and expressions&lt;br /&gt;
    -- such as links=8/2 produced some interesting values with the old&lt;br /&gt;
    -- template, but we will ignore those for simplicity.&lt;br /&gt;
    elseif type(linksToNum) == 'number' and linksToNum &amp;gt;= 0 then&lt;br /&gt;
        -- The old template rounded down decimals to the nearest integer.&lt;br /&gt;
        lineNum = math.floor( linksToNum )&lt;br /&gt;
        if lineNum == 0 then&lt;br /&gt;
            -- In the old template, values of links between 0 and 0.999&lt;br /&gt;
            -- suppressed line breaks.&lt;br /&gt;
            lineNum = math.huge&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        lineNum = 10 -- Default to 10 links.&lt;br /&gt;
    end&lt;br /&gt;
    return lineNum&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Gets the prefix to put before the archive links.&lt;br /&gt;
local function getLinkPrefix( prefix, space )&lt;br /&gt;
    -- Get the link prefix.&lt;br /&gt;
    local ret = ''&lt;br /&gt;
    if type(prefix) == 'string' then&lt;br /&gt;
        ret = prefix&lt;br /&gt;
        if space == 'yes' then&lt;br /&gt;
            ret = ret .. ' '&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the number to start listing archives from.&lt;br /&gt;
local function getStart( start )&lt;br /&gt;
    start = processNumArg( start )&lt;br /&gt;
    if start then&lt;br /&gt;
        return start&lt;br /&gt;
    else&lt;br /&gt;
        return 1&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Process the separator parameter.&lt;br /&gt;
local function getSeparator( sep )&lt;br /&gt;
    if sep and type(sep) == 'string' then&lt;br /&gt;
        if sep == 'dot' &lt;br /&gt;
            or sep =='pipe'&lt;br /&gt;
            or sep == 'comma'&lt;br /&gt;
            or sep == 'tpt-languages' then&lt;br /&gt;
            return mw.message.new( sep .. '-separator' ):plain()&lt;br /&gt;
        else&lt;br /&gt;
            return sep&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        return nil&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Generates the list of archive links. glargs.max must be either zero (for&lt;br /&gt;
-- no archives) or a positive integer value.&lt;br /&gt;
local function generateLinks( glargs )&lt;br /&gt;
    if type( glargs ) ~= 'table' or not glargs.max or not glargs.prefix then&lt;br /&gt;
        error('insufficient arguments passed to generateLinks', 2)&lt;br /&gt;
    end&lt;br /&gt;
    -- If there are no archives yet, return a message and a&lt;br /&gt;
    -- link to create Archive one.&lt;br /&gt;
    if glargs.max == 0 then&lt;br /&gt;
        return 'no archives yet ([[' .. glargs.prefix .. '1|create]])'&lt;br /&gt;
    end&lt;br /&gt;
    -- Return an html error if the start number is greater than the &lt;br /&gt;
    -- maximum number.&lt;br /&gt;
    local start = glargs.start or 1&lt;br /&gt;
    if start &amp;gt; glargs.max then&lt;br /&gt;
        return '&amp;lt;span class=&amp;quot;error&amp;quot;&amp;gt;Start value &amp;quot;' &lt;br /&gt;
            .. tostring( start ) &lt;br /&gt;
            .. '&amp;quot; is greater than the most recent archive number &amp;quot;' &lt;br /&gt;
            .. tostring( glargs.max ) &lt;br /&gt;
            .. '&amp;quot;.&amp;lt;/span&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
    local linkPrefix = glargs.linkPrefix or ''&lt;br /&gt;
    local sep = glargs.sep or mw.message.new( 'comma-separator' ):plain()&lt;br /&gt;
    local lineNum = glargs.lineNum or 10&lt;br /&gt;
    local lineSep = glargs.lineSep or '&amp;lt;br /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    -- Generate the archive links.&lt;br /&gt;
    local lineCounter = 1 -- The counter to see whether we need a line break or not.&lt;br /&gt;
    local ret = {} -- A table containing the strings to be returned.&lt;br /&gt;
    for archiveNum = start, glargs.max do&lt;br /&gt;
        local link = mw.ustring.format(&lt;br /&gt;
            '[[%s%d|%s%d]]',&lt;br /&gt;
            glargs.prefix, archiveNum, linkPrefix, archiveNum&lt;br /&gt;
        )&lt;br /&gt;
        table.insert( ret, link )&lt;br /&gt;
        -- If we don't need a new line, output a comma. We don't need&lt;br /&gt;
        -- a comma after the last link. &lt;br /&gt;
        if lineCounter &amp;lt; lineNum and archiveNum &amp;lt; glargs.max then&lt;br /&gt;
            table.insert( ret, sep )&lt;br /&gt;
            lineCounter = lineCounter + 1&lt;br /&gt;
        -- Output new lines if needed. We don't need a new line after&lt;br /&gt;
        -- the last link.&lt;br /&gt;
        elseif lineCounter &amp;gt;= lineNum and archiveNum &amp;lt; glargs.max then&lt;br /&gt;
            table.insert( ret, lineSep )&lt;br /&gt;
            lineCounter = 1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return table.concat( ret )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Get the archive data and pass it to generateLinks().&lt;br /&gt;
local function _main( args )&lt;br /&gt;
    local prefix = getPrefix( args.root, args.prefix, args.prefixspace )&lt;br /&gt;
    local max = getBiggestArchiveNum( prefix, args.max )&lt;br /&gt;
    local lineNum = getLineNum( args.links, args.nobr )&lt;br /&gt;
    local linkPrefix = getLinkPrefix( args.linkprefix, args.linkprefixspace )&lt;br /&gt;
    local start = getStart( args.start )&lt;br /&gt;
    local sep = getSeparator( args.sep )&lt;br /&gt;
    local lineSep = getSeparator( args.linesep )&lt;br /&gt;
    local glargs = {&lt;br /&gt;
        start = start,&lt;br /&gt;
        max = max,&lt;br /&gt;
        prefix = prefix,&lt;br /&gt;
        linkPrefix = linkPrefix,&lt;br /&gt;
        sep = sep,&lt;br /&gt;
        lineNum = lineNum,&lt;br /&gt;
        lineSep = lineSep&lt;br /&gt;
    }&lt;br /&gt;
    return generateLinks( glargs )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- A wrapper function to make getBiggestArchiveNum() available from&lt;br /&gt;
-- #invoke.&lt;br /&gt;
local function _count( args )&lt;br /&gt;
    local prefix = getPrefix( args.root, args.prefix, args.prefixspace )&lt;br /&gt;
    local archiveMax = getBiggestArchiveNum( prefix )&lt;br /&gt;
    return archiveMax&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function makeWrapper( func )&lt;br /&gt;
    return function( frame )&lt;br /&gt;
        -- If we are being called from #invoke, get the args from #invoke&lt;br /&gt;
        -- if they exist, or else get the arguments passed to the parent&lt;br /&gt;
        -- frame. Otherwise, assume the arguments are being passed directly&lt;br /&gt;
        -- in from another module or from the debug console.&lt;br /&gt;
        local origArgs&lt;br /&gt;
        if frame == mw.getCurrentFrame() then&lt;br /&gt;
            origArgs = frame:getParent().args&lt;br /&gt;
            for k, v in pairs( frame.args ) do&lt;br /&gt;
                origArgs = frame.args&lt;br /&gt;
                break&lt;br /&gt;
            end&lt;br /&gt;
        else&lt;br /&gt;
            origArgs = frame&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        -- Ignore blank values for parameters other than &amp;quot;links&amp;quot;,&lt;br /&gt;
        -- which functions differently depending on whether it is&lt;br /&gt;
        -- blank or absent.&lt;br /&gt;
        local args = {}&lt;br /&gt;
        for k, v in pairs( origArgs ) do&lt;br /&gt;
            if k == 'links' or v ~= '' then&lt;br /&gt;
                args[k] = v&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        return func( args )&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
    main = makeWrapper( _main ),&lt;br /&gt;
    count = makeWrapper( _count )&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Shawndouglas</name></author>
	</entry>
</feed>