Module:Infobox

De Starfield Wiki
Révision datée du 1 décembre 2023 à 18:18 par J. Hodgson (discussion | contributions) (Annulation des modifications 6068 de J. Hodgson (discussion))
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)
Documentation[voir] [modifier] [purger]

Ce module génère une infobox à partir d'un sous-module de paramétrage. Il s'agit d'une version simplifiée de Module:Infobox présent sur Wikipédia.

Créer une infobox

Pour créer une nouvelle infobox, il faut déclarer son paramétrage comme sous-module du module Infobox. Par exemple, si on souhaite créer Infobox Planète alors on déclarera son paramétrage dans Module:Infobox/Planète.

Le sous-module doit retourner une table contenant la structure de l'infobox.

-- Module https://fallout-wiki.com/Module:Infobox utilisé comme source et
-- lui-même inspiré de https://fr.wikipedia.org/wiki/Module:Infobox
-- Gère la construction des infobox dans le paramétrage doit être défini
-- un sous-module.

local p = {}

-- données concernant les paramètres passés au modèle
local localdata = {}

-- données concernant la page où est affichée l"infobox
local page = {
	name = mw.title.getCurrentTitle().prefixedText,
	namespace =  mw.title.getCurrentTitle().namespace
}

-- l"objet principal à retourner
local infobox = mw.html.create("div")

--[[ Outils ]]

local function get_value(value, part)
	if type(value) == "string" then
		return localdata[value]
	elseif type(value) == "function" then
		return value(localdata, part)
	elseif type(value) == "table" then
        -- si plusieurs paramètres possibles (legacy de vieux code),
        -- prendre le premier non vide
		for i, j in pairs(value) do
			if localdata[j] then
				return localdata[j]
			end
		end
	end
end

function p.separator()
	return mw.html.create("hr"):addClass("separator")	
end

--[[ Construction des blocs ]]

function p.build_title(part)
	local text = get_value(part.value, part) or part.textdefaultvalue or mw.title.getCurrentTitle().text
	local subtext = get_value(part.subtitle, part) or part.subtitledefaultvalue
	local classes = "avt-infobox-header " .. (part.class or "")
	
	-- Supprime l"indication d"homonymie
	text = mw.ustring.gsub(text, " [(][^()]*[)]$", "")
	
	if subtext and (subtext ~= text) then
		text = text .. "<br/><small>" .. subtext .. "</small>"
	end

	local title = mw.html.create("div")
		:addClass(classes)
		:tag("div")
			:addClass("avt-infobox-header-title")
			:wikitext(text)
		:allDone()
	
	return title
end
p.build_title = p.build_title

