<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.evospace.tech/index.php?action=history&amp;feed=atom&amp;title=Module%3AInfoboxItem%2Fsandbox</id>
	<title>Module:InfoboxItem/sandbox - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.evospace.tech/index.php?action=history&amp;feed=atom&amp;title=Module%3AInfoboxItem%2Fsandbox"/>
	<link rel="alternate" type="text/html" href="https://wiki.evospace.tech/index.php?title=Module:InfoboxItem/sandbox&amp;action=history"/>
	<updated>2026-09-05T19:03:52Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.44.0</generator>
	<entry>
		<id>https://wiki.evospace.tech/index.php?title=Module:InfoboxItem/sandbox&amp;diff=10236&amp;oldid=prev</id>
		<title>EvoBot: Sandbox: emit item categories from Module:Data Category field, guarded by page title</title>
		<link rel="alternate" type="text/html" href="https://wiki.evospace.tech/index.php?title=Module:InfoboxItem/sandbox&amp;diff=10236&amp;oldid=prev"/>
		<updated>2026-09-05T09:53:49Z</updated>

		<summary type="html">&lt;p&gt;Sandbox: emit item categories from Module:Data Category field, guarded by page title&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;-- Module:InfoboxItem&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
local KIND = {&lt;br /&gt;
    Plate = &amp;quot;Plates&amp;quot;, Parts = &amp;quot;Parts&amp;quot;, Ore = &amp;quot;Ores&amp;quot;, Dust = &amp;quot;Dusts&amp;quot;,&lt;br /&gt;
    Fluid = &amp;quot;Fluids&amp;quot;, Block = &amp;quot;Blocks&amp;quot;, Terrain = &amp;quot;Terrain&amp;quot;,&lt;br /&gt;
    Decoration = &amp;quot;Decoration&amp;quot;, Tools = &amp;quot;Tools&amp;quot;, Equipment = &amp;quot;Equipment&amp;quot;,&lt;br /&gt;
    Signal = &amp;quot;Signals&amp;quot;, Network = &amp;quot;Network&amp;quot;, Nuclear = &amp;quot;Nuclear&amp;quot;,&lt;br /&gt;
    Chemical = &amp;quot;Chemicals&amp;quot;, Organic = &amp;quot;Organics&amp;quot;, Resource = &amp;quot;Resources&amp;quot;,&lt;br /&gt;
    Vehicles = &amp;quot;Vehicles&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local function safeLoadData(name)&lt;br /&gt;
    local success, data = pcall(function()&lt;br /&gt;
        return mw.loadData(&amp;#039;Module:Data/&amp;#039; .. name)&lt;br /&gt;
    end)&lt;br /&gt;
    if success and type(data) == &amp;quot;table&amp;quot; then&lt;br /&gt;
        return data&lt;br /&gt;
    end&lt;br /&gt;
    return nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function normalizeArray(tbl)&lt;br /&gt;
    local result = {}&lt;br /&gt;
    if not tbl then return result end&lt;br /&gt;
    for k, v in pairs(tbl) do&lt;br /&gt;
        -- Каждая строка тоже может быть ассоциативной таблицей&lt;br /&gt;
        if type(v) == &amp;quot;table&amp;quot; then&lt;br /&gt;
            local name = v[1] or v.name or v[&amp;quot;1&amp;quot;]&lt;br /&gt;
            local count = v[2] or v.count or v[&amp;quot;2&amp;quot;] or 1&lt;br /&gt;
            table.insert(result, {name, count})&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    table.sort(result, function(a,b) return tostring(a[1]) &amp;lt; tostring(b[1]) end)&lt;br /&gt;
    return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function splitCamelCase(str)&lt;br /&gt;
    str = str:gsub(&amp;quot;_&amp;quot;, &amp;quot; &amp;quot;)&lt;br /&gt;
    str = str:gsub(&amp;quot;(%l)(%u)&amp;quot;, &amp;quot;%1 %2&amp;quot;)&lt;br /&gt;
    str = str:gsub(&amp;quot;(%a)(%d)&amp;quot;, &amp;quot;%1 %2&amp;quot;)&lt;br /&gt;
    str = str:gsub(&amp;quot;(%d)(%a)&amp;quot;, &amp;quot;%1 %2&amp;quot;)&lt;br /&gt;
    return str&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.show_inline(frame)&lt;br /&gt;
    local itemModule = frame.args[1]&lt;br /&gt;
    if not itemModule or itemModule == &amp;quot;&amp;quot; then&lt;br /&gt;
        return &amp;quot;❌ No data module provided&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    local data = safeLoadData(itemModule)&lt;br /&gt;
    if not data then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local pageName = splitCamelCase(itemModule)&lt;br /&gt;
    local imageName = (data.Image or &amp;quot;&amp;quot;) .. &amp;quot;.png&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return string.format(&amp;quot;[[File:%s|32px|link=%s]] [[%s]]&amp;quot;,&lt;br /&gt;
                         imageName, pageName, pageName);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.show(frame)&lt;br /&gt;
    local itemModule = frame.args[1]&lt;br /&gt;
    if not itemModule or itemModule == &amp;quot;&amp;quot; then&lt;br /&gt;
        return &amp;quot;❌ No data module provided&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    local data = safeLoadData(itemModule)&lt;br /&gt;
    if not data then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local pageName = splitCamelCase(itemModule)&lt;br /&gt;
    local imageName = (data.Image or &amp;quot;&amp;quot;) .. &amp;quot;.png&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local out = {}&lt;br /&gt;
    table.insert(out, &amp;#039;{| class=&amp;quot;infobox&amp;quot;&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    -- Первая строка: объединённая ячейка, иконка + название со ссылками&lt;br /&gt;
    table.insert(out, &amp;#039;|-&amp;#039;)&lt;br /&gt;
    table.insert(out, &amp;#039;| colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align:center;&amp;quot; | &amp;#039; ..&lt;br /&gt;
        string.format(&amp;#039;[[File:%s|64px|link=%s]] [[%s]]&amp;#039;,&lt;br /&gt;
            imageName, pageName, pageName))&lt;br /&gt;
&lt;br /&gt;
    -- Остальные поля&lt;br /&gt;
    table.insert(out, &amp;#039;|-&amp;#039;)&lt;br /&gt;
    table.insert(out, &amp;#039;! Category&amp;#039;)&lt;br /&gt;
    table.insert(out, &amp;#039;| &amp;#039; .. (data.Category or &amp;#039;&amp;#039;))&lt;br /&gt;
    table.insert(out, &amp;#039;|-&amp;#039;)&lt;br /&gt;
    table.insert(out, &amp;#039;! Tier&amp;#039;)&lt;br /&gt;
    table.insert(out, &amp;#039;| &amp;#039; .. (data.Tier or &amp;#039;&amp;#039;))&lt;br /&gt;
    table.insert(out, &amp;#039;|-&amp;#039;)&lt;br /&gt;
    table.insert(out, &amp;#039;! Stack size&amp;#039;)&lt;br /&gt;
    table.insert(out, &amp;#039;| &amp;#039; .. (data.StackSize or &amp;#039;&amp;#039;))&lt;br /&gt;
    table.insert(out, &amp;#039;|}&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    local title = mw.title.getCurrentTitle()&lt;br /&gt;
    if title.namespace == 0 and title.text == pageName then&lt;br /&gt;
        local kind = KIND[data.Category]&lt;br /&gt;
        if kind then&lt;br /&gt;
            table.insert(out, &amp;#039;[[Category:&amp;#039; .. kind .. &amp;#039;]]&amp;#039;)&lt;br /&gt;
        end&lt;br /&gt;
        table.insert(out, &amp;#039;[[Category:Items]]&amp;#039;)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return table.concat(out, &amp;#039;\n&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function renderRecipeInput(recipe)&lt;br /&gt;
    local inputs = normalizeArray(recipe.input)&lt;br /&gt;
    local tableNode = mw.html.create(&amp;quot;table&amp;quot;)&lt;br /&gt;
        :addClass(&amp;quot;recipe-table&amp;quot;)&lt;br /&gt;
    local str = &amp;#039;&amp;#039;&lt;br /&gt;
    if #inputs &amp;gt; 0 then&lt;br /&gt;
        for _, ing in ipairs(inputs) do&lt;br /&gt;
            str = str .. string.format(&amp;quot;[[File:T_%s.png|22px]]&amp;quot;, ing[1]) .. string.format(&amp;quot;[[%s]] × %s&amp;quot;, splitCamelCase(ing[1]), tostring(ing[2])) .. &amp;quot;\n\n&amp;quot;&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        str = str .. &amp;quot;—&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    return str&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.show_recipe(frame)&lt;br /&gt;
    local itemModule = frame.args[1]&lt;br /&gt;
    if not itemModule or itemModule == &amp;quot;&amp;quot; then&lt;br /&gt;
        return &amp;quot;❌ No data module provided&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    &lt;br /&gt;
    local data = safeLoadData(itemModule)&lt;br /&gt;
    if not data then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local dictName = &amp;quot;Data/&amp;quot;..itemModule..&amp;quot;/InOutput&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local success, recipes = pcall(mw.loadData, &amp;quot;Module:&amp;quot; .. dictName)&lt;br /&gt;
    if not success or type(recipes) ~= &amp;quot;table&amp;quot; then&lt;br /&gt;
        return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local pageName = splitCamelCase(itemModule)&lt;br /&gt;
    local imageName = (data.Image or &amp;quot;&amp;quot;) .. &amp;quot;.png&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local out = {}&lt;br /&gt;
    table.insert(out, &amp;#039;{| class=&amp;quot;infobox&amp;quot;&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    -- Первая строка: объединённая ячейка, иконка + название со ссылками&lt;br /&gt;
    table.insert(out, &amp;#039;|-&amp;#039;)&lt;br /&gt;
    table.insert(out, &amp;#039;| colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align:center;&amp;quot; | &amp;#039; ..&lt;br /&gt;
        string.format(&amp;#039;[[File:%s|64px|link=%s]] [[%s]]&amp;#039;,&lt;br /&gt;
            imageName, pageName, pageName))&lt;br /&gt;
&lt;br /&gt;
    -- Остальные поля&lt;br /&gt;
&lt;br /&gt;
    table.insert(out, &amp;#039;|-&amp;#039;)&lt;br /&gt;
    table.insert(out, &amp;#039;| colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align:center;&amp;quot; | &amp;#039; .. renderRecipeInput(recipes[1]))&lt;br /&gt;
    table.insert(out, &amp;#039;|}&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    return table.concat(out, &amp;#039;\n&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>EvoBot</name></author>
	</entry>
</feed>