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

мНет описания правки
Нет описания правки
Строка 3: Строка 3:
local JsonPaths = require('Module:JsonPaths')
local JsonPaths = require('Module:JsonPaths')
local getArgs = require('Module:Arguments').getArgs
local getArgs = require('Module:Arguments').getArgs
local function get_module_name(pagePath)
return JsonPaths.get(pagePath)
end


local function load_cached_data(moduleName)
local function load_cached_data(moduleName)
Строка 14: Строка 10:
end
end
return loaded
return loaded
end
local function parse_indexed_part(part)
local key, idx = string.match(part, "^(.-)%[(%d+)%]$")
if key then
return key, tonumber(idx)
end
local num = tonumber(part)
if num then
return nil, num
end
return part, nil
end
end


Строка 37: Строка 19:
local parsed = {}
local parsed = {}
for part in string.gmatch(path, "([^%.]+)") do
for part in string.gmatch(path, "([^%.]+)") do
parsed[#parsed + 1] = { parse_indexed_part(part) }
local key, idxStr = string.match(part, "^(.-)%[(%d+)%]$")
if key then
parsed[#parsed + 1] = { key, tonumber(idxStr) }
else
local num = tonumber(part)
if num then
parsed[#parsed + 1] = { nil, num }
else
parsed[#parsed + 1] = { part, nil }
end
end
end
end


Строка 43: Строка 35:
end
end


local function get_by_parsed_path(tbl, parsedPath)
local function navigate_path(tbl, path)
if not tbl or not parsedPath then
if not tbl then return nil end
return nil
if not path or path == "" then return tbl end
end


local cur = tbl
local cur = tbl
for i = 1, #parsedPath do
local start = 1
local token = parsedPath[i]
local len = #path
local key = token[1]
local idx = token[2]


if key and key ~= "" then
while start <= len do
if type(cur) ~= "table" then
local dotPos = string.find(path, ".", start, true)
return nil
local part
if dotPos then
part = string.sub(path, start, dotPos - 1)
start = dotPos + 1
else
part = string.sub(path, start)
start = len + 1
end
 
if type(cur) ~= "table" then return nil end
 
local bracketPos = string.find(part, "[", 1, true)
if bracketPos then
local key = string.sub(part, 1, bracketPos - 1)
local idx = tonumber(string.sub(part, bracketPos + 1, #part - 1))
 
if key ~= "" then
local val = cur[key]
if val == nil then val = cur["!type:" .. key] end
cur = val
end
end


local nextCur = cur[key]
if idx then
if nextCur == nil then
if type(cur) ~= "table" then return nil end
nextCur = cur["!type:" .. key]
cur = cur[idx]
end
end
cur = nextCur
else
end
local num = tonumber(part)
 
if num then
if idx then
cur = cur[num]
if type(cur) ~= "table" then
else
return nil
local val = cur[part]
if val == nil then val = cur["!type:" .. part] end
cur = val
end
end
cur = cur[idx]
end
end


if cur == nil then
if cur == nil then return nil end
return nil
end
end
end


return cur
return cur
end
local function get_by_path(tbl, path)
return get_by_parsed_path(tbl, parse_path(path))
end
end


local function format_value(v)
local function format_value(v)
local okJson, json = pcall(mw.text.jsonEncode, v)
if v == nil then
if okJson and json == "null" then
return "null"
return "null"
end
if v == nil then
return ""
end
end


Строка 99: Строка 97:
return tostring(v)
return tostring(v)
elseif t == "table" then
elseif t == "table" then
local ok, json2 = pcall(mw.text.jsonEncode, v)
local ok, json = pcall(mw.text.jsonEncode, v)
if ok and json2 then
if ok and json then
return json2
return json
end
end
return ""
return ""
Строка 107: Строка 105:
return tostring(v)
return tostring(v)
end
end
end
local function to_nowiki(v)
return "<nowiki>" .. v .. "</nowiki>"
end
end


Строка 173: Строка 167:
return merged
return merged
end
end
return deep_copy(specific)
return specific
end
end
end
 
local base = data["default"]
if type(base) == "table" then
return deep_copy(base)
end
 
return nil
end
 
local function resolve_path_value(data, id, parsedPath)
if type(data) ~= "table" or not parsedPath or not id or id == "" then
return nil
end
 
local direct = data[id]
if direct ~= nil then
local value = get_by_parsed_path(direct, parsedPath)
if value ~= nil then
return value
end
end
 
local idsTable = data.id
if type(idsTable) == "table" then
local specific = idsTable[id]
if type(specific) == "table" then
local value = get_by_parsed_path(specific, parsedPath)
if value ~= nil then
return value
end
end
end
end
Строка 212: Строка 174:
local base = data["default"]
local base = data["default"]
if type(base) == "table" then
if type(base) == "table" then
return get_by_parsed_path(base, parsedPath)
return base
end
end


return nil
return nil
end
local function resolve_entry_path_value(data, id, parsedPath)
if type(data) ~= "table" or not parsedPath or not id or id == "" then
return nil
end
local entry = resolve_entry(data, id)
if type(entry) ~= "table" then
return nil
end
return get_by_parsed_path(entry, parsedPath)
end
end


Строка 256: Строка 205:


local function contains_target(v, target)
local function contains_target(v, target)
if type(v) == "string" then
return v == target
end
if type(v) == "table" then
if type(v) == "table" then
if is_array(v) then
if is_array(v) then
Строка 342: Строка 294:


local parts = {}
local parts = {}
local function append_table_json(key, value)
local ok, json = pcall(mw.text.jsonEncode, value)
if ok and json then
parts[#parts + 1] = key .. "=" .. to_nowiki(json)
end
end


local function walk(tbl, prefix)
local function walk(tbl, prefix)
Строка 366: Строка 311:
if type(v) == "table" then
if type(v) == "table" then
if next(v) ~= nil then
if next(v) ~= nil then
append_table_json(key, v)
local ok, json = pcall(mw.text.jsonEncode, v)
if ok and json then
parts[#parts + 1] = key .. "=<nowiki>" .. json .. "</nowiki>"
end
if is_array(v) then
if is_array(v) then
local first = v[1]
local first = v[1]
Строка 406: Строка 354:
local ok, json = pcall(mw.text.jsonEncode, value)
local ok, json = pcall(mw.text.jsonEncode, value)
if ok and json then
if ok and json then
parts[#parts + 1] = key .. "=" .. to_nowiki(json)
parts[#parts + 1] = key .. "=<nowiki>" .. json .. "</nowiki>"
end
end
return
return
Строка 426: Строка 374:
if type(key) == "string" and key ~= "" and not seen[key] then
if type(key) == "string" and key ~= "" and not seen[key] then
seen[key] = true
seen[key] = true
append_flattened_part(parts, key, get_by_path(entry, key))
append_flattened_part(parts, key, navigate_path(entry, key))
end
end
end
end
Строка 465: Строка 413:
end
end


local function build_tpl(id, pagePath, tplPath, data, tplArgs)
local function build_tpl(id, pagePath, tplPath, data, tplArgs, preEntry)
if id == "" or pagePath == "" or tplPath == "" then
if id == "" or pagePath == "" or tplPath == "" then
return ""
return ""
end
end


local moduleName = get_module_name(pagePath)
local moduleName = JsonPaths.get(pagePath)
data = data or load_cached_data(moduleName)
data = data or load_cached_data(moduleName)
if not data then
if not data then
Строка 476: Строка 424:
end
end


local entry = resolve_entry(data, id)
local entry = preEntry or resolve_entry(data, id)
local extra = flatten_entry(entry)
local extra = flatten_entry(entry)
local extraTplArgs = tplArgs or ""
local extraTplArgs = tplArgs or ""
Строка 509: Строка 457:


local storeName = (kind == "prototype") and "prototype_store.json" or "component_store.json"
local storeName = (kind == "prototype") and "prototype_store.json" or "component_store.json"
local moduleName = get_module_name(storeName)
local moduleName = JsonPaths.get(storeName)
local data = load_cached_data(moduleName)
local data = load_cached_data(moduleName)
if not data then
if not data then
Строка 546: Строка 494:
end
end


local moduleName = get_module_name(pagePath)
local moduleName = JsonPaths.get(pagePath)
local data = load_cached_data(moduleName)
local data = load_cached_data(moduleName)
if not data then
if not data then
Строка 570: Строка 518:
end
end


local moduleName = get_module_name(pagePath)
local moduleName = JsonPaths.get(pagePath)
local data = load_cached_data(moduleName)
local data = load_cached_data(moduleName)
if not data then
if not data then
Строка 595: Строка 543:
end
end


local moduleName = get_module_name(pagePath)
local moduleName = JsonPaths.get(pagePath)
local data = load_cached_data(moduleName)
local data = load_cached_data(moduleName)
if not data then
if not data then
Строка 610: Строка 558:
end
end


local value = get_by_path(entry, keyPath)
return format_value(navigate_path(entry, keyPath))
return format_value(value)
end
end


Строка 649: Строка 596:
if key and key ~= "" then
if key and key ~= "" then
nextCur = tbl[key]
nextCur = tbl[key]
if nextCur == nil then
if nextCur == nil then nextCur = tbl["!type:" .. key] end
nextCur = tbl["!type:" .. key]
end
else
else
nextCur = tbl
nextCur = tbl
Строка 717: Строка 662:
end
end


local moduleName = get_module_name(pagePath)
local moduleName = JsonPaths.get(pagePath)
local data = load_cached_data(moduleName)
local data = load_cached_data(moduleName)
if not data then
if not data then
Строка 785: Строка 730:
end
end


local moduleName = get_module_name(pagePath)
local moduleName = JsonPaths.get(pagePath)
local data = load_cached_data(moduleName)
local data = load_cached_data(moduleName)
if not data then
if not data then
Строка 802: Строка 747:


local matches = {}
local matches = {}
local entryCache = {}


if searchType == "path" then
if searchType == "path" then
for _, idKey in ipairs(ids) do
for _, idKey in ipairs(ids) do
local entry = resolve_entry(data, idKey)
local entry = resolve_entry(data, idKey)
entryCache[idKey] = entry
if type(entry) == "table" and entry_has_any_nonempty_path(entry, parsedPath) then
if type(entry) == "table" and entry_has_any_nonempty_path(entry, parsedPath) then
matches[#matches + 1] = idKey
matches[#matches + 1] = idKey
Строка 814: Строка 761:
for _, idKey in ipairs(ids) do
for _, idKey in ipairs(ids) do
local entry = resolve_entry(data, idKey)
local entry = resolve_entry(data, idKey)
entryCache[idKey] = entry
if type(entry) == "table" and entry_matches_path(entry, parsedPath, target, searchType) then
if type(entry) == "table" and entry_matches_path(entry, parsedPath, target, searchType) then
matches[#matches + 1] = idKey
matches[#matches + 1] = idKey
Строка 826: Строка 774:
local out = {}
local out = {}
for _, idKey in ipairs(matches) do
for _, idKey in ipairs(matches) do
local tpl = build_tpl(idKey, pagePath, tplPath, data, tplArgs)
local tpl = build_tpl(idKey, pagePath, tplPath, data, tplArgs, entryCache[idKey])
if tpl ~= "" then
if tpl ~= "" then
out[#out + 1] = tpl
out[#out + 1] = tpl
Строка 852: Строка 800:
end
end


local moduleName = get_module_name(pagePath)
local moduleName = JsonPaths.get(pagePath)
local data = frame.data
local data = frame.data
if not data then
if not data then
Строка 890: Строка 838:
end
end


local moduleName = get_module_name(pagePath)
local moduleName = JsonPaths.get(pagePath)
local data = load_cached_data(moduleName)
local data = load_cached_data(moduleName)
if not data then
if not data then
Строка 948: Строка 896:
end
end


local moduleName = get_module_name("component.json")
local moduleName = JsonPaths.get("component.json")
local data = load_cached_data(moduleName)
local data = load_cached_data(moduleName)
if not data then
if not data then
Строка 963: Строка 911:
end
end


local target = tostring(compName)
for _, v in ipairs(entry) do
for _, v in ipairs(entry) do
if tostring(v) == target then
if tostring(v) == compName then
return "true"
return "true"
end
end
Строка 983: Строка 930:
end
end


local moduleName = get_module_name(pagePath)
local moduleName = JsonPaths.get(pagePath)
local data = load_cached_data(moduleName)
local data = load_cached_data(moduleName)
if not data then
if not data then
Строка 1034: Строка 981:
end
end


local moduleName = get_module_name(pagePath)
local moduleName = JsonPaths.get(pagePath)
local data = load_cached_data(moduleName)
local data = load_cached_data(moduleName)
if not data then
if not data then
Строка 1063: Строка 1010:
local ok, json = pcall(mw.text.jsonEncode, value)
local ok, json = pcall(mw.text.jsonEncode, value)
if ok and json then
if ok and json then
return to_nowiki(json)
return "<nowiki>" .. json .. "</nowiki>"
end
end
return nil
return nil
Строка 1142: Строка 1089:
local json = encode_nowiki_json(value)
local json = encode_nowiki_json(value)
if json then
if json then
parts[#parts + 1] = prefix .. "=" .. tostring(json)
parts[#parts + 1] = prefix .. "=" .. json
end
end
end
end
Строка 1162: Строка 1109:
local json = encode_nowiki_json(v)
local json = encode_nowiki_json(v)
if json then
if json then
parts[#parts + 1] = key .. "=" .. tostring(json)
parts[#parts + 1] = key .. "=" .. json
end
end
elseif options.nestedKeyMode == "raw" then
elseif options.nestedKeyMode == "raw" then
local json = encode_nowiki_json(v)
local json = encode_nowiki_json(v)
if json then
if json then
parts[#parts + 1] = key .. "=" .. tostring(json)
parts[#parts + 1] = key .. "=" .. json
end
end
end
end
Строка 1260: Строка 1207:
local json = encode_nowiki_json(v)
local json = encode_nowiki_json(v)
if json then
if json then
parts[#parts + 1] = "value=" .. tostring(json)
parts[#parts + 1] = "value=" .. json
end
end
append_table_fields(parts, v, rawTypeOptions, nil)
append_table_fields(parts, v, rawTypeOptions, nil)
Строка 1270: Строка 1217:
local json = encode_nowiki_json(v)
local json = encode_nowiki_json(v)
if json then
if json then
parts[#parts + 1] = "value=" .. tostring(json)
parts[#parts + 1] = "value=" .. json
end
end
end
end