Jump to content

Module:TemplateStarter: Difference between revisions

// via Wikitext Extension for VSCode
// via Wikitext Extension for VSCode
Line 1: Line 1:
-- Module:TemplateStarter
-- Module:TemplateStarter
-- Generates empty template structures for new pages using ConfigRepository
-- Generates configurable template structures for new pages using ConfigRepository


local p = {}
local p = {}
Line 8: Line 8:
local ErrorHandling = require('Module:ErrorHandling')
local ErrorHandling = require('Module:ErrorHandling')


-- Cache for template lists to improve performance
-- Cache for template lists
local templateListCache = nil
local templateListCache = nil
local templateListCacheTime = 0
local templateListCacheTime = 0
local CACHE_DURATION = 300 -- 5 minutes in seconds
local CACHE_DURATION = 300 -- 5 minutes


-- Generate empty template wikitext from template type
-- Generate empty template wikitext from template type
Line 20: Line 20:
     end
     end
      
      
     -- Sanitize input - remove any potentially harmful characters
     -- Sanitize input: remove any potentially harmful characters
     templateType = mw.text.trim(tostring(templateType))
     templateType = mw.text.trim(tostring(templateType))
      
      
Line 27: Line 27:
     end
     end
      
      
     -- Create error context for better error handling
     -- Create error context
     local errorContext = ErrorHandling.createContext("TemplateStarter")
     local errorContext = ErrorHandling.createContext("TemplateStarter")
      
      
Line 95: Line 95:
     lines[lineCount] = "}}"
     lines[lineCount] = "}}"
      
      
     -- Add intro boilerplate after template if available
     -- Add intro boilerplate after template (if available)
     if config.boilerplate and config.boilerplate.intro then
     if config.boilerplate and config.boilerplate.intro then
         lineCount = lineCount + 1
         lineCount = lineCount + 1
Line 104: Line 104:
         lines[lineCount] = config.boilerplate.intro
         lines[lineCount] = config.boilerplate.intro
     end
     end
   
 
    -- Add outro boilerplate if available (kept for backward compatibility)
     -- Join with newlines
    if config.boilerplate and config.boilerplate.outro then
        lineCount = lineCount + 1
        lines[lineCount] = ""  -- Empty line for spacing
        lineCount = lineCount + 1
        lines[lineCount] = config.boilerplate.outro
    end
   
     -- Join with newlines (more efficient than multiple concatenations)
     return table.concat(lines, "\n")
     return table.concat(lines, "\n")
end
end
Line 146: Line 138:
end
end


-- Generate a dynamic preload template (main function used by JavaScript)
-- Generate a dynamic preload template (main function used by JS)
function p.preload(frame)
function p.preload(frame)
     local args = frame.args
     local args = frame.args
Line 167: Line 159:
     end
     end
      
      
     -- Simple approach without complex error handling
     -- No complex error handling here
     local templates = {}
     local templates = {}
      
      
Line 181: Line 173:
         table.sort(templates)
         table.sort(templates)
     end
     end
   
     -- No fallback! If ConfigRepository fails, return empty list (single source of truth)
     -- No fallback - if ConfigRepository fails, return empty list
 
    -- This ensures we only use data from the single source of truth
   
     -- Update cache
     -- Update cache
     templateListCache = templates
     templateListCache = templates
Line 192: Line 182:
end
end


-- Test function to list available templates (clean output for JavaScript consumption)
-- Test function to list available templates (clean output for JS consumption)
function p.listTemplates(frame)
function p.listTemplates(frame)
     local templates = p.getAvailableTemplates()
     local templates = p.getAvailableTemplates()

Revision as of 00:04, 11 June 2025

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

-- Module:TemplateStarter
-- Generates configurable template structures for new pages using ConfigRepository

local p = {}

-- Required modules
local ConfigRepository = require('Module:ConfigRepository')
local ErrorHandling = require('Module:ErrorHandling')

-- Cache for template lists
local templateListCache = nil
local templateListCacheTime = 0
local CACHE_DURATION = 300 -- 5 minutes

