Module:Convert: Difference between revisions

(update from sandbox per Template talk:Convert#Module version 9)
(update from sandbox per Template talk:Convert#Module version 10)
Line 316:
local cat = wanted_category(text_code.all_categories[msg[3]]) or ''
local anchor = msg[4] or ''
local fmt = text_code.all_messages[msg.format or 'cvt_format'] or 'convert: bug'
title = title:gsub('"', '"')
return format(fmt, anchor, title, text, cat)
Line 326:
-- If enabled, add a warning that will be displayed after the convert result.
-- To reduce output noise, only the first warning is displayed.
if config.warnings or level < 0 then
if level <= (tonumber(config.warnings) or 1) then
if parms.warnings == nil then
Line 741:
if engscale then
local success, result = lookup(baseunit, opt_sp_us, 'no_combination', utable, fails, depth)
if success and not success(result.offset thenor returnresult.builtin false,or result.engscale) endthen
if not (result.offset or result.builtin or result.engscale) then
result.defkey = unitcode -- key to lookup default exception
result.engscale = engscale
Line 849 ⟶ 848:
return true
end
end
 
local function ntsh(num, debug)
-- Return html text to be used for a hidden sort key so that
-- the given number will be sorted in numeric order.
-- If debug == true, output is in a box (not hidden).
-- This implements Template:Ntsh (number table sorting, hidden).
num = num or 0
local result, style
if not valid_number(num) then
if num < 0 then
result = '1000000000000000000'
else
result = '9000000000000000000'
end
elseif num == 0 then
result = '5000000000000000000'
else
local mag = floor(log10(abs(num)) + 1e-14)
local prefix
if num > 0 then
prefix = 7000 + mag
else
prefix = 2999 - mag
num = num + 10^(mag+1)
end
result = format('%d', prefix) .. format('%015.0f', floor(num * 10^(14-mag)))
end
if debug then
style = 'border:1px solid'
else
style = 'display:none'
end
return '<span style="' .. style .. '">' .. result .. '</span>'
end
 
Line 913 ⟶ 878:
return name:sub(1, pos+1) .. name:sub(pos+2):gsub(' ', '-')
end
elseif name:sub(-1, -1) == ')' then
pos = name:find('(', 1, true)
if pos then
Line 1,455 ⟶ 1,420:
-- that allows input like 2e6 to be spelled as "two million" which works
-- because the spell module converts '2e6' to '2000000' before spelling.
local function rounded(value, default)
local precision = parms.input_precisionopt_ri
if precision and 0 <= precision and precision <= 8 then
local fmt = '%.' .. format('%d', precision) .. 'f'
return fmt:format(tonumber(value) + 2e-14) -- fudge for some common cases of bad rounding
end
return default
end
singular = (value == 1)
Line 1,466 ⟶ 1,432:
local significand, exponent = clean:match('^([%d.]+)[Ee]([+%-]?%d+)')
if significand then
show = with_exponent(rounded(tonumber(significand)) or, significand), exponent)
scientific = true
else
show = with_separator(parms, rounded(value) or, clean))
end
show = propersign .. show
if parms.opt_spell_in then
show = spell_number(parms, 'in', propersign .. rounded(clean, clean)) or show
scientific = false
end
Line 1,766 ⟶ 1,732:
end
end
elseif en_name == 'stylein' or en_name == 'styleout' then
en_value = loc_value -- accept user text with no validation
else
en_value = text_code.en_option_value[en_name][loc_value]
if en_value and en_value:sub(-1) == '?' then
en_value = en_value:sub(1, -2)
add_warning(parms, -1, 'cvt_deprecated', loc_name .. '=' .. loc_value)
end
if en_value == nil then
if loc_value == '' then
add_warning(parms, 2, 'cvt_empty_option', loc_name)
else
add_warning(parms, 1, 'cvt_unknown_option', loc_name .. '=' .. loc_value)
-- loc_value can no longer be nil here (at one time, that could occur
-- with aliases like |sing=off|adj=on), but am retaining safety check.
local text = loc_value and (loc_name .. '=' .. loc_value) or loc_name
add_warning(parms, 1, 'cvt_unknown_option', text)
end
elseif en_value == '' then
Line 1,781 ⟶ 1,750:
elseif type(en_value) == 'string' and en_value:sub(1, 4) == 'opt_' then
for _, v in ipairs(split(en_value, ',')) do
local lhs, rhs = v:match('^(.-)=(.+)$')
parms[v] = true
if rhs then
parms[lhs] = tonumber(rhs) or rhs
else
parms[v] = true
end
end
en_value = nil
Line 1,789 ⟶ 1,763:
else
add_warning(parms, 1, 'cvt_unknown_option', loc_name .. '=' .. loc_value)
end
end
if parms.adj then
if parms.adj:sub(1, 2) == 'ri' then
-- It is known that adj is 'riN' where N is a single digit, so precision is valid.
-- Only a single en digit is accepted.
parms.input_precision = tonumber(parms.adj:sub(-1))
parms.adj = nil
end
end
Line 1,822 ⟶ 1,788:
else
parms.abbr = 'out' -- default is to abbreviate output only (use symbol, not name)
end
if parms.opt_spell_out and not abbr_entered then
parms.abbr = 'off' -- should show unit name when spelling the output value
end
if parms.opt_flip then
Line 1,848 ⟶ 1,817:
parms.opt_values = true
end
local alignparms.table_align = format('style="text-align: %s;"', parms.opt_table and 'right' or 'center')
end
parms.table_joins = { align .. '|', '\n|' .. align .. '|' }
if parms.table_align or parms.opt_sortable_on then
parms.need_table_or_sort = true
end
local disp_joins = text_code.disp_joins
Line 1,982 ⟶ 1,953:
-- Testing shows this function is successful for 96% of converts in articles,
-- and that on average it speeds up converts by 8%.
if parms.input_precisionopt_ri or parms.opt_spell_in then return end
local clean = to_en(strip(parms[1] or ''), parms)
if #clean > 10 or not clean:match('^[0-9.]+$') then return end
Line 2,347 ⟶ 2,318:
end
return false, { 'cvt_bug_convert' } -- should never occur
end
 
