Модуль:Сущность/data: различия между версиями

Нет описания правки
Нет описания правки
Строка 195: Строка 195:
     end
     end
     return table.concat(parts, "\n")
     return table.concat(parts, "\n")
end
local function split_title_key(key)
    local main, sub = (key or ""):match("^([^_]+)_(.+)$")
    if main and sub then
        return main, sub
    end
    return key, nil
end
local function renderGroupedTitleBlocks(frame, keyOrder, keyToTemplates, noHeaders, showSource)
    local groups = {}
    local groupOrder = {}
    for _, key in ipairs(keyOrder or {}) do
        local mainTitle, subTitle = split_title_key(key)
        if mainTitle and mainTitle ~= "" then
            local group = groups[mainTitle]
            if not group then
                group = { blocks = {} }
                groups[mainTitle] = group
                groupOrder[#groupOrder + 1] = mainTitle
            end
            group.blocks[#group.blocks + 1] = {
                subTitle = subTitle,
                entries = keyToTemplates[key] or {}
            }
        end
    end
    local out = {}
    for _, mainTitle in ipairs(groupOrder) do
        local group = groups[mainTitle]
        local parts = {}
        if not noHeaders then
            parts[#parts + 1] = "<h2>" .. mw.text.encode(mainTitle) .. "</h2>"
        end
        for _, block in ipairs(group.blocks or {}) do
            local tplCalls, sources = collect_tpl_calls(block.entries or {})
            local blockText = renderTitleBlock(block.subTitle or mainTitle, tplCalls, sources, false, frame, showSource)
            if blockText ~= "" then
                if block.subTitle and not noHeaders then
                    parts[#parts + 1] = "<h3>" .. mw.text.encode(block.subTitle) .. "</h3>"
                end
                parts[#parts + 1] = blockText
            end
        end
        if #parts > 0 then
            out[#out + 1] = table.concat(parts, "\n")
        end
    end
    return table.concat(out, "\n")
end
local function matches_card_list(list, callKey, compositeKey)
    if not list then
        return false
    end
    return list[callKey] or list[compositeKey] or false
end
end


Строка 246: Строка 310:
end
end


local function cardWrapper(frame, keyOrder, keyToTemplates, keySources, entityId, noHeaders)
local function cardWrapper(frame, keyOrder, keyToTemplates, keySources, entityId, noHeaders, cardFilter)
     local merged = {
     local merged = {
         sections = {},
         sections = {},
Строка 257: Строка 321:
         tagSet = {}
         tagSet = {}
     }
     }
    local rawContentParts = {}
     for _, callKey in ipairs(keyOrder or {}) do
     for _, callKey in ipairs(keyOrder or {}) do
         local entries = keyToTemplates[callKey] or {}
         local entries = keyToTemplates[callKey] or {}
Строка 271: Строка 336:
                 local section = (callKey:find("_", 1, true)) and callKey:match("^([^_]+)") or "Сущность"
                 local section = (callKey:find("_", 1, true)) and callKey:match("^([^_]+)") or "Сущность"


                 if displayLabel ~= "" or content ~= "" then
                local isWhitelisted = cardFilter and matches_card_list(cardFilter.whitelist, callKey, compositeKey) or false
                local isBlacklisted = cardFilter and matches_card_list(cardFilter.blacklist, callKey, compositeKey) or false
                if isWhitelisted and content ~= "" then
                    rawContentParts[#rawContentParts + 1] = content
                end
 
                 if not isWhitelisted and not isBlacklisted and (displayLabel ~= "" or content ~= "") then
                     if not merged.sectionsMap[section] then
                     if not merged.sectionsMap[section] then
                         merged.sectionsMap[section] = true
                         merged.sectionsMap[section] = true
Строка 297: Строка 368:
                 end
                 end


                 if tagText ~= "" then
                 if not isWhitelisted and not isBlacklisted and tagText ~= "" then
                     if not merged.tagSet[tagText] then
                     if not merged.tagSet[tagText] then
                         merged.tagSet[tagText] = true
                         merged.tagSet[tagText] = true
Строка 306: Строка 377:
         end
         end
     end
     end
    local out = {}
    if #rawContentParts > 0 then
        out[#out + 1] = table.concat(rawContentParts, "\n")
    end
    local cardCall = buildCardCall(merged, entityId)


     if noHeaders then
     if noHeaders then
Строка 324: Строка 402:


         if not hasLabel and not hasContent then
         if not hasLabel and not hasContent then
             return ""
             return table.concat(out, "\n")
         end
         end
     end
     end


     return buildCardCall(merged, entityId)
    if cardCall ~= "" then
        out[#out + 1] = cardCall
    end
 
     return table.concat(out, "\n")
end
end


Строка 361: Строка 443:
         end
         end
     end,
     end,
     render_full = function(frame, keyOrder, keyToTemplates, keySources, entityId, noHeaders)
     render_full = function(frame, keyOrder, keyToTemplates, keySources, entityId, noHeaders, showSource, cardFilter)
         return cardWrapper(frame, keyOrder, keyToTemplates, keySources, entityId, noHeaders)
         return cardWrapper(frame, keyOrder, keyToTemplates, keySources, entityId, noHeaders, cardFilter)
     end
     end
})
})


register_switch_mode("title", {
register_switch_mode("title", {
    full = true,
     build_entry = function(ctx, key)
     build_entry = function(ctx, key)
         return {
         return {
Строка 381: Строка 464:
         }
         }
     end,
     end,
     render_key = function(frame, key, entries, noHeaders, showSource)
     render_full = function(frame, keyOrder, keyToTemplates, keySources, entityId, noHeaders, showSource)
        local tplCalls, sources = collect_tpl_calls(entries)
         return renderGroupedTitleBlocks(frame, keyOrder, keyToTemplates, noHeaders, showSource)
         return renderTitleBlock(key, tplCalls, sources, not noHeaders, frame, showSource)
     end
     end
})
})
Строка 443: Строка 525:
     filter.blacklist = parseListArg(args.blacklist or "")
     filter.blacklist = parseListArg(args.blacklist or "")
     filter.whitelist = parseListArg(args.whitelist or "")
     filter.whitelist = parseListArg(args.whitelist or "")
     filter.hasWhitelist = next(filter.whitelist) ~= nil
     filter.hasWhitelist = false
    for _, sw in ipairs(switchModeOrder) do
        if filter.whitelist[sw] and next(filter.whitelist[sw]) ~= nil then
            filter.hasWhitelist = true
            break
        end
    end
     return filter
     return filter
end
local function build_render_options(filter)
    return {
        noHeaders = false,
        cardFilter = {
            blacklist = filter.blacklist.cardContent or {},
            whitelist = filter.whitelist.cardContent or {}
        }
    }
end
end


Строка 466: Строка 564:
end
end


local function collect_entity_sets(id, componentDefs, prototypeStoreDefs, ignoreComponents, ignorePrototypes)
local function parse_csv_set(str)
    local res = {}
    each_csv_value(str, function(name)
        res[name] = true
    end)
    return res
end
 
local function apply_entity_set_filters(foundSet, whitelistSet, blacklistSet)
    local hasWhitelist = next(whitelistSet or {}) ~= nil
 
    if hasWhitelist then
        for name in pairs(foundSet) do
            if not whitelistSet[name] then
                foundSet[name] = nil
            end
        end
    end
 
    for name in pairs(blacklistSet or {}) do
        foundSet[name] = nil
    end
end
 
local function collect_entity_sets(id, componentDefs, prototypeStoreDefs,
    componentWhitelist, componentBlacklist, prototypeWhitelist, prototypeBlacklist)
     local foundComponents, foundPrototypes = {}, {}
     local foundComponents, foundPrototypes = {}, {}


Строка 488: Строка 611:
     end)
     end)


     each_csv_value(ignoreComponents, function(name)
     apply_entity_set_filters(foundComponents, parse_csv_set(componentWhitelist), parse_csv_set(componentBlacklist))
        foundComponents[name] = nil
     apply_entity_set_filters(foundPrototypes, parse_csv_set(prototypeWhitelist), parse_csv_set(prototypeBlacklist))
    end)
 
     each_csv_value(ignorePrototypes, function(name)
        foundPrototypes[name] = nil
    end)


     return foundComponents, foundPrototypes
     return foundComponents, foundPrototypes
Строка 578: Строка 696:
end
end


local function renderBlocks(frame, state, noHeaders, entityId, showSource)
local function renderBlocks(frame, state, renderOptions, entityId, showSource)
     local outLocal = {}
     local outLocal = {}
    local noHeaders = renderOptions and renderOptions.noHeaders
    local cardFilter = renderOptions and renderOptions.cardFilter
     for _, sw in ipairs(switchModeOrder) do
     for _, sw in ipairs(switchModeOrder) do
         local mode = switchModeRegistry[sw] or {}
         local mode = switchModeRegistry[sw] or {}
Строка 586: Строка 706:
             if type(mode.render_full) == "function" then
             if type(mode.render_full) == "function" then
                 outStr = mode.render_full(frame, state.keyOrder[sw], state.keyToTemplates[sw], state.keySources[sw],
                 outStr = mode.render_full(frame, state.keyOrder[sw], state.keyToTemplates[sw], state.keySources[sw],
                     entityId, noHeaders)
                     entityId, noHeaders, showSource, cardFilter)
             end
             end
             if outStr and outStr ~= "" then table.insert(outLocal, outStr) end
             if outStr and outStr ~= "" then table.insert(outLocal, outStr) end
Строка 610: Строка 730:


     local filter = build_key_filter(args)
     local filter = build_key_filter(args)
    local renderOptions = build_render_options(filter)


     local ignoreComponents = args.ignoreComponents or args.ignoreComponent or ""
     local componentWhitelist = args.componentWhitelist or args.componentwhitelist or ""
     local ignorePrototypes = args.ignorePrototypes or args.ignorePrototype or ""
     local componentBlacklist = args.componentBlacklist or args.componentblacklist or ""
    local prototypeWhitelist = args.prototypeWhitelist or args.prototypewhitelist or ""
    local prototypeBlacklist = args.prototypeBlacklist or args.prototypeblacklist or ""


     local componentDefs = load_module_data("component.json")
     local componentDefs = load_module_data("component.json")
Строка 618: Строка 741:
     if not componentDefs or not prototypeStoreDefs then return "" end
     if not componentDefs or not prototypeStoreDefs then return "" end


     local foundComponents, foundPrototypes = collect_entity_sets(id, componentDefs, prototypeStoreDefs, ignoreComponents,
     local foundComponents, foundPrototypes = collect_entity_sets(id, componentDefs, prototypeStoreDefs,
         ignorePrototypes)
         componentWhitelist, componentBlacklist, prototypeWhitelist, prototypeBlacklist)
     local state = new_switch_state()
     local state = new_switch_state()


Строка 694: Строка 817:
     end
     end


     local blocks = renderBlocks(frame, state, filter.hasWhitelist, id, showSource)
    renderOptions.noHeaders = filter.hasWhitelist
 
     local blocks = renderBlocks(frame, state, renderOptions, id, showSource)
     for _, b in ipairs(blocks) do
     for _, b in ipairs(blocks) do
         table.insert(out, b)
         table.insert(out, b)
Строка 708: Строка 833:


     local showSource = trim(args.nosource or "") == ""
     local showSource = trim(args.nosource or "") == ""
    local previewFilter = build_key_filter(args)
    local renderOptions = build_render_options(previewFilter)


     local content = load_template_content(tplPath)
     local content = load_template_content(tplPath)
Строка 728: Строка 855:
     }, nil, true)
     }, nil, true)


     local whitelist = parseListArg(args.whitelist or "")
     local whitelist = previewFilter.whitelist
     local hasWhitelist = next(whitelist) ~= nil
     local hasWhitelist = previewFilter.hasWhitelist
    renderOptions.noHeaders = hasWhitelist


     local out = {}
     local out = {}
     local blocks = renderBlocks(frame, state, hasWhitelist, "", showSource)
     local blocks = renderBlocks(frame, state, renderOptions, "", showSource)
     for _, b in ipairs(blocks) do
     for _, b in ipairs(blocks) do
         table.insert(out, b)
         table.insert(out, b)