Jump to content

Module:ConfigRepository

From ICANNWiki

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

-- Module:ConfigRepository
-- Central repository for configurations that works together with TemplateHelpers; this module is a single source of truth.
--
-- This module provides a standardized configuration structure for all templates with the following components:
--
-- meta:        Template metadata including description
-- categories:  Base and conditional categories for the template
-- patterns:    Regular expression patterns used by the template
-- 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 semantic properties to multiple possible template fields
--   transforms:           Functions to transform field values before storing as semantic properties
--   skipProperties:       Properties to exclude from automatic processing

local p = {}

------------------------------------------------------------------------------
-- Global Constants and Properties
------------------------------------------------------------------------------

-- Global field labels used across multiple templates
p.fieldLabels = {
    date = "Date",
    region = "Region",
    country = "Country",
    website = "Website"
    -- Add other cross-template field labels as needed
}

-- Global semantic property names used across multiple templates
p.semanticProperties = {
    region = "Has ICANN region",
    country = "Has country",
    language = "Knows language",
    person = "Has person"
    -- Add other cross-template properties as needed
}

------------------------------------------------------------------------------
-- Template-specific configurations are stored in the following table
------------------------------------------------------------------------------
p.templates = {

--------------------------------------------------------------------------------
-- ANCHOR: EVENT TEMPLATE
--------------------------------------------------------------------------------

    Event = {
        meta = {
            description = "Module for rendering Event templates, including next/previous navigation"
        },
        
        categories = {
            base = {"Events"} -- Base category always applied to Event pages
        },

        patterns = {
            -- Patterns for event navigation detection
            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 country" and "Has ICANN region" handled by CountryData.addCountrySemanticProperties
                ["Has city"] = "city",
                ["Has venue"] = "venue",
                ["Has event organizer"] = "organizer"
                -- "Has event subject"
            },
            
            additionalProperties = {
                ["Has country"] = {"country", "territory"}
                -- REVIEW "Has event subject" UNUSED
            },
            
            transforms = {
                ["Has start date"] = function(value)
                    return tostring(require('Module:NormalizationDate').formatDate(value))
                end,
                ["Has end date"] = function(value)
                    return tostring(require('Module:NormalizationDate').formatDate(value))
                end
            },
            
            skipProperties = {
                ["Has country"] = true,  -- Skip country as it's handled separately
                ["Has ICANN region"] = true, -- Skip region as it's handled separately
                ["Has event subject"] = true  -- REVIEW: UNUSED
            }
        }
    },
    
--------------------------------------------------------------------------------
-- ANCHOR: PERSON TEMPLATE
--------------------------------------------------------------------------------

    Person = {
        meta = {
            description = "Renders profiles of people with a carousel for multiple images, supporting various normalizations"
        },
        
        categories = {
            base = {"Person"} -- Base category always applied to Person pages
        },
        
        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",
                -- "Has ICANN region", "Has country", "Knows language", are all handled separately
            },
            
            additionalProperties = {
                -- Handle multiple countries and regions in the special case handlers
                ["Has country"] = {"country"},
                ["Has ICANN region"] = {"region"}
            },
            
            transforms = {
                ["Has governance community"] = function(value)
                    local CanonicalForms = require('Module:CanonicalForms')
                    return select(1, CanonicalForms.normalize(value, p.templates.Person.mappings.community)) or value
                end,
                ["Knows language"] = function(value)
                    -- Return raw value, the semantic property should store the raw data
                    return value
                end
            },
            
            skipProperties = {
                ["Has country"] = true,  -- Skip country as it's handled separately
                ["Has ICANN region"] = true  -- Skip region as it's handled separately
            }
        }
    },
    
--------------------------------------------------------------------------------
-- ANCHOR: TLD TEMPLATE
--------------------------------------------------------------------------------

    TLD = {
        meta = {
            description = "Versatile module for rendering TLD/ccTLD article templates with extensive normalization and dynamic content"
        },
        
        categories = {
            base = {}, -- No base category for TLDs as they use type-based categories
            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 = {
            legacyTLDs = {
                com=true,net=true,org=true,edu=true,gov=true,mil=true,int=true,info=true,
                aero=true,asia=true,cat=true,coop=true,jobs=true,mobi=true,museum=true,
                post=true,tel=true,travel=true,xxx=true
            }
        },
        
        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",
                -- "Has country" is handled separately through addMultiCountrySemanticProperties
                ["Date introduced"] = "introduced",
                ["Date implemented"] = "date", -- Will also handle implemented
                ["Uses writing script"] = "script", -- Will also handle language
                ["Has registry operator"] = "registry", -- Will also handle registryprovider
                ["Has PIC or RVC"] = "RVC" -- Will also handle PIC
                -- "Is IDN" is handled separately as a boolean property
            },
            
            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)
                    local CanonicalForms = require('Module:CanonicalForms')
                    return select(1, CanonicalForms.normalize(value, p.templates.TLD.mappings.type)) or value
                end,
                ["Has TLD subtype"] = function(value)
                    local CanonicalForms = require('Module:CanonicalForms')
                    return select(1, CanonicalForms.normalize(value, p.templates.TLD.mappings.subtype)) or value
                end,
                ["Date introduced"] = function(value)
                    return tostring(require('Module:NormalizationDate').formatDate(value))
                end,
                ["Date implemented"] = function(value)
                    return tostring(require('Module:NormalizationDate').formatDate(value))
                end,
                ["Has PIC or RVC"] = function(value)
                    -- If value exists and is not empty, return "true"
                    if value and value ~= "" then
                        return "true"
                    end
                    return nil -- Return nil for empty values
                end
            },
            
            skipProperties = {
                ["Has country"] = true  -- Skip country as it's handled separately
            }
        }
    },
    
--------------------------------------------------------------------------------
-- ANCHOR: LIBRARY INTERVIEW TEMPLATE
--------------------------------------------------------------------------------

    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"},
            {key="Interviewee", label="Interviewee"},
            {key="ID", label="Permanent ID"}
        },
        
        semantics = {
            properties = {
                ["Has interview format"] = "Format",
                ["Has date"] = "Date",
                ["Has interviewer"] = "Interviewer", 
                ["Has interviewee"] = "Interviewee"
            },
            
            additionalProperties = {
                ["Has person"] = {"Interviewer", "Interviewee"}
            },
            
            transforms = {
                ["Has date"] = function(value) 
                    return tostring(require('Module:NormalizationDate').formatDate(value)) 
                end
            },
            
            skipProperties = {
                -- No properties to skip in the library interview template
            }
        }
    }
}

-- Get configuration for a specific template type
function p.getConfig(templateType)
    return p.templates[templateType] or {}
end

-- Get a standard config object for use with existing template modules
-- This integrates with TemplateHelpers.createStandardConfig
function p.getStandardConfig(templateType, customOverrides)
    local TemplateHelpers = require('Module:TemplateHelpers')
    
    -- Get the base configuration
    local baseConfig = p.getConfig(templateType)
    
    -- Create a standard config using TemplateHelpers
    return TemplateHelpers.createStandardConfig(baseConfig, customOverrides)
end

return p