Jump to content

Module:DailyFeatured: Difference between revisions

From the Vrienden Universe, a fictional wiki
No edit summary
No edit summary
 
(10 intermediate revisions by 2 users not shown)
Line 1: Line 1:
local p = {}
local p = {}
local POOL_TEMPLATE = "Featured pool"
local STYLES_PAGE = "Template:Featured box/styles.css"
local function trim(s)
return mw.text.trim(s or "")
end
local function makeStylesTag(frame)
frame = frame or mw.getCurrentFrame()
return frame:extensionTag("templatestyles", "", { src = STYLES_PAGE })
end
local function hasImageExtension(name)
if not name or name == "" then
return false
end
local lower = mw.ustring.lower(name)
return lower:match("%.png$")
or lower:match("%.jpg$")
or lower:match("%.jpeg$")
or lower:match("%.svg$")
end


local function getPool()
local function getPool()
local content = mw.getCurrentFrame():expandTemplate{ title = "Featured pool" }
local content = mw.getCurrentFrame():expandTemplate{ title = POOL_TEMPLATE }
local pages = {}
local pages = {}


for line in mw.text.gsplit(content or "", "\n", true) do
for line in mw.text.gsplit(content or "", "\n", true) do
line = mw.text.trim(line)
line = trim(line)
line = line:gsub("<!%-%-.-%-%->", "")
line = trim(line)
 
if line ~= "" then
if line ~= "" then
line = line:gsub("^%*%s*", "")
line = line:gsub("^%*%s*", "")
line = trim(line)
local linkedTitle =
line:match("^%[%[([^|%]]+)%]%]$")
or line:match("^%[%[([^|%]]+)|.-%]%]$")
if linkedTitle then
line = linkedTitle
end
line = trim(line)
if line ~= "" then
if line ~= "" then
table.insert(pages, line)
table.insert(pages, line)
Line 18: Line 58:
end
end


local function cleanWikitext(s)
local function removeBalancedTemplates(s)
local previous
 
repeat
previous = s
s = s:gsub("%b{}", "")
until s == previous
 
return s
end
 
local function removeRefs(s)
s = s:gsub("<ref[^>/]-/>", "")
s = s:gsub("<ref.->.-</ref>", "")
s = s:gsub("<ref.->", "")
return s
end
 
local function removeFiles(s)
s = s:gsub("%[%[%s*[Ff]ile%s*:.-%]%]", "")
s = s:gsub("%[%[%s*[Ii]mage%s*:.-%]%]", "")
return s
end
 
local function cleanLeadWikitext(s)
if not s or s == "" then
if not s or s == "" then
return ""
return ""
end
end
s = s:gsub("<!--.-?-->", "")
 
s = s:gsub("%[%[File:.-%]%]", "")
s = s:gsub("<!%-%-.-%-%->", "")
s = s:gsub("%{%b{}%}", "")
s = removeRefs(s)
s = s:gsub("<ref.->.-</ref>", "")
s = removeFiles(s)
s = s:gsub("<ref.->", "")
s = removeBalancedTemplates(s)
s = s:gsub("\r", ""):gsub("[ \t]+", " ")
s = s:gsub("<br%s*/?>", "\n")
return mw.text.trim(s)
s = s:gsub("<br%s*>", "\n")
s = s:gsub("\r", "")
 
s = s:gsub("'''", "")
s = s:gsub("''", "")
s = s:gsub("%[https?://[^%s%]]+%s+([^%]]+)%]", "%1")
s = s:gsub("%[https?://[^%s%]]+%]", "")
s = s:gsub("<[^>]+>", "")
 
local cleanedLines = {}
 
for line in mw.text.gsplit(s, "\n", true) do
local cleaned = trim(line)
 
if cleaned ~= ""
and not cleaned:match("^__%u+__$")
and not cleaned:match("^%[%[[Cc]ategory:")
and not cleaned:match("^%s*|")
and not cleaned:match("^%s*}") then
table.insert(cleanedLines, cleaned)
end
end
 
return trim(table.concat(cleanedLines, "\n\n"))
end
end


local function extractHeadlineFromContent(wikitext)
local function extractLeadFromContent(wikitext)
if not wikitext or wikitext == "" then
if not wikitext or wikitext == "" then
return ""
return ""
end
end


-- Prefer first section heading if present
local leadLines = {}
 
