Jump to content

Module:WikitextProcessor: Difference between revisions

// via Wikitext Extension for VSCode
// via Wikitext Extension for VSCode
Line 68: Line 68:
              
              
             local success2, encodedText = pcall(function()
             local success2, encodedText = pcall(function()
                 return mw.text.encode(text)
                -- Ensure text is a string before encoding
                local textStr = type(text) == "string" and text or tostring(text)
                 return mw.text.encode(textStr)
             end)
             end)
              
              

Revision as of 20:54, 1 August 2025

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

local p = {}

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

-- 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, 'campaignBanner', '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, 'campaignBanner', '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, 'campaignBanner', '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, 'campaignBanner', 'Pattern 2 mw.uri.fullUrl failed', 'Error: ' .. tostring(pageUrl))
                end
                return '[[' .. pageName .. '|' .. text .. ']]'
            end
            
            local success2, encodedText = pcall(function()
                -- Ensure text is a string before encoding
                local textStr = type(text) == "string" and text or tostring(text)
                return mw.text.encode(textStr)
            end)
            
            if not success2 then
                if errorContext then
                    ErrorHandling.addStatus(errorContext, 'campaignBanner', '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, 'campaignBanner', '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, 'campaignBanner', '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, 'campaignBanner', '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, 'campaignBanner', 'Pattern 3 string.format failed', 'Error: ' .. tostring(result))
                end
                return '[[#' .. anchor .. '|' .. text .. ']]'
            end
            
            return result
        end
    }
}

-- Normalizes content string by cleaning up whitespace
function p.normalizeContentString(content)
    if not content or content == "" then
        return content
    end
    
    -- Apply string normalization exactly like the original T-Campaign code
    return content:gsub("%s+", " "):gsub("^%s+", ""):gsub("%s+$", "")
end

-- Replaces placeholder patterns ($VARIABLE$) with actual values
function p.replacePlaceholders(content, placeholderMap)
    if not content or not placeholderMap then
        return content
    end
    
    local result = content
    
    -- Apply placeholder replacement exactly like the original T-Campaign code
    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 (TemplateStarter's removeEmptyPlaceholders logic)
    result = result:gsub("%$[A-Z_]+%$", "")
    result = result:gsub("%s+", " "):gsub("^%s+", ""):gsub("%s+$", "")
    
    return result
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
    
    -- UNIFIED PIPELINE: Process ALL wiki links with custom patterns (no frame:preprocess)
    local originalContent = content
    local result = content
    
    -- Process each wiki link pattern in sequence exactly like the original T-Campaign code
    for _, patternInfo in ipairs(WIKI_LINK_PATTERNS) do
        result = result:gsub(patternInfo.pattern, function(...)
            return patternInfo.processor(..., errorContext)
        end)
    end
    
    return result
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
    
    -- 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

return p