Module:BuildingLink: Difference between revisions

From Against the Storm Official Wiki
(Changed NBSP to regular space)
(New version of building links using external view and with more flexibility)
Line 1: Line 1:
---
--- This module renders the {{Building_link}} template.
--- https://hoodedhorse.com/wiki/Against_the_Storm/Template:Building_link
---
--- The template #invokes BuildingLink.renderLink(frame), below.
---
--- The template requires an argument, the name of the building to link to.
--- Optionally, the template accepts a second argument to render an icon next
--- to the link. The building is passed to Module:WorkshopsData, which is used
--- to identify the wiki page to link to.
---
--- Using the data returned, this module creates an icon and the name of the
--- building, and wraps both in a link to the building's wiki page. If no icon
--- size is specified, only the name of the building will be rendered by the
--- template.
---
--- The icons are sized consistently by using existing wiki templates,
--- {{ImgS}}, {{ImgM}}, etc. The sizes of the icons are not stored or known by
--- this module.
---
--- @module BuildingLink
--- @module BuildingLink
local BuildingLink = {}
local BuildingLink = {}
Line 24: Line 4:




local WorkshopsData = require("Module:WorkshopsData")
--region Dependencies
local InstitutionsData = require("Module:InstitutionsData")
local FarmsData = require("Module:FarmsData")
local CampsData = require("Module:CampsData")
local CollectorsData = require("Module:CollectorsData")


-- This module lazily loads dependencies, since they're expensive but only one is needed, we just don't know which in advance.
local WorkshopsData
local InstitutionsData
local FarmsData
local CampsData
local CollectorsData


local VIEW_TEMPLATE = "Building_link/view"


--region Private constants
--endregion


local DEFAULT_SIZE_SMALL = "small"


local ICON_SIZES = {
[DEFAULT_SIZE_SMALL] = mw.getCurrentFrame():expandTemplate{ title = "ImgS" },
["med"] = mw.getCurrentFrame():expandTemplate{ title = "ImgM" },
["large"] = mw.getCurrentFrame():expandTemplate{ title = "ImgL" },
["huge"] = mw.getCurrentFrame():expandTemplate{ title = "ImgH" }
}


local SPACE = " "
--region Private constants


--endregion
--endregion
Line 49: Line 25:




--region Public methods
--region Private methods
 
local function tryData(name, buildingInterface)
 
local buildingID = buildingInterface.getID(name)


---
return buildingInterface.getIcon(buildingID)
--- Renders an icon and the name of a building linked to a wiki page
end
--- corresponding to the provided building.
---
--- Uses MediaWiki markup to display the name of a wiki page and an icon that
--- has been uploaded to the wiki. Both must be known by the data model,
--- or the template's behavior may be different than expected.
---
--- @param frame table the template's calling context, with parameters
--- @return string wiki markup
function BuildingLink.renderLink(frame)


-- Extract the template parameters.
local argBuildingName = frame.args.building
local argIconSize = frame.args.iconsize


-- Validate that there's a name to use.
if not argBuildingName or "" == argBuildingName then
return "The Building Link template requires the a name of a building."
end


-- Look up the icon from the data sources. This validates that the building
local function validateBuildingName(name)
-- name that was provided is spelled correctly and, if used, will link into
-- a valid page.
local iconFilename


local workshopIconFilename = WorkshopsData.getWorkshopIcon(argBuildingName)
-- Lazy-load of external data, since it's expensive. Start with the most likely so that most pages load as fast as possible.
if workshopIconFilename then
WorkshopsData = require("Module:WorkshopsData")
iconFilename = workshopIconFilename
local validatedIcon = tryData(name, WorkshopsData)
else
if not validatedIcon then
local InstitutionIconFilename = InstitutionsData.getInstitutionIcon(argBuildingName)
InstitutionsData = require("Module:InstitutionsData")
if InstitutionIconFilename then
validatedIcon = tryData(name, InstitutionsData)
iconFilename = InstitutionIconFilename
if not validatedIcon then
else
FarmsData = require("Module:FarmsData")
local FarmIconFilename = FarmsData.getFarmIcon(argBuildingName)
validatedIcon = tryData(name, FarmsData)
if FarmIconFilename then
if not validatedIcon then
iconFilename = FarmIconFilename
CollectorsData = require("Module:CollectorsData")
else
validatedIcon = tryData(name, CollectorsData)
local CampIconFilename = CampsData.getCampIcon(argBuildingName)
if not validatedIcon then
if CampIconFilename then
CampsData = require("Module:CampsData")
iconFilename = CampIconFilename
validatedIcon = tryData(name, CampsData)
else
if not validatedIcon then
local CollectorIconFilename = CollectorsData.getCollectorIcon(argBuildingName)
error("No building found with name: " .. name .. ".")
if CollectorIconFilename then
iconFilename = CollectorIconFilename
else
return "No building found with provided name: " .. argBuildingName .. "."
end
end
end
end
Line 104: Line 61:
end
end


-- Wiki link to the building's page just uses the in-game name.
return validatedIcon
local linkPart = "[[" .. argBuildingName .. "]]"
end
 
--endregion
 
 
 
--region Public methods
 
