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

Нет описания правки
Метка: отменено
мНет описания правки
Метки: ручная отмена отменено
Строка 100: Строка 100:


local t = type(v)
local t = type(v)
if t == "string" then
if t == "string" or t == "number" or t == "boolean" then
return v
elseif t == "number" or t == "boolean" then
return tostring(v)
return tostring(v)
elseif t == "table" then
elseif t == "table" then
Строка 116: Строка 114:


local function is_array(tbl)
local function is_array(tbl)
local n = #tbl
local max = 0
if n == 0 then
return false
end
if tbl[n] == nil then
return false
end
local count = 0
local count = 0
for k in pairs(tbl) do
for k in pairs(tbl) do
if type(k) ~= "number" then
if type(k) ~= "number" then
return false
return false
end
if k > max then
max = k
end
end
count = count + 1
count = count + 1
end
end
return count == n
return count > 0 and max == count
end
 
local function is_array_of_primitives(tbl)
if type(tbl) ~= "table" then return false end
local n = #tbl
if n == 0 or tbl[n] == nil then return false end
local count = 0
for k, v in pairs(tbl) do
if type(k) ~= "number" then return false end
if type(v) == "table" then return false end
count = count + 1
end
return count == n
end
end


Строка 158: Строка 140:
end
end


local function merge_copy(base, specific)
local function deep_merge(dst, src)
local result = {}
for k, v in pairs(src) do
for k, v in pairs(base) do
if type(v) == "table" and type(dst[k]) == "table" then
local specificV = specific[k]
deep_merge(dst[k], v)
if specificV ~= nil then
if type(v) == "table" and type(specificV) == "table" then
result[k] = merge_copy(v, specificV)
elseif type(specificV) == "table" then
result[k] = deep_copy(specificV)
else
result[k] = specificV
end
elseif type(v) == "table" then
elseif type(v) == "table" then
result[k] = deep_copy(v)
dst[k] = deep_copy(v)
else
else
result[k] = v
dst[k] = v
end
end
end
end
for k, v in pairs(specific) do
if result[k] == nil then
if type(v) == "table" then
result[k] = deep_copy(v)
else
result[k] = v
end
end
end
return result
end
end


Строка 205: Строка 169:
local base = data["default"]
local base = data["default"]
if type(base) == "table" then
if type(base) == "table" then
return merge_copy(base, specific)
local merged = deep_copy(base)
deep_merge(merged, specific)
return merged
end
end
return specific
return specific
Строка 254: Строка 220:
end
end
if type(v) == "table" then
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
for _, item in pairs(v) do
if tostring(item) == target then
if tostring(item) == target then
Строка 332: Строка 307:


