Module:Popular list

local p = {}

---------------------------------------------
-- Helper function to parse a row from a
-- wikitext table.
---------------------------------------------
local function parseRow(cells, headerMap)
    -- We need rank, page title, and views
    if not (headerMap.rank and headerMap.page and headerMap.views) then 
        return nil 
    end

    local entry = {}
    
    -- rank
    entry.rank = tonumber(cells[headerMap.rank])
    
    -- page title
    local pageCell = cells[headerMap.page] or ""
    entry.page = pageCell:match("%[%[:?([^|%]]+)")

    -- views
    local viewsCell = cells[headerMap.views] or ""
    local viewsNum = viewsCell:match("{{FORMATNUM:(%d+)}}") or viewsCell:match("(%d+)")
    entry.views = tonumber(viewsNum)

    -- toolforge URL
    if entry.page then
        entry.url = "https://pageviews.toolforge.org/?project=en.wikipedia.org&pages=" .. entry.page:gsub(" ", "_")
    end

    -- assessment (optional)
    if headerMap.assessment and cells[headerMap.assessment] then
        local cell = cells[headerMap.assessment]
        entry.assessment = cell:match("Category:([^%-]+)%-Class") or cell:match("{{([^}%-]+)%-Class}}")
    end

    -- importance (optional)
    if headerMap.importance and cells[headerMap.importance] then
        local cell = cells[headerMap.importance]
        entry.importance = cell:match("Category:([^%-]+)%-importance") or cell:match("{{([^}%-]+)%-importance}}")
    end

    -- ensure we have the required data 
	-- (we can render without assessment or importance)
    return (entry.rank and entry.page and entry.views) and entry or nil
end

---------------------------------------------
-- Main function top7 will create a list of 7
-- or specified number of list items.
---------------------------------------------
function p.top7(frame)
    local pageName = frame.args[1] or ""
    local limit = tonumber(frame.args[2]) or 7

    if pageName == "" then
        return "ERROR: Missing page name parameter ([[Template:Popular list/doc#Missing page name parameter|help]])"
    end

    local title = mw.title.new(pageName)
	if not title then
		return "ERROR: Invalid page name '" .. pageName .. "' ([[Template:Popular list/doc#Invalid page name|help]])"
	end
	
    local pageContent = title and title:getContent()
    if not pageContent then
        return "ERROR: Page does not exist or cannot be read ([[Template:Popular list/doc#Page does not exist|help]])"
    end

    -- NORMALIZATION: Handle double-pipes and double-exclamations
    pageContent = pageContent:gsub("%s*||%s*", "\n|"):gsub("%s*!!%s*", "\n!")

    local entries = {}
    local headerMap = {}
    local currentRow = {}
    local inTable = false

    -- Line-by-line processing
    for line in (pageContent .. "\n"):gmatch("(.-)\n") do
        line = mw.text.trim(line)

        if line:match("^{|") then
            inTable = true
        elseif line:match("^|}") then
            -- Process the final row before closing
            if #currentRow > 0 and inTable then
                local entry = parseRow(currentRow, headerMap)
                if entry and entry.rank <= limit then table.insert(entries, entry) end
            end
            break
        elseif inTable and line:match("^[|!]%-") then
            -- A row is finished. Determine if it was a Header row or Data row.
            if #currentRow > 0 then
                local isHeaderRow = false
                for _, val in ipairs(currentRow) do
                    if val:find("Rank") or val:find("Page") then isHeaderRow = true break end
                end

                if isHeaderRow then
                    for i, content in ipairs(currentRow) do
                        local lowContent = content:lower()
                        if lowContent:find("rank") then headerMap.rank = i
                        elseif lowContent:find("page") or lowContent:find("article") then headerMap.page = i
                        elseif lowContent:find("class") or lowContent:find("assessment") then headerMap.assessment = i
                        elseif lowContent:find("importance") then headerMap.importance = i
                        -- Precision Views check (excludes "daily", "day", etc.)
                        elseif lowContent:find("views") and not lowContent:find("da") then
                            if content == "Views" or not headerMap.views then
                                headerMap.views = i
                            end
                        end
                    end
                else
                    -- It's a data row, parse it using the map we built
                    local entry = parseRow(currentRow, headerMap)
                    if entry and entry.rank <= limit then 
                        table.insert(entries, entry) 
                    end
                end
            end
            currentRow = {}
        elseif inTable and (line:match("^|") or line:match("^!")) then
            -- Capture cell content, removing the leading | or !
            local cellData = line:match("^[|!]+%s*(.*)$")
            if cellData then table.insert(currentRow, cellData) end
        end
    end

    -- Validate that we actually found the table structure
    if not (headerMap.rank and headerMap.page and headerMap.views) then
        return "ERROR: No wikitable found on page ([[Template:Popular list/doc#No wikitable found on page|help]])"
    end

    if #entries == 0 then
        return "ERROR: No entries found in table ([[Template:Popular list/doc#No entries found in table|help]])"
    end

    -- Sort by rank (1, 2, 3...)
    table.sort(entries, function(a, b) return a.rank < b.rank end)

    -- BUILD OUTPUT (Your "Pile-on" Logic)
    local list = mw.html.create('ol'):addClass('popular-list')
    
    for _, entry in ipairs(entries) do
        local formattedViews = mw.language.getContentLanguage():formatNum(entry.views)
        local annotatedLink = frame:preprocess("{{Annotated link|" .. entry.page .. "}}")
        
        -- Start string: (VIEWS
        local metaStr = "(" .. string.format("[%s %s views]", entry.url, formattedViews)
        
        -- Add Assessment if it exists
        if entry.assessment and entry.assessment ~= "" then
            metaStr = metaStr .. ", " .. entry.assessment .. " rating"
        end
        
        -- Add Importance if it exists
        if entry.importance and entry.importance ~= "" then
            metaStr = metaStr .. ", " .. entry.importance .. " importance"
        end
        
        -- Cap it: )
        metaStr = metaStr .. ")"

        -- Format as: Link ''(Metadata)''
        local itemText = string.format("%s ''%s''", annotatedLink, metaStr)
        list:tag('li'):wikitext(itemText)
    end

    return tostring(list)
end

return p

Content Disclaimer

Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.