Changes

Jump to navigation Jump to search
local p = {}
local private = {}

--##########
--## Constants
--##########
-- The valid status values.
local statuses = {
ok = "ok",
summary = "optional",
unofficial = "unofficial",
workaround = "workaround",
broken = "broken",
abandoned = "abandoned",
obsolete = "obsolete"
}


--##########
--## Public functions
--##########
--- Render a mod row in the SMAPI compatibility table.
-- @param frame The arguments passed to the script.
-- @test p.entry({ args = { name="Lookup Anything", name2="LookupAnything", author="Pathoschild", author2="Pathos", id="Pathoschild.LookupAnything", ["old ids"]="LookupAnything", ["nexus id"]="541", ["cf id"]="4250", ["github"]="Pathoschild/StardewMods", warnings="warning A, warning B", links="https://google.ca" }})
function p.entry(frame)
-- read input args
local names = private.parseCommaDelimited((private.trim(frame.args["name"]) or '') .. ',' .. (private.trim(frame.args["name2"]) or ''))
local authors = private.parseCommaDelimited((private.trim(frame.args["author"]) or '') .. ',' .. (private.trim(frame.args["author2"]) or ''))
local ids = private.parseCommaDelimited((private.trim(frame.args["id"]) or '') .. ',' .. (private.trim(frame.args["old ids"]) or ''))
local nexusID = private.emptyToNil(private.trim(frame.args["nexus id"]))
local github = private.emptyToNil(private.trim(frame.args["github"]))
local summary = private.emptyToNil(private.trim(frame.args["summary"]))
local brokeIn = private.emptyToNil(private.trim(frame.args["broke in"]))

local status = private.emptyToNil(private.trim(frame.args["status"]))
local unofficialVersion = private.emptyToNil(private.trim(frame.args["unofficial version"]))
local unofficialUrl = private.emptyToNil(private.trim(frame.args["unofficial url"]))
local oldIDs = private.emptyToNil(private.trim(frame.args["old ids"]))
local chucklefishID = private.emptyToNil(private.trim(frame.args["cf id"]))
local customUrl = private.emptyToNil(private.trim(frame.args["url"]))
local customSource = private.emptyToNil(private.trim(frame.args["source"]))
local name2 = private.emptyToNil(private.trim(frame.args["name2"]))
local author2 = private.emptyToNil(private.trim(frame.args["author2"]))
local links = private.parseCommaDelimited(frame.args["links"])
local warnings = private.parseCommaDelimited(frame.args["warnings"])

local betaSummary = private.emptyToNil(private.trim(frame.args["beta summary"]))
local betaBrokeIn = private.emptyToNil(private.trim(frame.args["beta broke in"]))
local betaStatus = private.emptyToNil(private.trim(frame.args["beta status"]))
local betaUnofficialVersion = private.emptyToNil(private.trim(frame.args["beta unofficial version"]))
local betaUnofficialUrl = private.emptyToNil(private.trim(frame.args["beta unofficial url"]))

-- parse compatibility
local compat = private.getCompatInfo(status, summary, brokeIn, unofficialVersion, unofficialUrl)
local betaCompat = nil
if betaStatus or betaBrokeIn or betaUnofficialUrl or betaUnofficialVersion then
betaCompat = private.getCompatInfo(betaStatus, betaSummary, betaBrokeIn, betaUnofficialVersion, betaUnofficialUrl)
end

-- get main URL
local url = nil
if nexusID then
url = "https://www.nexusmods.com/stardewvalley/mods/" .. mw.uri.encode(nexusID, "PATH")
elseif chucklefishID then
url = "https://community.playstarbound.com/resources/" .. mw.uri.encode(chucklefishID, "PATH")
else
url = customUrl
end

-- get source url
local sourceUrl = customSource
if github then
sourceUrl = "https://github.com/" .. string.gsub(mw.uri.encode(github, "PATH"), "%%2F", "/")
end

-- get background color
local background = '#999'
if status == statuses.ok or status == statuses.optional then
background = '#9F9'
elseif status == statuses.workaround or statuses.unofficial then
background = '#CF9'
elseif status == statuses.broken then
background = '#F99'
elseif status == statuses.obsolete or status == statuses.abandoned then
background = '#999'
end

