Module:Cartel d'art/dimensions

 Documentation[créer] [purger]
---- vi: set sw=4 ts=4 ai sm noet:
----
---- Module:Cartel d'art/dimensions
---- Création : Wikipédia en français, juillet 2024
---- Usage normale par [[Modèle:Cartel d'art/dimensions]]
----
---- Ce module vise à faciliter le mis en forme des dimensions d'un œuvre d'art,
---- p. ex. 123 × 234 × 345 cm
----
---- Ce format est expliqué dans le document suivant :
---- https://artexte.ca/app/uploads/2017/02/guidecitation_oeuvres.pdf
----
---- Les règles concernant les espaces sont tiré du Ramat de la typographie, 11e édition (Ramat et Benoit, 2017).

require ('strict');
local p = {};

local insec = mw.ustring.char(0xa0);	-- espace insécable
local langue = mw.getContentLanguage();	-- la langue française

-- Tous les symboles d'unité de longuer qu'on reconnait
p.symboles = {
	['mm'] = true;
	['cm'] = true;
	['m'] = true;
	['km'] = true;
};

-- Fonction auxiliaire pour rendre un nombre conformément aux règles typographiques en français
--
-- Paramètres :
-- n : nombre
--
-- Résultat :
-- (chaîne de caractères) le nombre n mis en forme
local function formatNum (n)
	local it = mw.ustring.gsub(langue:formatNum(n), '% ', insec);	-- v. Ramat 11 p. 145
	return it;
end

-- Fonction auxiliaire pour ajouter une dimension à un résultat précédent
--
-- Paramètres :
-- a : (chaîne de caractères ou nil) un résultat précédent produit par ce fonction, ou nil
-- b : (nombre) dimension
--
-- Résultat :
-- (chaîne de caractères) Le valeur a, suivi par un signe de multiplication si a n'est pas nil, suivi par b mis en forme
local function cat (a, b)
	local it;
	if not b then
		it = a;
	elseif a then
		it = a .. insec .. '×' .. insec .. formatNum(b);	-- p. 193
	else
		it = formatNum(b);
	end
	return it;
end

---
--- Entrée principale
--- Normalement exécuté par {{#invoke:Cartel d'art/dimensions|main}} dans le Modèle:Cartel d'art/dimensions
---
p.main = function (frame)
	local parent = frame:getParent();
	local it;

	local hauteur, largeur, profondeur, unite;
	for _, a in pairs({frame, parent}) do
		if a then
			local exposant_prevu = false;
			for k, v in pairs(a.args) do
				v = v:gsub('^%s+', ''):gsub('%s+$', '');
				if type(k) == 'number' then
					if exposant_prevu then
						error("Exposant non prévu dans les cartels d'art");
					elseif v:match('^[a-zA-ZÅ°]+$') then
						unite = v;
						exposant_prevu = true;
					elseif k == 1 then
						hauteur = v;
					elseif k == 2 then
						largeur = v;
					elseif k == 3 then
						profondeur = v;
					elseif k == 4 then
						error('Trop de dimensions, paramètre « ' .. v .. ' » non prévu');
					end
				elseif k == 'hauteur' then
					hauteur = v;
				elseif k == 'largeur' then
					largeur = v;
				elseif k == 'profondeur' then
					profondeur = v;
				elseif k == 'unité' then
					unite = v;
				else
					error('Paramètre « ' .. k .. ' » inconnu');
				end
			end
		end
	end
	if not hauteur and not largeur and not profondeur then
		error('Dimension.s manquante.s');
	elseif not unite then
		error('Unité manquante');
	end
	if hauteur then
		it = cat(it, langue:parseFormattedNumber(hauteur));
	end
	if largeur then
		it = cat(it, langue:parseFormattedNumber(largeur));
	end
	if profondeur then
		it = cat(it, langue:parseFormattedNumber(profondeur));
	end
	if p.symboles[unite] then
		it = it .. insec .. unite;	-- v. Ramat p. 193
	else
		it = it .. ' '.. unite;
	end
	return it;
end

---
--- Tests unitaires
--- Normalement executée dans la console de débogage par p.test()
---
--- En cas de succès, aucun résultat se produit
--- En cas de défaut, une erreur se produit par un appel assert()
---
p.test = function ()
	local a, b;

	assert(formatNum(123) == '123');
	assert(formatNum(123.4) == '123,4');

	b = formatNum(1234);
	assert(b ~= '1234' and mw.ustring.match(b, '^1.234$'));

	-- Découvrir quelle sorte d'espace s'est produit par formatNum
	local sp = mw.ustring.gsub(formatNum(11111), '1', '');

	assert(cat(nil, nil) == nil);
	assert(cat(nil, 1) == '1');
	assert(cat('1', nil) == '1');
	assert(cat('1', 2) == '1' .. insec .. '×' .. insec .. '2');

	-- Émuler {{#invoke:Cartel d'art/dimensions|main}} (aucun paramètre)
	-- Résultat prévu: erreur (Dimension.s manquante.s)
	a, b = pcall(p.main, {
		['getParent'] = function ()
			return {
				extensionTag = function () return '' end;
				args= {
				};
			};
		end;
		extensionTag = function () return '' end;
		args = {
		};
	});
	assert(not a and b:match('Dimension.s manquante.s'));

	-- Émuler {{#invoke:Cartel d'art/dimensions|main|123}}
	-- Résultat prévu: erreur (Unité manquante)
	a, b = pcall(p.main, {
		['getParent'] = function ()
			return {
				extensionTag = function () return '' end;
				args= {
				};
			};
		end;
		extensionTag = function () return '' end;
		args = {
			'123'
		};
	});
	assert(not a and b:match('Unité manquante'));

	-- Émuler {{#invoke:Cartel d'art/dimensions|main|123|cm}}
	-- Résultat prévu: 123 cm (espace insécable)
	a, b = pcall(p.main, {
		['getParent'] = function ()
			return {
				extensionTag = function () return '' end;
				args= {
				};
			};
		end;
		extensionTag = function () return '' end;
		args = {
			'123',
			'cm'
		};
	});
	assert(a and b == '123' .. insec .. 'cm');

	-- Émuler {{#invoke:Cartel d'art/dimensions|main|123|234|cm}}
	-- Résultat prévu: 123 × 234 cm (espaces insécables)
	a, b = pcall(p.main, {
		['getParent'] = function ()
			return {
				extensionTag = function () return '' end;
				args= {
				};
			};
		end;
		extensionTag = function () return '' end;
		args = {
			'123',
			'234',
			'cm'
		};
	});
	assert(a and b == '123' .. insec .. '×' .. insec .. '234' .. insec .. 'cm');

	-- Émuler {{#invoke:Cartel d'art/dimensions|main|12|34|56|m}}
	-- Résultat prévu: 12 × 34 × 56 m (espaces insécables)
	a, b = pcall(p.main, {
		['getParent'] = function ()
			return {
				extensionTag = function () return '' end;
				args= {
				};
			};
		end;
		extensionTag = function () return '' end;
		args = {
			'12',
			'34',
			'56',
			'm'
		};
	});
	assert(a and b == '12' .. insec .. '×' .. insec .. '34' .. insec .. '×' .. insec .. '56' .. insec .. 'm');

	-- Émuler {{#invoke:Cartel d'art/dimensions|main|largeur=1234|mm}}
	-- Résultat prévu: 1 234 mm (espaces insécables)
	a, b = pcall(p.main, {
		['getParent'] = function ()
			return {
				extensionTag = function () return '' end;
				args= {
				};
			};
		end;
		extensionTag = function () return '' end;
		args = {
			'1234',
			'mm'
		};
	});
	assert(a and b == '1' .. sp .. '234' .. insec .. 'mm');

	-- Émuler {{#invoke:Cartel d'art/dimensions|main|hauteur=12|pieds}}
	-- Résultat prévu: 12 pieds (espace sécable)
	a, b = pcall(p.main, {
		['getParent'] = function ()
			return {
				extensionTag = function () return '' end;
				args= {
				};
			};
		end;
		extensionTag = function () return '' end;
		args = {
			'12',
			'pieds'
		};
	});
	assert(a and b == '12 pieds');
end

p.formatNum = formatNum;
return p