Aller au contenu

Module:Format

Cette page fait l’objet d’une mesure de semi-protection étendue.
Une page de Wikipédia, l'encyclopédie libre.
Ceci est une version archivée de cette page, en date du 2 mars 2022 à 23:17 et modifiée en dernier par Od1n (discuter | contributions) (si le paramètre est vide, faire le early return ici, plus élégant que de reposer sur l'échec du tonumber() juste après). Elle peut contenir des erreurs, des inexactitudes ou des contenus vandalisés non présents dans la version actuelle.

 Documentation[créer] [purger]
-- Module dédié au formatage de texte

local fun = {}

-- Mise en forme des nombres
-- Mime le comportement du mot magique formatnum, sans paramètre R
function fun.formatnum(frame)
    return fun.do_formatnum(frame:getParent().args)
end

function fun.do_formatnum(arguments)
    local number = arguments[1]

    -- Vérification du paramètre
    if not number or number == "" then
        return ""
    end
    if type(tonumber(number)) ~= "number" then
        return number
    end

    -- Extraction des parties du nombre
    local start, _, minus, intPart, point, fracPart = number:find("^([^0-9.]?)0*(%d*)(%.?)(%d*)$")

    -- Le parsage échoue avec par exemple les notations scientifiques : "1e+16"
    if not start then
        return number
    end

    local result = ""

    -- Signe moins
    result = result .. minus
    -- Partie entière
    if #intPart > 0 then
        local index = #intPart
        for digit in intPart:gfind("%d") do
            result = result .. digit
            -- Espace tous les trois chiffres
            if index % 3 == 1 and index > 1 then
                result = result .. " "
            end
            index = index - 1
        end
    else
        -- Ajout d'un zéro si la partie décimale est vide
        result = result .. "0"
    end
    -- Virgule
    if point ~= "" then
        result = result .. ","
    end
    -- Partie fractionnaire
    result = result .. fracPart

    return result
end

-- Mise en forme des nombres avec unité
-- Basé sur Modèle:Unité, mais sans limitation de nombre d'arguments
function fun.unite(frame)
    return fun.do_unite(frame:getParent().args)
end

-- Réalisation de la fonction précédente
function fun.do_unite(arguments)
    local result = ""

    -- Formatage de la valeur principale
    if arguments[1] ~= nil then
        result = fun.do_formatnum{arguments[1]}
    end

    -- Formatage de la puissance de 10 éventuelle
    if arguments.e ~= nil then
        result = result .. fun.do_x10{arguments.e}
    end

    -- Parcours des unités et exposants
    local index = 2
    while arguments[index] ~= nil do
        if index == 2 then
            -- Première unité : espace insécable
            result = result .. " "
        else
            -- Unités suivantes : point médian
            result = result .. "⋅"
        end

        -- Affichage de l'unité
        result = result .. arguments[index]

        -- Exposant éventuel
        if arguments[index+1] ~= nil then
            result = result .. fun.do_expo{arguments[index+1]}
        end

        index = index + 2
    end

    -- Non-retour à la ligne
    result = "<span class=\"nowrap\">" .. result .. "</span>"

    return result
end

-- Mise en forme des exposants
-- Basé sur Modèle:Exp
function fun.expo(frame)
    return fun.do_expo(frame:getParent().args)
end

-- Réalisation de la fonction précédente
function fun.do_expo(arguments)
    local result = ""
    if arguments[1] ~= nil then
        result = result .. arguments[1]
    end
    result = "<sup>" .. result .. "</sup>"

    return result
end

-- Mise en forme des puissances de 10
-- Basé sur Modèle:x10
function fun.x10(frame)
    return fun.do_x10(frame:getParent().args)
end

-- Réalisation de la fonction précédente
function fun.do_x10(arguments)
    local result = "×10" .. fun.do_expo{arguments[1]}
    return result
end

-- Affichage d'une valeur en parsecs
-- Basé sur Modèle:Parsec
function fun.parsec(frame)
    return fun.do_parsec(frame:getParent().args)
end

-- Réalisation de la fonction précédente
function fun.do_parsec(arguments)
    local result = ""

    -- Unités disponibles
    local units = {
        pc = {"[[parsec|pc]]", [false] = {1, ""}, [true] = {1, ""}},
        kpc = {"[[Kiloparsec|kpc]]", [false] = {1000, ""}, [true] = {0.001, "million"}},
        mpc = {"[[Mégaparsec|Mpc]]", [false] = {1, "million"}, [true] = {0.001, "milliard"}},
        gpc = {"[[Gigaparsec|Gpc]]", [false] = {1, "milliard"}, [true] = {1, "milliard"}}
    }

    -- Valeur principale
    local resultVal = fun.do_formatnum{(arguments[1] or "")}

    -- Unité utilisée
    local unitData = (units[arguments[2]] or units.pc)

    if arguments.marge ~= nil or arguments.sup ~= nil then
        -- Marge éventuelle
        if arguments.marge ~= nil then
            local resultMarge = "" ;
            if tonumber(arguments.marge) ~= nil then
                resultMarge = "<small>&plusmn;" .. arguments.marge .. "</small>"
            else
                resultMarge = arguments.marge
            end
            resultVal = resultVal .. resultMarge
        end

        -- Deuxième valeur éventuelle
        if arguments.sup ~= nil then
            resultVal = resultVal .. " à&nbsp;" .. arguments.sup
        end
    else
        -- "Environ" si c'est une valeur brute seule
        result = result .. "environ&nbsp;"
    end
    -- Affichage de la valeur
    result = result .. fun.do_unite{resultVal,unitData[1]} .. " "

    -- Affichage de la conversion en années-lumière
    local numVal = tonumber(arguments[1])
    if numVal ~= nil then
        -- On utilise un autre ordre de grandeur si la valeur est trop grande
        local isBigVal = (numVal*3.2616 >= 1000)
        -- Valeur en années-lumière
        local alVal = numVal*unitData[isBigVal][1]*3.2616
        -- Première valeur
        result = result .. "(&sim;" .. fun.do_formatnum{fun.do_chiffresSignificatifs{alVal,3}} .. "&nbsp;"
        if arguments.sup ~= nil and tonumber(arguments.sup) ~= nil then
            -- Deuxième valeur éventuelle
            alVal = tonumber(arguments.sup)*unitData[isBigVal][1]*3.2616
            result = result .. "à&nbsp;" .. fun.do_formatnum{fun.do_chiffresSignificatifs{alVal,3}} .. "&nbsp;"
        end
        -- La dernière valeur affichée (alVal) entraîne-t-elle un pluriel ?
        local unitFull = ""
        if unitData[isBigVal][2] ~= "" then -- Il faut avoir un mot à mettre au pluriel
            if alVal >= 1.995 then
                unitFull = "s"
            end
            unitFull = unitData[isBigVal][2] .. unitFull .. " d'"
        end
        -- Affichage de l'unité
        result = result .. unitFull .. "[[Année-lumière|a.l.]])" ;
    end

    return result
end

-- Affichage d'un nombre avec chiffres significatifs
function fun.chiffresSignificatifs(frame)
    return fun.do_chiffresSignificatifs(frame:getParent().args)
end

-- Réalisation de la fonction précédente
-- Attention, renvoie une chaîne
-- Usage : fun.do_chiffresSignificatifs{valeur, nb de chiffres significatifs}
function fun.do_chiffresSignificatifs(arguments)
    local result = ""
    local value, digits = tonumber(arguments[1]), tonumber(arguments[2])
    if value ~= nil and digits ~= nil then
        local logVal = math.ceil(math.log10(value))
        local mult = 10^(digits-logVal)
        local rounded = math.floor(value*mult+0.5)/mult
        result = string.format("%." .. tostring(math.max(digits-logVal,0)) .. "f", rounded)
    end
    return result
end

-- Ajoute des hyperliens aux mots séparés par des virgules, comme ceux des propriétés Wikidata
function fun.ajouterLiens(frame)
    local arguments = frame:getParent().args
    local mots = mw.text.split(arguments[2], ",")
    local liens = table.concat(mots, "]], [[")
    if liens ~= nil and liens ~= "" then
        return "[[" .. liens .. "]]"
    else
        return ""
    end
end

return fun