Documentation for this module may be created at Module:UpdateExcerpt/doc

-- Module:UpdateExcerpt
-- Usage: {{#invoke:UpdateExcerpt|render|Month|Day_Year|number_of_lines}}
-- Example: {{#invoke:UpdateExcerpt|render|March|6,_2026|5}}

local p = {}

function p.render(frame)
    local args = frame.args
    local month     = args[1]
    local day_year  = args[2]
    local maxLines  = tonumber(args[3]) or 5

    -- Validate arguments
    if not month or not day_year then
        return '<span class="error">Usage: {{#invoke:UpdateExcerpt|render|Month|Day_Year|lines}}</span>'
    end

    -- Extract day and year from day_year (expects format: "Day,_Year")
    local day, year = day_year:match("^(%d+),%s*_(%d+)$")
    if not day or not year then
        return '<span class="error">Invalid day_year format. Expected "Day,_Year".</span>'
    end

    -- Build the page title  (e.g. "Update:March 6, 2026")
    local pageTitle = "Update:" .. month .. " " .. day .. ", " .. year

    local titleObj = mw.title.new(pageTitle)
    if not titleObj then
        return '<span class="error">Invalid page title: ' .. pageTitle .. '</span>'
    end

    local content = titleObj:getContent()
    if not content then
        return '<span class="error">Page not found: [[' .. pageTitle .. ']]</span>'
    end

    -----------------------------------------------------------------
    -- Locate the  | notes =  parameter inside {{Update layout …}}
    -----------------------------------------------------------------
    local notesStart = content:find("|%s*notes%s*=")
    if not notesStart then
        return '<span class="error">No notes parameter found on [[' .. pageTitle .. ']]</span>'
    end

    -- Grab everything after the '=' sign
    local sub   = content:sub(notesStart)
    local eqPos = sub:find("=")
    local notesRaw = sub:sub(eqPos + 1)

    -- Strip the final closing  }}  that belongs to {{Update layout}}
    -- Using the *last* occurrence so nested templates inside notes
    -- (if any) are preserved.
    local lastClose = notesRaw:find("}}%s*$")
    if lastClose then
        notesRaw = notesRaw:sub(1, lastClose - 1)
    end

    notesRaw = mw.text.trim(notesRaw)

    if notesRaw == "" then
        return ""
    end

    -----------------------------------------------------------------
    -- Split into non-empty lines
    -----------------------------------------------------------------
    local lines = {}
    for line in notesRaw:gmatch("[^\n]+") do
        -- keep the line only if it isn't pure whitespace
        if mw.text.trim(line) ~= "" then
            table.insert(lines, line)
        end
    end

    if #lines == 0 then
        return ""
    end

    -----------------------------------------------------------------
    -- Build output: first N lines, then "…" linking to the full page
    -----------------------------------------------------------------
    local count  = math.min(maxLines, #lines)
    local result = {}
    for i = 1, count do
        table.insert(result, lines[i])
    end

    local output = table.concat(result, "\n")

    if #lines > maxLines then
        output = output .. "\n[[" .. pageTitle .. "|Read more]]"
    end

    return frame:preprocess(output)
end

return p