Jump to content

Module:T-TLD

Documentation for this module may be created at Module:T-TLD/doc

--Module:T-TLD
-- Makes use of ICANNWiki's "Template Blueprint Framework" to render the "TLD" template

local p = {}

-- ==================== Required modules ====================
local Blueprint = require('Module:LuaTemplateBlueprint')
local ErrorHandling = require('Module:ErrorHandling')
local LinkParser = require('Module:LinkParser')

-- Blueprint possible default: Module-level cache for lazy-loaded modules
local moduleCache = {}

-- Blueprint possible default: Lazy module loader
local function lazyRequire(moduleName)
    return function()
        if not moduleCache[moduleName] then
            moduleCache[moduleName] = require(moduleName)
        end
        return moduleCache[moduleName]
    end
end

-- Blueprint default: Modules to lazy load
local getPunycode = lazyRequire('Module:Punycode')
local getCanonicalForms = lazyRequire('Module:CanonicalForms')

-- ==================== Helper Functions ====================
-- Blueprint default: Create error context for the module
local errorContext = ErrorHandling.createContext("T-TLD")

-- ================================================================================

-- IMPORTANT! TEMPLATE BLUEPRINT FRAMEWORK INSTRUCTIONS
-- CONTROL OF TEMPLATE FEATURES: THIS LIST SPECIFIES IN AN EXPLICIT MANNER WHAT FEATURES ARE TO BE CALLED/RENDERED BY THE TEMPLATE.
local template = Blueprint.registerTemplate('TLD', {
    features = {
        title = true,
        logo = true,
        tldflair = true,
        fields = true,
        socialMedia = true,
        ntldstats = true,
        semanticProperties = true,
        categories = true,
        errorReporting = true
    }
})

-- Blueprint default: Initialize standard configuration
Blueprint.initializeConfig(template)

-- CONTROL THE VISUAL ORDER THAT EACH ASPECT IS RENDERED IN
template.config.blockSequence = {
    'title',
    'logo',
    'tldflair',
    'fields',
    'socialMedia',
    'ntldstats',
    'semanticProperties',
    'categories',
    'errors'
}

-- ================================================================================

-- TEMPLATE-SPECIFIC CALLS AND CODE

-- ELEMENT:TLD FLAIR
if template.features.tldflair then
    local ElementTLDFlair = ErrorHandling.safeRequire(errorContext, 'Module:ElementTLDFlair', false)
    if ElementTLDFlair and ElementTLDFlair.elementName then
        Blueprint.registerElement(ElementTLDFlair.elementName, ElementTLDFlair)
        Blueprint.addElementToTemplate(template, 'tldflair')
    end
end

-- ELEMENT:NTLDSTATS
if template.features.ntldstats then
    local ElementNTLDStats = ErrorHandling.safeRequire(errorContext, 'Module:ElementNTLDStats', false)
    if ElementNTLDStats and ElementNTLDStats.elementName then
        Blueprint.registerElement(ElementNTLDStats.elementName, ElementNTLDStats)
        Blueprint.addElementToTemplate(template, 'ntldstats')
    end
end

-- Custom title row based on whether the TLD is a "g" or a "cc"
template.config.blocks = template.config.blocks or {}
template.config.blocks.title = {
    feature = 'title',
    render = function(template, args)
        return Blueprint.protectedExecute(
            template,
            'CustomBlock_title',
            function()
                local titleText = (args._type == 'ccTLD') and 'ccTLD' or 'gTLD'
                return require('Module:TemplateStructure').renderTitleBlock(
                    args,
                    'template-title template-title-tld',
                    titleText
                )
            end,
            '',
            args
        )
    end
}

-- PROCESSORS
template.config.processors = template.config.processors or {}
-- PIC/RVC link processor
template.config.processors.RVC = function(value, args)
    local val = tostring(value)
    if val:find("gtldresult.icann.org") then
        return string.format("[%s Here]", val)
    elseif val:match("^%d+$") then
        return string.format("[https://gtldresult.icann.org/applicationstatus/applicationdetails/%s Here]", val)
    end
    return nil
end
template.config.processors.PIC = template.config.processors.RVC

-- Override singular `language` field to skip normalization
template.config.processors.language = function(value, args)
    return value
end

-- ================================================================================

-- ==================== Preprocessors ====================
-- IDN detection preprocessor - sets idn="true" for boolean transform to handle
local function detectIDNStatus(template, args)
    if args.idn and args.idn ~= '' then
        local idnVal = string.lower(args.idn)
        if idnVal == 'yes' or idnVal == 'true' or idnVal == '1' then
            -- Set idn directly to "true" - will be handled by "boolean" transform
            args.idn = "true"
            
            -- Generate ASCII representation for IDN TLDs
            local titleObj = mw.title.getCurrentTitle()
            local pageName = titleObj and titleObj.text or ''
            local puny = Blueprint.protectedExecute(
                template,
                'IDN_toASCII',
                function()
                    return getPunycode().encode(pageName:gsub('^%.',''))
                end,
                pageName
            )
            args.ascii = 'xn--' .. puny
        end
    end
    return args
end

-- Map tld_type to internal _type for title block display logic
local function mapTldTypeToInternalType(template, args)
    if args.tld_type and args.tld_type ~= '' then
        args._type = select(1, getCanonicalForms().normalize(args.tld_type, template.config.mappings.tld_type)) or args.tld_type
    end
    return args
end

-- Call preprocessors
Blueprint.addPreprocessor(template, 'setPageIdField') -- Blueprint default
Blueprint.addPreprocessor(template, 'deriveRegionFromCountry') -- Blueprint possible default
Blueprint.addPreprocessor(template, mapTldTypeToInternalType) -- TLD type detection
Blueprint.addPreprocessor(template, detectIDNStatus) -- IDN detection

-- ==================== Main Render Function ====================
-- Blueprint default: Render
function p.render(frame)
    return ErrorHandling.protect(
        errorContext,
        "render",
        function()
            return template.render(frame)
        end,
        ErrorHandling.getMessage("TEMPLATE_RENDER_ERROR"),
        frame
    )
end

return p