Modül:Location
Methods for managing location data storage and formatting.
location.parseList(list)(function)- Parses a list of locations, usually from infoboxes, into a quintuplet of
{name, hash, text, hasLink}, wherenameis the page name,hashis the section of that page,textis the text in parenthesis after the link, andhasLinkis set totrueif the original text has a link. Examples: - Parameter:
listList of locations to parse (string) - Returns: List of aforementioned quintuplets (table)
location.formatList(list)(function)- Formats a list returned by
location. parseListinto a bullet point list for display in the infobox. - Parameter:
list{name, hash, text, hasLink}quadruplets for each location list item (table) - Returns: Formatted bullet point list with links (string)
location.storeListMetadata(list, frame)(function)- Returns all categories that a page should be categorized under based on its location list in the infobox.
- Parameters:
- Returns: Categories that the page should be under (string)
location.format()(function)- Formats a list of locations in an infobox and categorizes the page under appropriate categories.
- Returns: Formatted list with categories (string)
location.storeData(frame)(function)- Categorizes a location page under Category:Locations, as well as under a category named by itself, if it exists.
- Parameter:
frameScribunto's frame object (table) - Returns: Location's categories (string)
location.minigame(frame)(function)- Categorizes a minigame page under Category:Minigames, as well as under all the category pages that location pages are usually categorized under, if the
categoryparameter has been passed. - Parameter:
frameScribunto's frame object (table) - Returns: Minigame's categories (string)
--- Methods for managing location data storage and formatting.
-- @module location
-- @require Module:Util
-- @author [[User:KockaAdmiralac|KockaAdmiralac]]
-- @author [[User:Jacky720|Jacky720]]
-- <nowiki>
require('strict')
local location = {}
-- Package imports.
local util = require('Module:Util')
local infoboxData = mw.loadData('Module:Infobox/data')
-- Package variables.
local title = mw.title.getCurrentTitle()
local bucket = mw.ext.bucket
local LOCATION_PATTERNS = {
-- [[Card Castle]] (Jevil)
{'^%[%[([^%]]+)%]%]%s*%(([^)]*)%)?$', true},
-- [[Card Castle]]
{'^%[%[([^%]]+)%]%]$', true},
-- Card Castle (Jevil)
{'^([^(]+)%s*%(([^)]+)%)$'},
}
-- Private logic.
local function mergeTables(destination, source)
for _, item in ipairs(source) do
table.insert(destination, item)
end
end
local function getLocationCategories(name)
local locations = mw.loadData('Module:Location/locations')
local locationData = locations[name]
if not locationData then
return {}
end
if locationData.category then
return {string.format('[[%s]]', locationData.category)}
end
local categories = {}
for _, parentLocation in ipairs(locationData.locations) do
mergeTables(categories, getLocationCategories(parentLocation))
end
return categories
end
-- Package items.
--- Parses a list of locations, usually from infoboxes, into a quintuplet of
-- <code>{name, hash, text, hasLink}</code>, where <code>name</code> is the
-- page name, <code>hash</code> is the section of that page, <code>text</code>
-- is the text in parenthesis after the link, and <code>hasLink</code> is set
-- to <code>true</code> if the original text has a link.
-- Examples:
-- <pre>Card Castle → {'Card Castle', nil, nil}</pre>
-- <pre>[[Card Castle]] → {'Card Castle', nil, nil, true}</pre>
-- <pre>Card Castle#F1 → {'Card Castle', 'F1', 'F1'}</pre>
-- <pre>Card Castle#F1 (unused) → {'Card Castle', 'F1', 'F1, unused'}</pre>
-- <pre>[[Island Board (Original Game)]] → {'Island Board (Original Game)', nil, nil, true}</pre>
-- @function location.parseList
-- @param {string} list List of locations to parse
-- @returns {table} List of aforementioned quintuplets
function location.parseList(list)
local locations = {}
local locationData = mw.loadData('Module:Location/locations')
for line in mw.text.gsplit(list, '*', true) do
line = mw.text.trim(line)
if line ~= '' then
-- Match the line against several patterns to extract the link and
-- description text separately, and note down if the link was already
-- inserted.
local link, text, pattern, hasLink
for _, attempt in ipairs(LOCATION_PATTERNS) do
pattern, hasLink = unpack(attempt)
link, text = mw.ustring.match(line, pattern)
if link ~= nil then
break
end
end
-- If none of the patterns matched, we assume the whole line is a potential
-- link, with no description text.
if link == nil then
link = line
end
link = mw.text.trim(link)
local name, hash
-- Attempt to split the link into the main and hash part.
if mw.ustring.find(link, '|', 0, true) then
-- Our hash splitting breaks links like:
-- [[Cyber World/Puzzles#The puzzle|Cyber Field]]
name = link
else
name, hash = unpack(mw.text.split(link, '#', true))
end
if hash then
-- Hash should be displayed in the description text too.
if text and text ~= '' then
text = string.format('%s, %s', hash, text)
else
text = hash
end
else
hash = ''
if not text then
text = ''
end
end
if not hasLink then
if locationData[name] or infoboxData.locations[name] then
hasLink = true
else
hasLink = false
end
end
table.insert(locations, {name, hash, text, hasLink})
end
end
return locations
end
--- Formats a list returned by <code>location.parseList</code> into a bullet
-- point list for display in the infobox.
-- @function location.formatList
-- @param {table} list <code>{name, hash, text, hasLink}</code>
-- quadruplets for each location list item
-- @returns {string} Formatted bullet point list with links
function location.formatList(list)
local formattedList = {}
for _, loc in ipairs(list) do
local name, hash, text, hasLink = unpack(loc)
if hasLink then
if hash ~= '' then
-- [[Card Castle#F1|Card Castle]] (F1)
table.insert(formattedList, string.format(
'[[%s#%s|%s]] (%s)',
name, hash, name, text
))
elseif text ~= '' then
table.insert(formattedList, string.format(
'[[%s]] (%s)',
name, text
))
else
table.insert(formattedList, string.format('[[%s]]', name))
end
else
if hash ~= '' then
table.insert(formattedList, string.format(
'%s#%s (%s)',
name, hash, text
))
elseif text ~= '' then
table.insert(formattedList, string.format('%s (%s)', name, text))
else
table.insert(formattedList, name)
end
end
end
return util.formatBulletList(formattedList)
end
--- Returns all categories that a page should be categorized under based on its
-- location list in the infobox.
-- @function location.storeListMetadata
-- @param {table} list List from <code>location.parseList</code>
-- @param {table} frame Scribunto frame object
-- @returns {string} Categories that the page should be under
function location.storeListMetadata(list, frame)
if title.namespace ~= 0 then
return ''
end
local categories = {}
local pages = {}
for _, loc in ipairs(list) do
local name, _, _, hasLink = unpack(loc)
if hasLink then
table.insert(pages, name)
end
if name == 'Unused' then
table.insert(categories, '[[Category:Unused items]]')
elseif infoboxData.locations[name] then
local legacyCategories = infoboxData.locations[name].categories or {}
for _, category in ipairs(legacyCategories) do
table.insert(categories, string.format('[[Category:%s]]', category))
end
else
mergeTables(categories, getLocationCategories(name))
end
end
bucket('located').put({
entity = frame:getParent().args.name or title.text,
location = pages,
})
return table.concat(categories)
end
--- Formats a list of locations in an infobox and categorizes the page under
-- appropriate categories.
-- @function location.format
-- @returns {string} Formatted list with categories
function location.format(frame)
local parsedList = location.parseList(frame.args[1])
local formattedList = location.formatList(parsedList)
local metadata = location.storeListMetadata(parsedList, frame)
return formattedList .. metadata
end
--- Categorizes a location page under [[:Category:Locations]], as well as under
-- a category named by itself, if it exists.
-- @function location.storeData
-- @param {table} frame Scribunto's frame object
-- @returns {string} Location's categories
function location.storeData(frame, addCategory)
if title.namespace ~= 0 then
return
end
local args = frame:getParent().args
local cats = {'[[Category:Locations]]'}
if addCategory then
table.insert(cats, addCategory)
end
local category = args.category
if category then
local sortkey = category
if category == title.text then
sortkey = '*'
end
category = string.format('Category:%s', category)
table.insert(cats, string.format('[[%s|%s]]', category, sortkey))
end
bucket('location').put({
name = args.name or title.text,
image = args.image,
chapter = tonumber(args.chapter),
category = category,
})
return table.concat(cats)
end
--- Categorizes a minigame page under [[:Category:Minigames]], as well as under
-- all the category pages that location pages are usually categorized under, if
-- the <code>category</code> parameter has been passed.
-- @function location.minigame
-- @param {table} frame Scribunto's frame object
-- @returns {string} Minigame's categories
function location.minigame(frame)
if title.namespace ~= 0 then
return
end
if not frame:getParent().args.category then
return '[[Category:Minigames]]'
end
return location.storeData(frame, '[[Category:Minigames]]')
end
return location
-- </nowiki>