Module:News

From Soyjak Wiki, the free ensoyclopedia
Jump to navigationJump to search
This page is currently under development(You) VVILL NOT edit the page until it's properly finished.

local p = {}

local cfg = mw.loadData('Module:News/config')
local records = mw.loadData('Module:News/data').issues or {}
local lang = mw.language.getContentLanguage()

p.cfg = cfg

local function lookup(path)
	local value = cfg
	for key in path:gmatch('[^.]+') do
		if type(value) ~= 'table' then return nil end
		value = value[key]
	end
	return value
end

function p.need(path)
	local value = lookup(path)
	if value == nil then error('News config: missing "' .. path .. '"', 0) end
	return value
end

function p.pageTitle(key)
	local base = p.need('pages.base')
	if key == 'base' then return base end
	local sub = cfg.pages[key]
	if sub then return base .. '/' .. sub end
end

function p.fill(text, token)
	return (
		tostring(text):gsub('%$(%a+)', function(name)
			local value = token and token[name]
			if value ~= nil then return tostring(value) end
		end)
	)
end

function p.text(state, key, token)
	local text = p.need('labels')[key]
	if text == nil then return p.errorText(state, 'unknownLabel', { value = tostring(key) }) end
	return p.fill(text, token)
end

function p.newState()
	return { hasError = false, categories = {} }
end

function p.addCategory(state, key)
	local name = p.need('categories.' .. key)
	if state.categories[name] then return end
	state.categories[name] = true
	table.insert(state.categories, name)
end

function p.errorText(state, key, token)
	state.hasError = true
	p.addCategory(state, 'errors')
	return '<strong class="error">' .. p.fill(p.need('messages')[key] or key, token) .. '</strong>'
end

function p.finish(state, output)
	output = output or ''
	local namespace = mw.title.getCurrentTitle().namespace
	for _, skip in ipairs(cfg.skipCategoryNamespaces or {}) do
		if skip == namespace then return output end
	end
	for _, name in ipairs(state.categories) do
		output = output .. '[[Category:' .. name .. ']]'
	end
	return output
end

function p.today(frame)
	return frame:preprocess('{{LOCALYEAR}}-{{LOCALMONTH}}-{{LOCALDAY2}}')
end

function p.isDate(value)
	if type(value) ~= 'string' or not value:match('^%d%d%d%d%-%d%d%-%d%d$') then return false end
	local ok, roundTrip = pcall(lang.formatDate, lang, 'Y-m-d', value)
	return ok and roundTrip == value
end

function p.formatDate(format, iso)
	if not p.isDate(iso) then return iso or '' end
	return lang:formatDate(format, iso)
end

function p.idDate(id)
	if type(id) ~= 'string' then return nil end
	local date = id:match('^(%d%d%d%d%-%d%d%-%d%d)$') or id:match('^(%d%d%d%d%-%d%d%-%d%d)%-%l+$')
	if p.isDate(date) then return date end
end

function p.get(frame)
	local path = mw.text.trim(frame.args[1] or '')
	local value = lookup(path)
	if value == nil then value = frame.args[2] end
	if type(value) == 'string' or type(value) == 'number' then return tostring(value) end
	local state = p.newState()
	return p.finish(state, p.errorText(state, 'unknownSetting', { value = path }))
end

function p.page(frame)
	local key = mw.text.trim(frame.args[1] or '')
	local title = p.pageTitle(key)
	if title then return title end
	local state = p.newState()
	return p.finish(state, p.errorText(state, 'unknownPage', { value = key }))
end

local function makeIssue(id, rec, today)
	local date = p.idDate(id)
	local issue = {
		id = id,
		rec = rec,
		date = rec and rec.date and tostring(rec.date) or date,
		page = rec and rec.page or p.need('pages.base') .. '/' .. id,
	}
	if not date then
		issue.state = 'malformed'
	elseif not rec then
		issue.state = 'draft'
	elseif type(rec.embargo) == 'string' and rec.embargo > today then
		issue.state = 'embargoed'
	else
		issue.state = 'listed'
	end
	return issue
end

local function before(a, b)
	if a.date ~= b.date then return a.date > b.date end
	return a.id > b.id
end

function p.issue(id, today)
	if id then return makeIssue(id, records[id], today) end
end

function p.listed(today)
	local list = {}
	for id, rec in pairs(records) do
		local issue = makeIssue(id, rec, today)
		if issue.state == 'listed' then table.insert(list, issue) end
	end
	table.sort(list, before)
	return list
end

function p.numberText(state, issue)
	local number = issue.rec and issue.rec.number
	local text = p.text(state, 'numberPrefix') .. (number and tostring(number) or p.text(state, 'unknownNumber'))
	if issue.rec and not number then
		text = text .. ' ' .. p.errorText(state, 'missingField', { id = issue.id, field = 'number' })
	end
	return text
end

return p