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

Модуль:Навигация курса

Материал из Викиверситета

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

-- Module:Навигация
local p = {}

-- Функция для обрезки пробельных символов с начала и конца строки.
local function trim(s)
    return (s:gsub("^%s*(.-)%s*$", "%1"))
end

-- Основная функция навигации.
function p.nav(frame)
    local args = frame.args

    -- Получаем аргументы: main – имя главной страницы, page – имя текущей подстраницы.
    local parentTitle = args.main or args[1]
    local currentSubPage = args.page or args[2]

    if not parentTitle or not currentSubPage then
        return "Ошибка: не переданы обязательные аргументы 'main' (главная страница) и 'page' (текущая подстраница)."
    end

    -- Если имя подстраницы содержит слэш, оставляем только часть после последнего слеша.
    if currentSubPage:find("/") then
        local temp = currentSubPage:match(".*/(.*)")
        if temp then 
            currentSubPage = trim(temp)
        end
    else
        currentSubPage = trim(currentSubPage)
    end

    -- Получаем объект главной страницы и её содержимое.
    local parentPageObj = mw.title.new(parentTitle)
    local parentContent = parentPageObj and parentPageObj:getContent() or ""
    if parentContent == "" then
        return "Не удалось получить содержимое главной страницы '" .. parentTitle .. "'."
    end

    -- Ищем в содержимом блок шаблона {{Содержание ...}}
    local contentBlock = parentContent:match("{{Содержание(.-)}}")
    if not contentBlock then
        return "На странице '" .. parentTitle .. "' не найден шаблон {{Содержание}}."
    end

    -- Собираем список страниц из найденного блока.
    local pages = {}
    for line in contentBlock:gmatch("[^\n]+") do
        local trimmedLine = trim(line)
        -- Обрабатываем только строки, начинающиеся с *, : или #
        if trimmedLine:match("^[%*#:]") then
            -- Ищем все wikilinks в строке.
            for link in trimmedLine:gmatch("%[%[([^%]]-)%]%]") do
                local target, display = link:match("([^|]+)|(.+)")
                if target and target:match("^/") then
                    -- Если target начинается со слеша, берём текст после него и игнорируем display.
                    table.insert(pages, trim(target:sub(2)))
                elseif display then
                    table.insert(pages, trim(display))
                else
                    -- Если нет разделителя, выделяем часть после слеша, если она есть.
                    local afterSlash = link:match(".*/(.*)")
                    if afterSlash then
                        table.insert(pages, trim(afterSlash))
                    else
                        table.insert(pages, trim(link))
                    end
                end
            end
        end
    end

    if #pages == 0 then
        return "Не удалось извлечь список страниц из шаблона {{Содержание}} на странице '" .. parentTitle .. "'."
    end

    -- Ищем индекс текущей подстраницы в массиве.
    local currentIndex = nil
    for i, page in ipairs(pages) do
        if page == currentSubPage then
            currentIndex = i
            break
        end
    end

    if not currentIndex then
        return "Имя страницы '" .. parentTitle .. "/" .. currentSubPage .. "' не найдено в содержании родительской страницы."
    end

    -- Формируем ссылки на предыдущую и следующую страницы, если они существуют.
    local prevLink = ""
    local nextLink = ""

    if currentIndex > 1 then
        local prevPage = pages[currentIndex - 1]
        prevLink = "[[" .. parentTitle .. "/" .. prevPage .. "|" .. prevPage .. "]]"
    end

    if currentIndex < #pages then
        local nextPage = pages[currentIndex + 1]
        nextLink = "[[" .. parentTitle .. "/" .. nextPage .. "|" .. nextPage .. "]]"
    end

    -- Обработка аргумента type: prev, next или оба варианта.
    local navType = (args.type and args.type:lower()) or ""
    if navType == "prev" then
        if prevLink ~= "" then
            return "[[Файл:Left Arrow - The Noun Project.svg|25px|link=]] " .. prevLink
        else
            return ""
        end
    elseif navType == "next" then
        if nextLink ~= "" then
            return nextLink .. " [[Файл:Right Arrow - The Noun Project.svg|25px|link=]]"
        else
            return ""
        end
    else
        local outputParts = {}
        if prevLink ~= "" then
            table.insert(outputParts, "Предыдущая: " .. prevLink)
        end
        if nextLink ~= "" then
            table.insert(outputParts, "Следующая: " .. nextLink)
        end
        return table.concat(outputParts, " | ")
    end
end

return p