Module:Popular list/sandbox
| This is the module sandbox page for Module:Popular list (diff). |
Usage
This template implements {{popular list}}, as {{#invoke:Popular list|top7}}.
Parameters
|1=(Required)- The full page name of the "Popular pages" list (e.g.,
Wikipedia:WikiProject Comics/Popular pages). The page must contain a wikitable with "Rank", "Page", and "Views" headers. Column order does not matter as long as headers are present. |2=(Optional)- The number of entries to display. Defaults to
7.'
local p = {}
-- ==========================================
-- HELPER: Parse a single data row
-- ==========================================
local function parseRow(cells, headerMap)
-- We need Rank, Page, and Views. If headers weren't found, we can't parse.
if not (headerMap.rank and headerMap.page and headerMap.views) then
return nil
end
local entry = {}
-- 1. Rank
entry.rank = tonumber(cells[headerMap.rank])
-- 2. Page Title
local pageCell = cells[headerMap.page] or ""
entry.page = pageCell:match("%[%[:?([^|%]]+)")
-- 3. Views (Handles {{FORMATNUM:}} or raw numbers)
local viewsCell = cells[headerMap.views] or ""
local viewsNum = viewsCell:match("{{FORMATNUM:(%d+)}}") or viewsCell:match("(%d+)")
entry.views = tonumber(viewsNum)
-- Construct the toolforge URL
if entry.page then
entry.url = "https://pageviews.toolforge.org/?project=en.wikipedia.org&pages=" .. entry.page:gsub(" ", "_")
end
-- 4. Assessment (Captures 'B' from 'Category:B-Class' or '{{B-Class}}')
if headerMap.assessment and cells[headerMap.assessment] then
local cell = cells[headerMap.assessment]
entry.assessment = cell:match("Category:([^%-]+)%-Class") or cell:match("{{([^}%-]+)%-Class}}")
end
-- 5. Importance (Captures 'Top' from 'Category:Top-importance' or '{{Top-importance}}')
if headerMap.importance and cells[headerMap.importance] then
local cell = cells[headerMap.importance]
entry.importance = cell:match("Category:([^%-]+)%-importance") or cell:match("{{([^}%-]+)%-importance}}")
end
-- Safety check: ensure we actually got the core data
return (entry.rank and entry.page and entry.views) and entry or nil
end
-- ==========================================
-- MAIN FUNCTION: top7
-- ==========================================
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)
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: Could not find valid header row (Rank, Page, Views) ([[Template:Popular list/doc#Header error|help]])"
end
if #entries == 0 then
return "ERROR: No entries found in table ([[Template:Popular list/doc#No entries|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.
- 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:
- 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.
- 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.
- 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.
- Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.