Модуль:GetField: различия между версиями
Pok (обсуждение | вклад) Нет описания правки |
Pok (обсуждение | вклад) Нет описания правки |
||
| (не показано 16 промежуточных версий этого же участника) | |||
| Строка 216: | Строка 216: | ||
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 | ||
| Строка 736: | Строка 749: | ||
matches = {} | matches = {} | ||
for _, idKey in ipairs(ids) do | for _, idKey in ipairs(ids) do | ||
local v = | local v = resolve_entry_path_value(data, idKey, parsedPath) | ||
if is_nonempty_value(v) then | if is_nonempty_value(v) then | ||
matches[#matches + 1] = idKey | matches[#matches + 1] = idKey | ||
| Строка 775: | Строка 788: | ||
if not seen[idKey] then | if not seen[idKey] then | ||
local specific = idsTable[idKey] | local specific = idsTable[idKey] | ||
local specificValue = type(specific) == "table" and get_by_parsed_path(specific, parsedPath) or nil | local specificValue = type(specific) == "table" and get_by_parsed_path(specific, parsedPath) or | ||
nil | |||
if specificValue == nil then | if specificValue == nil then | ||
matches[#matches + 1] = idKey | matches[#matches + 1] = idKey | ||
| Строка 1034: | Строка 1048: | ||
local result = table.concat(out, " ") | local result = table.concat(out, " ") | ||
return preprocess_or_return(frame, result) | return preprocess_or_return(frame, result) | ||
end | |||
local function encode_nowiki_json(value) | |||
local ok, json = pcall(mw.text.jsonEncode, value) | |||
if ok and json then | |||
return to_nowiki(json) | |||
end | |||
return nil | |||
end | |||
local function collect_sorted_keys(tbl, stringOnly) | |||
local keys = {} | |||
for k in pairs(tbl) do | |||
if not stringOnly or type(k) == "string" then | |||
keys[#keys + 1] = k | |||
end | |||
end | |||
table.sort(keys, function(a, b) | |||
return tostring(a) < tostring(b) | |||
end) | |||
return keys | |||
end | |||
local function choose_id_key(obj) | |||
local keys = {} | |||
for k in pairs(obj) do | |||
if type(k) == "string" then | |||
keys[#keys + 1] = k | |||
end | |||
end | |||
if #keys == 0 then | |||
return nil | |||
end | |||
table.sort(keys, function(a, b) | |||
local av = obj[a] | |||
local bv = obj[b] | |||
local aPrimitive = type(av) ~= "table" | |||
local bPrimitive = type(bv) ~= "table" | |||
if aPrimitive ~= bPrimitive then | |||
return aPrimitive | |||
end | |||
return tostring(a) < tostring(b) | |||
end) | |||
return keys[1] | |||
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 | |||
return false | |||
end | |||
end | |||
return true | |||
end | |||
local function append_table_fields(parts, value, options, prefix) | |||
if type(value) ~= "table" or next(value) == nil then | |||
return | |||
end | |||
local valueIsPrimitiveArray = is_array_of_primitives(value) | |||
if options.skipPrimitiveRoot and is_array_of_primitives(value) then | |||
return | |||
end | |||
if prefix and options.includeJsonAtPrefix then | |||
local json = encode_nowiki_json(value) | |||
if json then | |||
parts[#parts + 1] = prefix .. "=" .. tostring(json) | |||
end | |||
end | |||
local keys = collect_sorted_keys(value, false) | |||
for _, k in ipairs(keys) do | |||
if not (options.nestedKeyMode == "raw" and type(k) == "number") then | |||
local v = value[k] | |||
local key | |||
if prefix then | |||
key = prefix .. "." .. tostring(k) | |||
else | |||
key = tostring(k) | |||
end | |||
if type(v) == "table" then | |||
if is_array_of_primitives(v) then | |||
local json = encode_nowiki_json(v) | |||
if json then | |||
parts[#parts + 1] = key .. "=" .. tostring(json) | |||
end | |||
elseif options.nestedKeyMode == "raw" then | |||
local json = encode_nowiki_json(v) | |||
if json then | |||
parts[#parts + 1] = key .. "=" .. tostring(json) | |||
end | |||
end | |||
if next(v) ~= nil and not is_array_of_primitives(v) then | |||
local childPrefix = (type(k) == "string") and key or nil | |||
append_table_fields(parts, v, options, childPrefix) | |||
end | |||
else | |||
parts[#parts + 1] = key .. "=" .. tostring(v) | |||
end | |||
end | |||
end | |||
end | end | ||
| Строка 1053: | Строка 1186: | ||
local calls = {} | local calls = {} | ||
local nestedOptions = { | |||
includeJsonAtPrefix = true, | |||
nestedKeyMode = "prefixed", | |||
skipPrimitiveRoot = false, | |||
} | |||
local rawTypeOptions = { | |||
includeJsonAtPrefix = false, | |||
nestedKeyMode = "raw", | |||
skipPrimitiveRoot = true, | |||
} | |||
local function | local function makeCall(obj) | ||
if type(obj) ~= "table" then | |||
return | |||
end | |||
local idKey = choose_id_key(obj) | |||
if | if not idKey then | ||
return | return | ||
end | end | ||
local parts = { | local parts = { "{{Шаблон:" .. resolve_template_path(tplPath) } | ||
if tplArgs ~= "" then | if tplArgs ~= "" then | ||
parts[#parts + 1] = tplArgs | parts[#parts + 1] = tplArgs | ||
end | end | ||
if type( | parts[#parts + 1] = tostring(idKey) | ||
local keys = collect_sorted_keys(obj, true) | |||
parts[#parts + 1] = | for _, k in ipairs(keys) do | ||
local v = obj[k] | |||
if k == idKey then | |||
if type(k) == "string" and string.sub(k, 1, 6) == "!type:" then | |||
if type(v) == "table" then | |||
append_table_fields(parts, v, rawTypeOptions, nil) | |||
elseif v ~= nil then | |||
parts[#parts + 1] = "value=" .. tostring(v) | |||
end | |||
elseif type(v) == "table" then | |||
if is_array_of_primitives(v) then | |||
local json = encode_nowiki_json(v) | |||
if json then | |||
parts[#parts + 1] = "value=" .. tostring(json) | |||
end | |||
end | |||
if next(v) ~= nil then | |||
append_table_fields(parts, v, nestedOptions, k) | |||
append_table_fields(parts, v, rawTypeOptions, nil) | |||
end | |||
elseif v ~= nil then | |||
parts[#parts + 1] = "value=" .. tostring(v) | |||
end | |||
else | |||
if type(v) == "table" then | |||
if next(v) ~= nil then | |||
append_table_fields(parts, v, nestedOptions, k) | |||
end | |||
elseif v ~= nil then | |||
parts[#parts + 1] = k .. "=" .. tostring(v) | |||
end | |||
end | end | ||
end | end | ||
| Строка 1084: | Строка 1258: | ||
if is_array(data) then | if is_array(data) then | ||
for _, item in ipairs(data) do | for _, item in ipairs(data) do | ||
makeCall(item) | |||
end | end | ||
else | else | ||
makeCall(data) | |||
end | end | ||
| Строка 1100: | Строка 1268: | ||
end | end | ||
return frame:preprocess(table.concat(calls, " ")) | |||
end | end | ||
| Строка 1231: | Строка 1398: | ||
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 | end | ||
return p | return p | ||