|
|
| (не показано 25 промежуточных версий этого же участника) |
| Строка 1: |
Строка 1: |
| local p = {}
| |
|
| |
|
| local function split(s, sep)
| |
| if s == nil then return {} end
| |
| local parts = {}
| |
| sep = sep or "%."
| |
| for part in string.gmatch(s, "([^" .. sep .. "]+)") do
| |
| table.insert(parts, part)
| |
| end
| |
| return parts
| |
| end
| |
|
| |
| local function parse_indexed_part(part)
| |
| -- supports "key", "key[1]" and numeric "1" forms
| |
| local key, idx = string.match(part, "^(.-)%[(%d+)%]$")
| |
| if key then
| |
| return key, tonumber(idx)
| |
| end
| |
| -- numeric-only part (array index)
| |
| local num = tonumber(part)
| |
| if num then
| |
| return nil, num
| |
| end
| |
| return part, nil
| |
| end
| |
|
| |
| local function get_by_path(tbl, path)
| |
| if not tbl then return nil end
| |
| local parts = split(path, "%.")
| |
| local cur = tbl
| |
| for _, part in ipairs(parts) do
| |
| local key, idx = parse_indexed_part(part)
| |
| if key and key ~= "" then
| |
| cur = cur[key]
| |
| end
| |
| if idx then
| |
| -- Lua tables from mw.loadData are 1-based for arrays, so we use the index directly.
| |
| if type(cur) ~= "table" then
| |
| return nil
| |
| end
| |
| cur = cur[idx]
| |
| end
| |
| if cur == nil then
| |
| return nil
| |
| end
| |
| end
| |
| return cur
| |
| end
| |
|
| |
| local function is_array(t)
| |
| if type(t) ~= "table" then return false end
| |
| local i = 0
| |
| for _ in pairs(t) do
| |
| i = i + 1
| |
| -- if any key is not a number then not a pure array
| |
| end
| |
| -- We'll treat table as array if all keys are numeric 1..n
| |
| local n = 0
| |
| for k in pairs(t) do
| |
| if type(k) ~= "number" then
| |
| return false
| |
| end
| |
| if k > n then n = k end
| |
| end
| |
| return n > 0
| |
| end
| |
|
| |
| local function format_value(v)
| |
| if v == nil then return "" end
| |
| local t = type(v)
| |
| if t == "string" or t == "number" or t == "boolean" then
| |
| return tostring(v)
| |
| elseif t == "table" then
| |
| -- array-like: join with commas
| |
| if is_array(v) then
| |
| local out = {}
| |
| local max = 0
| |
| for k in pairs(v) do if type(k) == "number" and k > max then max = k end end
| |
| for i = 1, max do
| |
| table.insert(out, format_value(v[i]))
| |
| end
| |
| return table.concat(out, ", ")
| |
| else
| |
| -- associative table: "k: v" pairs joined by ", "
| |
| local out = {}
| |
| for k, val in pairs(v) do
| |
| table.insert(out, tostring(k) .. ": " .. format_value(val))
| |
| end
| |
| return table.concat(out, ", ")
| |
| end
| |
| else
| |
| return tostring(v)
| |
| end
| |
| end
| |
|
| |
| -- Public entry point for invocation
| |
| function p.get(frame)
| |
| local args = frame.args or {}
| |
| local id = args[1] or ""
| |
| local pagePath = args[2] or ""
| |
| local keyPath = args[3] or ""
| |
|
| |
| -- Build module load path. The user requested appending to IanComradeBot/
| |
| local baseUser = "IanComradeBot/"
| |
| local moduleName = "Module:" .. baseUser .. pagePath .. "/data"
| |
|
| |
| -- Try load
| |
| local ok, data = pcall(mw.loadData, moduleName)
| |
| if not ok or not data then
| |
| -- Fallback: try using pagePath directly as a Module name (in case the caller passed full path)
| |
| local altModuleName = "Module:" .. pagePath .. "/data"
| |
| ok, data = pcall(mw.loadData, altModuleName)
| |
| if not ok or not data then
| |
| return ""
| |
| end
| |
| end
| |
|
| |
| -- Find by id, fallback to default
| |
| local entry = nil
| |
| if id ~= "" then
| |
| entry = data[id]
| |
| end
| |
| if entry == nil then
| |
| entry = data["default"]
| |
| end
| |
| if entry == nil then
| |
| return ""
| |
| end
| |
|
| |
| if keyPath == "" then
| |
| -- If no keyPath provided, return formatted entire entry
| |
| return format_value(entry)
| |
| end
| |
|
| |
| local value = get_by_path(entry, keyPath)
| |
| return format_value(value)
| |
| end
| |
|
| |
| return p
| |