Модуль:JsonLoader: различия между версиями

Материал из Space Station 14 Вики
Нет описания правки
Метка: отменено
Содержимое страницы заменено на «local p = {} function p.getFromTitle(titleName) local title = mw.title.new(titleName) local jsonText = title and title:getContent() or "" local ok, data = pcall(mw.text.jsonDecode, jsonText) if ok and type(data) == "table" then return data else return {} end end function p.invoke(frame) local name = frame.args.title return p.getFromTitle(name) end return p»
Метки: замена ручная отмена отменено
Строка 1: Строка 1:
local p = {}
local p = {}
local function skip_ws(text, pos)
local len = #text
while pos <= len do
local ch = string.sub(text, pos, pos)
if ch ~= " " and ch ~= "\n" and ch ~= "\r" and ch ~= "\t" then
return pos
end
pos = pos + 1
end
return pos
end
local function skip_string(text, pos)
pos = pos + 1
local len = #text
while pos <= len do
local ch = string.sub(text, pos, pos)
if ch == "\\" then
pos = pos + 2
elseif ch == "\"" then
return pos
else
pos = pos + 1
end
end
return nil
end
local function find_value_end(text, pos)
local ch = string.sub(text, pos, pos)
if ch == "\"" then
return skip_string(text, pos)
end
if ch == "{" or ch == "[" then
local depth = 0
local len = #text
while pos <= len do
ch = string.sub(text, pos, pos)
if ch == "\"" then
pos = skip_string(text, pos)
if not pos then
return nil
end
elseif ch == "{" or ch == "[" then
depth = depth + 1
elseif ch == "}" or ch == "]" then
depth = depth - 1
if depth == 0 then
return pos
end
end
pos = pos + 1
end
return nil
end
local len = #text
while pos <= len do
ch = string.sub(text, pos, pos)
if ch == "," or ch == "}" or ch == "]" or ch == "\n" or ch == "\r" then
return pos - 1
end
pos = pos + 1
end
return len
end
local function decode_json(text)
local ok, data = pcall(mw.text.jsonDecode, text)
if ok then
return data
end
return nil
end
local function find_member_range(text, objectStart, keyName)
local pos = skip_ws(text, objectStart)
if string.sub(text, pos, pos) ~= "{" then
return nil, nil
end
pos = skip_ws(text, pos + 1)
while pos <= #text and string.sub(text, pos, pos) ~= "}" do
if string.sub(text, pos, pos) ~= "\"" then
return nil, nil
end
local keyStart = pos
local keyEnd = skip_string(text, pos)
if not keyEnd then
return nil, nil
end
local key = decode_json(string.sub(text, keyStart, keyEnd))
pos = skip_ws(text, keyEnd + 1)
if string.sub(text, pos, pos) ~= ":" then
return nil, nil
end
local valueStart = skip_ws(text, pos + 1)
local valueEnd = find_value_end(text, valueStart)
if not valueEnd then
return nil, nil
end
if key == keyName then
return valueStart, valueEnd
end
pos = skip_ws(text, valueEnd + 1)
local sep = string.sub(text, pos, pos)
if sep == "," then
pos = skip_ws(text, pos + 1)
elseif sep == "}" then
return nil, nil
else
return nil, nil
end
end
return nil, nil
end
local function deep_copy(src)
local dst = {}
for k, v in pairs(src) do
if type(v) == "table" then
dst[k] = deep_copy(v)
else
dst[k] = v
end
end
return dst
end
local function deep_merge(dst, src)
for k, v in pairs(src) do
if type(v) == "table" and type(dst[k]) == "table" then
deep_merge(dst[k], v)
elseif type(v) == "table" then
dst[k] = deep_copy(v)
else
dst[k] = v
end
end
end
local function new_loader(titleName)
local loader = {}
local title = mw.title.new(titleName)
local jsonData
local fullData
local defaultData
local idDataCache = {}
local function get_json()
if jsonData == nil then
jsonData = title and title:getContent() or ""
end
return jsonData
end
local function decode_root_member(keyName)
local text = get_json()
local rootStart = string.find(text, "{", 1, true)
if not rootStart then
return nil
end
local valueStart, valueEnd = find_member_range(text, rootStart, keyName)
if not valueStart then
return nil
end
return decode_json(string.sub(text, valueStart, valueEnd))
end
local function decode_id_member(id)
if idDataCache[id] ~= nil then
return idDataCache[id]
end
local text = get_json()
local rootStart = string.find(text, "{", 1, true)
if not rootStart then
idDataCache[id] = false
return nil
end
local idsStart = find_member_range(text, rootStart, "id")
if not idsStart then
idDataCache[id] = false
return nil
end
local valueStart, valueEnd = find_member_range(text, idsStart, id)
if not valueStart then
idDataCache[id] = false
return nil
end
local data = decode_json(string.sub(text, valueStart, valueEnd))
idDataCache[id] = data or false
return data
end
function loader.all()
if fullData == nil then
local data = decode_json(get_json())
fullData = type(data) == "table" and data or {}
end
return fullData
end
function loader.get(id)
id = tostring(id or "")
if defaultData == nil then
local data = decode_root_member("default")
defaultData = type(data) == "table" and data or false
end
local base = defaultData ~= false and defaultData or nil
if id == "" then
return base
end
local specific = decode_id_member(id)
if type(specific) ~= "table" then
return base
end
if type(base) == "table" then
local merged = deep_copy(base)
deep_merge(merged, specific)
return merged
end
return specific
end
return loader
end


function p.getFromTitle(titleName)
function p.getFromTitle(titleName)
return new_loader(titleName)
    local title = mw.title.new(titleName)
end
    local jsonText = title and title:getContent() or ""
 
    local ok, data = pcall(mw.text.jsonDecode, jsonText)
function p.getAllFromTitle(titleName)
    if ok and type(data) == "table" then
return new_loader(titleName).all()
        return data
    else
        return {}
    end
end
end


function p.invoke(frame)
function p.invoke(frame)
local name = frame.args.title
    local name = frame.args.title
return p.getAllFromTitle(name)
    return p.getFromTitle(name)
end
end


return p
return p

Версия от 19:20, 18 июня 2026

Для документации этого модуля может быть создана страница Модуль:JsonLoader/doc

local p = {}

function p.getFromTitle(titleName)
    local title = mw.title.new(titleName)
    local jsonText = title and title:getContent() or ""
    local ok, data = pcall(mw.text.jsonDecode, jsonText)
    if ok and type(data) == "table" then
        return data
    else
        return {}
    end
end

function p.invoke(frame)
    local name = frame.args.title
    return p.getFromTitle(name)
end

return p