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

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


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


local function is_array(tbl)
local function is_array(tbl)
local max = 0
local n = #tbl
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
Строка 120: Строка 128:
return false
return false
end
end
if k > max then
max = k
end
count = count + 1
count = count + 1
end
end
return count > 0 and max == count
return count == n
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


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


local function deep_merge(dst, src)
local function merge_copy(base, specific)
for k, v in pairs(src) do
local result = {}
if type(v) == "table" and type(dst[k]) == "table" then
for k, v in pairs(base) do
deep_merge(dst[k], v)
local specificV = specific[k]
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
dst[k] = deep_copy(v)
result[k] = deep_copy(v)
else
else
dst[k] = v
result[k] = v
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
end
end
return result
end
end


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


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


for _, k in ipairs(keys) do
for _, e in ipairs(entries) 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)


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


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


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


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


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


table.sort(ids, function(a, b)
local sortedIds = {}
return tostring(a) < tostring(b)
for i = 1, #ids do
end)
sortedIds[i] = { ids[i], tostring(ids[i]) }
 
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 _, idKey in ipairs(ids) do
for _, e in ipairs(sortedIds) 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
Строка 1186: Строка 1200:
end
end
return nil
return nil
end
local function collect_sorted_entries(tbl, stringOnly)
if stringOnly then
local keys = {}
for k in pairs(tbl) do
if type(k) == "string" then
keys[#keys + 1] = k
end
end
table.sort(keys)
local entries = {}
for i = 1, #keys do
entries[i] = { keys[i], keys[i] }
end
return entries
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
end


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


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


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


table.sort(keys, function(a, b)
table.sort(entries, function(a, b)
local av = obj[a]
if a[2] ~= b[2] then
local bv = obj[b]
return not a[2]
 
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 keys[1]
return entries[1][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


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


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


for _, k in ipairs(keys) do
for _, e in ipairs(entries) 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 .. "." .. tostring(k)
key = prefix .. "." .. kStr
else
else
key = tostring(k)
key = kStr
end
end


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


Строка 1336: Строка 1359:
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 "")
Строка 1369: Строка 1381:
end
end


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


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


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


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


local processed = 0
local processed = 0


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


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


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


local MARK_KEY = "\31KEY\31"
local MARK_KEY = "\31KEY\31"
Строка 1566: Строка 1579:
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(tostring(k), keyPattern, kRepl)
local keyStr0 = apply_pattern(kStr, keyPattern, kRepl)
local keyStr = tostring(keyStr0):gsub(MARK_VAL, vStr0)
local keyStr = tostring(keyStr0):gsub(MARK_VAL, vStr0)


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


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