for line in mw.text.gsplit(wikitext, "\n", true) do
if line:match("^%s*==+%s*[^=].-==+%s*$") then
break
end
 
table.insert(leadLines, line)
end
 
return cleanLeadWikitext(table.concat(leadLines, "\n"))
end
 
local function normalizeImageFile(value)
if not value or value == "" then
return nil
end
 
value = trim(value)
value = value:gsub("<!%-%-.-%-%->", "")
value = trim(value)
 
if value == "" then
return nil
end
 
local linked =
value:match("%[%[%s*[Ff]ile%s*:%s*([^|%]]+)")
or value:match("%[%[%s*[Ii]mage%s*:%s*([^|%]]+)")
 
if linked then
value = linked
else
value = value:gsub("^%s*[Ff]ile%s*:%s*", "")
value = value:gsub("^%s*[Ii]mage%s*:%s*", "")
value = value:gsub("|.*$", "")
value = value:gsub("%]%].*$", "")
end
 
value = trim(value)
 
if value == "" then
return nil
end
 
local lower = mw.ustring.lower(value)
 
if lower == "none" or lower == "no" or lower == "n/a" or lower == "-" then
return nil
end
 
if not hasImageExtension(value) then
return nil
end
 
return "File:" .. value
end
 
local function isImageParameterName(name)
if not name then
return false
end
 
name = mw.ustring.lower(trim(name))
 
return name == "image"
or name == "photo"
or name == "picture"
or name == "portrait"
or name == "logo"
or name == "flag"
or name == "emblem"
or name:match("^image%d+$")
or name:match("^photo%d+$")
or name:match("^picture%d+$")
or name:match("^portrait%d+$")
or name:match("^logo%d+$")
or name:match("^flag%d+$")
or name:match("^emblem%d+$")
end
 
local function extractImageFromContent(wikitext)
if not wikitext or wikitext == "" then
return nil
end
 
for line in mw.text.gsplit(wikitext, "\n", true) do
for line in mw.text.gsplit(wikitext, "\n", true) do
line = cleanWikitext(line)
local name, value = line:match("^%s*|%s*([%w_%-]+)%s*=%s*(.-)%s*$")
if line:match("^==+%s*[^=].-==+%s*$") then
 
line = line:gsub("^=+%s*", ""):gsub("%s*=+$", "")
if name and value and isImageParameterName(name) then
line = mw.text.trim(line)
local file = normalizeImageFile(value)
if line ~= "" then
 
return line
if file then
return file
end
end
end
end
end
end


-- Otherwise first meaningful non-empty line
for name, value in wikitext:gmatch("|%s*([%w_%-]+)%s*=%s*([^|\n}]+)") do
for line in mw.text.gsplit(wikitext, "\n", true) do
if isImageParameterName(name) then
line = cleanWikitext(line)
local file = normalizeImageFile(value)
if line ~= ""
 
