Jump to content

Module:News

From HopperWiki

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

-- ================================================================================
-- Module dependencies
-- ================================================================================
local p = {}
local json_decode = require("mw.text").jsonDecode

-- ================================================================================
-- Utility function to sort news items
-- ================================================================================
local function sort_news_items_by_date(news_items)
    table.sort(news_items, function(a, b)
        return a.date_posted > b.date_posted  -- descending order
    end)
end

-- ================================================================================
-- Fetch and parse news data from a given page
-- ================================================================================
local function fetch_news_data(data_page)
    local raw_content = mw.title.new(data_page):getContent()
    if not raw_content then return {} end
    -- Remove <pre> tags
    raw_content = raw_content:gsub("^<pre>%s*", ""):gsub("%s*</pre>$", "")
    -- Decode JSON
    local success, news_data = pcall(json_decode, raw_content)
    return success and news_data or {}
end

-- ================================================================================
-- Render a news feed given a data page
-- ================================================================================
local function render_news_feed(data_page, limit, archive_link, archive_text)
    limit = tonumber(limit) or 7  -- default to 7 if not provided/invalid

    local news_items = fetch_news_data(data_page)
    sort_news_items_by_date(news_items)  -- Sort by date

    local output = {}
    table.insert(output, '<div class="news-feed">')
    table.insert(output, '<ul>')
    for i, news_item in ipairs(news_items) do
        if i > limit then break end  -- Limit to `limit` items
        local title_display
        if news_item.link and news_item.link ~= "" then
            if news_item.link:match("^https?://") then
                -- External link: [url title]
                title_display = string.format('<b>[%s %s]</b>', news_item.link, news_item.title)
            else
                -- Internal wiki page: [[page|title]]
                title_display = string.format('<b>[[%s|%s]]</b>', news_item.link, news_item.title)
            end
        else
            title_display = string.format('<b>%s</b>', news_item.title)
        end
        -- Styling lives in MediaWiki:Common.css (.hw-news-meta), themed via
        -- the --hw-text-muted token so it stays legible in dark mode.
        local posted_date = news_item.date_posted and string.format(
            '<br><span class="hw-news-meta">Posted: %s</span>',
            news_item.date_posted
        ) or ""
        table.insert(output, string.format('<li>%s - %s%s</li>', title_display, news_item.summary, posted_date))
    end
    table.insert(output, '</ul>')

    if archive_link and archive_link ~= "" then
        local link_text = (archive_text and archive_text ~= "") and archive_text or "See previous news items"
        table.insert(output, string.format(
            '<div class="news-feed-archive-link">[[%s|%s]]</div>',
            archive_link, link_text
        ))
    end

    table.insert(output, '</div>')
    return table.concat(output, "\n")
end

-- ================================================================================
-- Exposed render functions
-- ================================================================================
function p.render_hopperwiki_news(frame)
    local args = frame.args
    return frame:preprocess(render_news_feed(
        "Data:HopperWiki news",
        args.limit,
        args.archive_link,
        args.archive_text
    ))
end

function p.render_orthoptera_news(frame)
    local args = frame.args
    return frame:preprocess(render_news_feed(
        "Data:Orthoptera news",
        args.limit,
        args.archive_link,
        args.archive_text
    ))
end

return p
Cookies help us deliver our services. By using our services, you agree to our use of cookies.