10,916
editsMore actions
Improve output of htmlList style.
No edit summary Tag: Reverted |
(Improve output of htmlList style.) |
||
(28 intermediate revisions by 3 users not shown) | |||
Line 2: | Line 2: | ||
local p = {} | local p = {} | ||
-- Config options, | -- Config options, set in main function | ||
local | local listDelimiters | ||
local | local makeElementsLinks | ||
local | local makeElementsPlural | ||
local | local makeElementsSingular | ||
local makeElementsLowercase | |||
local useTemplateOnElements | |||
local useTwoArgTemplateOnElements | |||
local textDelim | |||
local textLastDelim | |||
local function | local function splitListString(listString) | ||
local strings = {} | |||
for str in listString:gmatch("[^" .. listDelimiters .. "]+") do | |||
table.insert(strings, str:match("^%s*(.-)%s*$")) | |||
end | |||
return strings | |||
end | end | ||
-- This is a TWO-WAY conversion table of singular words and their corresponding | |||
-- plural form, for those that wouldn't be handled correctly by the automatic | |||
-- rules implemented further down below. Note that we don't need to cover most | |||
-- regular English words, as they're unlikely to ever be used with this module. | |||
-- The kind of stuff you want to add here is gameplay elements like classes, | |||
-- weapons, races, and so on. | |||
local specialPlurals = { | local specialPlurals = { | ||
-- Weapons | |||
Glaive = "Glaives", | |||
glaive = "glaives", | |||
Staff = "Staves", | |||
staff = "staves", | |||
-- Races | |||
Gith = "Gith", | |||
gith = "gith", | |||
Githyanki = "Githyanki", | |||
githyanki = "githyanki", | |||
Duergar = "Duergar", | |||
duergar = "duergar", | |||
Drow = "Drow", | |||
drow = "drow", | |||
Dragonborn = "Dragonborn", | |||
dragonborn = "dragonborn", | |||
-- Creature types | |||
Fey = "Fey", | |||
fey = "fey", | |||
Undead = "Undead", | |||
undead = "undead", | |||
} | } | ||
local function | -- Checks if str is equal to or ends in one of the keys in specialPlurals. | ||
-- Returns the pluralized version if so, otherwise nil. | |||
local function findSpecialPlural(str) | |||
if | for singular, plural in pairs(specialPlurals) do | ||
if str == singular then | |||
return plural | return plural | ||
end | end | ||
local len = #singular | |||
if | local suffix = str:sub(-len, -1) | ||
return | if (suffix == singular) then | ||
return str:sub(1, -len - 1) .. plural | |||
return str | end | ||
end | |||
end | |||
-- Checks if str is equal to or ends in one of the values in specialPlurals. | |||
-- Returns the singular version if so, otherwise nil. | |||
local function findSpecialSingular(str) | |||
for singular, plural in pairs(specialPlurals) do | |||
if str == plural then | |||
return singular | |||
end | |||
local len = #plural | |||
local suffix = str:sub(-len, -1) | |||
if suffix == plural then | |||
return str:sub(1, -len - 1) .. singular | |||
end | end | ||
end | end | ||
end | end | ||
local function | -- Checks for a special pluralization first, then implements these rules: | ||
local | -- ...f -> ...ves | ||
-- ...y -> ...ies | |||
-- ...s -> ...ses | |||
-- ...ch -> ...ches | |||
-- ...sh -> ...shes | |||
-- ... -> ...s | |||
local function makePlural(str) | |||
local sp = findSpecialPlural(str) | |||
if sp then | |||
return | return sp | ||
end | |||
local last1 = str:sub(-1) | |||
if last1 == "f" then | |||
local | return str:sub(1, -2) .. "ves" | ||
elseif last1 == "y" then | |||
result = result .. | return str:sub(1, -2) .. "ies" | ||
elseif last1 == "s" then | |||
result = result .. | return str .. "es" | ||
end | |||
local last2 = str:sub(-2) | |||
if last2 == "ch" or last2 == "sh" then | |||
return str .. "es" | |||
end | |||
return str .. "s" | |||
end | |||
-- Checks for a special singularization first, then implements these rules: | |||
-- ...ves -> ...f | |||
-- ...ies -> ...y | |||
-- ...ses -> ...s | |||
-- ...ches -> ...ch | |||
-- ...shes -> ...sh | |||
-- ...s -> ... | |||
-- ... -> ... | |||
local function makeSingular(str) | |||
local special = findSpecialSingular(str) | |||
if special then | |||
return special | |||
end | |||
local last3 = str:sub(-3) | |||
if last3 == "ves" then | |||
return str:sub(1, -4) .. "f" | |||
elseif last3 == "ies" then | |||
return str:sub(1, -4) .. "y" | |||
elseif last3 == "ses" then | |||
return str:sub(1, -3) | |||
end | |||
local last4 = str:sub(-4) | |||
if last4 == "ches" or last4 == "shes" then | |||
return str:sub(1, -3) | |||
end | |||
if str:sub(-1) == "s" then | |||
return str:sub(1, -2) | |||
end | |||
return str | |||
end | |||
-- Applies the various per-element transforms. Frame is needed for template | |||
-- expansion; it may be nil if template transforms won't be applied. | |||
local function processElement(str, frame) | |||
local original = str | |||
if makeElementsPlural then | |||
str = makePlural(str) | |||
elseif makeElementsSingular then | |||
str = makeSingular(str) | |||
end | |||
if makeElementsLowercase then | |||
str = str:lower() | |||
end | |||
if makeElementsLinks then | |||
return "[[" .. original .. "|" .. str .. "]]" | |||
elseif useTemplateOnElements then | |||
return frame:expandTemplate{ | |||
title = useTemplateOnElements, | |||
args = { str } | |||
} | |||
elseif useTwoArgTemplateOnElements then | |||
return frame:expandTemplate{ | |||
title = useTwoArgTemplateOnElements, | |||
args = { original, str } | |||
} | |||
end | |||
return str | |||
end | |||
-- These functions implement different output styles. The elements will have | |||
-- already gone through processElement() at this point, so they only need to be | |||
-- glued together to produce the desired style of listing format. | |||
local converters = { | |||
text = function (elements) | |||
local result = "" | |||
local count = #elements | |||
for i, str in ipairs(elements) do | |||
if i == 1 then | |||
result = str | |||
elseif i < count then | |||
result = result .. textDelim .. str | |||
else | |||
result = result .. textLastDelim .. str | |||
end | |||
end | |||
return result | |||
end, | |||
htmlList = function (elements) | |||
local result = "<ul>\n" | |||
for i, str in ipairs(elements) do | |||
result = result .. "<li>" .. str .. "</li>\n" | |||
end | |||
return result .. "</ul>" | |||
end, | |||
tableList = function (elements) | |||
local result = "<div class=\"bg3wiki-tablelist\">" | |||
for i, str in ipairs(elements) do | |||
result = result .. str .. "\n" | |||
end | |||
return result .. "</div>" | |||
end, | |||
htmlListNoBullets = function (elements) | |||
local result = "<ul style='list-style: none; margin: 0;'>\n" | |||
for i, str in ipairs(elements) do | |||
result = result .. "<li>" .. str .. "</li>\n" | |||
end | |||
return result .. "</ul>" | |||
end, | |||
simpleList = function (elements) | |||
local result = "" | |||
local first = true | |||
for i, str in ipairs(elements) do | |||
if first then | |||
result = str | |||
first = false | |||
else | |||
result = result .. ", " .. str | |||
end | |||
end | end | ||
return result | |||
end, | |||
} | |||
function p.main(frame) | |||
local args = getArgs(frame, { frameOnly = true }) | |||
return p._main(args, frame) | |||
end | end | ||
function p. | -- Frame is needed for template expansion; may be nil if the useTemplate and | ||
-- useTemplate2 args are nil. | |||
function p._main(args, frame) | |||
listDelimiters = args['delimiter'] or "," | |||
makeElementsLinks = args['makeLinks'] | |||
makeElementsPlural = args['makePlural'] | |||
makeElementsSingular = args['makeSingular'] | |||
makeElementsLowercase = args['makeLowercase'] | |||
useTemplateOnElements = args['useTemplate'] | |||
useTwoArgTemplateOnElements = args['useTemplate2'] | |||
textDelim = args['textDelim'] | |||
if textDelim then | |||
textLastDelim = args['textLastDelim'] or textDelim | |||
else | |||
textDelim = ', ' | |||
textLastDelim = args['textLastDelim'] or ', and ' | |||
end | |||
local style = args['style'] or args['type'] or 'text' | |||
local converter = converters[style] | |||
local elements = {} | |||
local listString = args[1] | |||
local strings = splitListString(listString) | |||
for i, str in ipairs(strings) do | |||
table.insert(elements, processElement(str, frame)) | |||
end | |||
return converter(elements) | |||
end | end | ||
return p | return p |