Module:WikitextProcessor

Revision as of 20:06, 1 August 2025 by MarkWD (talk | contribs) (// via Wikitext Extension for VSCode)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

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

-- Module:WikitextProcessor
-- Processes JSON content with wikitext formatting for frontend display
-- Handles placeholder replacement, wiki link conversion to HTML, and content normalization
-- Extracted from T-Campaign.lua for reusability across templates

local p = {}

-- Dependencies
local ErrorHandling = require('Module:ErrorHandling')

-- Module-level cache for processed content
local contentCache = {}

-- Constants as upvalues for performance
local WIKI_LINK_PATTERNS = {
    -- Pattern 1: [[Page Name]] -> HTML page links
    {
        pattern = '%[%[([^#|%]]+)%]%]',
        processor = function(pageName, errorContext)
            local spacesReplaced = (pageName:gsub(' ', '_'))
            local success1, pageUrl = pcall(function()
                return tostring(mw.uri.fullUrl(spacesReplaced))
            end)
            
            if not success1 then
                if errorContext then
                    ErrorHandling.addStatus(errorContext, 'wikiLinkProcessor', 'mw.uri.fullUrl failed for page link', 'Page: ' .. pageName .. ', Error: ' .. tostring(pageUrl))
                end
                return '[[' .. pageName .. ']]'
            end
            
            local success2, encodedName = pcall(function()
                return mw.text.encode(pageName)
            end)
            
            if not success2 then
                if errorContext then
                    ErrorHandling.addStatus(errorContext, 'wikiLinkProcessor', 'mw.text.encode failed for page link', 'Page: ' .. pageName .. ', Error: ' .. tostring(encodedName))
                end
                return '[[' .. pageName .. ']]'
            end
            
            local success3, result = pcall(function()
                return string.format('<a href="%s">%s</a>', pageUrl, encodedName)
            end)
            
            if not success3 then
                if errorContext then
                    ErrorHandling.addStatus(errorContext, 'wikiLinkProcessor', 'string.format failed for page link', 'Page: ' .. pageName .. ', Error: ' .. tostring(result))
                end
                return '[[' .. pageName .. ']]'
            end
            
            return result
        end
    },
    
    -- Pattern 2: [[Page|text]] -> HTML page links with custom text
    {
        pattern = '%[%[([^#|%]]+)|([^%]]+)%]%]',
        processor = function(pageName, text, errorContext)
            local success1, pageUrl = pcall(function()
                return tostring(mw.uri.fullUrl((pageName:gsub(' ', '_'))))
            end)
            
            if not success1 then
                if errorContext then
                    ErrorHandling.addStatus(errorContext, 'wikiLinkProcessor', 'Pattern 2 mw.uri.fullUrl failed', 'Error: ' .. tostring(pageUrl))
                end
                return '[[' .. pageName .. '|' .. text .. ']]'
            end
            
            local success2, encodedText = pcall(function()
                return mw.text.encode(text)
            end)
            
            if not success2 then
                if errorContext then
                    ErrorHandling.addStatus(errorContext, 'wikiLinkProcessor', 'Pattern 2 mw.text.encode failed', 'Error: ' .. tostring(encodedText))
                end
                return '[[' .. pageName .. '|' .. text .. ']]'
            end
            
            local success3, result = pcall(function()
                return string.format('<a href="%s">%s</a>', pageUrl, encodedText)
            end)
            
            if not success3 then
                if errorContext then
                    ErrorHandling.addStatus(errorContext, 'wikiLinkProcessor', 'Pattern 2 string.format failed', 'Error: ' .. tostring(result))
                end
                return '[[' .. pageName .. '|' .. text .. ']]'
            end
            
            return result
        end
    },
    
    -- Pattern 3: [[#anchor|text]] -> HTML anchor links
    {
        pattern = '%[%[#([^|%]]+)|([^%]]+)%]%]',
        processor = function(anchor, text, errorContext)
            local success1, encodedAnchor = pcall(function()
                return mw.uri.anchorEncode(anchor)
            end)
            
            if not success1 then
                if errorContext then
                    ErrorHandling.addStatus(errorContext, 'wikiLinkProcessor', 'Pattern 3 mw.uri.anchorEncode failed', 'Error: ' .. tostring(encodedAnchor))
                end
                return '[[#' .. anchor .. '|' .. text .. ']]'
            end
            
            local success2, encodedText = pcall(function()
                return mw.text.encode(text)
            end)
            
            if not success2 then
                if errorContext then
                    ErrorHandling.addStatus(errorContext, 'wikiLinkProcessor', 'Pattern 3 mw.text.encode failed', 'Error: ' .. tostring(encodedText))
                end
                return '[[#' .. anchor .. '|' .. text .. ']]'
            end
            
            local success3, result = pcall(function()
                return string.format('<a href="#%s">%s</a>', encodedAnchor, encodedText)
            end)
            
            if not success3 then
                if errorContext then
                    ErrorHandling.addStatus(errorContext, 'wikiLinkProcessor', 'Pattern 3 string.format failed', 'Error: ' .. tostring(result))
                end
                return '[[#' .. anchor .. '|' .. text .. ']]'
            end
            
            return result
        end
    }
}

-- Use TemplateHelpers caching functions for consistency
local TemplateHelpers = require('Module:TemplateHelpers')

-- Normalizes content string by cleaning up whitespace
function p.normalizeContentString(content)
    if not content or content == "" then
        return content
    end
    
    local cacheKey = TemplateHelpers.generateCacheKey("normalizeContentString", content)
    
    return TemplateHelpers.withCache(cacheKey, function()
        -- Apply string normalization - consolidate whitespace operations
        -- Handle multiple return values from gsub properly
        local result = (content:gsub("%s+", " "))
        result = (result:gsub("^%s+", ""))
        result = (result:gsub("%s+$", ""))
        return result
    end)
end

-- Replaces placeholder patterns ($VARIABLE$) with actual values
function p.replacePlaceholders(content, placeholderMap)
    if not content or not placeholderMap then
        return content
    end
    
    local cacheKey = TemplateHelpers.generateCacheKey("replacePlaceholders", content, tostring(placeholderMap))
    
    return TemplateHelpers.withCache(cacheKey, function()
        local result = content
        
        -- Apply placeholder replacement - handle multiple return values
        for key, value in pairs(placeholderMap) do
            if value and value ~= "" then
                result = (result:gsub("%$" .. key .. "%$", value))
            end
        end
        
        -- Clean up any remaining unfilled placeholders
        result = (result:gsub("%$[A-Z_]+%$", ""))
        
        -- Final normalization after placeholder replacement
        result = (result:gsub("%s+", " "))
        result = (result:gsub("^%s+", ""))
        result = (result:gsub("%s+$", ""))
        return result
    end)
end

-- Processes wiki links in content and converts them to HTML
function p.processWikiLinksToHTML(content, errorContext)
    if not content or content == "" then
        return content
    end
    
    local cacheKey = TemplateHelpers.generateCacheKey("processWikiLinksToHTML", content)
    
    return TemplateHelpers.withCache(cacheKey, function()
        local result = content
        
        -- Process each wiki link pattern in sequence
        for _, patternInfo in ipairs(WIKI_LINK_PATTERNS) do
            -- Handle multiple return values from gsub properly
            result = (result:gsub(patternInfo.pattern, function(...)
                return patternInfo.processor(..., errorContext)
            end))
        end
        
        return result
    end)
end

-- Main entry point: Processes JSON content with wikitext formatting for frontend display
-- @param content The content string to process
-- @param placeholders Optional table of placeholder values for $VARIABLE$ replacement
-- @param errorContext Optional error context for error reporting
-- @return Processed content ready for frontend display
function p.processContentForFrontend(content, placeholders, errorContext)
    if not content or content == "" then
        return content
    end
    
    -- Create cache key including all parameters
    local placeholdersKey = placeholders and tostring(placeholders) or "nil"
    local cacheKey = TemplateHelpers.generateCacheKey("processContentForFrontend", content, placeholdersKey)
    
    return TemplateHelpers.withCache(cacheKey, function()
        -- Step 1: Normalize content string
        local processedContent = p.normalizeContentString(content)
        
        -- Step 2: Replace placeholders if provided
        if placeholders then
            processedContent = p.replacePlaceholders(processedContent, placeholders)
        end
        
        -- Step 3: Process wiki links to HTML
        processedContent = p.processWikiLinksToHTML(processedContent, errorContext)
        
        return processedContent
    end)
end

return p