Module:ConfigRepository
Documentation for this module may be created at Module:ConfigRepository/doc
--[=[<%-- [PAGE_INFO]
pageTitle = #Module:ConfigRepository#
[END_PAGE_INFO] --%>]=]
-- Module:ConfigRepository
-- Single source of truth for all template configurations across the ICANNWiki ecosystem
-- Implements stop-gaps:
-- ▸ Hoist singletons (NormalizationDate & CanonicalForms)
-- ▸ Load big constant tables via mw.loadData
--
-- Works with the Template Blueprint Framework to power rendering & semantic processing
local p = {}
-- Stop-gap A: hoist singletons
local DateFmt = require('Module:NormalizationDate')
local CanonicalForms = require('Module:CanonicalForms')
-- Stop-gap B: load large tables externally
local ClassicTLDs = mw.loadData('Module:ConfigRepository/Data/ClassicTLDs')
------------------------------------------------------------------------------
-- Global Constants and Properties
------------------------------------------------------------------------------
p.fieldLabels = {
region = "Region",
country = "Country",
date = "Date",
website = "Website",
}
p.dateFormatting = {
useShortMonthNames = true
}
p.semanticProperties = {
region = "Has ICANN region",
country = "Has country",
language = "Knows language",
person = "Has person",
}
------------------------------------------------------------------------------
-- TEMPLATE-SPECIFIC CONFIGURATIONS
------------------------------------------------------------------------------
p.templates = {}
------------------------------------------------------------------------------
-- ANCHOR: EVENT TEMPLATE
------------------------------------------------------------------------------
p.templates.Event = {
meta = { description = "Module for rendering Event templates, including next/previous navigation" },
categories = { base = {"Events"} },
patterns = {
seriesNumber = "^([%w%s]+)%s+(%d+)$", -- e.g., "ICANN 76"
seriesYear = "^([%w%s]+)%s+(%d%d%d%d)$" -- e.g., "IGF 2023"
},
fields = {
{key="logo" , label="Logo"},
{key="process" , label="Process"},
{key="start" , label="Start Date"},
{key="end" , label="End Date"},
{key="region" , label=p.fieldLabels.region},
{keys={"country","territory"}, label=p.fieldLabels.country},
{key="city" , label="City"},
{key="venue" , label="Venue"},
{key="organizer", label="Organizer"},
{keys={"website","url"}, label=p.fieldLabels.website},
{keys={"subject","category"}, label="Subject"}
},
semantics = {
properties = {
["Has start date"] = "start",
["Has end date"] = "end",
["Part of process"] = "process",
["Has city"] = "city",
["Has venue"] = "venue",
["Has event organizer"] = "organizer",
},
additionalProperties = {
["Has country"] = {"country","territory"},
},
transforms = {
["Has start date"] = function(value)
return tostring(DateFmt.formatDate(value))
end,
["Has end date"] = function(value)
return tostring(DateFmt.formatDate(value))
end,
},
skipProperties = {
["Has country"] = true,
["Has ICANN region"] = true,
["Has event subject"] = true,
}
}
}
------------------------------------------------------------------------------
-- ANCHOR: PERSON TEMPLATE
------------------------------------------------------------------------------
p.templates.Person = {
meta = { description = "Renders profiles of people with a carousel for multiple images, supporting various normalizations" },
categories = { base = {"Person"} },
mappings = {
community = {
{canonical="ICANN Community", synonyms={"icann","community"}, category="ICANN Community"},
{canonical="ICANN Staff" , synonyms={"staff","icann org"}, category="ICANN Staff"},
{canonical="Root Server Operator Community", synonyms={"root server operator","rso"}, category="Root Server Operator Community"},
{canonical="RIR Community" , synonyms={"rir"}, category="RIR Community"},
{canonical="Universal Acceptance Community", synonyms={"universal acceptance","ua","ua member","idn","idn community"}, category="Universal Acceptance Community"},
{canonical="ISOC Community" , synonyms={"isoc","internet society","internet society community","isoc member"}, category="ISOC Community"},
{canonical="IETF Community" , synonyms={"ietf","ietf member"}, category="IETF Community"},
{canonical="W3C Community" , synonyms={"w3c","w3c member"}, category="W3C Community"},
{canonical="IGF Community" , synonyms={"igf","nri","youth igf"}, category="IGF Community"},
{canonical="Governmental" , synonyms={"government"}, category="Governmental"},
{canonical="Intergovernmental", synonyms={"igo"}, category="Intergovernmental"},
}
},
fields = {
{key="community" , label="Community"},
{key="affiliation", label="ICANN group"},
{key="organization", label="Organization"},
{key="region" , label=p.fieldLabels.region},
{key="country" , label=p.fieldLabels.country},
{key="languages" , label="Languages"},
{key="website" , label=p.fieldLabels.website},
{key="soi" , label="SOI"},
{key="userbox" , label="Achievements"},
},
patterns = {
itemDelimiter = ";%s*",
websitePattern = "^https?://[^%s]+",
},
semantics = {
properties = {
["Has governance community"] = "community",
["Has ICANN affiliation"] = "affiliation",
["Has organization"] = "organization",
},
additionalProperties = {
["Has country"] = {"country"},
["Has ICANN region"] = {"region"},
},
transforms = {
["Has governance community"] = function(value)
return select(1, CanonicalForms.normalize(value, p.templates.Person.mappings.community)) or value
end,
["Knows language"] = function(value)
return value
end,
},
skipProperties = {
["Has country"] = true,
["Has ICANN region"] = true,
}
}
}
------------------------------------------------------------------------------
-- ANCHOR: TLD TEMPLATE
------------------------------------------------------------------------------
p.templates.TLD = {
meta = { description = "Versatile module for rendering TLD/ccTLD article templates with extensive normalization and dynamic content" },
categories = {
base = {},
conditional = { rvc="TLDs with RVCs", idn="IDN", idn_cctld="IDN ccTLD" },
},
mappings = {
type = {
{canonical="gTLD", synonyms={"generic","tld","generic top level domain","generic top-level domain","generic tld"}, category="gTLD"},
{canonical="ccTLD", synonyms={"country","cc","country code top level domain","country code top-level domain","country tld"}, category="ccTLD"},
},
subtype = {
{canonical="geoTLD", synonyms={"geo tld","geo","geographic","geographical","geographic top level domain","geographic top-level domain","geographic tld"}, css="tld-template-subtype-geotld", category="geoTLD"},
{canonical="dotBrand", synonyms={"brand","brandtld","brand tld","brand top level domain","brand top-level domain"}, css="tld-template-subtype-brandtld", category="dotBrand"},
{canonical="Sponsored TLD", synonyms={"sponsored","sponsored top level domain","sponsored top-level domain"}, css="tld-template-subtype-sponsored", category="Sponsored TLD"},
{canonical="Legacy TLD", synonyms={"legacy","legacy top level domain","legacy top-level domain"}, css="tld-template-subtype-legacytld", category="Legacy TLD"},
{canonical="2012 gTLD Round", synonyms={"gtld round 2012","2012 ngtld round","2012 ngtld","ngtld 2012","ngtld","2012"}, css="tld-template-subtype-ngtld-round-2012", category="2012 gTLD Round"},
}
},
constants = {
classicTLDs = ClassicTLDs,
},
patterns = {
tldExtension = "%.([^%.]+)$",
countryDelimiter = "([^;]+)",
},
fields = {
{key="type", label="Type"},
{key="subtype", label="Subtype"},
{key="status", label="Status"},
{keys={"country","territory"}, label=p.fieldLabels.country},
{key="introduced", label="Introduced"},
{keys={"date","implemented"}, label="Implemented"},
{keys={"script","language"}, label="Script"},
{key="translation", label="English version"},
{key="ascii", label="Punycode"},
{keys={"registry","registryprovider"}, label="Registry"},
{key="website", label=p.fieldLabels.website},
{keys={"RVC","PIC"}, label="PIC/RVC"},
},
semantics = {
properties = {
["Has TLD type"] = "type",
["Has TLD subtype"] = "subtype",
["Has TLD status"] = "status",
["Date introduced"] = "introduced",
["Date implemented"] = "date",
["Uses writing script"] = "script",
["Has registry operator"] = "registry",
["Has PIC or RVC"] = "RVC",
},
additionalProperties = {
["Has country"] = {"country","territory"},
["Date implemented"] = {"date","implemented"},
["Uses writing script"] = {"script","language"},
["Has registry operator"] = {"registry","registryprovider"},
["Has PIC or RVC"] = {"RVC","PIC"},
},
transforms = {
["Has TLD type"] = function(value)
return select(1, CanonicalForms.normalize(value, p.templates.TLD.mappings.type)) or value
end,
["Has TLD subtype"] = function(value)
return select(1, CanonicalForms.normalize(value, p.templates.TLD.mappings.subtype)) or value
end,
["Date introduced"] = function(value)
return tostring(DateFmt.formatDate(value))
end,
["Date implemented"] = function(value)
return tostring(DateFmt.formatDate(value))
end,
["Has PIC or RVC"] = function(value)
if value and value ~= "" then return "true" end
end
},
skipProperties = {
["Has country"] = true
}
}
}
------------------------------------------------------------------------------
-- ANCHOR: LIBRARY INTERVIEW TEMPLATE
------------------------------------------------------------------------------
p.templates.LibraryInterview = {
meta = { description = "Module for rendering the Library Interview template with semantics" },
categories = {
base = { "Internet & Digital Governance Library", "ICANNWiki Interviews" }
},
constants = {
title = "Internet & Digital Governance Library",
tableClass = "library-box"
},
fields = {
{ key="Title" , label="Title" },
{ key="Format" , label="Format" },
{ key="Date" , label=p.fieldLabels.date },
{ key="Interviewer", label="Interviewer", autoWikiLink=true },
{ key="Interviewee", label="Interviewee", autoWikiLink=true },
{ key="ID" , label="Permanent ID" },
},
semantics = {
properties = {
["Has interview format"] = "Format",
["Has date"] = "Date",
["Has interviewer"] = "Interviewer",
["Has interviewee"] = "Interviewee",
["Permanent ID"] = "ID",
},
additionalProperties = {
["Has person"] = {"Interviewer","Interviewee"},
},
transforms = {
["Has date"] = function(value) return tostring(DateFmt.formatDate(value)) end,
["Permanent ID"] = function(value) return tostring(value or "") end,
},
}
}
------------------------------------------------------------------------------
-- CONFIGURATION ACCESS FUNCTIONS
------------------------------------------------------------------------------
function p.getConfig(templateType)
return p.templates[templateType] or {}
end
function p.createStandardConfig(config)
config = config or {}
return {
meta = config.meta or { description = "Template module configuration" },
mappings = config.mappings or {},
fields = config.fields or {},
semantics = config.semantics or { properties={}, transforms={}, additionalProperties={} },
constants = config.constants or {},
patterns = config.patterns or {},
categories = config.categories or {},
}
end
function p.getStandardConfig(templateType, customOverrides)
return p.createStandardConfig(p.getConfig(templateType), customOverrides)
end
------------------------------------------------------------------------------
mw.log('ConfigRepository loaded; heap '..collectgarbage('count')..' kB')
return p