Перейти к содержанию

Модуль:CatalogSection

Материал из Викиучебника — открытых книг для открытого мира

Для документации этого модуля может быть создана страница Модуль:CatalogSection/doc

-- Модуль:CatalogSection
-- Универсальный модуль: выводит разделы либо подразделы и оборачивает их в шаблон «Заглавная страница/Раздел».
-- Для каталога (главных полок) сохраняет статические списки.
-- Для страниц Полка:… (неглавных полок) вместо списка дочерних ссылок вставляет DPL.
-- ID в шаблоне жёстко = "tfa".

local p = {}

function p.render(frame)
    local title = mw.title.getCurrentTitle()
    local full = title.prefixedText

    -- Загружаем исходный список
    local listTitle = mw.title.new('Викиучебник:Каталог учебников/Список')
    if not listTitle or not listTitle.exists then
        return ''
    end
    local content = listTitle:getContent()

    -- Извлекаем строки после {{Шапка}}
    local lines = {}
    local start = false
    for _, line in ipairs(mw.text.split(content, '\n')) do
        if start then
            table.insert(lines, line)
        elseif line:find('Викиучебник:Каталог учебников/Шапка', 1, true) then
            start = true
        end
    end

    -- Собираем секции и дочерние элементы
    local sections = {}
    for _, line in ipairs(lines) do
        local stars, text = line:match('^(%*+)%s*(.+)')
        if stars == '*' then
            table.insert(sections, { header = text, children = {} })
        elseif stars == '**' then
            local last = sections[#sections]
            if last then table.insert(last.children, text) end
        end
    end

    -- Определяем контекст: catalog или shelf
    local isShelf = full:match('^Полка:')
    local targets = {}
    if full == 'Викиучебник:Каталог учебников' then
        targets = sections
    elseif isShelf then
        local shelfName = full:match('^Полка:(.+)$') or ''
        for _, sec in ipairs(sections) do
            if sec.header:find('Полка:' .. shelfName, 1, true) then
                -- создаём отдельные секции по дочерним элементам
                for _, child in ipairs(sec.children) do
                    table.insert(targets, { header = child, children = {} })
                end
                break
            end
        end
    else
        return ''
    end

    -- Функция генерации колонок
    local function makeBlocks(list)
        local blocks = {}
        local iconPattern = '(%[%[Файл:[^|%]]+)%|%d+px'
        for _, sec in ipairs(list) do
            -- Заголовок с иконкой 25px
            local headerIcon = sec.header:gsub(iconPattern, '%1|25px')
            -- Получаем чистое имя полки
            local pageName = sec.header:match('%[%[Полка:([^|%]]+)') or ''

            local body
            if isShelf then
                -- Для неглавных полок вставляем DPL
                local dpl = table.concat({
                    '{{#tag:DynamicPageList|',
                    'category = ' .. pageName,
                    'namespace = Основной',
                    'shownamespace = false',
                    'suppresserrors = true',
                    'ordermethod = categorysortkey',
                    'order = ascending',
                    '}}'
                }, '\n')
                body = '<h2>' .. headerIcon .. '</h2>\n' .. dpl
            else
                -- Для каталога: статический список дочерних ссылок, если есть
                local items = {}
                for _, child in ipairs(sec.children) do
                    table.insert(items, '* ' .. child)
                end
                local listText = items[1] and table.concat(items, '\n') or ''
                body = '<h2>' .. headerIcon .. '</h2>\n' .. listText
            end

            -- Параметры шаблона
            local args = {
                ID = 'tfa',
                ['Содержание'] = body,
                ['Читателям'] = '*[[Полка:' .. pageName .. '|<span class="mw-ui-button mw-ui-quiet">Все учебники на полке</span>]]'
            }
            local tpl = frame:expandTemplate{ title = 'Заглавная страница/Раздел', args = args }
            table.insert(blocks, '<div class="main-wrapper-column">' .. tpl .. '</div>')
        end
        return blocks
    end

    -- Собираем и группируем их по 3
    local columnBlocks = makeBlocks(targets)
    local wrapped = {}
    for i, block in ipairs(columnBlocks) do
        if (i-1) % 3 == 0 then table.insert(wrapped, '<div class="main-wrapper">') end
        table.insert(wrapped, block)
        if i % 3 == 0 or i == #columnBlocks then table.insert(wrapped, '</div>') end
    end

    -- Возвращаем с препроцессингом
    local result = table.concat(wrapped, '\n')
    return frame:preprocess(result)
end

return p