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

Нет описания правки
мНет описания правки
(не показано 17 промежуточных версий этого же участника)
Строка 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
Строка 285: Строка 237:
end
end
return true
return true
end
local function find_matching_ids(idsTable, keyPath, searchValue)
local parsedPath = parse_path(keyPath)
local target = tostring(searchValue)
local matches = {}
for idKey, entry in pairs(idsTable) do
if type(entry) == "table" then
local v = get_by_parsed_path(entry, parsedPath)
if v ~= nil and contains_target(v, target) then
matches[#matches + 1] = idKey
end
end
end
return matches
end
end


Строка 359: Строка 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)
Строка 383: Строка 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]
Строка 423: Строка 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
Строка 443: Строка 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
Строка 482: Строка 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
Строка 493: Строка 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 ""
Строка 526: Строка 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
Строка 563: Строка 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
Строка 587: Строка 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
Строка 612: Строка 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
Строка 627: Строка 558:
end
end


local value = get_by_path(entry, keyPath)
return format_value(navigate_path(entry, keyPath))
return format_value(value)
end
 
local function collect_by_parsed_path(tbl, parsedPath, pos, out)
if pos > #parsedPath then
out[#out + 1] = tbl
return
end
 
if type(tbl) ~= "table" then
return
end
 
local token = parsedPath[pos]
local key = token[1]
local idx = token[2]
 
if key == "*" then
for _, child in pairs(tbl) do
local nextCur = child
 
if idx then
if type(nextCur) ~= "table" then
nextCur = nil
else
nextCur = nextCur[idx]
end
end
 
collect_by_parsed_path(nextCur, parsedPath, pos + 1, out)
end
return
end
 
local nextCur
 
if key and key ~= "" then
nextCur = tbl[key]
if nextCur == nil then nextCur = tbl["!type:" .. key] end
else
nextCur = tbl
end
 
if idx then
if type(nextCur) ~= "table" then
return
end
nextCur = nextCur[idx]
end
 
collect_by_parsed_path(nextCur, parsedPath, pos + 1, out)
end
 
local function get_by_parsed_path_multi(tbl, parsedPath)
local out = {}
collect_by_parsed_path(tbl, parsedPath, 1, out)
return out
end
 
local function entry_matches_path(entry, parsedPath, searchValue, searchType)
local values = get_by_parsed_path_multi(entry, parsedPath)
local target = tostring(searchValue)
 
for _, v in ipairs(values) do
if searchType == "key" then
if type(v) == "table" and v[target] ~= nil then
return true
end
else
if contains_target(v, target) then
return true
end
end
end
 
return false
end
 
local function entry_has_any_nonempty_path(entry, parsedPath)
local values = get_by_parsed_path_multi(entry, parsedPath)
 
for _, v in ipairs(values) do
if is_nonempty_value(v) then
return true
end
end
 
return false
end
 
local function split_csv_list(text)
text = mw.text.unstripNoWiki(text or "")
local out = {}
 
for part in string.gmatch(text, "([^,]+)") do
part = mw.text.trim(part)
if part ~= "" then
out[#out + 1] = part
end
end
 
return out
end
 
local function add_scalar_values(value, set)
if type(value) == "table" then
if is_array(value) then
for _, item in ipairs(value) do
add_scalar_values(item, set)
end
else
for _, item in pairs(value) do
add_scalar_values(item, set)
end
end
elseif value ~= nil then
set[tostring(value)] = true
end
end
 
local function table_has_all_values(value, targets)
if type(targets) ~= "table" or #targets == 0 then
return false
end
 
if type(value) ~= "table" then
return #targets == 1 and tostring(value) == targets[1]
end
 
local set = {}
add_scalar_values(value, set)
 
for i = 1, #targets do
if not set[targets[i]] then
return false
end
end
 
return true
end
end


Строка 645: Строка 713:
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
Строка 656: Строка 724:
end
end


local idsTable = type(data.id) == "table" and data.id or data
local ids = collect_id_keys(data)
local ids = collect_id_keys(data)
if #ids == 0 then
if #ids == 0 then
Строка 662: Строка 729:
end
end


local matches
local matches = {}
if searchType == "key" then
local target = tostring(searchValue)
local target = tostring(searchValue)
 
matches = {}
for _, idKey in ipairs(ids) do
for _, idKey in ipairs(ids) do
local entry = resolve_entry(data, idKey)
local v = resolve_path_value(data, idKey, parsedPath)
if type(entry) == "table" and entry_matches_path(entry, parsedPath, target, searchType) then
if type(v) == "table" and v[target] ~= nil then
matches[#matches + 1] = idKey
matches[#matches + 1] = idKey
end
end
 
if #matches == 0 then
return ""
end
 
local ok, json = pcall(mw.text.jsonEncode, matches)
if ok and json then
return json
end
 
return ""
end
 
function p.search(frame)
local args = getArgs(frame, { removeBlanks = false })
local mode = (args[1] or ""):lower()
local rawList = args[2] or ""
 
if mode ~= "component" and mode ~= "tag" then
return "[]"
end
 
local targets = split_csv_list(rawList)
if #targets == 0 then
return "[]"
end
 
local pagePath
if mode == "component" then
pagePath = "component.json"
else
pagePath = "component/tag.json"
end
 
local moduleName = JsonPaths.get(pagePath)
local data = load_cached_data(moduleName)
if not data or type(data) ~= "table" then
return "[]"
end
 
local ids = collect_id_keys(data)
if #ids == 0 then
return "[]"
end
 
table.sort(ids, function(a, b)
return tostring(a) < tostring(b)
end)
 
local function entry_has_all_targets_component(entry, wanted)
if type(entry) ~= "table" then
return false
end
 
local set = {}
for _, v in ipairs(entry) do
set[tostring(v)] = true
end
 
for i = 1, #wanted do
if not set[wanted[i]] then
return false
end
end
end
end
else
 
local target = tostring(searchValue)
return true
matches = {}
end
if idsTable == data then
 
matches = find_matching_ids(idsTable, keyPath, searchValue)
local function entry_has_all_targets_tag(entry, wanted)
if type(entry) ~= "table" then
return false
end
 
local tags = entry.tags or entry.tag
if type(tags) ~= "table" then
return false
end
 
local set = {}
if is_array(tags) then
for _, v in ipairs(tags) do
set[tostring(v)] = true
end
else
else
for _, idKey in ipairs(ids) do
for _, v in pairs(tags) do
local v = resolve_path_value(data, idKey, parsedPath)
set[tostring(v)] = true
if v ~= nil and contains_target(v, target) then
end
matches[#matches + 1] = idKey
end
end
 
for i = 1, #wanted do
if not set[wanted[i]] then
return false
end
end
end
end
return true
end
end


if #matches == 0 then
local matches = {}
return ""
 
for _, idKey in ipairs(ids) do
local entry = resolve_entry(data, idKey)
if mode == "component" then
if entry_has_all_targets_component(entry, targets) then
matches[#matches + 1] = idKey
end
else
if entry_has_all_targets_tag(entry, targets) then
matches[#matches + 1] = idKey
end
end
end
end


Строка 696: Строка 856:
end
end


return ""
return "[]"
end
end


Строка 729: Строка 889:
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
Строка 745: Строка 905:
end
end


local matches
local matches = {}
local entryCache = {}
 
if searchType == "path" then
if searchType == "path" then
matches = {}
for _, idKey in ipairs(ids) do
for _, idKey in ipairs(ids) do
local v = resolve_entry_path_value(data, idKey, parsedPath)
local entry = resolve_entry(data, idKey)
if is_nonempty_value(v) then
entryCache[idKey] = entry
if type(entry) == "table" and entry_has_any_nonempty_path(entry, parsedPath) then
matches[#matches + 1] = idKey
matches[#matches + 1] = idKey
end
end
end
end
elseif searchType == "key" then
else
local target = tostring(searchValue)
local target = tostring(searchValue)
matches = {}
for _, idKey in ipairs(ids) do
for _, idKey in ipairs(ids) do
local v = resolve_path_value(data, idKey, parsedPath)
local entry = resolve_entry(data, idKey)
if type(v) == "table" and v[target] ~= nil then
entryCache[idKey] = entry
if type(entry) == "table" and entry_matches_path(entry, parsedPath, target, searchType) then
matches[#matches + 1] = idKey
matches[#matches + 1] = idKey
end
end
else
local idsTable = data.id
if type(idsTable) == "table" then
local directMatches = find_matching_ids(idsTable, keyPath, searchValue)
local defaultValue = nil
local includeDefault = false
local base = data["default"]
if type(base) == "table" then
defaultValue = get_by_parsed_path(base, parsedPath)
includeDefault = defaultValue ~= nil and contains_target(defaultValue, tostring(searchValue))
end
if includeDefault and #directMatches < #ids then
local seen = {}
for i = 1, #directMatches do
seen[directMatches[i]] = true
end
matches = {}
for _, idKey in ipairs(directMatches) do
matches[#matches + 1] = idKey
end
for _, idKey in ipairs(ids) do
if not seen[idKey] then
local specific = idsTable[idKey]
local specificValue = type(specific) == "table" and get_by_parsed_path(specific, parsedPath) or
nil
if specificValue == nil then
matches[#matches + 1] = idKey
end
end
end
else
matches = directMatches
end
else
local target = tostring(searchValue)
matches = {}
for _, idKey in ipairs(ids) do
local v = resolve_path_value(data, idKey, parsedPath)
if v ~= nil and contains_target(v, target) then
matches[#matches + 1] = idKey
end
end
end
end
end
Строка 816: Строка 933:
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
Строка 842: Строка 959:
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
Строка 880: Строка 997:
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
Строка 938: Строка 1055:
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
Строка 953: Строка 1070:
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
Строка 961: Строка 1077:


return "false"
return "false"
end
function p.getComp(frame)
local args = getArgs(frame, { removeBlanks = false })
local entityId = args[1] or ""
if entityId == "" then
return "[]"
end
local moduleName = JsonPaths.get("component.json")
local data = load_cached_data(moduleName)
if not data or type(data) ~= "table" then
return "[]"
end
local entry = data[entityId]
if type(entry) ~= "table" then
return "[]"
end
local out = {}
for _, v in ipairs(entry) do
if v ~= nil and v ~= "" then
out[#out + 1] = v
end
end
local ok, json = pcall(mw.text.jsonEncode, out)
if ok and json then
return json
end
return "[]"
end
end


Строка 973: Строка 1123:
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
Строка 1024: Строка 1174:
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
Строка 1053: Строка 1203:
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
Строка 1093: Строка 1243:


if aPrimitive ~= bPrimitive then
if aPrimitive ~= bPrimitive then
return aPrimitive
return not aPrimitive
end
end


Строка 1100: Строка 1250:


return keys[1]
return keys[1]
end
local function is_wrapper_block_key(key)
return type(key) == "string" and not key:match("^[%a_][%w_]*$")
end
end


Строка 1128: Строка 1282:
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
Строка 1135: Строка 1289:


for _, k in ipairs(keys) do
for _, k in ipairs(keys) do
local v = value[k]
if not (options.nestedKeyMode == "raw" and type(k) == "number") then
local key
local v = value[k]
if prefix and options.nestedKeyMode == "prefixed" then
local key
key = prefix .. "." .. tostring(k)
if prefix then
else
key = prefix .. "." .. tostring(k)
key = tostring(k)
else
end
key = tostring(k)
end


if type(v) == "table" then
if type(v) == "table" then
if is_array_of_primitives(v) then
if is_array_of_primitives(v) 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
elseif options.nestedKeyMode == "raw" then
local json = encode_nowiki_json(v)
if json then
parts[#parts + 1] = key .. "=" .. json
end
end
end
elseif options.nestedKeyMode == "raw" then
 
local json = encode_nowiki_json(v)
if next(v) ~= nil and not is_array_of_primitives(v) then
if json then
local childPrefix
parts[#parts + 1] = key .. "=" .. tostring(json)
if options.nestedKeyMode == "prefixed" then
childPrefix = key
elseif type(k) == "string" then
childPrefix = key
else
childPrefix = nil
end
append_table_fields(parts, v, options, childPrefix)
end
end
else
parts[#parts + 1] = key .. "=" .. tostring(v)
end
end
if next(v) ~= nil then
local childPrefix = (options.nestedKeyMode == "prefixed") and key or nil
append_table_fields(parts, v, options, childPrefix)
end
else
parts[#parts + 1] = key .. "=" .. tostring(v)
end
end
end
end
Строка 1193: Строка 1356:
skipPrimitiveRoot = true,
skipPrimitiveRoot = true,
}
}
local function is_object_map(tbl)
local count = 0
for k, v in pairs(tbl) do
if type(k) ~= "string" or type(v) ~= "table" then
return false
end
count = count + 1
end
return count > 1
end
local firstParamOverride = mw.text.unstripNoWiki(args.first or args.firstParam or args.idKey or "")


local function makeCall(obj)
local function makeCall(obj)
Строка 1199: Строка 1375:
end
end


local idKey = choose_id_key(obj)
local idKey = firstParamOverride
if idKey == "" then
idKey = choose_id_key(obj)
end
if not idKey then
if not idKey then
return
return
Строка 1217: Строка 1396:


if k == idKey then
if k == idKey then
if type(k) == "string" and string.sub(k, 1, 6) == "!type:" then
if is_wrapper_block_key(k) then
if type(v) == "table" then
if type(v) == "table" then
local json = encode_nowiki_json(v)
if json then
parts[#parts + 1] = "value=" .. json
end
append_table_fields(parts, v, rawTypeOptions, nil)
append_table_fields(parts, v, rawTypeOptions, nil)
elseif v ~= nil then
elseif v ~= nil then
Строка 1227: Строка 1410:
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
Строка 1237: Строка 1420:
elseif v ~= nil then
elseif v ~= nil then
parts[#parts + 1] = "value=" .. tostring(v)
parts[#parts + 1] = "value=" .. tostring(v)
parts[#parts + 1] = k .. "=" .. tostring(v)
end
end
else
else
Строка 1255: Строка 1439:
if is_array(data) then
if is_array(data) then
for _, item in ipairs(data) do
for _, item in ipairs(data) do
makeCall(item)
if type(item) == "table" then
makeCall(item)
elseif item ~= nil and item ~= "" then
makeCall({ [item] = {} })
end
end
elseif is_object_map(data) then
local keys = collect_sorted_keys(data, true)
for _, k in ipairs(keys) do
makeCall({ [k] = data[k] })
end
end
else
else
Строка 1280: Строка 1473:
end
end


local outputType = (args.type or "list"):lower()
local outputType = (args.type or "list")


local bullet = mw.text.unstripNoWiki(args.prefix or "* ")
local bullet = mw.text.unstripNoWiki(args.prefix or "* ")
local sep = mw.text.unstripNoWiki(args.sep or ": ")
local sep = mw.text.unstripNoWiki(args.sep or ": ")
if outputType == "none" then
if outputType == "none" then
bullet = ""
bullet = ""
sep = ""
sep = ""
elseif outputType == "revertList" then
sep = mw.text.unstripNoWiki(args.sep or " ")
end
end


Строка 1296: Строка 1492:
local pairPattern = mw.text.unstripNoWiki(args.pattern or "(.*)")
local pairPattern = mw.text.unstripNoWiki(args.pattern or "(.*)")
local pairReplace = mw.text.unstripNoWiki(args.replace or "\\1")
local pairReplace = mw.text.unstripNoWiki(args.replace or "\\1")
local maxItems = tonumber(args.max or args.limit or args.max_count or args.maxCount or "")
if maxItems ~= nil then
maxItems = math.floor(maxItems)
if maxItems < 0 then
maxItems = nil
end
end


local out = {}
local out = {}


if is_array(data) then
if is_array(data) then
local processed = 0
for _, v in ipairs(data) do
for _, v in ipairs(data) do
processed = processed + 1
if maxItems ~= nil and processed > maxItems then
break
end
local text = ""
local text = ""


Строка 1343: Строка 1554:
return tostring(a) < tostring(b)
return tostring(a) < tostring(b)
end)
end)
local processed = 0


for _, k in ipairs(keys) do
for _, k in ipairs(keys) do
processed = processed + 1
if maxItems ~= nil and processed > maxItems then
break
end
local v = data[k]
local v = data[k]
local vStr
local vStr
Строка 1377: Строка 1595:
if outputType == "enum" then
if outputType == "enum" then
line = vStr .. " " .. keyStr
line = vStr .. " " .. keyStr
elseif outputType == "revertList" then
line = bullet .. vStr .. sep .. keyStr
else
else
line = bullet .. keyStr .. sep .. vStr
line = bullet .. keyStr .. sep .. vStr
Строка 1392: Строка 1612:
if outputType == "enum" then
if outputType == "enum" then
return frame:preprocess(table.concat(out, ", "))
return frame:preprocess(table.concat(out, ", "))
elseif outputType == "list" then
elseif outputType == "list" or outputType == "revertList" then
return frame:preprocess(table.concat(out, "\n"))
return frame:preprocess(table.concat(out, "\n"))
else
else
return frame:preprocess(table.concat(out, " "))
return frame:preprocess(table.concat(out, " "))
end
end
end
function p.flattenFieldSelectiveDirect(id, dataPage, paramNames)
if id == "" or dataPage == "" or type(paramNames) ~= "table" or #paramNames == 0 then
return ""
end
local moduleName = JsonPaths.get(dataPage)
local data = load_cached_data(moduleName)
if not data then
return ""
end
local entry = resolve_entry(data, id) or {}
local parts = flatten_selected_parts(entry, paramNames)
if #parts == 0 then
return ""
end
return table.concat(parts, "|")
end
end


return p
return p