local function user_style(parms, i)
-- Return text for a user-specified style for a table cell, or '' if none,
-- given i = 1 (input style) or 2 (output style).
local style = parms[(i == 1) and 'stylein' or 'styleout']
if style then
style = style:gsub('"', '')
if style ~= '' then
if style:sub(-1) ~= ';' then
style = style .. ';'
end
return style
end
end
return ''
end
 
local function make_table_or_sort(parms, invalue, info, in_current)
-- Set options to handle output for a table or a sort key, or both.
-- The text sort key is based on the value resulting from converting
-- the input to a fake base unit with scale = 1, and other properties
-- required for a conversion derived from the input unit.
local sortkey
if parms.opt_sortable_on then
local base = { -- a fake unit with enough fields for a valid convert
scale = 1,
invert = in_current.invert and 1,
iscomplex = in_current.iscomplex,
offset = in_current.offset and 0,
}
local outvalue, extra = convert(parms, invalue, info, in_current, base)
if extra then
outvalue = extra.outvalue
end
if not valid_number(outvalue) then
if outvalue < 0 then
sortkey = '1000000000000000000'
else
sortkey = '9000000000000000000'
end
elseif outvalue == 0 then
sortkey = '5000000000000000000'
else
local mag = floor(log10(abs(outvalue)) + 1e-14)
local prefix
if outvalue > 0 then
prefix = 7000 + mag
else
prefix = 2999 - mag
outvalue = outvalue + 10^(mag+1)
end
sortkey = format('%d', prefix) .. format('%015.0f', floor(outvalue * 10^(14-mag)))
end
end
if sortkey and (parms.opt_sortable_debug or not parms.table_align) then
parms.join_before = parms.opt_sortable_debug and
'<span style="border:1px solid">' .. sortkey .. '</span>' or
'<span style="display:none">' .. sortkey .. '</span>'
end
if parms.table_align then
local style = 'style="text-align:' .. parms.table_align .. ';'
local sort = sortkey and ' data-sort-value="' .. sortkey .. '"' or ''
local joins = {}
for i = 1, 2 do
joins[i] = (i == 1 and '' or '\n|') .. style .. user_style(parms, i) .. '"' .. sort .. '|'
end
parms.table_joins = joins
end
end
 
Line 2,376 ⟶ 2,416:
end
local outvalue, extra = convert(parms, invalue, info, in_current, out_current)
if parms.need_table_or_sort then
parms.need_table_or_sort = nil -- process using first input value only
make_table_or_sort(parms, invalue, info, in_current)
end
if extra then
if not outvalue then return false, extra end
Line 2,396 ⟶ 2,440:
precision = parms.precision
if not precision then
local sigfig =if parms.sigfig then
show, exponent = make_sigfig(outvalue, parms.sigfig)
if sigfig then
elseif parms.opt_round then
show, exponent = make_sigfig(outvalue, sigfig)
elseif local parms.opt_round5n or= parms.opt_round25 thenopt_round
local n = parms.opt_round5 and 5 or 25
show = format('%.0f', floor((outvalue / n) + 0.5) * n)
else
Line 2,597 ⟶ 2,640:
local i = t.multiple and table_len(combo) or 1
ucode = combo[i]
end
else
-- Try for an automatically generated combination.
local item = ucode:match('^(.-)%+') or ucode:match('^(%S+)%s')
if all_units[item] then
return item
end
end
Line 3,358 ⟶ 3,407:
end
local flipped = parms.opt_flip and not bad_input_mcode
local sortkey
if parms.opt_sortable_in then
sortkey = ntsh(invalue1, parms.opt_sortable_debug)
end
local parts = {}
for part = 1, 2 do
Line 3,417 ⟶ 3,462:
if not success then return false, item end
table.insert(outputs, item)
end
if parms.opt_sortable_out then
local value
local info = out_first and out_first.valinfo
if info then
info = info[1]
value = info.raw_absvalue
if value and info.sign == MINUS then
value = -value
end
end
sortkey = ntsh(value, parms.opt_sortable_debug)
end
if parms.opt_input_unit_only then
parts[part] = ''
else
local sep = parms.table_joins and parms.table_joins[2] or parms.join_between
local sep
if parms.table_joins then
sep = parms.table_joins[2] .. (sortkey or '')
else
sep = parms.join_between
end
parts[part] = table.concat(outputs, sep)
end
end
end
if sortkeyparms.join_before then
forparts[1] i,= vparms.join_before in.. ipairs(parts) do[1]
if i == 1 or parms.table_joins then
parts[i] = sortkey .. v
end
end
end
local wikitext
Anonymous user