Module:ItemBoxGive feedback
Documentation for this module may be created at Module:ItemBox/doc
local p = {}
local function charWidth(cp)
-- Fullwidth & Wide ranges (CJK, Hangul, etc.) → 2 units
if
(cp >= 0x1100 and cp <= 0x115F) or -- Hangul Jamo
(cp >= 0x2E80 and cp <= 0x303E) or -- CJK radicals, Kangxi
(cp >= 0x3041 and cp <= 0x33BF) or -- Hiragana, Katakana, CJK compat
(cp >= 0x33FF and cp <= 0xA4CF) or -- CJK unified
(cp >= 0xA960 and cp <= 0xA97F) or -- Hangul Jamo Extended
(cp >= 0xAC00 and cp <= 0xD7FF) or -- Hangul syllables
(cp >= 0xF900 and cp <= 0xFAFF) or -- CJK compatibility ideographs
(cp >= 0xFE10 and cp <= 0xFE1F) or -- Vertical forms
(cp >= 0xFE30 and cp <= 0xFE6F) or -- CJK compatibility forms
(cp >= 0xFF01 and cp <= 0xFF60) or -- Fullwidth Latin/punctuation
(cp >= 0xFFE0 and cp <= 0xFFE6) or -- Fullwidth signs
(cp >= 0x1B000 and cp <= 0x1B0FF) or -- Kana supplement
(cp >= 0x1F300 and cp <= 0x1F9FF) or -- Emoji block
(cp >= 0x20000 and cp <= 0x2FFFD) or -- CJK Extension B–F
(cp >= 0x30000 and cp <= 0x3FFFD) -- CJK Extension G+
then
return 2
-- Narrow Latin specifics
elseif cp == 0x69 or cp == 0x6C or -- i, l
cp == 0x49 or -- I
cp == 0x31 or -- 1
cp == 0x21 or cp == 0x7C -- !, |
then
return 0.5
-- Wide Latin
elseif cp == 0x6D or cp == 0x77 or -- m, w
cp == 0x4D or cp == 0x57 -- M, W
then
return 1.5
-- Cyrillic and other "ambiguous" scripts — slightly wider than Latin
elseif cp >= 0x0400 and cp <= 0x04FF then
-- Wide Cyrillic (1.5)
local wide = {
[0x0416]=true, [0x0436]=true, -- Ж ж
[0x041C]=true, [0x043C]=true, -- М м
[0x0424]=true, [0x0444]=true, -- Ф ф
[0x0428]=true, [0x0448]=true, -- Ш ш
[0x0429]=true, [0x0449]=true, -- Щ щ
[0x042E]=true, [0x044E]=true, -- Ю ю
[0x042B]=true, [0x044B]=true, -- Ы ы
}
-- Narrow Cyrillic (0.5)
local narrow = {
[0x0406]=true, [0x0456]=true, -- І і (Ukrainian I)
[0x0407]=true, [0x0457]=true, -- Ї ї
}
if wide[cp] then
return 1.5
elseif narrow[cp] then
return 0.5
else
return 1.1
end
-- Default for everything else (Arabic, Hebrew, Thai, etc.)
else
return 1
end
end
local function wordWidth(word)
local width = 0
for i = 1, mw.ustring.len(word) do
local cp = mw.ustring.codepoint(word, i, i)
width = width + charWidth(cp)
end
return math.ceil(width)
end
function p.getFontSize(frame)
local name = frame.args[1] or ""
local words = {}
for word in name:gmatch("%S+") do
table.insert(words, word)
end
local longestLine = 0
if #words == 1 then
longestLine = wordWidth(words[1])
elseif #words == 2 then
longestLine = math.max(wordWidth(words[1]), wordWidth(words[2]))
elseif #words == 3 then
local first = wordWidth(words[1])
local mid = wordWidth(words[2])
local last = wordWidth(words[3])
local shorterOuter = math.min(first, last)
local longerOuter = math.max(first, last)
local combined = mid + 1 + shorterOuter
longestLine = math.max(combined, longerOuter)
else
-- 4+ words: take the max of all individual word widths
for _, word in ipairs(words) do
longestLine = math.max(longestLine, wordWidth(word))
end
end
local fullSize = 15
local fontSize
if longestLine <= 8 then
fontSize = fullSize
else
fontSize = fullSize - (longestLine - 8) * 1
end
fontSize = math.max(6, fontSize)
return fontSize
end
return p