and not line:match("^__%u+__$")
if file then
and not line:match("^%[%[Category:") then
return file
if #line > 180 then
line = line:sub(1, 177) .. "…"
end
end
return line
end
end
end
for file in wikitext:gmatch("%[%[%s*[Ff]ile%s*:%s*([^|%]]+)") do
local normalized = normalizeImageFile(file)
if normalized then
return normalized
end
end
for file in wikitext:gmatch("%[%[%s*[Ii]mage%s*:%s*([^|%]]+)") do
local normalized = normalizeImageFile(file)
if normalized then
return normalized
end
end
for file in wikitext:gmatch("([%w%s%._%-%(%)]+%.[Pp][Nn][Gg])") do
local normalized = normalizeImageFile(file)
if normalized then
return normalized
end
end
for file in wikitext:gmatch("([%w%s%._%-%(%)]+%.[Jj][Pp][Gg])") do
local normalized = normalizeImageFile(file)
if normalized then
return normalized
end
end
for file in wikitext:gmatch("([%w%s%._%-%(%)]+%.[Jj][Pp][Ee][Gg])") do
local normalized = normalizeImageFile(file)
if normalized then
return normalized
end
end
for file in wikitext:gmatch("([%w%s%._%-%(%)]+%.[Ss][Vv][Gg])") do
local normalized = normalizeImageFile(file)
if normalized then
return normalized
end
end
return nil
end
local function plainLower(s)
s = mw.ustring.lower(s or "")
s = s:gsub("_", " ")
s = s:gsub("%s+", " ")
return s
end
local function contains(text, needle)
return mw.ustring.find(text, needle, 1, true) ~= nil
end
local function getFeaturedClass(title, content)
local titleText = plainLower(title)
local contentText = plainLower(content)
local allText = titleText .. "\n" .. contentText
if contains(allText, "bucharest butchers")
or contains(allText, "snubable enterprise")
or contains(titleText, "snubable") then
return "featured-bucharest"
end
if contains(titleText, "noord")
or contains(contentText, "[[noord family")
or contains(contentText, "[[category:noord family")
or contains(contentText, "family = [[noord family")
or contains(contentText, "|family=[[noord family") then
return "featured-noord"
end
if contains(titleText, "paap")
or contains(contentText, "[[paap family")
or contains(contentText, "[[category:paap family")
or contains(contentText, "family = [[paap family")
or contains(contentText, "|family=[[paap family") then
return "featured-paap"
end
if contains(titleText, "van hetten")
or contains(contentText, "[[van hetten family")
or contains(contentText, "[[category:van hetten family")
or contains(contentText, "family = [[van hetten family")
or contains(contentText, "|family=[[van hetten family") then
return "featured-van-hetten"
end
if contains(titleText, "hoos")
or contains(contentText, "[[hoos family")
or contains(contentText, "[[category:hoos family")
or contains(contentText, "family = [[hoos family")
or contains(contentText, "|family=[[hoos family") then
return "featured-hoos"
end
if contains(titleText, "schroeter")
or contains(contentText, "[[schroeter family")
or contains(contentText, "[[category:schroeter family")
or contains(contentText, "family = [[schroeter family")
or contains(contentText, "|family=[[schroeter family") then
return "featured-schroeter"
end
if contains(allText, "tanoa einsatzgruppen")
or contains(titleText, "tanoa")
or contains(contentText, "[[category:tanoa")
or contains(contentText, "[[tanoa") then
return "featured-tanoa"
end
end


Line 64: Line 354:
end
end


function p.main(frame)
local function getFeaturedData()
local pages = getPool()
local pages = getPool()
if #pages == 0 then
if #pages == 0 then
return "No featured pages defined."
return nil, "No featured pages defined."
end
end


