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

Нет описания правки
мНет описания правки
 
(не показана 21 промежуточная версия этого же участника)
Строка 4: Строка 4:
local getArgs = require('Module:Arguments').getArgs
local getArgs = require('Module:Arguments').getArgs


local function load_cached_data(moduleName)
function p.loadCachedData(pagePath)
local ok, loaded = pcall(mw.loadData, moduleName)
local titleName = JsonPaths.get(pagePath)
if not ok or not loaded then
if not titleName or titleName == "" then
return nil
return nil
end
end
return loaded
 
local ok, data = pcall(mw.loadData, titleName)
if not ok or type(data) ~= "table" then
return nil
end
 
return data
end
end


Строка 90: Строка 96:
local function format_value(v)
local function format_value(v)
if v == nil then
if v == nil then
return "null"
return ""
end
end


Строка 146: Строка 152:
end
end


local function resolve_entry(data, id)
function p.ucfirst(s)
if type(data) ~= "table" then
if not s or s == "" then return s end
return string.upper(s:sub(1, 1)) .. (s:sub(2) or "")
end
 
function p.normalizeComponentName(name)
if type(name) ~= "string" or name == "" then
return nil
end
name = mw.text.trim(name)
if name:sub(1, 5) == "type:" then
name = name:sub(6)
elseif name:sub(1, 6) == "!type:" then
name = name:sub(7)
end
if name == "" then
return nil
return nil
end
end
return name
end
local function split_data_page_path(pagePath)
local kind, name = string.match(pagePath or "", "^(component)/([^/]+)%.json$")
if not kind then
return nil, nil
end
return kind, p.ucfirst(name)
end


if id and id ~= "" then
local function get_component_from_entity(entity, componentName)
local direct = data[id]
if type(entity) ~= "table" or type(entity.components) ~= "table" then
if direct ~= nil then
return nil
return direct
end
end


local idsTable = data.id
return entity.components["type:" .. componentName]
if type(idsTable) == "table" then
or entity.components[componentName]
local specific = idsTable[id]
or entity.components["!type:" .. componentName]
if type(specific) == "table" then
end
local base = data["default"]
 
if type(base) == "table" then
local function load_specific_entry(pagePath, id, allowDefault)
local merged = deep_copy(base)
local kind, name = split_data_page_path(pagePath)
deep_merge(merged, specific)
if not kind or not id or id == "" then
return merged
return nil
end
end
return specific
 
end
if kind ~= "component" then
return nil
end
 
local base
local defaultData = p.loadCachedData(kind .. "/" .. name .. "/defaultFields.json")
if type(defaultData) == "table" then
base = deep_copy(defaultData)
end
 
local entityPage = "prototype/Entity/" .. id .. ".json"
local entity = p.loadCachedData(entityPage)
local specific = get_component_from_entity(entity, name)
 
if type(specific) ~= "table" then
if allowDefault == false then
return nil
end
end
return base
end
end


local base = data["default"]
if base then
if type(base) == "table" then
deep_merge(base, specific)
return base
return base
end
end


return nil
return specific
end
end


local function collect_id_keys(data)
local function resolve_entry_from_data(data, id, allowDefault)
if type(data) ~= "table" then
if type(data) ~= "table" then
return {}
return nil
end
end


local idsTable = data.id
if id and id ~= "" then
local ids = {}
local direct = data[id]
if direct ~= nil then
return direct
end