---main
--- Extracts parameters, validates the building by getting its icon, and then sends the data to the view template for rendering.
---
--- @param frame table the template's context, with arguments
--- @return string wiki markup
function BuildingLink.main(frame)
 
local name = frame.args.name
local iconSize = frame.args.size
local needsPlural = frame.args.plural
local display = frame.args.display


-- If the specified size is small, skip the icon.
-- If the iconSize was not specified, but plural was, then these will match. We need to unset the iconSize to be default.
if argIconSize == DEFAULT_SIZE_SMALL then
if iconSize == needsPlural then
return linkPart
iconSize = nil
end
end


local size = ICON_SIZES[argIconSize]
-- It is valid by now; the above method already threw an error if not.
validatedIcon = validateBuildingName(name)


-- If the specified size was invalid, skip the icon.
-- The only valid value for mustBePlural is "s," so then make on check to see if name ends in a way that we need to add "es" at the end instead of just "s". For names that end in "y", we swap out the last character for "ies" instead. (This will require one-time setup for redirect pages.)
if not size then
if needsPlural == "s" or needsPlural == "es" then
return linkPart
if string.match(name, "y$") then
name = string.sub(name, 1, -2) .. "ies"
needsPlural = nil -- unset, since it's incorporated into the name
else
local needsSyllable = string.match(name, "[sxz]$") or string.match(name, "sh$") or string.match(name, "ch$")
needsPlural = needsSyllable and "es" or "s"
end
else
needsPlural = nil
end
end


local iconPart = "[[File:" .. iconFilename .. "|" .. size ..
viewParameters = {
"|link=" .. argBuildingName .. "|alt=" .. argBuildingName .. "|" .. argBuildingName .. "]]"
["name"] = name,
["plural"] = needsPlural,
["iconfilename"] = validatedIcon,
["iconsize"] = iconSize,
["display"] = display,
}


-- combine the file part with the link part
return frame:expandTemplate{
return iconPart .. SPACE .. linkPart
title = VIEW_TEMPLATE,
args = viewParameters,
}
end
end



Revision as of 01:45, 15 October 2024

Documentation for this module may be created at Module:BuildingLink/doc

--- @module BuildingLink
local BuildingLink = {}



--region Dependencies

-- This module lazily loads dependencies, since they're expensive but only one is needed, we just don't know which in advance.
local WorkshopsData
local InstitutionsData
local FarmsData
local CampsData
local CollectorsData

local VIEW_TEMPLATE = "Building_link/view"

--endregion



--region Private constants

--endregion



--region Private methods

local function tryData(name, buildingInterface)

	local buildingID = buildingInterface.getID(name)

	return buildingInterface.getIcon(buildingID)
end



local function validateBuildingName(name)

	-- Lazy-load of external data, since it's expensive. Start with the most likely so that most pages load as fast as possible.
	WorkshopsData = require("Module:WorkshopsData")
	local validatedIcon = tryData(name, WorkshopsData)
	if not validatedIcon then
		InstitutionsData = require("Module:InstitutionsData")
		validatedIcon = tryData(name, InstitutionsData)
		if not validatedIcon then
			FarmsData = require("Module:FarmsData")
			validatedIcon = tryData(name, FarmsData)
			if not validatedIcon then
				CollectorsData = require("Module:CollectorsData")
				validatedIcon = tryData(name, CollectorsData)
				if not validatedIcon then
					CampsData = require("Module:CampsData")
					validatedIcon = tryData(name, CampsData)
					if not validatedIcon then
						error("No building found with name: " .. name .. ".")
					end
				end
			end
		end
	end

	return validatedIcon
end

--endregion



--region Public methods

---main
--- Extracts parameters, validates the building by getting its icon, and then sends the data to the view template for rendering.
---
--- @param frame table the template's context, with arguments
--- @return string wiki markup
function BuildingLink.main(frame)

	local name = frame.args.name
	local iconSize = frame.args.size
	local needsPlural = frame.args.plural
	local display = frame.args.display

	-- If the iconSize was not specified, but plural was, then these will match. We need to unset the iconSize to be default.
	if iconSize == needsPlural then
		iconSize = nil
	end

	-- It is valid by now; the above method already threw an error if not.
	validatedIcon = validateBuildingName(name)

	-- The only valid value for mustBePlural is "s," so then make on check to see if name ends in a way that we need to add "es" at the end instead of just "s". For names that end in "y", we swap out the last character for "ies" instead. (This will require one-time setup for redirect pages.)
	if needsPlural == "s" or needsPlural == "es" then
		if string.match(name, "y$") then
			name = string.sub(name, 1, -2) .. "ies"
			needsPlural = nil -- unset, since it's incorporated into the name
		else
			local needsSyllable = string.match(name, "[sxz]$") or string.match(name, "sh$") or string.match(name, "ch$")
			needsPlural = needsSyllable and "es" or "s"
		end
	else
		needsPlural = nil
	end

	viewParameters = {
		["name"] = name,
		["plural"] = needsPlural,
		["iconfilename"] = validatedIcon,
		["iconsize"] = iconSize,
		["display"] = display,
	}

	return frame:expandTemplate{
		title = VIEW_TEMPLATE,
		args = viewParameters,
	}
end

--endregion

return BuildingLink