-- build HTML row
local row = mw.html.create("tr")
row:addClass("mod")
row:attr("id", names[1] and mw.uri.anchorEncode(names[1]) or nil);
row:attr("data-name", table.concat(names, ","))
row:attr("data-id", table.concat(ids, ","))
row:attr("data-author", table.concat(authors, ","))
row:attr("data-url", url)
row:attr("data-nexus-id", nexusID)
row:attr("data-cf-id", chucklefishID)
row:attr("data-github", github)
row:attr("data-custom-source", customSource)
row:attr("data-status", compat.status)
row:attr("data-summary", compat.summary)
row:attr("data-broke-in", compat.brokeIn)
row:attr("data-unofficial-version", compat.unofficialVersion)
row:attr("data-unofficial-url", compat.unofficialUrl)
row:attr("data-beta-status", betaCompat and betaCompat.status or nil)
row:attr("data-beta-summary", betaCompat and betaCompat.summary or nil)
row:attr("data-beta-broke-in", betaCompat and betaCompat.brokeIn or nil)
row:attr("data-beta-unofficial-version", betaCompat and betaCompat.unofficialVersion or nil)
row:attr("data-beta-unofficial-url", betaCompat and betaCompat.unofficialUrl or nil)
row:attr("data-warnings", private.emptyToNil(table.concat(warnings, ",")))
row:attr("style", "line-height: 1em; background: " .. background .. ";")
row:newline()

-- add name field
do
local field = mw.html.create("td")
field:wikitext("[" .. url .. " " .. names[1] .. "]")

if #names > 1 then
local altNames = mw.html.create("small"):wikitext("(aka ")
for k, v in pairs(names) do
if k > 1 then
altNames:wikitext(v)
end
end
altNames:wikitext(")")
field:node(mw.html.create("br"))
field:node(altNames)
end

row:node(field)
row:newline()
end

-- add author field
do
local field = mw.html.create("td")

field:wikitext(authors[1])
if #authors > 1 then
local altNames = mw.html.create("small"):wikitext("(aka ")
for k, v in pairs(authors) do
if k > 1 then
altNames:wikitext(v)
end
end
altNames:wikitext(")")
field:node(mw.html.create("br"))
field:node(altNames)
end

row:node(field)
row:newline()
end

-- add summary field
do
local field = mw.html.create("td")

-- stable status
field:wikitext(compat.summaryIcon .. " " .. compat.summary)
if compat.status == statuses.optional then
field:wikitext("<ref name=\"optional-update\" />")
end

-- beta status
if betaCompat ~= nill then
field:node(mw.html.create("br"))
field:wikitext("'''SDV beta only:''' " .. betaCompat.summaryIcon .. " " .. betaCompat.summary)
if betaCompat.status == statuses.optional then
field:wikitext("<ref name=\"optional-update\" />")
end
end

-- warnings
if #warnings > 0 then
for k, v in pairs(warnings) do
field:node(mw.html.create("br"))
field:wikitext("⚠ " .. v)
end
end

row:node(field)
row:newline()
end

-- add 'broke in' field
do
local field = mw.html.create("td")

if betaCompat ~= nil and betaCompat.brokeIn ~= nil then
field:wikitext(betaCompat.brokeIn)
elseif compat.brokeIn ~= nil then
field:wikitext(compat.brokeIn)
end

row:node(field)
row:newline()
end

-- add 'source' field
do
local field = mw.html.create("td")

if sourceUrl then
field:wikitext("[" .. sourceUrl .. " source]")
else
field:wikitext("<span style=\"color: red; font-size: 0.85em; opacity: 0.5;\">closed source</span>")
end

row:node(field)
row:newline()
end

-- add metadata field
do
local field = mw.html.create("td")
field:attr("style", "font-size: 0.8em")

-- anchor
field:wikitext("[[#" .. names[1] .. "|#]] ")

-- reference links
for k, v in pairs(links) do
field:wikitext("[" .. v .. " " .. k .. "] ")
end

-- 'no id' warning
if #ids == 0 then
field:wikitext("⚠ no id")
end