if type(idsTable) == "table" then
local idsTable = data.id
for k in pairs(idsTable) do
if type(idsTable) == "table" then
ids[#ids + 1] = k
local specific = idsTable[id]
if type(specific) == "table" then
local base = data["default"]
if type(base) == "table" then
local merged = deep_copy(base)
deep_merge(merged, specific)
return merged
end
return specific
end
end
end
return ids
end
end


for k in pairs(data) do
if allowDefault == false then
if k ~= "default" and k ~= "id" then
return nil
ids[#ids + 1] = k
end
end
 
local base = data["default"]
if type(base) == "table" then
return base
end
end


return ids
return nil
end
end


local function contains_target(v, target)
local function load_entry(id, pagePath, data, allowDefault)
if type(v) == "string" then
local specificPageEntry = load_specific_entry(pagePath, id, allowDefault)
return v == target
if specificPageEntry ~= nil then
return specificPageEntry
end
end
if type(v) == "table" then
if is_array(v) then
for _, item in ipairs(v) do
if tostring(item) == target then
return true
end
end
return false
end


for _, item in pairs(v) do
data = data or p.loadCachedData(pagePath)
if tostring(item) == target then
if allowDefault == nil then
return true
allowDefault = true
end
end
return resolve_entry_from_data(data, id, allowDefault)
end
 
local function collect_id_keys(data)
if type(data) ~= "table" then
return {}
end
 
local idsTable = data.id
local ids = {}
 
if type(idsTable) == "table" then
for k in pairs(idsTable) do
ids[#ids + 1] = k
end
return ids
end
 
for k in pairs(data) do
if k ~= "default" and k ~= "id" then
ids[#ids + 1] = k
end
end
return false
end
end


return tostring(v) == target
return ids
end
end


local function is_nonempty_value(v)
local function contains_target(v, target)
if v == nil then
if type(v) == "string" then
return false
return v == target
end
end
if type(v) == "table" then
if type(v) == "table" then
return next(v) ~= nil
if is_array(v) then
for _, item in ipairs(v) do
if tostring(item) == target then
return true
end
end
return false
end
 
for _, item in pairs(v) do
if tostring(item) == target then
return true
end
end
return false
end
end
return true
 
return tostring(v) == target
end
end


local function preprocess_or_return(frame, text)
local function is_nonempty_value(v)
if v == nil then
return false
end
if type(v) == "table" then
return next(v) ~= nil
end
return true
end
 
local function preprocess_or_return(frame, text)
if type(frame) == "table" and type(frame.preprocess) == "function" then
if type(frame) == "table" and type(frame.preprocess) == "function" then
return frame:preprocess(text)
return frame:preprocess(text)
Строка 413: Строка 510:
end
end


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


local moduleName = JsonPaths.get(pagePath)
local entry
data = data or load_cached_data(moduleName)
if strictExact then
if not data then
entry = load_entry(id, pagePath, data, false)
else
entry = preEntry or load_entry(id, pagePath, data)
end
 
if entry == nil then
return ""
return ""
end
end


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 ""
Строка 447: Строка 548:
local searchId = args[1] or ""
local searchId = args[1] or ""
local kind = (args[2] or ""):lower()
local kind = (args[2] or ""):lower()
local fieldId = args[3] or ""
local fieldId = p.ucfirst(args[3] or "")


if searchId == "" or fieldId == "" then
if searchId == "" or fieldId == "" then
Строка 457: Строка 558:


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 = JsonPaths.get(storeName)
local data = p.loadCachedData(storeName)
local data = load_cached_data(moduleName)
if not data then
if not data then
return ""
return ""
Строка 494: Строка 594:
end
end


local moduleName = JsonPaths.get(pagePath)
local entry = load_entry(id, pagePath) or {}
local data = load_cached_data(moduleName)
if not data then
return ""
end
 
local entry = resolve_entry(data, id) or {}
return flatten_entry(entry)
return flatten_entry(entry)
end
end
Строка 518: Строка 612:
end
end


local moduleName = JsonPaths.get(pagePath)
local entry = load_entry(id, pagePath) or {}
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, keys)
local parts = flatten_selected_parts(entry, keys)
if #parts == 0 then
if #parts == 0 then
Строка 543: Строка 631:
end
end


local moduleName = JsonPaths.get(pagePath)
local entry = load_entry(id, pagePath)
local data = load_cached_data(moduleName)
if not data then
return ""
end
 
local entry = resolve_entry(data, id)
if entry == nil then
if entry == nil then
return ""
return ""
Строка 646: Строка 728:


return false
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
end


Строка 662: Строка 758:
end
end


local moduleName = JsonPaths.get(pagePath)
local data = p.loadCachedData(pagePath)
local data = load_cached_data(moduleName)
if not data then
if not data then
return "[]"
return "[]"
Строка 682: Строка 777:


for _, idKey in ipairs(ids) do
for _, idKey in ipairs(ids) do
local entry = resolve_entry(data, idKey)
local entry = resolve_entry_from_data(data, idKey)
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
Строка 700: Строка 795:
end
end


function p.searchIdTpl(frame)
local function collect_ids_from_entry(entry)
local args = getArgs(frame, { removeBlanks = false })
local out = {}
local searchValue = args[1] or ""
local seen = {}
local pagePath = args[2] or ""
local keyPath = args[3] or ""
local tplPath = mw.text.unstripNoWiki(args[4] or "")
local tplArgs = args.tplArgs or args.templateArgs or ""
local searchType = (args.searchType or ""):lower()


if searchType == "" then
local function add(v)
searchType = "value"
if v == nil then
return
end
local s = tostring(v)
if s ~= "" and not seen[s] then
seen[s] = true
out[#out + 1] = s
end
end
end


if searchType == "path" then
if type(entry) == "table" then
searchValue = ""
if is_array(entry) then
pagePath = args[1] or ""
for _, v in ipairs(entry) do
keyPath = args[2] or ""
add(v)
tplPath = mw.text.unstripNoWiki(args[3] or "")
end
tplArgs = args[4] or args.tplArgs or args.templateArgs or ""
else
for _, v in pairs(entry) do
if type(v) == "table" and is_array(v) then
for _, item in ipairs(v) do
add(item)
end
elseif type(v) ~= "table" then
add(v)
end
end
end
else
add(entry)
end
end


tplPath, tplArgs = split_template_spec(tplPath, tplArgs)
return out
end
 
function p.search(frame)
local args = getArgs(frame, { removeBlanks = false })
local mode = (args[1] or ""):lower()
local rawList = args[2] or ""


if pagePath == "" or keyPath == "" or tplPath == "" then
if mode ~= "component" and mode ~= "tag" then
return ""
return ""
end
end
if searchType ~= "path" and searchValue == "" then
 
local targets = split_csv_list(rawList)
if #targets == 0 then
return ""
return ""
end
end


local moduleName = JsonPaths.get(pagePath)
local pagePath = (mode == "component") and "component.json" or "tag.json"
local data = load_cached_data(moduleName)
local data = p.loadCachedData(pagePath)
if not data then
if not data then
return ""
return ""
end
end


local parsedPath = parse_path(keyPath)
local matches = {}
if not parsedPath then
local seen = {}
return ""
 
local function add_id(id)
local s = tostring(id)
if s ~= "" and not seen[s] then
seen[s] = true
matches[#matches + 1] = s
end
end
end


local ids = collect_id_keys(data)
for _, key in ipairs(targets) do
if #ids == 0 then
local entry = resolve_entry_from_data(data, key)
return ""
if entry ~= nil then
end
local ids = collect_ids_from_entry(entry)
 
for _, id in ipairs(ids) do
local matches = {}
add_id(id)
local entryCache = {}
 
if searchType == "path" then
for _, idKey in ipairs(ids) do
local entry = resolve_entry(data, idKey)
entryCache[idKey] = entry
if type(entry) == "table" and entry_has_any_nonempty_path(entry, parsedPath) then
matches[#matches + 1] = idKey
end
end
else
local target = tostring(searchValue)
for _, idKey in ipairs(ids) do
local entry = resolve_entry(data, idKey)
entryCache[idKey] = entry
if type(entry) == "table" and entry_matches_path(entry, parsedPath, target, searchType) then
matches[#matches + 1] = idKey
end
end
end
end
end
end


if #matches == 0 then
table.sort(matches, function(a, b)
return ""
return tostring(a) < tostring(b)
end
end)


local out = {}
local ok, json = pcall(mw.text.jsonEncode, matches)
for _, idKey in ipairs(matches) do
if ok and json then
local tpl = build_tpl(idKey, pagePath, tplPath, data, tplArgs, entryCache[idKey])
return json
if tpl ~= "" then
out[#out + 1] = tpl
end
end
end


if #out == 0 then
return ""
return ""
end
 
local result = table.concat(out, " ")
return preprocess_or_return(frame, result)
end
end


function p.getTpl(frame)
function p.searchIdTpl(frame)
local args = getArgs(frame, { removeBlanks = false })
local args = getArgs(frame, { removeBlanks = false })
local id = args[1] or ""
local searchValue = args[1] or ""
local pagePath = args[2] or ""
local pagePath = args[2] or ""
local tplPath = mw.text.unstripNoWiki(args[3] or "")
local keyPath = args[3] or ""
local tplArgs = args[4] or args.tplArgs or args.templateArgs or ""
local tplPath = mw.text.unstripNoWiki(args[4] or "")
tplPath, tplArgs = split_template_spec(tplPath, tplArgs)
local tplArgs = args.tplArgs or args.templateArgs or ""
local searchType = (args.searchType or ""):lower()


if id == "" or pagePath == "" or tplPath == "" then
if searchType == "" then
searchType = "value"
end
 
if searchType == "path" then
searchValue = ""
pagePath = args[1] or ""
keyPath = args[2] or ""
tplPath = mw.text.unstripNoWiki(args[3] or "")
tplArgs = args[4] or args.tplArgs or args.templateArgs or ""
end
 
tplPath, tplArgs = split_template_spec(tplPath, tplArgs)
 
if pagePath == "" or keyPath == "" or tplPath == "" then
return ""
end
if searchType ~= "path" and searchValue == "" then
return ""
return ""
end
end


local moduleName = JsonPaths.get(pagePath)
local data = p.loadCachedData(pagePath)
local data = frame.data
if not data then
if not data then
data = load_cached_data(moduleName)
return ""
end
end
if not data then
 
local parsedPath = parse_path(keyPath)
if not parsedPath then
return ""
return ""
end
end


local tplStr = build_tpl(id, pagePath, tplPath, data, tplArgs)
local ids = collect_id_keys(data)
return preprocess_or_return(frame, tplStr)
if #ids == 0 then
end
 
function p.searchStoreTpl(frame)
local args = getArgs(frame, { removeBlanks = false })
local searchId = args[1] or ""
local kind = (args[2] or ""):lower()
local generatorId = args[3] or ""
local tplPath = mw.text.unstripNoWiki(args[4] or "")
local tplArgs = args[5] or args.tplArgs or args.templateArgs or ""
tplPath, tplArgs = split_template_spec(tplPath, tplArgs)
 
if searchId == "" or generatorId == "" or tplPath == "" then
return ""
end
if kind ~= "prototype" and kind ~= "component" then
return ""
return ""
end
end


local dir = (kind == "prototype") and "prototype/" or "component/"
local matches = {}
local pagePath = dir .. generatorId .. ".json"
local entryCache = {}


local idsJson = p.findInGenerator({ args = { searchId, kind, generatorId } })
if searchType == "path" then
local ok, ids = pcall(mw.text.jsonDecode, idsJson or "")
for _, idKey in ipairs(ids) do
if not ok or type(ids) ~= "table" or #ids == 0 then
local entry = resolve_entry_from_data(data, idKey)
return ""
entryCache[idKey] = entry
if type(entry) == "table" and entry_has_any_nonempty_path(entry, parsedPath) then
matches[#matches + 1] = idKey
end
end
else
local target = tostring(searchValue)
for _, idKey in ipairs(ids) do
local entry = resolve_entry_from_data(data, idKey)
entryCache[idKey] = entry
if type(entry) == "table" and entry_matches_path(entry, parsedPath, target, searchType) then
matches[#matches + 1] = idKey
end
end
end
end


local moduleName = JsonPaths.get(pagePath)
if #matches == 0 then
local data = load_cached_data(moduleName)
if not data then
return ""
return ""
end
end


local out = {}
local out = {}
for _, id in ipairs(ids) do
for _, idKey in ipairs(matches) do
local tpl = build_tpl(id, pagePath, tplPath, data, tplArgs)
local tpl = build_tpl(idKey, pagePath, tplPath, data, tplArgs, entryCache[idKey], true)
if tpl ~= "" then
if tpl ~= "" then
out[#out + 1] = tpl
out[#out + 1] = tpl
end
end
end
if #out == 0 then
return ""
end
end


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


function p.flattenParams(entry)
function p.getTpl(frame)
return flatten_parts(entry)
local args = getArgs(frame, { removeBlanks = false })
end
local id = args[1] or ""
 
local pagePath = args[2] or ""
function p.searchStore(frame)
local tplPath = mw.text.unstripNoWiki(args[3] or "")
local tplArgs = args[4] or args.tplArgs or args.templateArgs or ""
tplPath, tplArgs = split_template_spec(tplPath, tplArgs)
 
if id == "" or pagePath == "" or tplPath == "" then
return ""
end
 
local data = frame.data
local tplStr = build_tpl(id, pagePath, tplPath, data, tplArgs, nil, true)
return preprocess_or_return(frame, tplStr)
end
 
function p.searchStoreTpl(frame)
local args = getArgs(frame, { removeBlanks = false })
local args = getArgs(frame, { removeBlanks = false })
local searchId = args[1] or ""
local searchId = args[1] or ""
local kind = (args[2] or ""):lower()
local kind = (args[2] or ""):lower()
local generatorId = args[3] or ""
local generatorId = p.ucfirst(args[3] or "")
local tplPath = mw.text.unstripNoWiki(args[4] or "")
local tplArgs = args[5] or args.tplArgs or args.templateArgs or ""
tplPath, tplArgs = split_template_spec(tplPath, tplArgs)


if searchId == "" or generatorId == "" then
if searchId == "" or generatorId == "" or tplPath == "" then
return ""
return ""
end
end
Строка 872: Строка 1005:
return ""
return ""
end
end
local dir = (kind == "prototype") and "prototype/" or "component/"
local pagePath = dir .. generatorId .. ".json"


local idsJson = p.findInGenerator({ args = { searchId, kind, generatorId } })
local idsJson = p.findInGenerator({ args = { searchId, kind, generatorId } })
Строка 879: Строка 1015:
end
end


local okOut, outJson = pcall(mw.text.jsonEncode, ids)
local data = p.loadCachedData(pagePath)
if okOut and outJson then
if not data then
return outJson
return ""
end
 
local out = {}
for _, id in ipairs(ids) do
local entry = resolve_entry_from_data(data, id)
if entry ~= nil then
local tpl = build_tpl(id, pagePath, tplPath, data, tplArgs, entry, true)
if tpl ~= "" then
out[#out + 1] = tpl
end
end
end
end


return ""
local result = table.concat(out, " ")
return preprocess_or_return(frame, result)
end
 
function p.flattenParams(entry)
return flatten_parts(entry)
end
end


function p.hasComp(frame)
function p.searchStore(frame)
local args = getArgs(frame, { removeBlanks = false })
local args = getArgs(frame, { removeBlanks = false })
local entityId = args[1] or ""
local searchId = args[1] or ""
local compName = args[2] or ""
local kind = (args[2] or ""):lower()
local generatorId = p.ucfirst(args[3] or "")


if entityId == "" or compName == "" then
if searchId == "" or generatorId == "" then
return "false"
return ""
end
if kind ~= "prototype" and kind ~= "component" then
return ""
end
end


local moduleName = JsonPaths.get("component.json")
local idsJson = p.findInGenerator({ args = { searchId, kind, generatorId } })
local data = load_cached_data(moduleName)
local ok, ids = pcall(mw.text.jsonDecode, idsJson or "")
if not data then
if not ok or type(ids) ~= "table" or #ids == 0 then
return "false"
return ""
end
end


if type(data) ~= "table" then
local okOut, outJson = pcall(mw.text.jsonEncode, ids)
return "false"
if okOut and outJson then
return outJson
end
end


local entry = data[entityId]
return ""
if type(entry) ~= "table" then
end
return "false"
 
function p.loadEntityData(entityId)
if entityId == "" then
return nil
end
end


for _, v in ipairs(entry) do
local pagePath = "prototype/Entity/" .. entityId .. ".json"
if tostring(v) == compName then
return p.loadCachedData(pagePath)
return "true"
end
end
 
function p.entityHasComponent(entity, compName)
if type(entity) ~= "table" or type(entity.components) ~= "table" then
return false
end
end


return "false"
return entity.components[compName] ~= nil
or entity.components["type:" .. compName] ~= nil
or entity.components["!type:" .. compName] ~= nil
end
end


function p.getAll(frame)
function p.collectEntityComponents(entity)
if type(entity) ~= "table" or type(entity.components) ~= "table" then
return {}
end
 
local out = {}
local seen = {}
local comps = entity.components
 
if #comps > 0 then
for _, v in ipairs(comps) do
local name = p.normalizeComponentName(v)
if name and not seen[name] then
seen[name] = true
out[#out + 1] = name
end
end
else
for k in pairs(comps) do
local name = p.normalizeComponentName(k)
if name and not seen[name] then
seen[name] = true
out[#out + 1] = name
end
end
end
 
table.sort(out)
return out
end
 
function p.hasComp(frame)
local args = getArgs(frame, { removeBlanks = false })
local entityId = args[1] or ""
local compName = args[2] or ""
 
if entityId == "" or compName == "" then
return "false"
end
 
local entity = p.loadEntityData(entityId)
if not entity then
return "false"
end
 
return p.entityHasComponent(entity, compName) and "true" or "false"
end
 
function p.getComp(frame)
local args = getArgs(frame, { removeBlanks = false })
local entityId = args[1] or ""
 
if entityId == "" then
return ""
end
 
local entity = p.loadEntityData(entityId)
if not entity then
return ""
end
 
local out = p.collectEntityComponents(entity)
local ok, json = pcall(mw.text.jsonEncode, out)
if ok and json then
return json
end
 
return ""
end
 
function p.getAll(frame)
local args = getArgs(frame, { removeBlanks = false })
local pagePath = args[1] or ""
local replace = mw.text.unstripNoWiki(args.replace or "")
local pattern = mw.text.unstripNoWiki(args.pattern or "(.*)")
 
if pagePath == "" then
return ""
end
 
local data = p.loadCachedData(pagePath)
if not data then
return ""
end
 
local idsTable = data.id or data
if type(idsTable) ~= "table" then
return ""
end
 
local ids = {}
for k in pairs(idsTable) do
ids[#ids + 1] = k
end
 
table.sort(ids)
 
if replace ~= "" then
local out = {}
for _, id in ipairs(ids) do
local text = apply_pattern(id, pattern, replace)
if text ~= "" then
out[#out + 1] = text
end
end
if #out == 0 then
return ""
end
return preprocess_or_return(frame, table.concat(out, "\n"))
end
 
local ok, json = pcall(mw.text.jsonEncode, ids)
if ok and json then
return json
end
 
return ""
end
 
function p.getAllTpl(frame)
local args = getArgs(frame, { removeBlanks = false })
local args = getArgs(frame, { removeBlanks = false })
local pagePath = args[1] or ""
local pagePath = args[1] or ""
local replace = mw.text.unstripNoWiki(args.replace or "")
local tplPath = args[2] or ""
local pattern = mw.text.unstripNoWiki(args.pattern or "(.*)")
local tplArgs = args[3] or args.tplArgs or args.templateArgs or ""
tplPath, tplArgs = split_template_spec(tplPath, tplArgs)


if pagePath == "" then
if pagePath == "" or tplPath == "" then
return ""
return ""
end
end


local moduleName = JsonPaths.get(pagePath)
local data = p.loadCachedData(pagePath)
local data = load_cached_data(moduleName)
if not data then
if not data then
return ""
return ""
end
end


local idsTable = data.id
local idsTable = data.id or data
if type(idsTable) ~= "table" then
if type(idsTable) ~= "table" then
return ""
return ""
end
end


local ids = {}
local out = {}
for k in pairs(idsTable) do
 
ids[#ids + 1] = k
for idKey in pairs(idsTable) do
local entry = resolve_entry_from_data(data, idKey)
if entry ~= nil then
local tpl = build_tpl(idKey, pagePath, tplPath, data, tplArgs, entry, true)
if tpl ~= "" then
out[#out + 1] = tpl
end
end
end
end


table.sort(ids)
table.sort(out)


if replace ~= "" then
local result = table.concat(out, " ")
local out = {}
return preprocess_or_return(frame, result)
for _, id in ipairs(ids) do
end
local text = apply_pattern(id, pattern, replace)
if text ~= "" then
out[#out + 1] = text
end
end
if #out == 0 then
return ""
end
return preprocess_or_return(frame, table.concat(out, "\n"))
end


local ok, json = pcall(mw.text.jsonEncode, ids)
local function encode_nowiki_json(value)
local ok, json = pcall(mw.text.jsonEncode, value)
if ok and json then
if ok and json then
return json
return "<nowiki>" .. json .. "</nowiki>"
end
end
 
return nil
return ""
end
end


function p.getAllTpl(frame)
local function collect_sorted_keys(tbl, stringOnly)
local args = getArgs(frame, { removeBlanks = false })
local keys = {}
local pagePath = args[1] or ""
for k in pairs(tbl) do
local tplPath = args[2] or ""
if not stringOnly or type(k) == "string" then
local tplArgs = args[3] or args.tplArgs or args.templateArgs or ""
keys[#keys + 1] = k
tplPath, tplArgs = split_template_spec(tplPath, tplArgs)
end
 
if pagePath == "" or tplPath == "" then
return ""
end
end


local moduleName = JsonPaths.get(pagePath)
table.sort(keys, function(a, b)
local data = load_cached_data(moduleName)
return tostring(a) < tostring(b)
if not data then
end)
return ""
end


local idsTable = data.id
return keys
if type(idsTable) ~= "table" then
end
return ""
end


local out = {}
local function choose_id_key(obj)
 
local keys = {}
for idKey in pairs(idsTable) do
for k in pairs(obj) do
local tpl = build_tpl(idKey, pagePath, tplPath, data, tplArgs)
if type(k) == "string" then
if tpl ~= "" then
keys[#keys + 1] = k
out[#out + 1] = tpl
end
end
end
end


table.sort(out)
if #keys == 0 then
return nil
end


local result = table.concat(out, " ")
table.sort(keys, function(a, b)
return preprocess_or_return(frame, result)
local av = obj[a]
end
local bv = obj[b]


local function encode_nowiki_json(value)
local aPrimitive = type(av) ~= "table"
local ok, json = pcall(mw.text.jsonEncode, value)
local bPrimitive = type(bv) ~= "table"
if ok and json then
return "<nowiki>" .. json .. "</nowiki>"
end
return nil
end


local function collect_sorted_keys(tbl, stringOnly)
if aPrimitive ~= bPrimitive then
local keys = {}
return not aPrimitive
for k in pairs(tbl) do
if not stringOnly or type(k) == "string" then
keys[#keys + 1] = k
end
end
end


table.sort(keys, function(a, b)
return tostring(a) < tostring(b)
return tostring(a) < tostring(b)
end)
end)


return keys
return keys[1]
end
end


local function choose_id_key(obj)
local function is_wrapper_block_key(key)
local keys = {}
return type(key) == "string" and not key:match("^[%a_][%w_]*$")
for k in pairs(obj) do
end
if type(k) == "string" then
keys[#keys + 1] = k
end
end


if #keys == 0 then
local function is_array_of_primitives(tbl)
return nil
if type(tbl) ~= "table" or not is_array(tbl) then
return false
end
end


table.sort(keys, function(a, b)
for _, v in ipairs(tbl) do
local av = obj[a]
local bv = obj[b]
 
local aPrimitive = type(av) ~= "table"
local bPrimitive = type(bv) ~= "table"
 
if aPrimitive ~= bPrimitive then
return not aPrimitive
end
 
return tostring(a) < tostring(b)
end)
 
return keys[1]
end
 
local function is_wrapper_block_key(key)
return type(key) == "string" and not key:match("^[%a_][%w_]*$")
end
 
local function is_array_of_primitives(tbl)
if type(tbl) ~= "table" or not is_array(tbl) then
return false
end
 
for _, v in ipairs(tbl) do
if type(v) == "table" then
if type(v) == "table" then
return false
return false
Строка 1299: Строка 1535:
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 = ""


Строка 1346: Строка 1597:
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
Строка 1402: Строка 1660:
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 entry = load_entry(id, dataPage) or {}
local parts = flatten_selected_parts(entry, paramNames)
if #parts == 0 then
return ""
end
return table.concat(parts, "|")
end
end


return p
return p