Модуль:Проблемы с объектом
Внешний вид
Для документации этого модуля может быть создана страница Модуль:Проблемы с объектом/doc
local p = {}
p.i18n = {
process_args_module = "Модуль:ProcessArgs",
description_arg_prefix = "назв", -- specify a string if you want to have separate parameters for descriptions of searched terms.
-- Useful as terms are necessarily English, and users may want to have localized descriptions
term_wrap = '«%s»', -- a string wrapped into quotes, for text output; quotes may be language-specific
pair_separator = ", ",
final_or_separator = " и ",
two_item_or_separator = " и ", -- the separators are used to concatenate tables to make strings like "A or B", "A, B, or C"
message = 'Отчёты об ошибках, связанных с %s, поддерживаются в системе отслеживания ошибок [[Mojira]]. Сообщайте о найденных ошибках [https://bugs.mojang.com/issues/?jql=%s там].',
message_dungeons = 'Отчёты об ошибках \'\'Minecraft Dungeons\'\', связанных с %s, с 28 сентября 2023 года не поддерживаются в системе отслеживания ошибок [[Mojira]]. Ошибки, обнаруженные до этой даты, можно увидеть [https://bugs.mojang.com/issues/?jql=%s здесь].',
message_legends = 'Отчёты об ошибках \'\'Minecraft Legends\'\', связанных с %s, с 10 января 2024 года не поддерживаются в системе отслеживания ошибок [[Mojira]]. Ошибки, обнаруженные до этой даты, можно увидеть [https://bugs.mojang.com/issues/?jql=%s здесь].',
namespace_dungeons = 10000,
namespace_legends = 10006,
release_mc = '1.21.4'
}
--[[
Concatenates a table using a set of separators. Behavior depends on which of the separators are provided.
Parameters:
• some_table (sequence table):
the table to concatenate; required
• pair_sep (string; required), final_sep (string), two_sep (string):
separators used in concatenation
If only `pair_sep` is provided, behaves like `table.concat(some_table, pair_sep)`.
If `final_sep` is also provided, it is used to separate the last pair of table entries.
If `two_sep` is also provided, it is used to separate the entries instead of `final_sep` if there are two of them.
Returns a string with the concatenated table.
Example:
```
local table1 = {"a", "b", "c"}
local table2 = {"a", "b"}
print( concat_table_3sep(table1, ", ") ) -- prints "a, b, c"
print( concat_table_3sep(table1, ", ", " and ") ) -- prints "a, b and c"
print( concat_table_3sep(table1, ", ", ", and ", " and ") ) -- prints "a, b, and c"
print( concat_table_3sep(table2, ", ") ) -- prints "a, b"
print( concat_table_3sep(table2, ", ", " and ") ) -- prints "a and b"
print( concat_table_3sep(table2, ", ", ", and ", " and ") ) -- prints "a and b"
```
]]
function p.concat_table_3sep(some_table, pair_sep, final_sep, two_sep)
local length = #some_table
if length < 3 then
local sep = two_sep or final_sep or pair_sep
return table.concat(some_table, sep)
end
local result_table = {}
for index = 1, length - 2 do
table.insert(result_table, some_table[index])
table.insert(result_table, pair_sep)
end
table.insert(result_table, some_table[length - 1])
table.insert(result_table, final_sep or pair_sep)
table.insert(result_table, some_table[length])
return table.concat(result_table)
end
--[[
Similar to ipairs, but iterates over string keys with a constant prefix and a
variable integer suffix.
Parameters:
• some_table (table):
the table to iterate over
• prefix (string):
the key prefix to use when iterating
• allow_numberless (boolean, optional):
if truthy, allows reading the key without an integer suffix as if it had the
suffix 1. WARNING: behavior is unspecified if:
1) allow_numberless is truthy;
2) a key without an integer suffix is mapped to a value;
3) a key with integer suffix 1 is also mapped to a value.
In such cases, there is no guarantee on which of the two values is used.
Example:
```
local t = {
a1 = 1,
a2 = 4,
a3 = 9
}
for index, value in prefixed_ipairs(t, "a") do
print(index, value)
end
```
This prints
```
1 1
2 4
3 9
```
With `allow_numberless = true`, the above example would also work identically
for the following table:
```
local t = {
a = 1,
a2 = 4,
a3 = 9
}
```
However, with the following table, the example may print either 1 or 2 in the
first line, depending on how prefixed_ipairs is currently implemented:
```
local t = {
a = 1,
a1 = 2, -- Don't do this!
a2 = 4,
a3 = 9
}
```
]]
function p.prefixed_ipairs(some_table, prefix, allow_numberless)
local i = 0
return function()
i = i + 1
local value = some_table[prefix .. tostring(i)]
if i == 1 and allow_numberless and some_table[prefix] ~= nil then
value = some_table[prefix]
end
if value ~= nil then
return i, value
end
end
end
-- Helper functions ------------------------------------------------------------
-- Returns the human-readable description of search terms.
local function get_subject_string(inclusions)
local lang = mw.language.getContentLanguage()
local wrapped_inclusions = {}
for index, inclusion in ipairs(inclusions) do
table.insert(wrapped_inclusions, p.i18n.term_wrap:format(lang:ucfirst(inclusion)))
end
return p.concat_table_3sep(
wrapped_inclusions,
p.i18n.pair_separator,
p.i18n.final_or_separator,
p.i18n.two_item_or_separator
)
end
-- Returns the part of the query string that lists what items to query.
local function get_query_string_inclusions(inclusions)
local query_inclusions = {}
for index, inclusion in ipairs(inclusions) do
table.insert(query_inclusions, 'summary ~ "' .. inclusion .. '"')
end
return "(" .. table.concat(query_inclusions, ' OR ') .. ")"
end
-- Returns the part of the query string that removes certain items from the output.
local function get_query_string_exclusions(exclusions)
if #exclusions == 0 then
return ""
end
local negated_exclusions = {}
for index, exclusion in ipairs(exclusions) do
table.insert(negated_exclusions, "-" .. exclusion)
end
local exclusions_string = table.concat(negated_exclusions, " ")
return (' AND summary ~ "%s"'):format(exclusions_string)
end
--[[
Returns the link query string for Mojira.
Note about numbers for resolution: the JIRA manual recommends
searching resolution IDs instead of names. Here's Mojira's IDs:
1 = fixed
2 = won't fix
3 = duplicate
4 = incomplete
5 = cannot reproduce
6 = works as intended
7 = invalid
"Unresolved" is seen as "empty" in JIRA.
]]
local function get_link_query_string(projects, inclusions_string, exclusions_string)
local query_string = 'project in ('
.. projects
.. ') AND (resolution is EMPTY OR resolution in (1, 2, 6))'
.. exclusions_string
.. " AND "
.. inclusions_string
.. " ORDER BY resolution DESC"
return mw.uri.encode(query_string, "PATH")
end
--[[
Returns the api query strings for Mojira.
]]
local function get_api_query_strings(api_list, projects, inclusions_string, exclusions_string)
for project in mw.text.gsplit( projects, '%s*,%s*' ) do
if project == 'MC' then
api_list:attr( 'data-mc',
-- No project needed due to post-migration API quirks
-- 'project = MC'
'"Confirmation Status" != Unconfirmed'
.. ' AND ('
.. 'resolution is EMPTY'
.. ' OR ('
.. 'resolution = "Fixed"'
.. ' AND affectedVersion = "' .. p.i18n.release_mc .. '"'
.. '))'
.. exclusions_string
.. ' AND '
.. inclusions_string
.. ' ORDER BY '
.. 'resolution ASC, '
.. '"Mojang Priority" ASC, '
.. 'votes DESC, '
.. 'key ASC'
)
elseif project == 'MCD' or project == 'MCLG' then
api_list:attr( 'data-' .. project:lower(),
-- 'project = ' .. project
'"Confirmation Status" != Unconfirmed'
.. ' AND (resolution is EMPTY OR resolution = "Won\'t Fix")'
.. exclusions_string
.. ' AND '
.. inclusions_string
.. ' ORDER BY '
.. 'votes DESC, '
.. 'key ASC'
)
else
api_list:attr( 'data-' .. project:lower(),
-- 'project = ' .. project
'"Confirmation Status" != Unconfirmed'
.. ' AND resolution is EMPTY'
.. exclusions_string
.. ' AND '
.. inclusions_string
.. ' ORDER BY '
.. 'votes DESC, '
.. 'key ASC'
)
end
end
end
-- Main functions and entry points ---------------------------------------------
p.issue_list = function(descriptions, projects, inclusions, exclusions)
local subject_string = get_subject_string(descriptions or inclusions)
local inclusions_string = get_query_string_inclusions(inclusions)
local exclusions_string = get_query_string_exclusions(exclusions)
local link_query_string = get_link_query_string(projects, inclusions_string, exclusions_string)
local message = p.i18n.message
if mw.title.getCurrentTitle().namespace == p.i18n.namespace_dungeons then
message = p.i18n.message_dungeons
elseif mw.title.getCurrentTitle().namespace == p.i18n.namespace_legends then
message = p.i18n.message_legends
end
message = message:format(subject_string, link_query_string)
local api_list = mw.html.create( 'div' )
api_list:addClass( 'issue-list' )
get_api_query_strings(api_list, projects, inclusions_string, exclusions_string)
return message .. '\n' .. tostring( api_list )
end
-- Entry point for [[Template:Issue list]].
p.issue_list_entry = function(frame)
local args = require(p.i18n.process_args_module).norm()
local inclusions = {}
local exclusions = {}
for _, arg in ipairs(args) do
if arg:find("^-") then
table.insert(exclusions, (arg:gsub("-", "")))
else
table.insert(inclusions, arg)
end
end
if #inclusions == 0 then
inclusions[1] = mw.title.getCurrentTitle().text
end
local projects = args.projects or nil
if projects == nil then
if mw.title.getCurrentTitle().namespace == p.i18n.namespace_dungeons then
projects = 'MCD'
elseif mw.title.getCurrentTitle().namespace == p.i18n.namespace_legends then
projects = 'MCLG'
else
projects = 'MC, MCPE'
end
end
local descriptions
if p.i18n.description_arg_prefix then
descriptions = {}
for _, arg in p.prefixed_ipairs(args, p.i18n.description_arg_prefix, true) do
table.insert(descriptions, arg)
end
if #descriptions == 0 then
table.insert(descriptions, mw.title.getCurrentTitle().text)
end
end
return p.issue_list(descriptions, projects, inclusions, exclusions)
end
return p