Module:Biglist/sandbox

-- This module provides some functions to help avoid problems with templates -- that might exceed expand size or time and which might put the page in -- Category:Pages where template include size is exceeded or -- Category:Pages with script errors (time exceeding 10 seconds).

local function collection -- Return a table to hold items. return { n = 0, add = function (self, item) self.n = self.n + 1 self[self.n] = item end, join = function (self, sep) return table.concat(self, sep) end, } end

local function strip_to_nil(text) -- If text is a non-empty string, return its trimmed content, -- otherwise return nothing (empty string or not a string). if type(text) == 'string' then return text:match('(%S.-)%s*$') end end

local function message(msg, nocat) -- Return formatted message text for an error. -- Can append "#FormattingError" to URL of a page with a problem to find it. -- This should not be called because there is no validity checking. local anchor = ' ' local category = nocat and  or  return anchor .. ' Error: ' .. msg .. ' ' ..		category .. '\n' end

local function urlencode(text) -- Return equivalent of. local function byte(char) return string.format('%%%02X', string.byte(char)) end return text:gsub('[^ %w%-._]', byte):gsub(' ', '+') end

local function replace2(text, template) -- Return template after substituting text and urlencoded text. local plain = text:gsub('%%', '%%%%') -- for gsub, '%' has a special meaning in replacement local plainp = plain:gsub(' ', '+')   -- plain and space replaced with plus local encoded = urlencode(text):gsub('%%', '%%%%') return template:gsub('', plain):gsub('', plainp):gsub('', encoded) end

local function clean(text, default) -- Return text, if not empty, after trimming leading/trailing whitespace. -- Otherwise return default which may be nil. if text then text = text:match("^%s*(.-)%s*$") if text ~= '' then return text end end return default end

local function make_list(args, formatter, template) -- Return a list of formatted items. -- Input is a string of multiple lines, one item per line. local text = args.list or args[1] or '' local prefix = clean(args.prefix) or '' local comment = clean(args.comment) local results = collection for line in string.gmatch(text .. '\n', '[\t ]*(.-)[\t\r ]*\n') do -- Skip line if empty or a comment. if line ~= '' then if not (comment and line:sub(1, #comment) == comment) then results:add(prefix .. formatter(line, template)) end end end return results:join('\n') end

local templates = { -- Equivalent of. userlinks = [=[  (talk · contribs · deleted contribs · logs · edit filter log · block user · block log) ]=], -- Equivalent of how is used. topicsearch = [=[  – (wp gwp g bwp b | eb 1911 co gct sw arc ht) ]=], }

local function main(formatter, tname) local template = templates[tname] if template then return function (frame) local args = frame.args local success, result = pcall(make_list, args, formatter, template) if success then return result end return message(result, clean(args.nocat)) end else return function (frame) local args = frame.args return message('Unknown template name "' .. tname .. '"', clean(args.nocat)) end end end

local function coltit(frame) -- List of RAL colors has "node-count limit exceeded" problem. -- Following are equivalent: --  	--   	-- or	-- --  	-- Output is an empty cell for a table; the cell has the given background color. -- This does not emulate other features of the template. local args = frame.args local hex = strip_to_nil(args[1]) -- should be hex color code such as 'AABBCC' if hex then return string.format('title="color %s" style="background:#%s;"| ', hex, hex) end local rgb = strip_to_nil(args.rgb) -- should be decimal triple such as '123,123,123' if rgb then return string.format('title="color %s" style="background:rgb(%s);"| ', rgb, rgb) end error('biglist coltit: need parameter 1 or rgb', 0) end

local function columnslist(frame) -- List of least concern fishes has problem exceeding template expansion size. -- Will possibly be other articles with similar problems. -- Following are equivalent: --  • xxx --  	-- Output is: --  xxx -- This assumes colwidth is wanted and does not emulate other features of the template. local args = frame.args local content = strip_to_nil(args[1]) or '' local colwidth = strip_to_nil(args.colwidth) or '30em' return frame:extensionTag{ name = 'templatestyles', args = { src = 'Div col/styles.css' } } .. '\n' .. content .. ' ' end

local function storm(frame) -- What Wikipedia is not has an example at WP:CRYSTAL -- where the name of a "virtually certain" future storm is needed. -- This function returns the next such name (unlinked) depending on the current date. -- Usage: --  	-- Output example: --  Tropical Storm Alex (2022) local storms = { [2017] = 'Tropical Storm Alberto (2018)', [2018] = 'Tropical Storm Andrea (2019)', [2019] = 'Tropical Storm Arthur (2020)', [2020] = 'Tropical Storm Ana (2021)', [2021] = 'Tropical Storm Alex (2022)', default = 'Tropical Storm Alberto (2030)', }	local date = os.date('!*t') -- today's UTC date local y, m = date.year, date.month -- full year, month (1-12) if m >= 11 then y = y + 1 end return storms[y] or storms.default end

local function weatherboxcols(frame) -- List of cities by sunshine duration has problem exceeding time available. -- Examples: --           → style="background:#B9B94C; font-size:85%;"|123.4 --   → style="background:#B9B94C; font-size:85%;"|1,823.0 local args = frame.args local display = strip_to_nil(args[1]) or '' local value = tonumber((display:gsub(',', ''))) local function show(bg, fg) local text = strip_to_nil(args[2]) or display if not fg and (value and value < 62) then fg = 'FFFFFF' end if fg then fg = 'color:#' .. fg .. ';'		else fg = '' end return 'style="background:#' .. bg .. ';' .. fg .. ' font-size:85%;"' .. '|' .. text end if not value then return show('FFFFFF', '000000') end local redgreen, blue if value <= 0 then redgreen = 0 elseif value <= 90 then redgreen = 1.889 * value elseif value <= 180 then redgreen = 0.472 * (270.169 + value) elseif value < 360 then redgreen = 0.236 * (720.424 + value) else redgreen = 255 end if value <= 0 then blue = 0 elseif value <= 90 then blue = 1.889 * value elseif value < 150 then blue = 2.883 * (150 - value) elseif value <= 270 then blue = 0 elseif value < 719.735 then blue = 0.567 * (value - 270) else blue = 255 end return show(string.format('%02X%02X%02X', redgreen, redgreen, blue)) end

return { coltit = coltit, ['columns-list'] = columnslist, storm = storm, topicsearch = main(replace2, 'topicsearch'), userlinks = main(replace2, 'userlinks'), weatherboxcols = weatherboxcols, }