PC Gaming Shelter
An archive dedicated to preserving PC Gaming history and more

Module:Resource: Difference between revisions

From PC Gaming Shelter
Created page with "local p = {} local function clean(value) if value == nil then return nil end value = mw.text.trim(tostring(value)) return value ~= '' and value or nil end local function isTruthy(value) value = clean(value) if not value then return false end value = mw.ustring.lower(value) return value == '1' or value == 'true' or value == 'yes' or value == 'y' or value == 'on' end local function splitValues(value) value = clean(value) if not value then return {} e..."
 
No edit summary
Line 173: Line 173:


local titleBox = titleLine:tag('div')
local titleBox = titleLine:tag('div')
titleBox:tag('div'):addClass('h4 mb-1'):wikitext(title)
if host then
if host then
titleBox:tag('div'):addClass('text-muted small mb-2'):wikitext(host)
titleBox:tag('div'):addClass('text-muted small mb-2'):wikitext(host)
Line 181: Line 179:
local badges = titleLine:tag('div'):addClass('text-sm-right mt-2 mt-sm-0')
local badges = titleLine:tag('div'):addClass('text-sm-right mt-2 mt-sm-0')
makeBadge(badges, resourceType, 'badge-info')
makeBadge(badges, resourceType, 'badge-info')
makeBadge(badges, contentType, 'badge-secondary')


if isTruthy(args['Has spoilers']) then
if isTruthy(args['Has spoilers']) then

Revision as of 09:35, 2 July 2026

Documentation for this module may be created at Module:Resource/doc

local p = {}

local function clean(value)
	if value == nil then
		return nil
	end

	value = mw.text.trim(tostring(value))
	return value ~= '' and value or nil
end

local function isTruthy(value)
	value = clean(value)
	if not value then
		return false
	end

	value = mw.ustring.lower(value)
	return value == '1' or value == 'true' or value == 'yes' or value == 'y' or value == 'on'
end

local function splitValues(value)
	value = clean(value)
	if not value then
		return {}
	end

	local values = {}
	for part in string.gmatch(value, '([^,]+)') do
		local item = clean(part)
		if item then
			table.insert(values, item)
		end
	end

	if #values == 0 then
		table.insert(values, value)
	end

	return values
end

local function firstValue(value)
	local values = splitValues(value)
	return values[1]
end

local function externalHost(url)
	url = clean(url)
	if not url then
		return nil
	end

	local host = mw.ustring.match(url, '^https?://([^/%?#]+)')
	if not host then
		return nil
	end

	return mw.ustring.gsub(host, '^www%.', '')
end

local function isValidUrl(url)
	return clean(url) and mw.ustring.match(url, '^https?://[^%s]+$') ~= nil
end

local function cssList(values, linked)
	if not values or #values == 0 then
		return nil
	end

	local items = {}
	for _, value in ipairs(values) do
		if linked then
			table.insert(items, string.format('[[%s]]', value))
		else
			table.insert(items, value)
		end
	end

	return table.concat(items, ', ')
end

local function addProperty(props, name, value, delimiter)
	value = clean(value)
	if not value then
		return
	end

	if delimiter then
		props[name] = splitValues(value)
	else
		props[name] = value
	end
end

local function setProperties(args)
	local props = {}

	addProperty(props, 'Has URL', args['Has URL'])
	addProperty(props, 'Related game', args['Related game'], ',')
	addProperty(props, 'Has resource type', args['Has resource type'], ',')
	addProperty(props, 'Has content type', args['Has content type'], ',')
	addProperty(props, 'Has date', args['Has date'])
	addProperty(props, 'Created by', args['Created by'])
	addProperty(props, 'Has language', args['Has language'], ',')
	addProperty(props, 'Has subtitles language', args['Has subtitles language'], ',')

	if isTruthy(args['Has spoilers']) then
		props['Has spoilers'] = 'Yes'
	end

	if isTruthy(args['Has subtitles']) then
		props['Has subtitles'] = 'Yes'
	end

	if next(props) then
		mw.smw.set(props)
	end
end

local function makeBadge(parent, text, badgeClass)
	if not clean(text) then
		return
	end

	parent
		:tag('span')
		:addClass('badge')
		:addClass(badgeClass or 'badge-secondary')
		:addClass('mr-1 mb-1')
		:wikitext(text)
end

local function addRow(parent, label, value)
	value = clean(value)
	if not value then
		return
	end

	local row = parent:tag('div'):addClass('infobox-section d-flex flex-column flex-sm-row border-0 rounded-0 px-3 py-1')
	row:tag('div'):addClass('infobox-label'):wikitext(label)
	row:tag('div'):addClass('infobox-value'):wikitext(value)
end

local function renderUrl(args)
	local url = clean(args['Has URL'])
	if not isValidUrl(url) then
		return nil
	end

	local label = externalHost(url) or url
	return string.format('[%s %s]', url, label)
end

local function renderResource(frame, args)
	local url = clean(args['Has URL'])
	local title = mw.title.getCurrentTitle().text
	local host = externalHost(url)
	local resourceType = firstValue(args['Has resource type'])

	local root = mw.html.create()
	local card = root
		:tag('div')
		:addClass('resource infobox d-flex flex-column card shadow-none rounded-0 bg-transparent mb-4')

	local header = card
		:tag('div')
		:addClass('infobox-block border-bottom pb-2 mb-2')

	local titleLine = header
		:tag('div')
		:addClass('d-flex flex-column flex-sm-row justify-content-between align-items-sm-start px-3 pt-3')

	local titleBox = titleLine:tag('div')
	if host then
		titleBox:tag('div'):addClass('text-muted small mb-2'):wikitext(host)
	end

	local badges = titleLine:tag('div'):addClass('text-sm-right mt-2 mt-sm-0')
	makeBadge(badges, resourceType, 'badge-info')
	makeBadge(badges, contentType, 'badge-secondary')

	if isTruthy(args['Has spoilers']) then
		makeBadge(badges, 'Spoilers', 'badge-warning')
	end

	if isTruthy(args['Has subtitles']) then
		makeBadge(badges, 'Subtitles', 'badge-success')
	end

	if isValidUrl(url) then
		header
			:tag('div')
			:addClass('px-3 pb-3')
			:tag('span')
			:addClass('btn btn-success font-weight-bold')
			:wikitext(renderUrl(args))
	else
		header
			:tag('div')
			:addClass('alert alert-warning mx-3 mb-3')
			:wikitext('No valid URL has been provided.')
	end

	local details = card:tag('div'):addClass('infobox-block')

	addRow(details, 'Game', cssList(splitValues(args['Related game']), true))
	addRow(details, 'Media type', cssList(splitValues(args['Has resource type']), true))
	addRow(details, 'Content type', cssList(splitValues(args['Has content type']), true))
	addRow(details, 'Date', clean(args['Has date']))
	addRow(details, 'Created by', clean(args['Created by']))
	addRow(details, 'Language', cssList(splitValues(args['Has language']), true))

	if isTruthy(args['Has subtitles']) then
		addRow(details, 'Subtitles', cssList(splitValues(args['Has subtitles language']), true) or 'Yes')
	end

	return root
		:wikitext('[[Category:Resources]]')
end

function p.main(frame)
	local parent = frame:getParent()
	local args = parent and parent.args or frame.args

	setProperties(args)
	return tostring(renderResource(frame, args))
end

return p