imported>Jacques Ducloy |
imported>Jacques Ducloy |
Ligne 1 : |
Ligne 1 : |
− | local p = {}
| + | <includeonly>{{safesubst:#invoke:Unité|unite}}</includeonly><noinclude> |
− | | + | {{Documentation}} |
− | -- local Delink = require( 'Module:Delink' ) -- chargé uniquement si nécessaire
| + | </noinclude> |
− | | |
− | -- Chargement de la base de données des nom d'unités avec gestion d'erreur.
| |
− | local moduleData = 'Module:Unité/Data'
| |
− | local dataSuccess, Data = pcall ( mw.loadData, moduleData )
| |
− | if dataSuccess and type( Data ) == 'table' then
| |
− | dataSuccess = type( Data.unit ) == 'table'
| |
− | and type( Data.prefix ) == 'table'
| |
− | and type( Data.exposant ) == 'table'
| |
− | end
| |
− | | |
− | local errorCat = '[[Catégorie:Page incorrectement traitée par le Module:Unité]]'
| |
− | local addErrorCat = false
| |
− | | |
− | local supUnicode = { ['0'] = '⁰', ['1'] = '¹', ['2'] = '²', ['3'] = '³', ['4'] = '⁴', ['5'] = '⁵', ['6'] = '⁶', ['7'] = '⁷', ['8'] = '⁸', ['9'] = '⁹',
| |
− | ['+'] = '⁺', ['-'] = '⁻', ['='] = '⁼', ['('] = '⁽', [')'] = '⁾', ['n'] = 'ⁿ' }
| |
− | local subUnicode = { ['0'] = '₀', ['1'] = '₁', ['2'] = '₂', ['3'] = '₃', ['4'] = '₄', ['5'] = '₅', ['6'] = '₆', ['7'] = '₇', ['8'] = '₈', ['9'] = '₉',
| |
− | ['+'] = '₊', ['-'] = '₋', ['='] = '₌', ['('] = '₍', [')'] = '₎',
| |
− | ['a'] = 'ₐ', ['e'] = 'ₑ', ['o'] = 'ₒ', ['x'] = 'ₓ', ['h'] = 'ₕ', ['k'] = 'ₖ', ['l'] = 'ₗ',
| |
− | ['m'] = 'ₘ', ['n'] = 'ₙ', ['p'] = 'ₚ', ['s'] = 'ₛ', ['t'] = 'ₜ',
| |
− | }
| |
− | --- Copie de Outils.trim acceptant les nombres.
| |
− | local function trim( texte )
| |
− | if type( texte ) == 'string' then
| |
− | texte = texte:gsub( '^%s*(%S?.-)%s*$', '%1' )
| |
− | if texte ~= '' then
| |
− | return texte
| |
− | end
| |
− | elseif type( texte ) == 'number' then
| |
− | return tostring( texte )
| |
− | end
| |
− | end
| |
− | | |
− | function p.sanitizeNum( nombre )
| |
− | if type( nombre ) == 'number' then
| |
− | return tostring( nombre )
| |
− | elseif type( nombre ) == 'string' then
| |
− | if nombre:match( '^%-?[%d.,]+$' ) then
| |
− | return nombre
| |
− | end
| |
− | local result = nombre
| |
− | -- remplacement des signes moins ou demi-cadratin par un tiret
| |
− | :gsub( '%−%f[%d]', '-') -- U+2212
| |
− | :gsub( '−%f[%d]', '-') -- html −
| |
− | :gsub( '\226\128[\146\147]%f[%d]', '-') -- U+2212, U+2213 (tiret numérique et demi-cadratin)
| |
− | -- remplacement des espaces insécable par des espace simple
| |
− | :gsub( '\194\160', ' ' )
| |
− | :gsub( ' ', ' ' )
| |
− | :gsub( '\226\128[\128-\138\175]', ' ' ) -- U+2002 à U+200A et U+202F
| |
− | -- trim
| |
− | :gsub( '^%s*(%S?.-)%s*$', '%1' )
| |
− | return result
| |
− | else
| |
− | return ''
| |
− | end
| |
− | end
| |
− | | |
− | ---
| |
− | -- parseNum transforme si possible une chaine formatée en un chaine interprétable par tonumber()
| |
− | -- retourne une chaine pour éviter les arrondi éventuels de lua.
| |
− | -- si "nombre" est une chaine non reconnue comme un nombre par la fonction, retourne "nombre".
| |
− | -- si "nombre" n'est pas un number ou une chaine retourne une chaine vide.
| |
− | function p.parseNombre( nombre )
| |
− | local result
| |
− | if type( nombre ) == 'number' then
| |
− | return tostring( nombre )
| |
− | else
| |
− | -- remplacement des signes moins ou demi-cadratin par un tiret
| |
− | result = p.sanitizeNum( nombre )
| |
− | if result == '' then
| |
− | return ''
| |
− | elseif not result:match( '^%-?[%d., ]*%d$' ) then
| |
− | return nombre
| |
− | end
| |
− | end
| |
− | | |
− | -- suppression espaces
| |
− | result = result:gsub( ' ', '' )
| |
− | | |
− | -- gestion des points et des virgules
| |
− | if result:match( '[.,]' ) then
| |
− | if result:match( '%d%.%d%d%d%.%d' ) then
| |
− | -- type 12.345.678
| |
− | result = result:gsub( '%.', '' ):gsub( ',', '.' )
| |
− | elseif result:match( '%d,%d%d%d,%d' ) -- type 1,234,567 ou 1.234,567,8
| |
− | or result:match( '%d,%d%d%d%.%d' ) -- format anglo-saxon type 1,234.5
| |
− | or result:match( '%d%.%d%d%d,%d' ) -- type 1.123,56 (utilisé en exemple pour sépararer les décimales avec l'ancien modèle unité ou formatnum)
| |
− | then
| |
− | result = result:gsub( ',', '' )
| |
− | else
| |
− | result = result:gsub( ',', '.' )
| |
− | end
| |
− | end
| |
− | | |
− | return result
| |
− | end
| |
− | | |
− | ---
| |
− | -- _formantNum transforme un nombre ou une chaine représentant un nombre en chaine formatée suivant les conventions du français
| |
− | -- si le paramètre ne représente pas un nombre lua il est retourné sans modification
| |
− | -- Le paramètre peut être transmis sous forme de table pour ajouter des options :
| |
− | -- * round : arrondi à n chiffre après la virgule (peut être négatif)
| |
− | -- * decimals : nombre de décimales affichées (peut être négatif, dans ce cas équivalent à round)
| |
− | -- * noHtml : n'utilise pas de balise HTML pour affiché les puissance de 10 (pour pouvoir être utilisé en title)
| |
− | function p.formatNum( num )
| |
− | local params = {}
| |
− | if type( num ) == 'table' then
| |
− | params = num
| |
− | num = params[1]
| |
− | end
| |
− | if type( num ) == 'number' then
| |
− | num = tostring( num )
| |
− | elseif type( num ) ~= 'string' or num == '' then
| |
− | return num
| |
− | end
| |
− | | |
− | -- séparation exposant
| |
− | local n, exponent = num:match( '^([-%d.]+)[eE]([+-]?%d+)$' )
| |
− | if exponent then
| |
− | num = n
| |
− | if params.noHtml then
| |
− | exponent = exponent:gsub('+?%f[%d]0', '' )
| |
− | :gsub( '[%d-]', supUnicode )
| |
− | else
| |
− | exponent = '<sup>' .. exponent:gsub('^%+?(%-?)0?', { ['-'] = '−', [''] = '' } ) .. '</sup>'
| |
− | end
| |
− | exponent = ' ×10' .. exponent
| |
− | else
| |
− | exponent = ''
| |
− | end
| |
− | | |
− | -- arrondi
| |
− | local decimals = tonumber( params.decimals )
| |
− | local round = tonumber( params.round ) or decimals
| |
− | if round and tonumber( num ) then
| |
− | local mult = 10 ^ round
| |
− | num = tostring( math.floor( num * mult + 0.5 ) / mult )
| |
− | end
| |
− | | |
− | local moins, entier, fraction = num:match( '^(%-?)(%d*)%.?(%d*)$' )
| |
− | if not entier then
| |
− | return num
| |
− | end
| |
− | | |
− | if moins == '-' then
| |
− | moins = '−' -- signe moins (U+2212)
| |
− | end
| |
− | | |
− | if entier == '' then
| |
− | entier = '0'
| |
− | elseif entier:len() > 3 then
| |
− | local ini = math.fmod( entier:len() - 1, 3 ) + 1
| |
− | entier = ( entier:sub( 1, ini ) or '') .. entier:sub( ini + 1 ):gsub( '(%d%d%d)', '\194\160%1' )
| |
− | end
| |
− | if fraction ~= '' or ( decimals and decimals > 0 ) then
| |
− | if decimals and decimals > #fraction then
| |
− | fraction = fraction .. string.rep( '0', decimals - #fraction )
| |
− | end
| |
− | if #fraction > 4 then
| |
− | fraction = ',' .. fraction:gsub( '(%d%d%d)', '%1\194\160' ):gsub( '\194\160$', '' )
| |
− | else
| |
− | fraction = ',' .. fraction
| |
− | end
| |
− | end
| |
− | | |
− | return moins .. entier .. fraction .. exponent
| |
− | end
| |
− | | |
− | ---
| |
− | -- formatNombre transforme un nombre formaté ou non en chaine formatée suivant les convention du français.
| |
− | -- si la chaine n'est pas reconnu comme un nombre, elle n'est pas modifiée.
| |
− | function p.formatNombre( num, round, decimals )
| |
− | return p.formatNum{ p.parseNombre( num ), round = round, decimals = decimals }
| |
− | end
| |
− | | |
− | --- formatNombres transforme tous les nombres d'une chaine en nombre formaté suivant les conventions du français.
| |
− | function p.formatNombres( nombres, round, decimals )
| |
− | if type( nombres ) == 'number' then
| |
− | return p.formatNum( nombres, round, decimals )
| |
− | elseif type( nombres ) == 'string' then
| |
− | -- retire les chiffres des strip marker
| |
− | local strip, i = {}, 0
| |
− | nombres = nombres:gsub(
| |
− | 'UNIQ%-%-%a+%-%x%x%x%x%x%x%x%x%-QINU',
| |
− | function ( marker )
| |
− | i = i + 1
| |
− | strip[ tostring( i ) ] = marker
| |
− | return 'UNIQ^' .. i .. '¤QINU'
| |
− | end
| |
− | )
| |
− | -- formatage proprement dit
| |
− | nombres = p.sanitizeNum( nombres )
| |
− | local formatN = function ( n )
| |
− | return p.formatNombre( n, round, decimals )
| |
− | end
| |
− | nombres = nombres
| |
− | :gsub( '%-?%f[%d.,][%d., ]*%de[+-]?%d+', formatN )
| |
− | :gsub( '%-?%f[%d.,][%d., ]*%d', formatN )
| |
− | | |
− | -- réintroduction des strip marker
| |
− | nombres = nombres:gsub( 'UNIQ^(%d+)¤QINU', strip )
| |
− | return nombres
| |
− | else
| |
− | return ''
| |
− | end
| |
− | end
| |
− | | |
− | function p.parseUnit( texte )
| |
− | local toParse = p.sanitizeNum( texte )
| |
− | if toParse ~= '' then
| |
− | local result
| |
− | local specificArgs = {
| |
− | ['à'] = 'à',
| |
− | et = 'et',
| |
− | ou = 'ou',
| |
− | ['/'] = '/',
| |
− | ['–'] = '–', ['-'] = '–', -- demi cadratin et tiret
| |
− | ['±'] = '±', ['+-'] = '±', ['+/-'] = '±',
| |
− | ['+'] = '+',
| |
− | ['−'] = '−', -- signe moins
| |
− | ['×'] = '×', x = '×', ['*'] = '×',
| |
− | ['××'] = '××', xx = '××', ['**'] = '××',
| |
− | }
| |
− | | |
− | -- valeur numérique
| |
− | local match, capture = toParse:match( '^(([%d., ]+%f[^d%(])%s*)' )
| |
− | local prefix
| |
− | if not match then
| |
− | -- cas ou le nombre est remplcé par un ou plusieurs points d'interrogation
| |
− | match, prefix = toParse:match( '^((%?+)%s*)' )
| |
− | end
| |
− | if not match then
| |
− | -- cas ou un mot type "vers", "environ" précède le nombre (mot simple, sans accent pour ne pas complexifier pour des cas minoritaires)
| |
− | match, prefix, capture = toParse:match( '^(([%a]+[.,]?[: ]* )([+-]?%f[%d.,][%d., ]*%d%f[%D])%s*)' )
| |
− | end
| |
− | if not match then
| |
− | -- cas ou le nombre est précédé par un signe, un symbole ASCII, ou suivit d'une incerititude entre parenthèse
| |
− | match, prefix, capture = toParse:match( '^(([(<>=~ ]*)([+-]?%f[%d.,][%d., ]*%d%(?%d*%)?)%s*)' )
| |
− | end
| |
− | if not match then
| |
− | -- cas ou le nombre est précédé par un symbole ≤, ≥ ou ≈
| |
− | match, prefix, capture = toParse:match( '^((\226\137[\164\165\136] ?)([+-]?%f[%d.,][%d., ]*%d%f[%D])%s*)' )
| |
− | end
| |
− | result = { capture or false, prefix = prefix }
| |
− | if match then
| |
− | toParse = toParse:sub( match:len() + 1 )
| |
− | | |
− | -- point de suspensions (ex π = 3.14159...)
| |
− | match = toParse:match( '^…%s*' )
| |
− | if not match then
| |
− | match, capture = toParse:match( '^%.%.%.%s*' )
| |
− | end
| |
− | if match then
| |
− | result[1] = result[1] .. '…'
| |
− | toParse = toParse:sub( match:len() + 1 )
| |
− | end
| |
− | | |
− | -- fraction
| |
− | match, capture = toParse:match( '^((%d*/%d+)%s*)' )
| |
− | if not match then
| |
− | match, capture = toParse:match( '^((\194[\188-\190])%s*)' ) -- ¼ à ¾
| |
− | end
| |
− | if not match then
| |
− | match, capture = toParse:match( '^((\226\133[\144-\158])%s*)' ) -- ⅐ à ⅞
| |
− | end
| |
− | if match then
| |
− | if capture:match( '^/' ) then
| |
− | local n = result[1]:match( ' %d+$' ) or result[1]:match( '^%d+$' ) or ''
| |
− | result[1] = result[1]:sub( 1, -1 - #n )
| |
− | result.fraction = n:gsub( '^ ', '' ) .. capture
| |
− | else
| |
− | result.fraction = capture
| |
− | end
| |
− | toParse = toParse:sub( match:len() + 1 )
| |
− | end
| |
− | | |
− | -- lien avec un deuxième nombre
| |
− | local match2, conj, num = mw.ustring.match( toParse, '^(([àetouM+/−x*×±–-]+) ?(%-?%f[%d.,][%d., ]*%d%f[%D]%)?)%s*)' )
| |
− | if match2 and specificArgs[ conj ]
| |
− | and not ( specificArgs[ conj ] == '×' and mw.ustring.match( toParse, '^[×x] ?10 ?e') ) then
| |
− | result[ specificArgs[ conj ] ] = num
| |
− | toParse = toParse:sub( match2:len() + 1 )
| |
− | end
| |
− | if result['+'] or result['×'] then
| |
− | match2, conj, num = mw.ustring.match( toParse, '^(([x*×−-]) ?(%-?%f[%d.,][%d., ]*%d%f[%D])%s*)' )
| |
− | if match2 then
| |
− | if specificArgs[ conj ] == '×' then
| |
− | result['××'] = num
| |
− | else
| |
− | result['−'] = num
| |
− | end
| |
− | toParse = toParse:sub( match2:len() + 1 )
| |
− | end
| |
− | end
| |
− | end
| |
− | | |
− | -- 10 exposant ( \195\151 = ×, signe multiplié)
| |
− | match, capture = toParse:match( '^(%s*e(%-?%d+)%s*)' )
| |
− | if not match then
| |
− | match, capture = toParse:match( '^(%s*[x\195]\151?10e(%-?%d+)%s*)' )
| |
− | end
| |
− | if match then
| |
− | result.e = capture
| |
− | toParse = toParse:sub( match:len() + 1 )
| |
− | end
| |
− | | |
− | -- unités
| |
− | if Data.unit[ toParse ] or mw.ustring.match( toParse, '^%a+$' ) or toParse:match( '%b<>' ) then
| |
− | table.insert( result, toParse )
| |
− | toParse = ''
| |
− | elseif toParse ~= '' then
| |
− | local unit, exp
| |
− | toParse = toParse:gsub( '²', '2' ):gsub( '³', '3' )
| |
− | repeat
| |
− | -- unité contenant un lien
| |
− | match, unit, exp = mw.ustring.match( toParse, '^((/?[^%s%d/%[%]]*%b[][^%s%d/]*) ?(%-?%d*)%s*)' )
| |
− | if not match then
| |
− | -- unité ne contenant pas de lien
| |
− | match, unit, exp = mw.ustring.match( toParse, '^((/?[^%s%d/]+) ?(%-?%d*)%s*)' )
| |
− | end
| |
− | if not match then
| |
− | -- l/100 km
| |
− | match, unit, exp = mw.ustring.match( toParse, '^((/100 ?[^%s%d/]+) ?(%-?%d*)%s*)' )
| |
− | end
| |
− | if match then
| |
− | if unit:match( '%-$' ) and exp ~= '' then
| |
− | unit = unit:gsub( '%-$', '' )
| |
− | exp = '-' .. exp
| |
− | elseif exp == '-' then
| |
− | unit = match
| |
− | exp = ''
| |
− | end
| |
− | if Data.unit[ unit ] or mw.ustring.match( unit, '[%a€£$«»]' ) then
| |
− | table.insert( result, unit )
| |
− | table.insert( result, exp )
| |
− | toParse = toParse:sub( match:len() + 1 )
| |
− | else
| |
− | break
| |
− | end
| |
− | end
| |
− | until toParse == '' or not match
| |
− | end
| |
− | | |
− | if toParse == '' then
| |
− | if #result > 1 and result[ #result ] == '' then
| |
− | result[ #result ] = nil
| |
− | end
| |
− | return result
| |
− | else
| |
− | -- une partie de la chaine n'a pas pu être décodée, on retourne la chaine originale
| |
− | addErrorCat = true
| |
− | return { texte }
| |
− | end
| |
− | else
| |
− | return { }
| |
− | end
| |
− | end
| |
− | | |
− | ---
| |
− | -- nomUtnit retourne le nom français du code d'une unité et de son exposant.
| |
− | -- si le code de l'unité n'est pas reconnu retourne 1 et false, de façon à ajouter false en première position d'une table.
| |
− | function p.nomUnit( unit, exposant )
| |
− | if not dataSuccess or type( unit ) ~= 'string' then
| |
− | return 1, false
| |
− | end
| |
− | | |
− | -- nettoyage des liens et balise HTML
| |
− | unit = unit:gsub( '^/' , '' )
| |
− | if unit:match( '%[' ) then
| |
− | local Delink = require( 'Module:Delink' )
| |
− | unit = Delink._delink{ unit }
| |
− | end
| |
− | if unit:match( '<' ) then
| |
− | unit = unit:gsub( '%b<>', '' )
| |
− | end
| |
− | | |
− | -- récupère le nom de l'unité
| |
− | local unitTab = Data.unit[ unit ]
| |
− | local unitPrefix = { nom = '' }
| |
− | if not unitTab then
| |
− | unitTab = Data.unit[ unit:sub( 2 ) ]
| |
− | unitPrefix = Data.prefix[ unit:sub( 1, 1 ) ]
| |
− | if not ( unitTab and unitPrefix ) then
| |
− | -- pour µ, Ki, Mi, Gi... qui sont codé sur deux octets
| |
− | unitTab = Data.unit[ unit:sub( 3 ) ]
| |
− | unitPrefix = Data.prefix[ unit:sub( 1, 2 ) ]
| |
− | if not ( unitTab and unitPrefix ) then
| |
− | unitTab = false
| |
− | end
| |
− | end
| |
− | end
| |
− | | |
− | -- récupère le nom de l'exposant
| |
− | if trim( exposant ) then
| |
− | local exp = tonumber( exposant )
| |
− | exp = exp and Data.exposant[ math.abs( exp ) ]
| |
− | exposant = exp or ' puissance ' .. exposant
| |
− | else
| |
− | exposant = ''
| |
− | end
| |
− | | |
− | -- assemble les deux partie
| |
− | if type( unitTab ) == 'table' and type( unitTab.nom ) == 'string' then
| |
− | return unitPrefix.nom .. unitTab.nom .. exposant
| |
− | elseif unit:match( '[/%d]' ) then
| |
− | -- ce n'est pas du texte simple, on anule l'infobule
| |
− | return 1, false
| |
− | else
| |
− | return unit .. exposant
| |
− | end
| |
− | end
| |
− | | |
− | function p._unite( args )
| |
− | -- remplacement de certains caractères, pour simplifier les pattern
| |
− | local nombre = p.sanitizeNum( args[1] )
| |
− | if nombre == '' then
| |
− | nombre = nil
| |
− | else
| |
− | -- formatage du nombre
| |
− | nombre = p.formatNombres( nombre, args.arrondi, args['décimales'] )
| |
− | end
| |
− | | |
− | local wiki = { args.prefix or '', nombre } -- prefix est un paramètre interne défini par p.parseUnit, utile notamment lorsque {{unité}} est utilisé dans les infobox
| |
− | | |
− | -- fraction
| |
− | if args.fraction then
| |
− | local nom, den = args.fraction:match( '^(.-)/(.+)$' )
| |
− | if nom then
| |
− | if nom:match( '^[ %dn()=+-]+$' ) and den:match( '^[ %daeoxhklmnpst()=+-]$' ) then
| |
− | nom = nom:gsub( '[%dn()=+-]', supUnicode )
| |
− | den = den:gsub( '[%daeoxhklmnpst()=+-]', subUnicode )
| |
− | else
| |
− | nom = '<sup style="font-size: 70%; vertical-align: 0.4em;">' .. nom .. '</sup>'
| |
− | den = '<sub style="font-size: 70%; vertical-align: 0em;">' .. den .. '</sub>'
| |
− | end
| |
− | args.fraction = nom .. '⁄' .. den
| |
− | end
| |
− | | |
− | if nombre then
| |
− | table.insert( wiki, '\194\160' )
| |
− | end
| |
− | table.insert( wiki, args.fraction )
| |
− | end
| |
− | | |
− | -- à, et, ou, ×, – (tiret cadratin)
| |
− | local specificArgs = { '–', 'à', 'et', 'ou', '/', '×', '××', '±' }
| |
− | for _, name in ipairs( specificArgs ) do
| |
− | local v = trim( args[ name ] )
| |
− | if v then
| |
− | v = p.formatNombres( v )
| |
− | if name == '–' and nombre and nombre:match( '^[^−]' ) and v:match( '^[^−]' ) then
| |
− | -- pas d'espace pour le tiret cadratin entre deux nombres positifs
| |
− | table.insert( wiki, '–' )
| |
− | elseif name == '/' then
| |
− | -- espace demi-cadratin (U+2002 ou  ) avec /
| |
− | table.insert( wiki, ' / ' )
| |
− | elseif name == '××' then
| |
− | table.insert( wiki, '\194\160×\194\160' )
| |
− | elseif name == '×' or name == '±' then
| |
− | table.insert( wiki, '\194\160' .. name .. '\194\160' )
| |
− | else
| |
− | table.insert( wiki, ' ' .. name .. ' ' )
| |
− | end
| |
− | table.insert( wiki, v )
| |
− | end
| |
− | end
| |
− | | |
− | -- analyse de l'unité pour la conversion (mais ne sera affiché qu'après l'incertitude + et - séparé
| |
− | local i = 1
| |
− | local unit = trim( args[ 2 * i ] )
| |
− | local units = ''
| |
− | local nomUnits, par = {}, false
| |
− | while unit do
| |
− | local exp = p.parseNombre( args[ 2 * i + 1 ] )
| |
− | local sep = ''
| |
− | -- gestion des exposants
| |
− | local expUnit = ''
| |
− | if exp == '' then
| |
− | if unit:sub( -2 ) == '²' then
| |
− | exp = '2'
| |
− | unit = unit:sub( 1, -3 )
| |
− | elseif unit:sub( -2 ) == '³' then
| |
− | exp = '3'
| |
− | unit = unit:sub( 1, -3 )
| |
− | end
| |
− | end
| |
− | if #exp > 0 then
| |
− | expUnit = '<sup>' .. exp:gsub( '^-', '−') .. '</sup>' -- remplace le tiret par un vrai signe moins
| |
− | end
| |
− | -- gestion de la séparation des unités et des unités en dénominateur
| |
− | if units ~= '' then
| |
− | if unit:sub( 1, 1 ) == '/' then
| |
− | sep = '/'
| |
− | unit = unit:sub( 2 )
| |
− | if not par then
| |
− | par = true
| |
− | table.insert( nomUnits, 'par' )
| |
− | end
| |
− | else
| |
− | sep = '\194\160' -- point médian désactivé : '⋅\194\160'
| |
− | end
| |
− | end
| |
− | if exp:match( '^-' ) and not par then
| |
− | par = true
| |
− | table.insert( nomUnits, 'par' )
| |
− | end
| |
− | -- remplacement de l'unité par son symbole
| |
− | if Data.unit[ unit ] then
| |
− | -- unit = Data.unit[ unit ].symbole
| |
− | -- désactivé car ne gère pas les multiple tel mL
| |
− | end
| |
− | units = units .. sep .. unit .. expUnit
| |
− | table.insert( nomUnits, p.nomUnit( unit, exp ) )
| |
− | i = i + 1
| |
− | unit = trim( args[ 2 * i ] )
| |
− | end
| |
− | | |
− | -- conversion
| |
− | local unitNameString = nomUnits[1] and table.concat( nomUnits, ' ' ) or ''
| |
− | unitNameString = mw.ustring.gsub( unitNameString, '(%a)s%f[%A]', '%1' )
| |
− | local multiple = 1
| |
− | local convertTable = Data.convert[ unitNameString ]
| |
− | if not convertTable and #unitNameString > 5 then
| |
− | -- gesion des multiples (Kilo, méga, mili...)
| |
− | local prefix = Data.prefix[ unitNameString:sub( 1, 4 ) ] or Data.prefix[ unitNameString:sub( 1, 5 ) ]
| |
− | local _, par = unitNameString:find( ' par ' )
| |
− | local prefix2
| |
− | if par then
| |
− | prefix2 = Data.prefix[ unitNameString:sub( par + 1, 4 ) ] or Data.prefix[ unitNameString:sub( par + 1, 5 ) ]
| |
− | end
| |
− | if prefix and Data.convert[ unitNameString:gsub( '^' .. prefix.nom, '' ) ] then
| |
− | convertTable = Data.convert[ unitNameString:gsub( '^' .. prefix.nom, '' ) ]
| |
− | multiple = 10 ^ prefix.puissance
| |
− | elseif prefix2 and Data.convert[ unitNameString:gsub( ' par ' .. prefix2.nom, '' ) ] then
| |
− | convertTable = Data.convert[ unitNameString:gsub( ' par ' .. prefix2.nom, '' ) ]
| |
− | multiple = 1 / 10 ^ prefix2.puissance
| |
− | elseif prefix and prefix2 and Data.convert[ unitNameString:gsub( '^' .. prefix.nom, '' ):gsub( ' par ' .. prefix2.nom, '' ) ] then
| |
− | convertTable = Data.convert[ unitNameString:gsub( '^' .. prefix.nom, '' ):gsub( ' par ' .. prefix2.nom, '' ) ]
| |
− | multiple = 10 ^ prefix.puissance / 10 ^ prefix2.puissance
| |
− | end
| |
− | end
| |
− | if convertTable then
| |
− | if type( convertTable[1] ) ~= 'table' then
| |
− | convertTable = { convertTable }
| |
− | end
| |
− | for i, v in ipairs( wiki ) do
| |
− | local n = tonumber( p.parseNombre( v ) )
| |
− | if n then
| |
− | n = n * 10 ^ ( tonumber( p.parseNombre( args.e ) ) or 0 )
| |
− | local converted = {}
| |
− | for _, c in ipairs( convertTable ) do
| |
− | local nConverted = n
| |
− | if c.inverse then
| |
− | nConverted = 1 / n
| |
− | end
| |
− | if c.M then
| |
− | -- M = masse molaire
| |
− | local M = tonumber( args.M )
| |
− | if not M then
| |
− | break
| |
− | end
| |
− | if c.M == '*' then
| |
− | nConverted = nConverted * M
| |
− | elseif c.M == '/' then
| |
− | nConverted = nConverted / M
| |
− | end
| |
− | end
| |
− | nConverted = nConverted * multiple * c[2] + ( c[3] or 0 )
| |
− | -- format
| |
− | nConverted = p.formatNum{ nConverted, round = c.round or 6, noHtml = true }
| |
− | local sep = ' '
| |
− | if mw.ustring.sub( c[1], 1, 1 ) == '°' then
| |
− | sep = ''
| |
− | end
| |
− | mw.log( c[1], mw.ustring.codepoint( sep, 1, 1))
| |
− | table.insert( converted, nConverted .. sep.. c[1] )
| |
− | end
| |
− | wiki[ i ] = '<span title="' .. table.concat( converted, ' ou ' ) ..'">' .. v ..'</span>'
| |
− | end
| |
− | end
| |
− | end
| |
− | | |
− | -- incertitude avec + et − séparés
| |
− | if trim( args['+'] ) then
| |
− | local approximation = '+' .. p.formatNombre( args['+'] ) .. ''
| |
− | if trim( args['−'] ) then
| |
− | approximation = approximation .. '<br> −' .. p.formatNombre( args['−'] )
| |
− | end
| |
− | table.insert( wiki, '<span class="nowrap"><span style="display:inline-block; padding-left:0.2em; vertical-align:top; line-height:1em; font-size:80%; text-align:left;">' )
| |
− | table.insert( wiki, approximation .. '</span></span>' )
| |
− | end
| |
− | | |
− | -- puissance de 10
| |
− | local exposant = trim( args.e )
| |
− | if exposant then
| |
− | exposant = p.formatNombre( exposant )
| |
− | if nombre then
| |
− | if trim( args['±'] ) and not nombre:match( '^%(' ) then
| |
− | table.insert( wiki, 1, '(' )
| |
− | table.insert( wiki, ')' )
| |
− | end
| |
− | table.insert( wiki, '\194\160× 10<sup>' .. exposant .. '</sup>' )
| |
− | else
| |
− | table.insert( wiki, '10<sup>' .. exposant .. '</sup>' )
| |
− | end
| |
− | end
| |
− | | |
− | if units ~= '' then
| |
− | local sep = '\194\160'
| |
− | if not ( nombre or args.fraction or exposant ) then
| |
− | sep = ''
| |
− | else
| |
− | local symbole = Data.unit[ units ] and Data.unit[ units ].symbole
| |
− | if symbole == '°' or symbole == '′' or symbole == '″' then
| |
− | sep = ''
| |
− | end
| |
− | end
| |
− | -- ajoute une abréviation si le nom de l'unité est différent de l'unité (en retirant les espaces qui peuvent être devenus insécables)
| |
− | if nomUnits[1] and mw.ustring.gsub( table.concat( nomUnits ), '[ \194\160]', '' ) ~= mw.ustring.gsub( units, '[ \194\160]', '' ) then
| |
− | units = string.format( '<abbr class=abbr title="%s">%s</abbr>', table.concat( nomUnits, ' ' ), units )
| |
− | end
| |
− | table.insert( wiki, sep .. units )
| |
− | end
| |
− | | |
− | if #wiki > 0 then
| |
− | return table.concat( wiki )
| |
− | end
| |
− | end
| |
− | | |
− | function p.unite( frame )
| |
− | local args
| |
− | if type( frame ) == 'table' then
| |
− | if type( frame.getParent ) == 'function' then
| |
− | args = frame:getParent().args;
| |
− | else
| |
− | args = frame
| |
− | end
| |
− | end
| |
− | if args then
| |
− | args[1] = trim( args[1] ) or false
| |
− | if args[1] then
| |
− | if args[1]:match('[^%d,. -]') then
| |
− | local tempArgs = p.parseUnit( args[1] )
| |
− | if not ( args[2] and tempArgs[2] ) then
| |
− | for k, v in pairs( tempArgs ) do
| |
− | args[k] = v
| |
− | end
| |
− | end
| |
− | end
| |
− | args[2] = trim( args[2] ) or false
| |
− | if args[2] and not args[3] and args[2]:match('/') then
| |
− | local tempArgs = p.parseUnit( args[2] )
| |
− | args[2] = false
| |
− | if tempArgs[1] ~= false then
| |
− | table.insert( tempArgs, 1, false )
| |
− | end
| |
− | for k, v in pairs( tempArgs ) do
| |
− | if args[k] and v then
| |
− | addErrorCat = true
| |
− | end
| |
− | args[k] = args[k] or v
| |
− | end
| |
− | end
| |
− | end
| |
− | -- args alias
| |
− | args['×'] = args['×'] or args['x'] -- lettre x → signe multiplié
| |
− | args['±'] = args['±'] or args['+-'] or args['+/-']
| |
− | if args['+'] then
| |
− | args['−'] = args['−'] or args['-'] -- tiret → signe moins
| |
− | else
| |
− | args['–'] = args['–'] or args['-'] -- tiret → demi-cadratin
| |
− | end
| |
− | local cat = ''
| |
− | if addErrorCat then
| |
− | cat = errorCat
| |
− | end
| |
− | return p._unite( args ) .. cat
| |
− | end
| |
− | end
| |
− | | |
− | return p
| |