Module:ConfigRepository: Difference between revisions
// via Wikitext Extension for VSCode |
// via Wikitext Extension for VSCode |
||
| (286 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
-- Module:ConfigRepository | -- Module:ConfigRepository | ||
-- | -- Single source of truth for all template configurations across the ICANNWiki ecosystem | ||
-- This module | -- | ||
-- This module centralizes configuration data to ensure consistency, eliminate duplication, | |||
-- and provide standardized structure for all templates. Works with the Template Blueprint | |||
-- Framework to power rendering and semantic processing. | |||
-- | |||
-- This module consists of three main parts: | |||
-- 1. Global constants and properties shared across templates | |||
-- 2. Template-specific configurations with standardized structure | |||
-- 3. Configuration access functions for retrieving and standardizing configurations | |||
-- | |||
-- Each template configuration provides a standardized structure with the following components: | |||
-- | |||
-- meta: Template metadata including description and rendering options | |||
-- categories: Base and conditional categories for the template | |||
-- patterns: Regular expression patterns for validation and parsing | |||
-- fields: Maps template field names in article source to display labels | |||
-- mappings: Canonical mappings for normalizing user input values | |||
-- constants: Template-specific constant values | |||
-- semantics: Semantic MediaWiki integration with the following sub-components: | |||
-- properties: Maps semantic properties to template fields (1:1 mapping) | |||
-- additionalProperties: Maps properties to multiple possible template fields | |||
-- transforms: Functions to transform field values before storing as properties | |||
-- skipProperties: Properties to exclude from automatic processing | |||
local p = {} | local p = {} | ||
local ErrorHandling = require('Module:ErrorHandling') | |||
local ConfigHelpers = require('Module:ConfigHelpers') | |||
-- | ------------------------------------------------------------------------------ | ||
-- Global Constants | |||
------------------------------------------------------------------------------ | |||
-- Global field labels used in multiple templates | |||
p.fieldLabels = { | |||
-- Geographic | |||
city = "City", | |||
country = "Country", | |||
region = "Region", | |||
-- Temporal | |||
date = "Date", | |||
ending = "End", | |||
start = "Start", | |||
-- Others | |||
process = "Process", | |||
website = "Websites" | |||
-- IMPORTANT: "Logo" is processed automatically whenever it is called as a key by the Template Blueprint, in such a way that it does not need to be declared for any templates in this repository | |||
} | |||
-- Global field patterns used in multiple templates | |||
p.fieldPatterns = { | |||
itemDelimiter = ";%s*", -- Matches semicolon followed by optional whitespace | |||
websitePattern = "^https?://[^%s]+" -- Matches URLs starting with http:// or https:// | |||
} | |||
-- Global field processors for reusable field definitions | |||
p.fieldProcessors = { | |||
website = { | |||
list = { mode = 'bullet_custom', bulletChar = '🔗', postProcess = 'website' } | |||
} | |||
} | |||
-- Global canonical mappings used in multiple templates | |||
p.mappings = { | |||
-- PROCESS (Property:Has process connection) | |||
process = { | |||
{canonical = "AFRINIC", | |||
category = "AFRINIC"}, | |||
{canonical = "APNIC", | |||
category = "APNIC"}, | |||
{canonical = "ARIN", | |||
category = "ARIN"}, | |||
{canonical = "DNS-OARC", | |||
category = "DNS-OARC"}, | |||
{canonical = "EuroDIG", | |||
category = "EuroDIG"}, | |||
{canonical = "ICANN", | |||
category = "ICANN"}, | |||
{canonical = "IEEE", | |||
category = "IEEE"}, | |||
{canonical = "IETF", | |||
category = "IETF"}, | |||
{canonical = "IGF", | |||
category = "IGF"}, | |||
{canonical = "ITU", | |||
category = "ITU"}, | |||
{canonical = "LACNIC", | |||
category = "LACNIC"}, | |||
{canonical = "RIPE NCC", | |||
category = "RIPE NCC"}, | |||
{canonical = "W3C", | |||
category = "W3C"}, | |||
{canonical = "WSIS", | |||
category = "WSIS"} | |||
} | |||
} | |||
-- Global semantic property names used in multiple templates (Cross-template semantic queries) | |||
p.semanticProperties = { | |||
country = "Has country", | |||
region = "Has ICANN region", | |||
language = "Knows language", | |||
person = "Has person", | |||
} | |||
-- Global date formatting configuration | |||
-- When true, use "Apr. 21, 2025" format; when false, use "April 21, 2025" | |||
p.dateFormatting = { | |||
useShortMonthNames = true | |||
} | |||
-- Global campaigns configuration | |||
-- Campaigns are defined centrally and specify which templates they can be applied to | |||
p.campaigns = { | |||
ASP2025 = { | |||
name = "ASP 2025 Pro Bono Service Provider", | |||
applicable_templates = {"Person", "Organization"}, | |||
json_config = "ASP2025" | |||
} | |||
} | |||
-- Global page creator fields for TemplateStarter form generation | |||
p.pageCreatorFields = { | |||
PAGE_NAME = { | |||
key = "PAGE_NAME", | |||
label = "Page Name", | |||
placeholder = "Enter page name...", | |||
required = true | |||
}, | |||
COUNTRY = { | |||
key = "COUNTRY", | |||
label = "Country", | |||
placeholder = "Enter country (optional)...", | |||
required = false | |||
}, | |||
YEAR = { | |||
key = "YEAR", | |||
label = "Year", | |||
placeholder = "Enter year (optional)...", | |||
required = false | |||
}, | |||
ORGANIZATION_TYPE = { | |||
key = "ORGANIZATION_TYPE", | |||
label = "Organization Type", | |||
placeholder = "Enter organization type (optional)...", | |||
required = false | |||
}, | |||
OCCUPATION = { | |||
key = "OCCUPATION", | |||
label = "Occupation", | |||
placeholder = "Enter occupation (optional)...", | |||
required = false | |||
}, | |||
NORM_TYPE = { | |||
key = "NORM_TYPE", | |||
label = "Type of Norm", | |||
placeholder = "Enter norm type (optional)...", | |||
required = false | |||
} | |||
} | |||
------------------------------------------------------------------------------ | |||
-- Transform registry mapping string keys to functions | |||
------------------------------------------------------------------------------ | |||
p.transformRegistry = { | |||
date = function(value) | |||
return tostring(require('Module:NormalizationDate').formatDate(value)) | |||
end, | |||
normalize = function(value, mappings) | |||
-- Return original if mappings invalid | |||
if type(mappings) ~= 'table' or #mappings == 0 then | |||
return value | |||
end | |||
local CanonicalForms = require('Module:CanonicalForms') | |||
local canonical = select(1, CanonicalForms.normalize(value, mappings)) | |||
return canonical or value | |||
end, | |||
semantic = function(value, templateName) | |||
return require('Module:TemplateHelpers').extractSemanticValue(value, templateName) | |||
end, | |||
boolean = function(value) | |||
if value and value ~= "" then | |||
return "true" | |||
end | |||
end, | |||
raw = function(value) | |||
return value | |||
end, | |||
string = function(value) | |||
return tostring(value or "") | |||
end | |||
} | |||
------------------------------------------------------------------------------ | |||
-- TEMPLATE-SPECIFIC CONFIGURATIONS | |||
------------------------------------------------------------------------------ | |||
p.templates = { | p.templates = { | ||
------------------------------------------------------------------------------ | |||
-- ANCHOR: EVENT TEMPLATE | -- ANCHOR: EVENT TEMPLATE | ||
------------------------------------------------------------------------------ | |||
Event = { | Event = { | ||
meta = { | meta = { | ||
description = " | description = "Event template" | ||
}, | }, | ||
categories = { -- Default categories | |||
categories = { | base = {"Events"} | ||
base = {"Events"} | }, | ||
boilerplate = { | |||
intro = "'''$PAGE_NAME$''' was an event that took place in $COUNTRY$ in $YEAR$." | |||
}, | }, | ||
creatorFields = {"PAGE_NAME", "COUNTRY", "YEAR"}, | |||
mappings = { | |||
-- Process (Property:Has process connection) | |||
process = p.mappings.process | |||
}, | }, | ||
patterns = { | patterns = { | ||
-- Patterns for event navigation detection | -- Patterns for event navigation detection | ||
seriesNumber = "^([%w%s]+)%s+(%d+)$", -- e.g., "ICANN 76" | seriesNumber = "^([%w%s]+)%s+(%d+)$", -- e.g., "ICANN 76" | ||
seriesYear = "^([%w%s]+)%s+(%d%d%d%d)$", -- e.g., "IGF 2023" | seriesYear = "^([%w%s]+)%s+(%d%d%d%d)$", -- e.g., "IGF 2023" | ||
itemDelimiter = p.fieldPatterns.itemDelimiter, | |||
websitePattern = p.fieldPatterns.websitePattern | |||
itemDelimiter = | |||
}, | }, | ||
fields = { | fields = { | ||
{key=" | {key="process", label=p.fieldLabels.process, autoWikiLink=true}, | ||
{key="start", label=p.fieldLabels.start}, | |||
{key="start", label= | {key="ending", label=p.fieldLabels.ending}, | ||
{key=" | {key="region", label=p.fieldLabels.region}, | ||
{key="region", label= | {key="country", label=p.fieldLabels.country}, | ||
{ | {key="city", label=p.fieldLabels.city}, | ||
{key="city", label= | |||
{key="venue", label="Venue"}, | {key="venue", label="Venue"}, | ||
{key="organizer", label="Organizer"}, | {key="organizer", label="Organizer"}, | ||
{keys={"website", "url"}, label= | {keys={"website", "url"}, label=p.fieldLabels.website, list=p.fieldProcessors.website.list}, | ||
}, | }, | ||
semantics = { | semantics = { | ||
properties = { | properties = { | ||
["Has process connection"] = "process", | |||
["Has start date"] = "start", | ["Has start date"] = "start", | ||
["Has end date"] = " | ["Has end date"] = "ending", | ||
["Has city"] = "city", | ["Has city"] = "city", | ||
["Has venue"] = "venue", | ["Has venue"] = "venue", | ||
["Has event organizer"] = "organizer" | ["Has event organizer"] = "organizer" | ||
}, | }, | ||
-- Normalizations applied | |||
-- | transforms = { | ||
["Has start date"] = "date", | |||
["Has end date"] = "date" | |||
}, | |||
fixedProperties = { | |||
["Has entity type"] = "Event" | |||
} | |||
} | |||
}, | |||
------------------------------------------------------------------------------ | |||
-- ANCHOR: LIBRARY INTERVIEW TEMPLATE | |||
------------------------------------------------------------------------------ | |||
LibraryInterview = { | |||
meta = { | |||
description = "Library Interview template", | |||
page_creator = false | |||
}, | |||
categories = { -- Default categories | |||
base = { | |||
"Internet & Digital Governance Library", | |||
"ICANNWiki Interviews" | |||
} | |||
}, | |||
constants = { -- REVIEW | |||
title = "Internet & Digital Governance Library", | |||
tableClass = "library-box" | |||
}, | |||
fields = { | |||
{key="title", label="Title"}, | |||
{key="format_interview", 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 = { | |||
-- Direct property mappings (1:1 relationship between property and field) | |||
properties = { | |||
["Has interview format"] = "format_interview", | |||
["Has date"] = "date", | |||
["Has interviewer"] = "interviewer", | |||
["Has interviewee"] = "interviewee", | |||
["Permanent ID"] = "id" | |||
}, | |||
-- Properties that map to multiple possible fields | |||
additionalProperties = { | additionalProperties = { | ||
["Has | ["Has person"] = {"interviewer", "interviewee"} -- Links interviews to person pages | ||
-- " | }, | ||
-- Normalizations applied | |||
transforms = { | |||
["Has date"] = "date", | |||
["Permanent ID"] = "string" | |||
}, | |||
fixedProperties = { | |||
["Has entity type"] = "Library" | |||
} | |||
} | |||
}, | |||
------------------------------------------------------------------------------ | |||
-- ANCHOR: NORM TEMPLATE | |||
------------------------------------------------------------------------------ | |||
Norm = { | |||
meta = { | |||
description = "Norm template for laws, regulations, standards, etc." | |||
}, | |||
categories = { | |||
base = {"Norms"} | |||
}, | |||
boilerplate = { | |||
intro = "'''$PAGE_NAME$''' is a $NORM_TYPE$ proposed in $YEAR$." | |||
}, | |||
creatorFields = {"PAGE_NAME", "NORM_TYPE", "YEAR"}, | |||
mappings = { | |||
norm_type = { | |||
{canonical = "Act", category = "Acts"}, | |||
{canonical = "Agreement", category = "Agreements"}, | |||
{canonical = "Framework", category = "Frameworks"}, | |||
{canonical = "Law", category = "Laws"}, | |||
{canonical = "Regulation", category = "Regulations"}, | |||
{canonical = "Standard", category = "Standards"}, | |||
{canonical = "Policy", category = "Policies"}, | |||
{canonical = "Guideline", category = "Guidelines"}, | |||
{canonical = "Treaty", category = "Treaties"}, | |||
{canonical = "Decree", category = "Decrees"}, | |||
{canonical = "Ordinance", category = "Ordinances"}, | |||
{canonical = "By-law", category = "By-laws"}, | |||
{canonical = "Code", category = "Codes"}, | |||
{canonical = "Convention", category = "Conventions"}, | |||
{canonical = "Directive", category = "Directives"} | |||
}, | }, | ||
scope_geo = { | |||
-- | {canonical = "Global", category = "Global Norms"}, | ||
{canonical = "Regional", category = "Regional Norms"}, | |||
{canonical = "National", category = "National Norms"} | |||
}, | |||
norm_status = { -- Key used in templatedata | |||
{canonical = "Active", category = "Active Norms"}, | |||
{canonical = "Repealed", category = "Repealed Norms"}, | |||
{canonical = "Draft", category = "Draft Norms"}, | |||
{canonical = "Proposed", category = "Proposed Norms"}, | |||
{canonical = "Superseded", category = "Superseded Norms"}, | |||
{canonical = "Amended", category = "Amended Norms"} | |||
} | |||
}, | |||
fields = { | |||
{key="norm_title", label="Norm title"}, | |||
{key="alternative_title", label="Alternative name"}, -- Key used in templatedata | |||
{key="norm_type", label="Type of norm"}, | |||
{key="issuing_body", label="Issuing body", autoWikiLink=true}, | |||
{key="scope_geo", label="Geographic scope"}, | |||
{key="country", label=p.fieldLabels.country}, | |||
{key="norm_status", label="Status"}, -- Key used in templatedata | |||
{key="official_text", label="Official text"}, | |||
{key="related_norm", label="Related Norms", list="bullet"}, | |||
{key="parent_framework", label="Parent legal framework", autoWikiLink=true}, | |||
{key="norm_language", label="Language"} | |||
}, | |||
semantics = { | |||
properties = { | |||
["Has alternative title"] = "alternative_title", | |||
["Has norm type"] = "norm_type", | |||
["Has issuing body"] = "issuing_body", | |||
["Has geographic scope"] = "scope_geo", | |||
["Has status"] = "norm_status", | |||
["Links to official text"] = "official_text", | |||
["Is related to norm"] = "related_norm", | |||
["Is part of framework"] = "parent_framework", | |||
["Has language"] = "norm_language" | |||
}, | |||
transforms = { | |||
["Has norm type"] = "normalize", | |||
["Has geographic scope"] = "normalize", | |||
["Has status"] = "normalize", | |||
["Has issuing body"] = "semantic", | |||
["Is related to norm"] = "semantic", | |||
["Is part of framework"] = "semantic", | |||
["Links to official text"] = "string", | |||
["Has language"] = "string" | |||
}, | |||
fixedProperties = { | |||
["Has entity type"] = "Norm" | |||
} | |||
} | |||
}, | |||
------------------------------------------------------------------------------ | |||
-- ANCHOR: ORGANIZATION TEMPLATE | |||
------------------------------------------------------------------------------ | |||
Organization = { | |||
meta = { | |||
description = "Organization template" | |||
}, | |||
categories = { -- Default categories | |||
base = {"Organization"} | |||
}, | |||
boilerplate = { | |||
intro = "'''$PAGE_NAME$''' is a $ORGANIZATION_TYPE$ founded in $YEAR$." | |||
}, | |||
creatorFields = {"PAGE_NAME", "ORGANIZATION_TYPE", "YEAR"}, | |||
mappings = { | |||
organization_type = { | |||
-- organization_type (Property:Has organization type) | |||
{canonical = "Academic institution", | |||
synonyms = {"university", "college", "academia", "institute", "school"}, | |||
category = "Academic institution"}, | |||
{canonical = "ALS", | |||
synonyms = {"at-large structure", "at large structure", "at-large", "at large"}, | |||
category = "ALS"}, | |||
{canonical = "Commercial", | |||
synonyms = {"for-profit", "for profit", "business", "private", "private company", "privately held", "company", "publicly held", "public", "joint stock company", "corporation", "corp", "firm", "enterprise", "limited liability", "llc", "gmbh"}, | |||
category = "Commercial"}, | |||
{canonical = "Community network", | |||
synonyms = {"community"}, | |||
category = "Community network"}, | |||
{canonical = "Consortium", | |||
synonyms = {"alliance", "joint venture", "joint-venture"}, | |||
category = "Consortium"}, | |||
{canonical = "Cooperative", | |||
synonyms = {"co-op", "coop", "co-operative"}, | |||
category = "Cooperative"}, | |||
{canonical = "Government agency", | |||
synonyms = {"government", "govt", "regulator", "regulatory authority", "nra", "bureau"}, | |||
category = "Government agency"}, | |||
{canonical = "Industry association", | |||
synonyms = {"trade association", "industry group", "trade group"}, | |||
category = "Industry association"}, | |||
{canonical = "Intergovernmental organization", | |||
synonyms = {"igo", "ingo"}, | |||
category = "Intergovernmental organization"}, | |||
{canonical = "Internet Society Chapter", | |||
synonyms = {"isoc chapter"}, | |||
category = "Internet Society Chapter"}, | |||
{canonical = "Non-profit", | |||
synonyms = {"nonprofit", "not-for-profit", "not for profit", "charity", "foundation", "economic forum", "ngo", "association", "non-profit organization"}, | |||
category = "Non-profit"}, | |||
{canonical = "Public-private partnership", | |||
synonyms = {"public-private partnership", "ppp"}, | |||
category = "Public-private partnership"}, | |||
{canonical = "Research institute", | |||
synonyms = {"research", "institute", "think tank"}, | |||
category = "Research institute"}, | |||
{canonical = "Standards development organization", | |||
synonyms = {"sdo", "standards body", "standards organisation, standards"}, | |||
category = "Standards development organization"} | |||
} | |||
}, | |||
patterns = { | |||
itemDelimiter = p.fieldPatterns.itemDelimiter, | |||
websitePattern = p.fieldPatterns.websitePattern | |||
}, | |||
fields = { | |||
{key="organization_type", label="Type"}, | |||
{key="focus", label="Focus"}, | |||
{key="region", label=p.fieldLabels.region}, | |||
{key="country", label=p.fieldLabels.country}, | |||
{key="city", label=p.fieldLabels.city}, | |||
{key="date_founded", label="Founded"}, | |||
{key="founders", label="Founders", autoWikiLink=true, list="bullet"}, | |||
{key="ownership", label="Ownership", autoWikiLink=true}, | |||
{key="subsidiaries", label="Subsidiaries", list="bullet"}, | |||
{keys={"website", "url"}, label=p.fieldLabels.website, list=p.fieldProcessors.website.list}, | |||
}, | |||
semantics = { | |||
properties = { | |||
["Has organization type"] = "organization_type", | |||
["Has focus"] = "focus", | |||
["Has city"] = "city", | |||
["Date founded"] = "date_founded", | |||
["Has owner"] = "ownership", | |||
["Has subsidiary"] = "subsidiaries" | |||
}, | |||
-- Normalizations applied | |||
transforms = { | transforms = { | ||
-- None | |||
}, | }, | ||
fixedProperties = { | |||
["Has entity type"] = "Organization" | |||
["Has | |||
} | } | ||
} | } | ||
}, | }, | ||
------------------------------------------------------------------------------ | |||
-- ANCHOR: PERSON TEMPLATE | -- ANCHOR: PERSON TEMPLATE | ||
------------------------------------------------------------------------------ | |||
Person = { | Person = { | ||
meta = { | meta = { | ||
description = " | description = "Person template" | ||
}, | }, | ||
categories = { -- Default categories | |||
categories = { | base = {"Person"} | ||
base = {"Person"} | }, | ||
boilerplate = { | |||
intro = "'''$PAGE_NAME$''' is a $OCCUPATION$ based in $COUNTRY$." | |||
}, | }, | ||
creatorFields = {"PAGE_NAME", "OCCUPATION", "COUNTRY"}, | |||
mappings = { | mappings = { | ||
-- REVIEW Community (Property:Has governance community) | |||
community = { | community = { | ||
-- Broad definition | |||
{canonical = "Internet Governance Community", | |||
synonyms = {"ig", "internet governance"}, | |||
category = "Internet Governance Community"}, | |||
-- ICANN-related communities | |||
{canonical = "ICANN Community", | {canonical = "ICANN Community", | ||
synonyms = {"icann", "community"}, | |||
category = "ICANN Community"}, | |||
{canonical = "ICANN Staff", | {canonical = "ICANN Staff", -- Category provided via "badge-icann-staff" | ||
synonyms = {"staff", "icann org"},}, | |||
-- Technical communities | |||
{canonical = "Technical Community", | |||
synonyms = {"technical"}, | |||
category = "Technical Community"}, | |||
{canonical = "Root Server Operator Community", | {canonical = "Root Server Operator Community", | ||
synonyms = {"root server operator", "rso"}, | |||
category = "Root Server Operator Community"}, | |||
{canonical = "RIR Community", | {canonical = "RIR Community", | ||
synonyms = {"rir"}, | |||
category = "RIR Community"}, | |||
{canonical = "Universal Acceptance Community", | {canonical = "Universal Acceptance Community", | ||
synonyms = {"universal acceptance", "ua", "uasg", "idn", "idn community"}, | |||
category = "Universal Acceptance Community"}, | |||
-- Internet governance organizations | |||
{canonical = "ISOC Community", | {canonical = "ISOC Community", | ||
synonyms = {"isoc", "internet society", "isoc member"}, | |||
category = "ISOC Community"}, | |||
{canonical = "IETF | {canonical = "IETF Community", | ||
synonyms = {"ietf", "ietf member"}, | |||
category = "IETF Community"}, | |||
{canonical = "IGF Community", | |||
synonyms = {"igf", "nri", "youth igf"}, | |||
category = "IGF Community"}, | |||
{canonical = "W3C Community", | {canonical = "W3C Community", | ||
synonyms = {"w3c", "w3c member"}, | |||
category = "W3C Community"}, | |||
-- Government-related | |||
{canonical = "Governmental", | {canonical = "Governmental", | ||
synonyms = {"government", "public sector", "gac"}, | |||
category = "Governmental"}, | |||
{canonical = "Intergovernmental", | {canonical = "Intergovernmental", | ||
synonyms = {"igo", "ingo"}, | |||
category = "Intergovernmental"} | |||
} | } | ||
}, | }, | ||
fields = { | fields = { | ||
{key="community", | {key="community", label="Community"}, | ||
{key=" | {key="icann_group", label="ICANN SO/AC", autoWikiLink=true}, -- (Property:Has ICANN affiliation) | ||
{key="organization",label="Organization"}, | {key="organization", label="Organization", autoWikiLink=true, list="bullet"}, | ||
{key="region", | {key="region", label=p.fieldLabels.region, list="bullet"}, | ||
{key="country", | {key="country", label=p.fieldLabels.country}, | ||
{key="languages", | {key="languages", label="Languages", list = { mode = 'bullet_custom', bulletChar = '🗣️', postProcess = 'language' }}, | ||
{key="website", | {key="website", label=p.fieldLabels.website, list=p.fieldProcessors.website.list}, | ||
{key="soi", | {key="soi", label="SOI"}, | ||
{key="userbox", | {key="userbox", label="Achievements"}, | ||
{key="user", label="User", hidden=true} | |||
}, | }, | ||
patterns = { | patterns = { | ||
itemDelimiter = | itemDelimiter = p.fieldPatterns.itemDelimiter, | ||
websitePattern = | websitePattern = p.fieldPatterns.websitePattern | ||
}, | }, | ||
semantics = { | semantics = { | ||
properties = { | properties = { | ||
["Has | ["Has governance community"] = "community", | ||
["Has ICANN affiliation"] = " | ["Has ICANN affiliation"] = "icann_group", | ||
["Has organization"] = "organization", | ["Has organization"] = "organization", | ||
-- "Has | ["Has username"] = "user" | ||
}, | |||
-- Normalizations applied | |||
transforms = { | |||
["Has governance community"] = "normalize" | |||
}, | |||
fixedProperties = { | |||
["Has entity type"] = "Person" | |||
} | |||
} | |||
}, | |||
------------------------------------------------------------------------------ | |||
-- ANCHOR: PROCESS TEMPLATE | |||
------------------------------------------------------------------------------ | |||
Process = { | |||
meta = { | |||
description = "Process Template", | |||
templateId = "process" | |||
}, | |||
categories = { | |||
base = {"Processes", "Events"} | |||
}, | |||
boilerplate = { | |||
intro = "'''$PAGE_NAME$''' is a process started in $YEAR$." | |||
}, | |||
creatorFields = {"PAGE_NAME", "YEAR"}, | |||
mappings = { | |||
-- Process (Property:Has process connection) | |||
process = p.mappings.process, | |||
-- Model (Property:Has process model) | |||
model = { | |||
{canonical = "Multistakeholder", | |||
synonyms = {"multi-stakeholder", "multi stakeholder"}, | |||
category = "Multistakeholder Processes"}, | |||
{canonical = "Single stakeholder", | |||
synonyms = {"single-stakeholder", "intergovernmental"}, | |||
category = "Single Stakeholder Processes"} | |||
}, | |||
-- Status (Property:Has process status) | |||
status = { | |||
{canonical = "Active", | |||
synonyms = {"ongoing"}, | |||
category = "Active Processes"}, | |||
{canonical = "Paused", | |||
synonyms = {"inactive", "dormant"}, | |||
category = "Dormant Processes"}, | |||
{canonical = "Concluded", | |||
synonyms = {"completed", "ended", "finished"}, | |||
category = "Concluded Processes"} | |||
}, | |||
-- Frequency (Property:Has frequency) | |||
frequency = { | |||
{canonical = "One-off", | |||
synonyms = {"one off", "single"}, | |||
category = "One-off Processes"}, | |||
{canonical = "Ad-hoc", | |||
synonyms = {"ad hoc", "eventual"}, | |||
category = "Ad-hoc Processes"}, | |||
{canonical = "Periodic", | |||
synonyms = {"recurring", "regular", "annual", "yearly"}, | |||
category = "Periodic Processes"}, | |||
{canonical = "Continuous", | |||
synonyms = {"permanent"}, | |||
category = "Continuous Processes"} | |||
}, | |||
-- Scope (Property:Has geographic scope) | |||
scope_geo = { | |||
{canonical = "Global", | |||
synonyms = {"worldwide", "world", "international"}, | |||
category = "Global Processes"}, | |||
{canonical = "Regional", | |||
synonyms = {"continent", "continental"}, | |||
category = "Regional Processes"}, | |||
{canonical = "National", | |||
synonyms = {"country", "domestic"}, | |||
category = "National Processes"} | |||
} | |||
}, | |||
fields = { | |||
{key="process", label=p.fieldLabels.process, autoWikiLink=true}, | |||
{key="model", label="Model"}, | |||
{key="start", label=p.fieldLabels.start}, | |||
{key="ending", label=p.fieldLabels.ending}, | |||
{key="process_status", label="Status"}, | |||
{key="governing_body", label="Governing Body", autoWikiLink=true}, | |||
{key="secretariat", label="Secretariat", autoWikiLink=true}, | |||
{key="frequency", label="Frequency"}, | |||
{key="scope_geo", label="Scope"}, | |||
{key="region", label=p.fieldLabels.region}, | |||
{key="country", label=p.fieldLabels.country}, | |||
{key="website", label=p.fieldLabels.website}, | |||
{key="has_previous", label="Preceded By", hidden=true}, | |||
{key="has_next", label="Succeeded By", hidden=true}, | |||
}, | |||
semantics = { | |||
properties = { | |||
["Has start date"] = "start", | |||
["Has end date"] = "ending", | |||
["Has process status"] = "process_status", | |||
["Has governing body"] = "governing_body", | |||
["Has event organizer"] = "secretariat", | |||
["Has process model"] = "model", | |||
["Has frequency"] = "frequency", | |||
["Has geographic scope"] = "scope_geo", | |||
["Has process connection"] = "process" | |||
}, | }, | ||
additionalProperties = { | additionalProperties = { | ||
["Has process connection"] = {"process", "has_previous", "has_next"} | |||
["Has | |||
}, | }, | ||
-- Normalizations applied | |||
-- | |||
transforms = { | transforms = { | ||
["Has | ["Has start date"] = "date", | ||
["Has end date"] = "date", | |||
["Has process status"] = "normalize", | |||
["Has process model"] = "normalize", | |||
[" | ["Has frequency"] = "normalize", | ||
["Has geographic scope"] = "normalize", | |||
["Has process connection"] = "semantic" | |||
}, | }, | ||
fixedProperties = { | |||
["Has entity type"] = "Process" | |||
["Has | |||
} | } | ||
} | } | ||
}, | }, | ||
------------------------------------------------------------------------------ | |||
-- ANCHOR: TLD TEMPLATE | -- ANCHOR: TLD TEMPLATE | ||
------------------------------------------------------------------------------ | |||
TLD = { | TLD = { | ||
meta = { | meta = { | ||
description = " | description = "TLD Template" | ||
}, | }, | ||
categories = { | categories = { | ||
base = {}, -- No | base = {}, -- No default category for TLDs as they use type-based categories | ||
conditional = { | conditional = { | ||
rvc = "TLDs with RVCs", | rvc = "TLDs with RVCs", | ||
| Line 212: | Line 722: | ||
}, | }, | ||
}, | }, | ||
boilerplate = { | |||
intro = "'''$PAGE_NAME$''' is a TLD proposed in $YEAR$." | |||
}, | |||
creatorFields = {"PAGE_NAME", "YEAR"}, | |||
mappings = { | mappings = { | ||
type = { | -- Type (Property:Has TLD type) | ||
tld_type = { | |||
{canonical = "gTLD", | {canonical = "gTLD", | ||
synonyms = {"generic", "tld", "generic top level domain", "generic top-level domain", "generic tld"}, | |||
category = "gTLD"}, | |||
{canonical = "ccTLD", | {canonical = "ccTLD", | ||
synonyms = {"country", "cc", "country code top level domain", "country code top-level domain", "country tld"}, | |||
category = "ccTLD"} | |||
}, | }, | ||
subtype = { | -- Subtype (Property:Has TLD subtype) | ||
tld_subtype = { | |||
{canonical="geoTLD", | {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", | {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", | {canonical="Sponsored TLD", | ||
synonyms={"sponsored","sponsored top level domain","sponsored top-level domain"}, | |||
css="tld-template-subtype-sponsored", | |||
category="Sponsored TLD"}, | |||
{canonical="Legacy 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", | {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"} | |||
} | } | ||
}, | }, | ||
patterns = { | patterns = { | ||
tldExtension="%.([^%.]+)$", | tldExtension="%.([^%.]+)$", -- Extracts the TLD part after the last dot (e.g., "com" from "example.com") | ||
countryDelimiter="([^;]+)" | countryDelimiter="([^;]+)", -- Matches any sequence of characters not containing semicolons; used for country parsing | ||
itemDelimiter = p.fieldPatterns.itemDelimiter, | |||
websitePattern = p.fieldPatterns.websitePattern | |||
}, | }, | ||
fields = { | fields = { | ||
{key=" | {key="tld_type", label="Type"}, | ||
{key=" | {key="tld_subtype", label="Subtype"}, | ||
{key=" | {key="tld_status", label="Status"}, -- (Property:Has TLD status) | ||
{ | {key="region", label=p.fieldLabels.region}, | ||
{key="introduced",label="Introduced"}, | {key="country", label=p.fieldLabels.country}, | ||
{ | {key="introduced", label="Introduced"}, | ||
{ | {key="implemented", label="Implemented"}, | ||
{key="translation",label="English | {key="script", label="Script"}, | ||
{key="ascii",label="Punycode"}, | {key="language", label="Language"}, | ||
{ | {key="translation", label="In English"}, | ||
{key="website",label= | {key="ascii", label="Punycode"}, | ||
{keys={"RVC", "PIC"},label="PIC/RVC"} | {key="registry", label="Registry", autoWikiLink=true}, | ||
{key="website", label=p.fieldLabels.website, list=p.fieldProcessors.website.list}, | |||
{keys={"RVC", "PIC"}, label = "PIC/RVC"} | |||
}, | }, | ||
semantics = { | semantics = { | ||
properties = { | properties = { | ||
["Has TLD type"] = " | ["Has TLD type"] = "tld_type", | ||
["Has TLD subtype"] = " | ["Has TLD subtype"] = "tld_subtype", | ||
["Has TLD status"] = " | ["Has TLD status"] = "tld_status", | ||
["Date introduced"] = "introduced", | ["Date introduced"] = "introduced", | ||
["Date implemented"] = " | ["Date implemented"] = "implemented", | ||
["Uses writing script"] = "script", | ["Uses writing script"] = "script", | ||
["Has registry operator"] = "registry", | ["Has registry operator"] = "registry", | ||
["Has PIC | ["Has language"] = "language", | ||
["Has PIC or RVC"] = "RVC", -- Will also handle PIC | |||
["Is IDN"] = "idn", -- Boolean | |||
}, | }, | ||
additionalProperties = { | additionalProperties = { | ||
["Has PIC or RVC"] = {"RVC", "PIC"} | |||
["Has PIC | |||
}, | }, | ||
-- Normalizations applied | |||
-- | |||
transforms = { | transforms = { | ||
["Has TLD type"] = | ["Has TLD type"] = "normalize", | ||
["Has TLD subtype"] = "normalize", | |||
["Date introduced"] = "date", | |||
["Date implemented"] = "date", | |||
["Has TLD subtype"] = | ["Has PIC or RVC"] = "boolean", | ||
["Is IDN"] = "boolean", | |||
["Date introduced"] = | |||
["Date implemented"] = | |||
}, | }, | ||
fixedProperties = { | |||
["Has entity type"] = "TLD" | |||
["Has | |||
} | } | ||
} | } | ||
}, | } | ||
} | |||
------------------------------------------------------------------------------ | |||
-- CONFIGURATION ACCESS FUNCTIONS | |||
------------------------------------------------------------------------------ | |||
-- Get configuration for a specific template type | |||
function p.getConfig(templateType) | |||
return p.templates[templateType] or {} | |||
end | |||
-- Local references to ConfigHelpers functions for better readability | |||
local deepMerge = ConfigHelpers.deepMerge | |||
local fieldHasKey = ConfigHelpers.fieldHasKey | |||
-- Creates a standardized configuration structure for template modules | |||
function p.createStandardConfig(config, customOverrides, templateType) | |||
config = config or {} | |||
customOverrides = customOverrides or {} | |||
-- | -- Initialize with defaults from config | ||
local standardConfig = { | |||
meta = config.meta or { | |||
description = "Template module configuration" | |||
}, | |||
meta = { | mappings = config.mappings or {}, | ||
description = " | fields = config.fields or {}, | ||
semantics = config.semantics or { | |||
properties = {}, | |||
transforms = {}, | |||
additionalProperties = {} | |||
}, | }, | ||
constants = config.constants or {}, | |||
patterns = config.patterns or {}, | |||
categories = config.categories or {} -- Add categories field to preserve base categories | |||
} | |||
-- Deep-merge customOverrides into standardConfig | |||
standardConfig = deepMerge(standardConfig, customOverrides) | |||
-- Auto-inject country/region semantic mappings if fields exist | |||
if standardConfig.fields and #standardConfig.fields > 0 then | |||
local hasCountryField = false | |||
local hasRegionField = false | |||
-- Check if country or region fields exist | |||
for _, field in ipairs(standardConfig.fields) do | |||
if fieldHasKey(field, "country") or fieldHasKey(field, "territory") then | |||
" | hasCountryField = true | ||
end | |||
if fieldHasKey(field, "region") then | |||
hasRegionField = true | |||
end | |||
end | |||
-- Initialize additionalProperties if it doesn't exist | |||
standardConfig.semantics.additionalProperties = standardConfig.semantics.additionalProperties or {} | |||
} | |||
-- Auto-inject country mapping if a country field exists | |||
if hasCountryField then | |||
standardConfig.semantics.additionalProperties[p.semanticProperties.country] = | |||
standardConfig.semantics.additionalProperties[p.semanticProperties.country] or {"country", "territory"} | |||
end | |||
-- Auto-inject region mapping if a region field exists | |||
if hasRegionField then | |||
standardConfig.semantics.additionalProperties[p.semanticProperties.region] = | |||
[" | standardConfig.semantics.additionalProperties[p.semanticProperties.region] or {"region"} | ||
end | |||
[ | end | ||
-- Inject built-in transform functions for declarative transforms | |||
for propertyName, transformIdentifier in pairs(standardConfig.semantics.transforms) do | |||
if type(transformIdentifier) == "string" then | |||
local registryFn = p.transformRegistry[transformIdentifier] | |||
if registryFn then | |||
standardConfig.semantics.transforms[propertyName] = function(value) | |||
if transformIdentifier == "normalize" then | |||
local mappingKey = standardConfig.semantics.properties[propertyName] | |||
local mappingTable = standardConfig.mappings[mappingKey] | |||
if not mappingTable then | |||
return | local suffix = mappingKey:match(".*_(.*)") | ||
mappingTable = suffix and standardConfig.mappings[suffix] or mappingTable | |||
end | |||
return registryFn(value, mappingTable) | |||
elseif transformIdentifier == "semantic" then | |||
return registryFn(value, templateType) | |||
else | |||
return registryFn(value) | |||
end | |||
end | end | ||
else | |||
ErrorHandling.addError( | |||
ErrorHandling.createContext(templateType), | |||
"TransformInjection", | |||
"Unknown transform type", | |||
transformIdentifier, | |||
false | |||
) | |||
end | |||
end | |||
end | |||
return standardConfig | |||
return | |||
end | end | ||
-- Get a standard config object for use with existing template modules | -- Get a standard config object for use with existing template modules | ||
function p.getStandardConfig(templateType, customOverrides) | function p.getStandardConfig(templateType, customOverrides) | ||
-- Get the base configuration | -- Get the base configuration | ||
local baseConfig = p.getConfig(templateType) | local baseConfig = p.getConfig(templateType) | ||
-- Create a standard config | -- Create a standard config | ||
return | return p.createStandardConfig(baseConfig, customOverrides, templateType) | ||
end | |||
function p.getSemanticPropertyName(propertyKey) | |||
for templateName, templateConfig in pairs(p.templates) do | |||
if templateConfig.semantics and templateConfig.semantics.additionalProperties then | |||
if templateConfig.semantics.additionalProperties[propertyKey] then | |||
return propertyKey | |||
end | |||
end | |||
end | |||
return nil | |||
end | end | ||
return p | return p | ||