-- backwards-compatible metadata (temporary)
local metadata = mw.html.create("div")
metadata:addClass("mod-metadata")
metadata:attr("style", "display: none;")
metadata:node(mw.html.create("div"):addClass("mod-anchor"):wikitext(names[1] and mw.uri.anchorEncode(names[1]) or nil))
metadata:node(mw.html.create("div"):addClass("mod-id"):wikitext(table.concat(ids, ",")))
metadata:node(mw.html.create("div"):addClass("mod-url"):wikitext(url))
if nexusID ~= nil then
metadata:node(mw.html.create("div"):addClass("mod-nexus-id"):wikitext(nexusID))
end
if chucklefishID ~= nil then
metadata:node(mw.html.create("div"):addClass("mod-cf-id"):wikitext(chucklefishID))
end
if github ~= nil then
metadata:node(mw.html.create("div"):addClass("mod-github"):wikitext(github))
end
if customSource ~= nil then
metadata:node(mw.html.create("div"):addClass("mod-custom-source"):wikitext(customSource))
end
metadata:node(mw.html.create("div"):addClass("mod-status"):wikitext(compat.status))
if compat.brokeIn ~= nil then
metadata:node(mw.html.create("div"):addClass("mod-broke-in"):wikitext(compat.brokeIn))
end
if compat.unofficialVersion ~= nil and compat.unofficialUrl ~= nil then
metadata:node(mw.html.create("div"):addClass("mod-unofficial-version"):wikitext(compat.unofficialVersion))
metadata:node(mw.html.create("div"):addClass("mod-unofficial-url"):wikitext(compat.unofficialUrl))
end
if betaCompat ~= nil then
metadata:node(mw.html.create("div"):addClass("mod-beta-status"):wikitext(betaCompat.status))
if betaCompat.brokeIn ~= nil then
metadata:node(mw.html.create("div"):addClass("mod-beta-broke-in"):wikitext(betaCompat.brokeIn))
end
if betaCompat.unofficialVersion ~= nil and betaCompat.unofficialUrl ~= nil then
metadata:node(mw.html.create("div"):addClass("mod-beta-unofficial-version"):wikitext(betaCompat.unofficialVersion))
metadata:node(mw.html.create("div"):addClass("mod-beta-unofficial-url"):wikitext(betaCompat.unofficialUrl))
end
end
if #warnings > 0 then
metadata:node(mw.html.create("div"):addClass("mod-warnings"):wikitext(table.concat(warnings, ",")))
end

field:node(metadata)
row:node(field)
end

mw.log(tostring(row))
end


--##########
--## Private functions
--##########
-- Get the normalised compatibility info for a mod.
-- @param status The specified status code (one of the `statuses` values). If nil or blank, it'll be derived from the other fields.
-- @param summary A human-readable summary of the compatibility info. If nil or blank, it'll be derived from the other fields.
-- @param brokeIn The SMAPI or Stardew Valley version which broke the mod, if applicable.
-- @param unofficialVersion The unofficial version which fixes compatibility, if applicable.
-- @param unofficialUrl The URL for the unofficial version which fixes compatibility, if applicable.
-- @param hasSource Whether the mod has public source code available.
function private.getCompatInfo(status, summary, brokeIn, unofficialVersion, unofficialUrl, hasSource)
-- normalise values
status = private.emptyToNil(private.trim(status))
summary = private.emptyToNil(private.trim(summary))
brokeIn = private.emptyToNil(private.trim(brokeIn))
unofficialVersion = private.emptyToNil(private.trim(unofficialVersion))
unofficialUrl = private.emptyToNil(private.trim(unofficialUrl))

-- derive status
if status == nil then
if unofficialVersion ~= nil then
status = statuses.unofficial
elseif brokeIn ~= nil then
status = statuses.broken
else
status = statuses.ok
end
end

-- derive summary icon
local summaryIcon = "✓"
if status == statuses.unofficial or status == statuses.workaround then
summaryIcon = "⚠"
elseif status == statuses.broken and hasSource then
summaryIcon = "↻"
elseif status == statuses.broken or status == statuses.obsolete or status == statuses.abandoned then
summaryIcon = "✖"
end

-- derive summary
if summary == nil then
if status == statuses.ok then
summary = "use latest version."
elseif status == statuses.optional then
summary = "use optional download."
elseif status == statuses.unofficial then
summary = "broken, use [" .. (unofficialUrl or "") .. " " .. "unofficial version]"
if unofficialVersion ~= nil then
summary = summary .. " (<small>" .. unofficialVersion .. "</small>)"
end
summary = summary .. "."
elseif status == statuses.workaround then
summary = "broken. '''error:''' should specify summary."
elseif status == statuses.broken then
if hasSource then
summary = "broken, not updated yet."
else
summary = "broken, not open-source."
end
elseif status == statuses.obsolete then
summary = "obsolete."
elseif status == statuses.abandoned then
summary = "no longer maintained."
else
summary = "'''error:''' unknown status '" .. status .. "'."
end
end

return {
status = status,
summaryIcon = summaryIcon,
summary = summary,
brokeIn = brokeIn,
unofficialVersion = unofficialVersion,
unofficialUrl = unofficialUrl
}
end

-- Trim a string value.
-- @param value The string to trim.
function private.trim(value)
if value ~= nil then
return mw.text.trim(value)
else
return value
end
end

-- Get a nil value if the specified value is an empty string, else return the value unchanged.
-- @param value The string to check.
function private.emptyToNil(value)
if value ~= "" then
return value
else
return nil
end
end

-- Parse a comma-delimited string into an array.
-- @param value The string to parse.
function private.parseCommaDelimited(value)
local result = {}

if value ~= nil then
for k, v in pairs(mw.text.split(value, ",", true)) do
v = mw.text.trim(v)
if v ~= "" then
table.insert(result, v)
end
end
end

return result
end

return p
translators
8,445

edits

Navigation menu