-- Generate empty template wikitext from template type
function p.generateTemplate(templateType)
    -- Input validation and sanitization
    if not templateType or templateType == "" then
        return "Error: Template type is required"
    end
    
    -- Sanitize input: remove any potentially harmful characters
    templateType = mw.text.trim(tostring(templateType))
    
    if not templateType:match("^[%w_%-]+$") then
        return "Error: Invalid template type format"
    end
    
    -- Create error context
    local errorContext = ErrorHandling.createContext("TemplateStarter")
    
    -- Protected function to get configuration
    local function getTemplateConfig()
        local config = ConfigRepository.getConfig(templateType)
        
        if not config then
            return nil, string.format("Template type '%s' not found in ConfigRepository", templateType)
        end
        
        if not config.fields then
            return nil, string.format("Template type '%s' has no fields configuration", templateType)
        end
        
        return config
    end
    
    -- Get configuration with error protection
    local config = ErrorHandling.protect(errorContext, 'getTemplateConfig', getTemplateConfig, nil)
    if not config then
        return "Error: Failed to load template configuration"
    end
    
    -- Pre-allocate lines table for better performance
    local lines = {}
    local lineCount = 0
    
    -- Check for boilerplate configuration
    local hasBoilerplate = config.boilerplate and (config.boilerplate.intro or config.boilerplate.outro)
    
    -- Add debug comment
    if hasBoilerplate then
        lineCount = lineCount + 1
        lines[lineCount] = "<!-- Boilerplate available for " .. templateType .. " template -->"
    else
        lineCount = lineCount + 1
        lines[lineCount] = "<!-- No boilerplate for this template -->"
    end
    
    -- Start the template
    lineCount = lineCount + 1
    lines[lineCount] = "{{" .. templateType
    
    -- Process each field with error protection
    local function processFields()
        for _, field in ipairs(config.fields) do
            -- Skip hidden fields
            if not field.hidden then
                -- Handle fields with multiple keys (prefer single key, fallback to first of multiple)
                local fieldKey = field.key or (field.keys and field.keys[1])
                
                if fieldKey and fieldKey ~= "" then
                    lineCount = lineCount + 1
                    lines[lineCount] = string.format("|%s = ", fieldKey)
                end
            end
        end
        return true
    end
    
    -- Process fields with error protection
    ErrorHandling.protect(errorContext, 'processFields', processFields, false)
    
    -- Close the template
    lineCount = lineCount + 1
    lines[lineCount] = "}}"
    
    -- Add intro boilerplate after template (if available)
    if config.boilerplate and config.boilerplate.intro then
        lineCount = lineCount + 1
        lines[lineCount] = ""  -- First empty line for separation
        lineCount = lineCount + 1
        lines[lineCount] = ""  -- Second empty line for distance
        lineCount = lineCount + 1
        lines[lineCount] = config.boilerplate.intro
    end

    -- Join with newlines
    return table.concat(lines, "\n")
end

-- Main function to be called from wiki (for testing/preview)
function p.main(frame)
    -- Simple validation without complex error handling for this function
    local args = frame.args
    local parent = frame:getParent()
    local pargs = parent and parent.args or {}
    
    -- Get parameters (check both direct and parent args)
    local articleName = args.articleName or pargs.articleName or args[1] or pargs[1]
    local templateType = args.templateType or pargs.templateType or args[2] or pargs[2]
    
    -- Validate inputs
    if not articleName or mw.text.trim(tostring(articleName)) == "" then
        return "Error: Article name is required"
    end
    
    if not templateType or mw.text.trim(tostring(templateType)) == "" then
        return "Error: Template type is required"
    end
    
    -- Generate the template content
    local content = p.generateTemplate(mw.text.trim(tostring(templateType)))
    
    -- For testing, return the generated content in a pre block
    return string.format('<pre>Page: %s\n\n%s</pre>', 
        mw.text.nowiki(mw.text.trim(tostring(articleName))), 
        mw.text.nowiki(content))
end

-- Generate a dynamic preload template (main function used by JS)
function p.preload(frame)
    local args = frame.args
    local templateType = args.templateType or args[1]
    
    if not templateType or mw.text.trim(tostring(templateType)) == "" then
        return "<!-- No template type specified -->"
    end
    
    return p.generateTemplate(mw.text.trim(tostring(templateType)))
end

-- Get list of available templates with caching
function p.getAvailableTemplates()
    local currentTime = os.time()
    
    -- Check if cache is valid
    if templateListCache and (currentTime - templateListCacheTime) < CACHE_DURATION then
        return templateListCache
    end
    
    -- No complex error handling here
    local templates = {}
    
    -- Check if ConfigRepository.templates exists
    if ConfigRepository.templates then
        local index = 1
        for templateName, _ in pairs(ConfigRepository.templates) do
            if templateName and templateName ~= "" then
                templates[index] = templateName
                index = index + 1
            end
        end
        table.sort(templates)
    end
    -- No fallback! If ConfigRepository fails, return empty list (single source of truth)

    -- Update cache
    templateListCache = templates
    templateListCacheTime = currentTime
    
    return templates
end

-- Test function to list available templates (clean output for JS consumption)
function p.listTemplates(frame)
    local templates = p.getAvailableTemplates()
    if #templates == 0 then
        return "No templates available"
    end
    return table.concat(templates, ", ")
end

return p