Module:RelatedNews: Difference between revisions
From TwogPedia
No edit summary |
No edit summary Tag: Reverted |
||
| Line 1: | Line 1: | ||
local getArgs = require('Module:Arguments').getArgs | local getArgs = require('Module:Arguments').getArgs | ||
local cargo = mw.ext.cargo | local cargo = mw.ext.cargo | ||
local p = {} | local p = {} | ||
local function | local function sanitize(input) | ||
if not input then return '' end | |||
return mw.ustring.gsub(input, '"', '""') | |||
end | end | ||
function | local function splitCsv(str) | ||
if not str then return {} end | |||
local parts = {} | |||
for word in mw.text.gsplit(str, ',') do | |||
table.insert(parts, mw.text.trim(word)) | |||
end | |||
return parts | |||
end | |||
local function getContentSnippet(content) | |||
local words = mw.text.split(content or '', ' ') | |||
return table.concat(words, ' ', 1, math.min(20, #words)) .. (#words > 20 and '...' or '') | |||
end | |||
local function formatDate(dateStr) | |||
local y, m, d = dateStr:match("(%d+)%-(%d+)%-(%d+)") | |||
local ok, time = pcall(os.time, {year = y, month = m, day = d}) | |||
return ok and os.date("%b %d, %Y", time) or 'Unknown' | |||
end | |||
local function getRelatedNewsBy(tagsOrCats, field, exclude, limit) | |||
local terms = splitCsv(tagsOrCats) | |||
if #terms == 0 then return {} end | |||
local where = {} | |||
if exclude then | |||
for _, name in ipairs(exclude) do | |||
table.insert(where, '_pageName != "' .. sanitize(name) .. '"') | |||
end | |||
end | |||
local orClause = {} | |||
end | for _, val in ipairs(terms) do | ||
table.insert(orClause, field .. ' HOLDS "' .. sanitize(val) .. '"') | |||
end | |||
table.insert(where, '(' .. table.concat(orClause, ' OR ') .. ')') | |||
local args = { | |||
where = table.concat(where, ' AND '), | |||
orderBy = 'date DESC', | |||
limit = limit or 5 | |||
} | |||
return cargo.query('News', '_pageName, date, tags, image, category, content', args) | |||
end | |||
local function renderArticle(result) | |||
local link = result._pageName | |||
local image = result.image or 'News placeholder.png' | |||
local category = mw.text.split(result.category or 'Uncategorized', ',')[1] | |||
local categoryClassMap = { | |||
['News'] = 'news-category-news', | |||
['Transfer Market'] = 'news-category-transfer', | |||
['Drama'] = 'news-category-drama', | |||
['Business'] = 'news-category-business', | |||
['Sponsorships'] = 'news-category-sponsorships' | |||
} | |||
local categoryClass = categoryClassMap[category] or 'default-category-class' | |||
local wrapper = mw.html.create('div'):addClass('related__article') | |||
wrapper:tag('div'):addClass('news-image-container') | |||
:wikitext('[[File:' .. image .. '|link=' .. link .. '|800px|class=news-image|alt=News Image]]') | |||
wrapper:tag('div'):addClass('news-title-twogpedia'):wikitext(link) | |||
wrapper:tag('p'):addClass('news-content'):wikitext(getContentSnippet(result.content)) | |||
local meta = mw.html.create('div'):addClass('news-meta-container') | |||
meta:tag('p'):addClass('news-meta news-category-meta ' .. categoryClass):wikitext(category) | |||
meta:tag('p'):addClass('news-meta news-date'):wikitext(formatDate(result.date)) | |||
wrapper:node(meta) | |||
return wrapper | |||
end | end | ||
function | function p.main(frame) | ||
local args = getArgs(frame) | |||
local currentPage = mw.title.getCurrentTitle().text | |||
local tagNews = getRelatedNewsBy(args.tags, 'tags', {currentPage}, 5) | |||
local newsItemContainer = mw.html.create('div'):addClass('related__news') | |||
for _, result in ipairs(tagNews) do | |||
newsItemContainer:node(renderArticle(result)) | |||
end | |||
if #tagNews < 5 then | |||
local excludeList = {} | |||
for _, r in ipairs(tagNews) do table.insert(excludeList, r._pageName) end | |||
table.insert(excludeList, currentPage) | |||
local catNews = getRelatedNewsBy(args.categories, 'category', excludeList, 5 - #tagNews) | |||
for _, result in ipairs(catNews) do | |||
newsItemContainer:node(renderArticle(result)) | |||
end | |||
end | |||
local container = mw.html.create('div'):addClass('related__news__container') | |||
local titleRow = mw.html.create('div') | |||
:addClass('related__news__title-container') | |||
:attr('style', 'display: flex; align-items: center;') | |||
titleRow:tag('h3'):addClass('news-icon') | |||
:wikitext('[[File:News-icon.png|30px|alt=Related News Icon]] Related news') | |||
titleRow:tag('div'):addClass('related__news__view-all'):attr('id', 'view-all-button'):wikitext('View All') | |||
container:node(titleRow):node(newsItemContainer) | |||
return tostring(container) | |||
end | end | ||
return p | return p | ||
Revision as of 21:27, 7 May 2025
Documentation for this module may be created at Module:RelatedNews/doc
local getArgs = require('Module:Arguments').getArgs
local cargo = mw.ext.cargo
local p = {}
local function sanitize(input)
if not input then return '' end
return mw.ustring.gsub(input, '"', '""')
end
local function splitCsv(str)
if not str then return {} end
local parts = {}
for word in mw.text.gsplit(str, ',') do
table.insert(parts, mw.text.trim(word))
end
return parts
end
local function getContentSnippet(content)
local words = mw.text.split(content or '', ' ')
return table.concat(words, ' ', 1, math.min(20, #words)) .. (#words > 20 and '...' or '')
end
local function formatDate(dateStr)
local y, m, d = dateStr:match("(%d+)%-(%d+)%-(%d+)")
local ok, time = pcall(os.time, {year = y, month = m, day = d})
return ok and os.date("%b %d, %Y", time) or 'Unknown'
end
local function getRelatedNewsBy(tagsOrCats, field, exclude, limit)
local terms = splitCsv(tagsOrCats)
if #terms == 0 then return {} end
local where = {}
if exclude then
for _, name in ipairs(exclude) do
table.insert(where, '_pageName != "' .. sanitize(name) .. '"')
end
end
local orClause = {}
for _, val in ipairs(terms) do
table.insert(orClause, field .. ' HOLDS "' .. sanitize(val) .. '"')
end
table.insert(where, '(' .. table.concat(orClause, ' OR ') .. ')')
local args = {
where = table.concat(where, ' AND '),
orderBy = 'date DESC',
limit = limit or 5
}
return cargo.query('News', '_pageName, date, tags, image, category, content', args)
end
local function renderArticle(result)
local link = result._pageName
local image = result.image or 'News placeholder.png'
local category = mw.text.split(result.category or 'Uncategorized', ',')[1]
local categoryClassMap = {
['News'] = 'news-category-news',
['Transfer Market'] = 'news-category-transfer',
['Drama'] = 'news-category-drama',
['Business'] = 'news-category-business',
['Sponsorships'] = 'news-category-sponsorships'
}
local categoryClass = categoryClassMap[category] or 'default-category-class'
local wrapper = mw.html.create('div'):addClass('related__article')
wrapper:tag('div'):addClass('news-image-container')
:wikitext('[[File:' .. image .. '|link=' .. link .. '|800px|class=news-image|alt=News Image]]')
wrapper:tag('div'):addClass('news-title-twogpedia'):wikitext(link)
wrapper:tag('p'):addClass('news-content'):wikitext(getContentSnippet(result.content))
local meta = mw.html.create('div'):addClass('news-meta-container')
meta:tag('p'):addClass('news-meta news-category-meta ' .. categoryClass):wikitext(category)
meta:tag('p'):addClass('news-meta news-date'):wikitext(formatDate(result.date))
wrapper:node(meta)
return wrapper
end
function p.main(frame)
local args = getArgs(frame)
local currentPage = mw.title.getCurrentTitle().text
local tagNews = getRelatedNewsBy(args.tags, 'tags', {currentPage}, 5)
local newsItemContainer = mw.html.create('div'):addClass('related__news')
for _, result in ipairs(tagNews) do
newsItemContainer:node(renderArticle(result))
end
if #tagNews < 5 then
local excludeList = {}
for _, r in ipairs(tagNews) do table.insert(excludeList, r._pageName) end
table.insert(excludeList, currentPage)
local catNews = getRelatedNewsBy(args.categories, 'category', excludeList, 5 - #tagNews)
for _, result in ipairs(catNews) do
newsItemContainer:node(renderArticle(result))
end
end
local container = mw.html.create('div'):addClass('related__news__container')
local titleRow = mw.html.create('div')
:addClass('related__news__title-container')
:attr('style', 'display: flex; align-items: center;')
titleRow:tag('h3'):addClass('news-icon')
:wikitext('[[File:News-icon.png|30px|alt=Related News Icon]] Related news')
titleRow:tag('div'):addClass('related__news__view-all'):attr('id', 'view-all-button'):wikitext('View All')
container:node(titleRow):node(newsItemContainer)
return tostring(container)
end
return p
No categories