local day = tonumber(os.date("%j")) -- day of year
local day = tonumber(os.date("%j")) or 1
local index = (day % #pages) + 1
local index = ((day - 1) % #pages) + 1
local title = pages[index]
local title = pages[index]


local args = (frame and frame.args) or {}
local page = mw.title.new(title)
local lead = ""
local image = nil
local content = ""
 
if page and page.exists then
content = page:getContent() or ""
lead = extractLeadFromContent(content)
image = extractImageFromContent(content)
end
 
if lead == "" then
lead = "Featured page for " .. os.date("%d %B %Y") .. "."
end
 
return {
title = title,
lead = lead,
image = image,
className = getFeaturedClass(title, content)
}
end
 
local function makeImageBlock(data)
if not data.image then
return ""
end
 
return
'<div class="featured-box-image-frame">' ..
'[[' .. data.image .. '|frameless|160x160px|link=' .. data.title .. '|' .. data.title .. ']]' ..
'</div>'
end
 
local function makeBoxClass(data)
local className = "featured-box"
 
if data and data.className and data.className ~= "" then
className = className .. " " .. data.className
end
 
return className
end
 
function p.main(frame)
local args = frame and frame.args or {}
local data, err = getFeaturedData()
 
if not data then
return err
end
 
if args.titleonly == "1" then
if args.titleonly == "1" then
return title
return data.title
end
end


local page = mw.title.new(title)
if args.imageonly == "1" then
local headline = ""
return data.image or ""
end


if page and page.exists then
if args.classonly == "1" then
local content = page:getContent() or ""
return data.className or ""
headline = extractHeadlineFromContent(content)
end
end


if headline == "" then
return
headline = "Featured page for " .. os.date("%d %B %Y") .. "."
makeStylesTag(frame) ..
makeImageBlock(data) ..
"'''[[" .. data.title .. "]]'''" ..
'<div class="featured-box-lead">' ..
data.lead ..
'</div>'
end
 
function p.box(frame)
local data, err = getFeaturedData()
 
if not data then
return
makeStylesTag(frame) ..
'<div class="featured-box">' ..
'<div class="featured-box-title">Featured page</div>' ..
'<div class="featured-box-body">' .. err .. '</div>' ..
'</div>'
end
end


return string.format(
return
"'''[[%s]]'''<div style=\"margin-top:0.35em;\"><small>%s</small></div>",
makeStylesTag(frame) ..
title,
'<div class="' .. makeBoxClass(data) .. '">' ..
headline
'<div class="featured-box-title">Featured page</div>' ..
)
'<div class="featured-box-body">' ..
makeImageBlock(data) ..
'<div class="featured-box-page-title">' ..
"'''[[" .. data.title .. "]]'''" ..
'</div>' ..
'<div class="featured-box-lead">' .. data.lead .. '</div>' ..
'<div class="featured-box-open">[[:' .. data.title .. '|Open page]]</div>' ..
'</div>' ..
'</div>'
end
end


return p
return p

Latest revision as of 10:32, 14 May 2026


local p = {}

local POOL_TEMPLATE = "Featured pool"
local STYLES_PAGE = "Template:Featured box/styles.css"

local function trim(s)
	return mw.text.trim(s or "")
end

local function makeStylesTag(frame)
	frame = frame or mw.getCurrentFrame()
	return frame:extensionTag("templatestyles", "", { src = STYLES_PAGE })
end

local function hasImageExtension(name)
	if not name or name == "" then
		return false
	end

	local lower = mw.ustring.lower(name)

	return lower:match("%.png$")
		or lower:match("%.jpg$")
		or lower:match("%.jpeg$")
		or lower:match("%.svg$")
end

local function getPool()
	local content = mw.getCurrentFrame():expandTemplate{ title = POOL_TEMPLATE }
	local pages = {}

	for line in mw.text.gsplit(content or "", "\n", true) do
		line = trim(line)
		line = line:gsub("<!%-%-.-%-%->", "")
		line = trim(line)

		if line ~= "" then
			line = line:gsub("^%*%s*", "")
			line = trim(line)

			local linkedTitle =
				line:match("^%[%[([^|%]]+)%]%]$")
				or line:match("^%[%[([^|%]]+)|.-%]%]$")

			if linkedTitle then
				line = linkedTitle
			end

			line = trim(line)

			if line ~= "" then
				table.insert(pages, line)
			end
		end
	end

	return pages
end

local function removeBalancedTemplates(s)
	local previous

	repeat
		previous = s
		s = s:gsub("%b{}", "")
	until s == previous

	return s
end

local function removeRefs(s)
	s = s:gsub("<ref[^>/]-/>", "")
	s = s:gsub("<ref.->.-</ref>", "")
	s = s:gsub("<ref.->", "")
	return s
end

local function removeFiles(s)
	s = s:gsub("%[%[%s*[Ff]ile%s*:.-%]%]", "")
	s = s:gsub("%[%[%s*[Ii]mage%s*:.-%]%]", "")
	return s
end

local function cleanLeadWikitext(s)
	if not s or s == "" then
		return ""
	end

	s = s:gsub("<!%-%-.-%-%->", "")
	s = removeRefs(s)
	s = removeFiles(s)
	s = removeBalancedTemplates(s)
	s = s:gsub("<br%s*/?>", "\n")
	s = s:gsub("<br%s*>", "\n")
	s = s:gsub("\r", "")

	s = s:gsub("'''", "")
	s = s:gsub("''", "")
	s = s:gsub("%[https?://[^%s%]]+%s+([^%]]+)%]", "%1")
	s = s:gsub("%[https?://[^%s%]]+%]", "")
	s = s:gsub("<[^>]+>", "")

	local cleanedLines = {}

	for line in mw.text.gsplit(s, "\n", true) do
		local cleaned = trim(line)

		if cleaned ~= ""
			and not cleaned:match("^__%u+__$")
			and not cleaned:match("^%[%[[Cc]ategory:")
			and not cleaned:match("^%s*|")
			and not cleaned:match("^%s*}") then
			table.insert(cleanedLines, cleaned)
		end
	end

	return trim(table.concat(cleanedLines, "\n\n"))
end

local function extractLeadFromContent(wikitext)
	if not wikitext or wikitext == "" then
		return ""
	end

	local leadLines = {}

	for line in mw.text.gsplit(wikitext, "\n", true) do
		if line:match("^%s*==+%s*[^=].-==+%s*$") then
			break
		end

		table.insert(leadLines, line)
	end

	return cleanLeadWikitext(table.concat(leadLines, "\n"))
end

local function normalizeImageFile(value)
	if not value or value == "" then
		return nil
	end

	value = trim(value)
	value = value:gsub("<!%-%-.-%-%->", "")
	value = trim(value)

	if value == "" then
		return nil
	end

	local linked =
		value:match("%[%[%s*[Ff]ile%s*:%s*([^|%]]+)")
		or value:match("%[%[%s*[Ii]mage%s*:%s*([^|%]]+)")

	if linked then
		value = linked
	else
		value = value:gsub("^%s*[Ff]ile%s*:%s*", "")
		value = value:gsub("^%s*[Ii]mage%s*:%s*", "")
		value = value:gsub("|.*$", "")
		value = value:gsub("%]%].*$", "")
	end

	value = trim(value)

	if value == "" then
		return nil
	end

	local lower = mw.ustring.lower(value)

	if lower == "none" or lower == "no" or lower == "n/a" or lower == "-" then
		return nil
	end

	if not hasImageExtension(value) then
		return nil
	end

	return "File:" .. value
end

local function isImageParameterName(name)
	if not name then
		return false
	end

	name = mw.ustring.lower(trim(name))

	return name == "image"
		or name == "photo"
		or name == "picture"
		or name == "portrait"
		or name == "logo"
		or name == "flag"
		or name == "emblem"
		or name:match("^image%d+$")
		or name:match("^photo%d+$")
		or name:match("^picture%d+$")
		or name:match("^portrait%d+$")
		or name:match("^logo%d+$")
		or name:match("^flag%d+$")
		or name:match("^emblem%d+$")
end

local function extractImageFromContent(wikitext)
	if not wikitext or wikitext == "" then
		return nil
	end

	for line in mw.text.gsplit(wikitext, "\n", true) do
		local name, value = line:match("^%s*|%s*([%w_%-]+)%s*=%s*(.-)%s*$")

		if name and value and isImageParameterName(name) then
			local file = normalizeImageFile(value)

			if file then
				return file
			end
		end
	end

	for name, value in wikitext:gmatch("|%s*([%w_%-]+)%s*=%s*([^|\n}]+)") do
		if isImageParameterName(name) then
			local file = normalizeImageFile(value)

			if file then
				return file
			end
		end
	end

	for file in wikitext:gmatch("%[%[%s*[Ff]ile%s*:%s*([^|%]]+)") do
		local normalized = normalizeImageFile(file)

		if normalized then
			return normalized
		end
	end

	for file in wikitext:gmatch("%[%[%s*[Ii]mage%s*:%s*([^|%]]+)") do
		local normalized = normalizeImageFile(file)

		if normalized then
			return normalized
		end
	end

	for file in wikitext:gmatch("([%w%s%._%-%(%)]+%.[Pp][Nn][Gg])") do
		local normalized = normalizeImageFile(file)

		if normalized then
			return normalized
		end
	end

	for file in wikitext:gmatch("([%w%s%._%-%(%)]+%.[Jj][Pp][Gg])") do
		local normalized = normalizeImageFile(file)

		if normalized then
			return normalized
		end
	end

	for file in wikitext:gmatch("([%w%s%._%-%(%)]+%.[Jj][Pp][Ee][Gg])") do
		local normalized = normalizeImageFile(file)

		if normalized then
			return normalized
		end
	end

	for file in wikitext:gmatch("([%w%s%._%-%(%)]+%.[Ss][Vv][Gg])") do
		local normalized = normalizeImageFile(file)

		if normalized then
			return normalized
		end
	end

	return nil
end

local function plainLower(s)
	s = mw.ustring.lower(s or "")
	s = s:gsub("_", " ")
	s = s:gsub("%s+", " ")
	return s
end

local function contains(text, needle)
	return mw.ustring.find(text, needle, 1, true) ~= nil
end

local function getFeaturedClass(title, content)
	local titleText = plainLower(title)
	local contentText = plainLower(content)
	local allText = titleText .. "\n" .. contentText

	if contains(allText, "bucharest butchers")
		or contains(allText, "snubable enterprise")
		or contains(titleText, "snubable") then
		return "featured-bucharest"
	end

	if contains(titleText, "noord")
		or contains(contentText, "[[noord family")
		or contains(contentText, "[[category:noord family")
		or contains(contentText, "family = [[noord family")
		or contains(contentText, "|family=[[noord family") then
		return "featured-noord"
	end

	if contains(titleText, "paap")
		or contains(contentText, "[[paap family")
		or contains(contentText, "[[category:paap family")
		or contains(contentText, "family = [[paap family")
		or contains(contentText, "|family=[[paap family") then
		return "featured-paap"
	end

	if contains(titleText, "van hetten")
		or contains(contentText, "[[van hetten family")
		or contains(contentText, "[[category:van hetten family")
		or contains(contentText, "family = [[van hetten family")
		or contains(contentText, "|family=[[van hetten family") then
		return "featured-van-hetten"
	end

	if contains(titleText, "hoos")
		or contains(contentText, "[[hoos family")
		or contains(contentText, "[[category:hoos family")
		or contains(contentText, "family = [[hoos family")
		or contains(contentText, "|family=[[hoos family") then
		return "featured-hoos"
	end

	if contains(titleText, "schroeter")
		or contains(contentText, "[[schroeter family")
		or contains(contentText, "[[category:schroeter family")
		or contains(contentText, "family = [[schroeter family")
		or contains(contentText, "|family=[[schroeter family") then
		return "featured-schroeter"
	end

	if contains(allText, "tanoa einsatzgruppen")
		or contains(titleText, "tanoa")
		or contains(contentText, "[[category:tanoa")
		or contains(contentText, "[[tanoa") then
		return "featured-tanoa"
	end

	return ""
end

local function getFeaturedData()
	local pages = getPool()

	if #pages == 0 then
		return nil, "No featured pages defined."
	end

	local day = tonumber(os.date("%j")) or 1
	local index = ((day - 1) % #pages) + 1
	local title = pages[index]

	local page = mw.title.new(title)
	local lead = ""
	local image = nil
	local content = ""

	if page and page.exists then
		content = page:getContent() or ""
		lead = extractLeadFromContent(content)
		image = extractImageFromContent(content)
	end

	if lead == "" then
		lead = "Featured page for " .. os.date("%d %B %Y") .. "."
	end

	return {
		title = title,
		lead = lead,
		image = image,
		className = getFeaturedClass(title, content)
	}
end

local function makeImageBlock(data)
	if not data.image then
		return ""
	end

	return
		'<div class="featured-box-image-frame">' ..
		'[[' .. data.image .. '|frameless|160x160px|link=' .. data.title .. '|' .. data.title .. ']]' ..
		'</div>'
end

local function makeBoxClass(data)
	local className = "featured-box"

	if data and data.className and data.className ~= "" then
		className = className .. " " .. data.className
	end

	return className
end

function p.main(frame)
	local args = frame and frame.args or {}
	local data, err = getFeaturedData()

	if not data then
		return err
	end

	if args.titleonly == "1" then
		return data.title
	end

	if args.imageonly == "1" then
		return data.image or ""
	end

	if args.classonly == "1" then
		return data.className or ""
	end

	return
		makeStylesTag(frame) ..
		makeImageBlock(data) ..
		"'''[[" .. data.title .. "]]'''" ..
		'<div class="featured-box-lead">' ..
		data.lead ..
		'</div>'
end

function p.box(frame)
	local data, err = getFeaturedData()

	if not data then
		return
			makeStylesTag(frame) ..
			'<div class="featured-box">' ..
			'<div class="featured-box-title">Featured page</div>' ..
			'<div class="featured-box-body">' .. err .. '</div>' ..
			'</div>'
	end

	return
		makeStylesTag(frame) ..
		'<div class="' .. makeBoxClass(data) .. '">' ..
		'<div class="featured-box-title">Featured page</div>' ..
		'<div class="featured-box-body">' ..
		makeImageBlock(data) ..
		'<div class="featured-box-page-title">' ..
		"'''[[" .. data.title .. "]]'''" ..
		'</div>' ..
		'<div class="featured-box-lead">' .. data.lead .. '</div>' ..
		'<div class="featured-box-open">[[:' .. data.title .. '|Open page]]</div>' ..
		'</div>' ..
		'</div>'
end

return p