function p.build_images(part)
	local images = {}
	local upright, link, caption, alt
	if type(part.imageparameters) == "string" then
		part.imageparameters = { part.imageparameters }
	end
	if not part.imageparameters then -- s"il n"y a pas de paramètre image, continuer, peut-être y a-t-il une image par défaut définie dans le module d"infobox
		part.imageparameters = {}
	end
	for j, k in ipairs(part.imageparameters) do
		table.insert(images, localdata[k])
	end

	-- Images par défaut
	if #images == 0 then
		if part.defaultimages then
			images = part.defaultimages
			if type(images) == "string" then
				images = { images }
			end
			upright = part.defaultimageupright
			caption = part.defaultimagecaption
			link = part.defaultimagelink
			alt = part.defaultimagealt
			if not alt then
				alt = "une illustration pour cette infobox serait bienvenue"
			end
		end
	end
	
	if #images == 0 then
		return nil
	end
	
	upright = upright or get_value(part.uprightparameter) or part.defaultupright or "1.2"
	link = link or get_value(part.linkparameter) or part.defaultlink
	caption = caption or get_value(part.captionparameter) or part.defaultcaption
	alt = alt or get_value(part.altparameter) or part.defaultalt
	
	if tonumber(upright) then
		upright = tostring( tonumber(upright) / #images )
	end

	local style = part.style or {}

	-- Partie image

	local imagesString = ""
	for i,image in pairs(images) do
		if image == "-" then
			return
		end
		imagesString = imagesString ..  "[[Fichier:" .. image .. "|frameless"
		if alt then
			imagesString = imagesString .. "|alt=" .. alt
		end
		if link then
			imagesString = imagesString .. "|link=" .. link
		end
		if upright then
			imagesString = imagesString .. "|upright=" .. upright
		elseif #images > 1 then
			imagesString = imagesString .. "|upright=" .. ( 1 / #images )
		end
		imagesString = imagesString .. "]]"
	end

	local image = mw.html.create("div")
		:addClass("avt-infobox-images")
		:css(style)
		:wikitext(imagesString)

	-- Partie légende
	local captionobj
	if caption then
		captionobj = mw.html.create("div")
			:wikitext(caption)
			:css(part.legendstyle or {})
			:addClass("avt-infobox-images-legend")
			:done()
	end
	
	-- séparateur
	local separator
	if part.separator then
		separator = separator(part)
	end
	return mw.html.create("div")
		:node(image)
		:node(captionobj)
		:node(separator)
		:done()
end
p.build_images = p.build_images

function p.build_text(part)
	local class = part.class or ""
	local style = {
		["text-align"] = "center",
		["font-weight"] = "bold",
	}
	if part.style then
		for i, j in pairs(part.style) do
			style[i] = j
		end
	end
	local text = get_value(part.value, part) or part.defaultvalue
	if text == "-" then
		return
	end
	if not text then
		return nil
	end
	local formattedtext = mw.html.create("p")
		:addClass(class)
		:css(style)
		:wikitext(text)
		:done()
	return formattedtext
end
p.build_text = p.build_text

function p.build_row(part)
	local class = part.class or ""
	local style = part.style or {}
	local valueClass = part.valueClass or ""
	local valueStyle = part.valueStyle or {}
	local value, number = get_value(part.value, part)
	
	if not value then
		value = part.defaultvalue
	end
	if value == nil then
		return nil
	end
	if not number then
		number = 0 -- == indéfini
	end

	local label = part.label
	if number > 1 and part.plurallabel then
		label = part.plurallabel
	elseif number == 1 and part.singularlabel then
		label = part.singularlabel
	end
	if type(label) == "function" then
			label = label(localdata, localdata.item)
	end

	-- format
	local formattedvalue = mw.html.create("div")
		-- Le "\n" est requis lorsque value est une liste 
		-- commençant par "*" ou "#"
		:wikitext("\n" .. value)
		
	if part.hidden == true then
		formattedvalue
			:attr({class="NavContent", style="display: none; text-align: left;"})
		formattedvalue = mw.html.create("div")
			:attr({class="NavFrame", title="[Afficher]/[Masquer]", style="border: none; padding: 0;"})
			:node(formattedvalue)
	end
	formattedvalue =  mw.html.create("td")
			:node(formattedvalue)
			:addClass(valueClass)
			:css(valueStyle)
			:allDone()
	
	local formattedlabel
	if label then
		formattedlabel = mw.html.create("th")
			:attr("scope", "row")
			:wikitext(label)
			:done()
	end
	local row = mw.html.create("tr")
		:addClass(class)
		:css(style)
		:node(formattedlabel)
		:node(formattedvalue)
		:done()
	
	return row
end
p.build_row = p.build_row

function p.build_succession(part)
	if not part.value then
		return nil
	end
	
	local values = part.value
	local before = get_value(values["before"], part)
	local center = get_value(values["center"], part)
	local after  = get_value(values["after"], part)
	
	if not before and not center and not after then
		return nil
	end
	
	local rowI = mw.html.create("tr")
	
	local styleI = {}
	local colspan = "2"
	styleI["padding"] = "1px"
	cellI = mw.html.create("td")
			:attr({colspan = colspan})
			:attr({align = "center"})
			:css(styleI)
	
	local styleT = {}
	styleT["margin"] = "0px"
	styleT["background-color"] = "transparent"
	styleT["width"] = "100%"
	tabC = mw.html.create("table")
			:attr({cellspacing = "0"})
			:addClass("navigation-not-searchable")
			:css(styleT)
	
	local row = mw.html.create("tr")

	local color = part.color

	local style = {}
	local arrowLeft
	local arrowRight
	
	if color == "default" then
		arrowLeft = "[[Fichier:SCRWEST.png|13px|alt=Précédent|link=]]"
		arrowRight = "[[Fichier:SCREAST.png|13px|alt=Suivant|link=]]"
	else
		arrowLeft = "[[Fichier:SCRWEST.png|13px|alt=Précédent|link=]]"
		arrowRight = "[[Fichier:SCREAST.png|13px|alt=Suivant|link=]]"
		style["background-color"] = color
	end
	
	local styleTrans = {}
	
	local widthCell = "44%"
	if center then
		widthCenter = "28%"
		widthCell = "29%"
	end
	
	local formattedbefore
	if before then
		formattedbefore = mw.html.create("td")
			:attr({valign = "middle"})
			:attr({align = "left"})
			:attr({width = "5%"})
			:css(style)
			:wikitext(arrowLeft)
			:done()
		row:node(formattedbefore)
		formattedbefore = mw.html.create("td")
			:attr({width = "1%"})
			:css(style)
			:wikitext("")
			:done()
		row:node(formattedbefore)
		formattedbefore = mw.html.create("td")
			:attr({align = "left"})
			:attr({valign = "middle"})
			:attr({width = widthCell})
			:css(style)
			:wikitext(before)
			:done()
		row:node(formattedbefore)
	else
		formattedbefore = mw.html.create("td")
			:attr({valign = "middle"})
			:attr({align = "left"})
			:attr({width = "5%"})
			:css(styleTrans)
			:wikitext("")
			:done()
		row:node(formattedbefore)
		formattedbefore = mw.html.create("td")
			:attr({width = "1%"})
			:css(styleTrans)
			:wikitext("")
			:done()
		row:node(formattedbefore)
		formattedbefore = mw.html.create("td")
			:attr({align = "left"})
			:attr({valign = "middle"})
			:attr({width = widthCell})
			:css(styleTrans)
			:wikitext("")
			:done()
		row:node(formattedbefore)
	end
	
	local formattedcenter
	formattedcenter = mw.html.create("td")
		:attr({width = "1%"})
		:css(styleTrans)
		:wikitext("")
		:done()
	row:node(formattedcenter)
	
	if center then
		formattedcenter = mw.html.create("td")
			:attr({align = "center"})
			:attr({valign = "middle"})
			:attr({width = widthCenter})
			:css(style)
			:wikitext(center)
			:done()
		row:node(formattedcenter)
		formattedcenter = mw.html.create("td")
			:attr({width = "1%"})
			:css(styleTrans)
			:wikitext("")
			:done()
		row:node(formattedcenter)
	end
	
	local formattedafter
	if after then
		formattedafter = mw.html.create("td")
			:attr({align = "right"})
			:attr({valign = "middle"})
			:attr({width = widthCell})
			:css(style)
			:wikitext(after)
			:done()
		row:node(formattedafter)
		formattedbefore = mw.html.create("td")
			:attr({width = "1%"})
			:css(style)
			:wikitext("")
			:done()
		row:node(formattedbefore)
		formattedafter = mw.html.create("td")
			:attr({align = "right"})
			:attr({valign = "middle"})
			:attr({width = "5%"})
			:css(style)
			:wikitext(arrowRight)
			:done()
		row:node(formattedafter)
	else
		formattedafter = mw.html.create("td")
			:attr({align = "right"})
			:attr({valign = "middle"})
			:attr({width = widthCell})
			:css(styleTrans)
			:wikitext("")
			:done()
		row:node(formattedafter)
		formattedbefore = mw.html.create("td")
			:attr({width = "1%"})
			:css(styleTrans)
			:wikitext("")
			:done()
		row:node(formattedbefore)
		formattedafter = mw.html.create("td")
			:attr({align = "right"})
			:attr({valign = "middle"})
			:attr({width = "5%"})
			:css(styleTrans)
			:wikitext("")
			:done()
		row:node(formattedafter)
	end
	
	row:done()
	tabC:node(row)
	tabC:done()
	cellI:node(tabC)
	cellI:done()
	rowI:node(cellI)
	rowI:allDone()
	
	return rowI
end
p.build_succession = p.build_succession

function p.build_row1col(part)
	if not part.value then
		return nil
	end

	local class = "row1col"
	if part.class then
		class = class .. " " .. part.class
	end
	
	local text = get_value(part.value, part)
	
	if not text then
		return nil
	end

	local formattedlabel
	formattedlabel = mw.html.create("th")
		:attr({ colspan = "2" })
		:addClass(class)
		:wikitext(text)
		:done()

	local row = mw.html.create("tr")
		:node(formattedlabel)
		:done()
	
	return row
end
p.build_row1Col = p.build_row1col

function p.buildtable(part)
	local class = nil
	if part.collapseparameters then
		if part.collapseparameters.collapsible == true then
			class = "mw-collapsible"
			if part.collapseparameters.collapsed == true then
				class = class .." mw-collapsed"
			end
		end
	end
	
	local tab = mw.html.create("table")
		:addClass(class)
		:css(part.style or {})

	local rows = part.rows
	
	-- expand parameters so that we have a list of tables
	local i = 1

	while (i <= #rows) do 
		local l = rows[i]
		if type(l) == "function" then 
			l = l(localdata, localdata.item)
		end
		if (type(l) == "table") and (l.type == "multi") then
			table.remove(rows, i)  
			for j, row in ipairs(l.rows) do
				table.insert(rows, i + j - 1, row) 
			end
		elseif type(l) == "nil" then
			table.remove(rows, i)
		elseif type(l) ~= "table" then 
			return error("les lignes d'infobox ('rows') doivent être des tables, est " .. type(l))
		else
			i = i + 1
		end
	end 

	-- CREATE ROW
	local expandedrows = {}
	for k, row in ipairs(rows) do
		local v = p.buildblock(row)
		if v then
			table.insert(expandedrows, v)
		end
	end
	if (#expandedrows == 0) then
		return nil
	end
	rows = expandedrows

	-- ADD TITLE
	local title
	if part.title or part.singulartitle or part.pluraltitle then
		local text
		if #rows > 1 and part.pluraltitle then
			text = part.pluraltitle
		elseif #rows == 1 and part.singulartitle then
			text = part.singulartitle
		else
			text = part.title
		end

		local style = part.titlestyle or {}

		title = mw.html.create("caption")
			:attr({ colspan = "2" })
			:css(style)
			:wikitext(text)
			:done()
	end
	
	if title then
		tab:node(title)
	end
	
	for i, j in pairs (rows) do
		tab:node(j)
	end
	
	if part.separator then
		local separator = p.separator(part)
		tab:node(separator)
	end
	tab:allDone()
	return tab
end
p.buildTable = p.buildtable

--[[
	Construction de l"infobox
]]

function p.buildblock(block)
	if type(block) == "function" then
		block = block(localdata)
	end

	 -- list of functions for block buildings
	local blocktypes = {
		["images"] = p.build_images,
		["table"] = p.buildtable,
		["row"] = p.build_row,
		["row1col"] = p.build_row1col,
		["succession"] = p.build_succession,
		["text"] = p.build_text,
		["title"] = p.build_title,
	}
	if type(block) ~= "table" or (not block.type) or (not blocktypes[block.type]) then
		return blocktypes["invalid"](block)
	end
	return blocktypes[block.type](block) 
end
p.buildBlock = p.buildblock

function p.build()
	localdata = require("Module:Infobox/Localdata")
	item = localdata.item

	-- chargement du module de paramétrage
	local moduledata = require("Module:Infobox/" .. localdata.modulename)
	moduledata.name = localdata.modulename
	
	-- class
	local class = "infobox avt-infobox"
	if moduledata.class then
		class = class .. " " .. moduledata.class
	end

	-- style
	local style = moduledata.style or {}
	
	-- build infobox
	infobox	:addClass(class)
			:css(style)
	
	for i, j in pairs(moduledata.parts) do
		infobox:node(p.buildblock(j))
	end

	return tostring(infobox)
end

return p