Documentation for this module may be created at Module:SongAuto/doc

local p = {}

-- Unicode superscripts → normal digits
local SUP_TO_NORM = {
  ['⁰']='0',['¹']='1',['²']='2',['³']='3',['⁴']='4',
  ['⁵']='5',['⁶']='6',['⁷']='7',['⁸']='8',['⁹']='9'
}

local function toNumberFromSupers(s)
  if not s or s == '' then return nil end
  local out = s:gsub('[⁰¹²³⁴⁵⁶⁷⁸⁹]', SUP_TO_NORM):gsub('%s','')
  return tonumber(out)
end

-- Parse things like: "1²⁰", "1^20", "1<sup>20</sup>", "1", "7", "23"
-- Returns: rank (number), exponent (number or nil)
local function parsePeak(peak)
  if not peak or peak == '' then return nil end
  peak = mw.text.trim(peak)

  -- 1<sup>20</sup>
  local r, e = peak:match('^(%d+)%s*<sup>([^<]+)</sup>')
  if not r then
    -- 1^20
    r, e = peak:match('^(%d+)%s*%^%s*([%d⁰¹²³⁴⁵⁶⁷⁸⁹]+)')
  end
  if not r then
    -- 1²⁰
    r, e = peak:match('^(%d+)%s*([⁰¹²³⁴⁵⁶⁷⁸⁹]+)')
  end
  if r then return tonumber(r), toNumberFromSupers(e) end

  -- Plain number like "7" or "23"
  local n = tonumber(peak:match('^(%d+)'))
  if n then return n, nil end
  return nil
end

-- Public: return just the base rank as a number string (e.g., 1, 7, 23)
function p.peakbase(frame)
  local args = frame:getParent() and frame:getParent().args or frame.args
  local peak = args.peak or args[1]
  local rank = parsePeak(peak)
  if type(rank) == 'table' then rank = rank[1] end
  local r, _ = parsePeak(peak)
  return r and tostring(r) or ''
end

-- Public: return the number of #1 peaks if peak is 1 with an exponent
-- For 1²⁰ → "20". For "1" (no exponent) → "" (blank). For non-#1 → "" (blank).
function p.num1peaks(frame)
  local args = frame:getParent() and frame:getParent().args or frame.args
  local peak = args.peak or args[1]
  local r, e = parsePeak(peak)
  if r == 1 and (e or 0) > 0 then
    return tostring(e)
  end
  return ''
end

return p