local function walk(tbl, prefix)
local function walk(tbl, prefix)
local entries = {}
local keys = {}
for k in pairs(tbl) do
for k in pairs(tbl) do
entries[#entries + 1] = { k, tostring(k) }
keys[#keys + 1] = k
end
end
table.sort(entries, function(a, b) return a[2] < b[2] end)
table.sort(keys, function(a, b)
return tostring(a) < tostring(b)
end)


for _, e in ipairs(entries) do
for _, k in ipairs(keys) do
local k = e[1]
local kStr = e[2]
local v = tbl[k]
local v = tbl[k]
local kStr = tostring(k)
local key = (prefix == "" and kStr or prefix .. "." .. kStr)
local key = (prefix == "" and kStr or prefix .. "." .. kStr)


Строка 463: Строка 439:
local templatePath = resolve_template_path(tplPath)
local templatePath = resolve_template_path(tplPath)


local tplParts = { "{{Шаблон:" .. templatePath }
local tplStr = "{{Шаблон:" .. templatePath
if extraTplArgs ~= "" then
if extraTplArgs ~= "" then
tplParts[#tplParts + 1] = extraTplArgs
tplStr = tplStr .. "|" .. extraTplArgs
end
end
tplParts[#tplParts + 1] = "id=" .. tostring(id)
tplStr = tplStr .. "|id=" .. tostring(id)
if extra ~= "" then
if extra ~= "" then
tplParts[#tplParts + 1] = extra
tplStr = tplStr .. "|" .. extra
end
end
tplParts[#tplParts + 1] = "}}"
tplStr = tplStr .. "}}"
return table.concat(tplParts, "|")
 
return tplStr
end
end


Строка 677: Строка 654:
local function add_scalar_values(value, set)
local function add_scalar_values(value, set)
if type(value) == "table" then
if type(value) == "table" then
for _, item in pairs(value) do
if is_array(value) then
add_scalar_values(item, set)
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
end
elseif value ~= nil then
elseif value ~= nil then
Строка 755: Строка 738:


return ""
return ""
end
local function entry_has_all_targets_component(entry, wanted)
if type(entry) ~= "table" then
return false
end
local set = {}
for _, v in pairs(entry) do
set[tostring(v)] = true
end
for i = 1, #wanted do
if not set[wanted[i]] then
return false
end
end
return true
end
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 = {}
for _, v in pairs(tags) do
set[tostring(v)] = true
end
for i = 1, #wanted do
if not set[wanted[i]] then
return false
end
end
return true
end
end


Строка 831: Строка 771:
end
end


local sortedIds = {}
table.sort(ids, function(a, b)
for i = 1, #ids do
return tostring(a) < tostring(b)
sortedIds[i] = { ids[i], tostring(ids[i]) }
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
 
return true
end
 
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
for _, v in pairs(tags) do
set[tostring(v)] = true
end
end
 
for i = 1, #wanted do
if not set[wanted[i]] then
return false
end
end
 
return true
end
end
table.sort(sortedIds, function(a, b) return a[2] < b[2] end)


local matches = {}
local matches = {}


for _, e in ipairs(sortedIds) do
for _, idKey in ipairs(ids) do
local idKey = e[1]
local entry = resolve_entry_from_data(data, idKey)
local entry = resolve_entry_from_data(data, idKey)
if mode == "component" then
if mode == "component" then
Строка 1202: Строка 1188:
end
end


local function collect_sorted_entries(tbl, stringOnly)
local function collect_sorted_keys(tbl, stringOnly)
if stringOnly then
local keys = {}
local keys = {}
for k in pairs(tbl) do
for k in pairs(tbl) do
if not stringOnly or type(k) == "string" then
if type(k) == "string" then
keys[#keys + 1] = k
keys[#keys + 1] = k
end
end
table.sort(keys)
local entries = {}
for i = 1, #keys do
entries[i] = { keys[i], keys[i] }
end
end
return entries
end
end
local entries = {}
for k in pairs(tbl) do
entries[#entries + 1] = { k, tostring(k) }
end
table.sort(entries, function(a, b) return a[2] < b[2] end)
return entries
end


local function collect_sorted_keys(tbl, stringOnly)
table.sort(keys, function(a, b)
local entries = collect_sorted_entries(tbl, stringOnly)
return tostring(a) < tostring(b)
local keys = {}
end)
for i = 1, #entries do
 
keys[i] = entries[i][1]
end
return keys
return keys
end
end


local function choose_id_key(obj)
local function choose_id_key(obj)
local entries = {}
local keys = {}
for k in pairs(obj) do
for k in pairs(obj) do
if type(k) == "string" then
if type(k) == "string" then
entries[#entries + 1] = { k, type(obj[k]) ~= "table" }
keys[#keys + 1] = k
end
end
end
end


if #entries == 0 then
if #keys == 0 then
return nil
return nil
end
end


table.sort(entries, function(a, b)
table.sort(keys, function(a, b)
if a[2] ~= b[2] then
local av = obj[a]
return not a[2]
local bv = obj[b]
 
local aPrimitive = type(av) ~= "table"
local bPrimitive = type(bv) ~= "table"
 
if aPrimitive ~= bPrimitive then
return not aPrimitive
end
end
return a[1] < b[1]
 
return tostring(a) < tostring(b)
end)
end)


return entries[1][1]
return keys[1]
end
end


local function is_wrapper_block_key(key)
local function is_wrapper_block_key(key)
return type(key) == "string" and not key:match("^[%a_][%w_]*$")
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
return false
end
end
return true
end
end


Строка 1276: Строка 1266:
end
end


local entries = collect_sorted_entries(value, false)
local keys = collect_sorted_keys(value, false)


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


Строка 1319: Строка 1307:
end
end
end
end
end
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
end


Строка 1359: Строка 1336:
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 firstParamOverride = mw.text.unstripNoWiki(args.first or args.firstParam or args.idKey or "")
Строка 1381: Строка 1369:
end
end


parts[#parts + 1] = idKey
parts[#parts + 1] = tostring(idKey)
local entries = collect_sorted_entries(obj, true)
local keys = collect_sorted_keys(obj, true)


for _, e in ipairs(entries) do
for _, k in ipairs(keys) do
local k = e[1]
local v = obj[k]
local v = obj[k]


Строка 1439: Строка 1426:
end
end
elseif is_object_map(data) then
elseif is_object_map(data) then
local dataEntries = collect_sorted_entries(data, true)
local keys = collect_sorted_keys(data, true)
for _, e in ipairs(dataEntries) do
for _, k in ipairs(keys) do
makeCall({ [e[1]] = data[e[1]] })
makeCall({ [k] = data[k] })
end
end
else
else
Строка 1536: Строка 1523:
end
end


out[#out + 1] = line
table.insert(out, line)
end
end
end
end
else
else
local dataEntries = {}
local keys = {}
for k in pairs(data) do
for k in pairs(data) do
dataEntries[#dataEntries + 1] = { k, tostring(k) }
keys[#keys + 1] = k
end
end
table.sort(dataEntries, function(a, b) return a[2] < b[2] end)
table.sort(keys, function(a, b)
return tostring(a) < tostring(b)
end)


local processed = 0
local processed = 0


for _, de in ipairs(dataEntries) do
for _, k in ipairs(keys) do
processed = processed + 1
processed = processed + 1
if maxItems ~= nil and processed > maxItems then
if maxItems ~= nil and processed > maxItems then
Строка 1554: Строка 1543:
end
end


local k = de[1]
local kStr = de[2]
local v = data[k]
local v = data[k]
local vStr
local vStr
Строка 1570: Строка 1557:
end
end


local baseKey = apply_pattern(kStr, keyPattern, "\\1")
local baseKey = apply_pattern(tostring(k), keyPattern, "\\1")


local MARK_KEY = "\31KEY\31"
local MARK_KEY = "\31KEY\31"
Строка 1579: Строка 1566:
local MARK_VAL = "\31VAL\31"
local MARK_VAL = "\31VAL\31"
local kRepl = (keyReplace or "\\1"):gsub("\\2", MARK_VAL)
local kRepl = (keyReplace or "\\1"):gsub("\\2", MARK_VAL)
local keyStr0 = apply_pattern(kStr, keyPattern, kRepl)
local keyStr0 = apply_pattern(tostring(k), keyPattern, kRepl)
local keyStr = tostring(keyStr0):gsub(MARK_VAL, vStr0)
local keyStr = tostring(keyStr0):gsub(MARK_VAL, vStr0)


Строка 1598: Строка 1585:
end
end


out[#out + 1] = line
table.insert(out, line)
end
end
end
end