Module:WikitextProcessor: Difference between revisions
Appearance
// via Wikitext Extension for VSCode |
// via Wikitext Extension for VSCode |
||
| Line 1: | Line 1: | ||
-- Module:WikitextProcessor | -- Module:WikitextProcessor | ||
-- | -- Clean, generalized content processor for wikitext formatting and frontend display | ||
-- Handles placeholder replacement, wiki link conversion to HTML, and content normalization | -- Handles placeholder replacement, wiki link conversion to HTML, and content normalization | ||
-- | |||
-- Features: | |||
-- - Simple, unified error handling | |||
-- - Three wiki link patterns: [[Page]], [[Page|text]], [[#anchor|text]] | |||
-- - Placeholder replacement with $VARIABLE$ syntax | |||
-- - Content normalization and whitespace cleanup | |||
-- - Resilient design that adapts to any context | |||
local p = {} | local p = {} | ||
| Line 8: | Line 15: | ||
local ErrorHandling = require('Module:ErrorHandling') | local ErrorHandling = require('Module:ErrorHandling') | ||
-- | -- Constants for performance | ||
local | local CONTEXT_NAME = 'wikitextProcessor' | ||
local ERROR_MESSAGES = { | local ERROR_MESSAGES = { | ||
urlFailed = 'URL generation failed for wiki link', | |||
encodeFailed = 'Text encoding failed for wiki link', | |||
formatFailed = 'HTML formatting failed for wiki link' | |||
} | } | ||
-- | -- Clean error handling | ||
local function handleError(errorContext, operation, fallbackValue) | |||
local function | |||
if errorContext then | if errorContext then | ||
ErrorHandling.addStatus(errorContext, CONTEXT_NAME, ERROR_MESSAGES[operation] or ERROR_MESSAGES.urlFailed, nil) | |||
end | end | ||
return fallbackValue | return fallbackValue | ||
| Line 81: | Line 37: | ||
pattern = '%[%[([^#|%]]+)%]%]', | pattern = '%[%[([^#|%]]+)%]%]', | ||
processor = function(pageName, errorContext) | processor = function(pageName, errorContext) | ||
local spacesReplaced = (pageName:gsub(' ', '_')) | local spacesReplaced = (pageName:gsub(' ', '_')) | ||
local | local success, pageUrl = pcall(function() | ||
return tostring(mw.uri.fullUrl(spacesReplaced)) | return tostring(mw.uri.fullUrl(spacesReplaced)) | ||
end) | end) | ||
if not success then | |||
if not | return handleError(errorContext, 'urlFailed', '[[' .. pageName .. ']]') | ||
return | |||
end | end | ||
local pageNameStr = type(pageName) == "string" and pageName or tostring(pageName) | local pageNameStr = type(pageName) == "string" and pageName or tostring(pageName) | ||
success, pageNameStr = pcall(mw.text.encode, pageNameStr) | |||
if not success then | |||
if not | return handleError(errorContext, 'encodeFailed', '[[' .. pageName .. ']]') | ||
return | |||
end | end | ||
success, pageUrl = pcall(string.format, '<a href="%s">%s</a>', pageUrl, pageNameStr) | |||
if not success then | |||
return handleError(errorContext, 'formatFailed', '[[' .. pageName .. ']]') | |||
if not | |||
return | |||
end | end | ||
return | return pageUrl | ||
end | end | ||
}, | }, | ||
| Line 120: | Line 64: | ||
pattern = '%[%[([^#|%]]+)|([^%]]+)%]%]', | pattern = '%[%[([^#|%]]+)|([^%]]+)%]%]', | ||
processor = function(pageName, text, errorContext) | processor = function(pageName, text, errorContext) | ||
local success, pageUrl = pcall(function() | |||
local | |||
return tostring(mw.uri.fullUrl((pageName:gsub(' ', '_')))) | return tostring(mw.uri.fullUrl((pageName:gsub(' ', '_')))) | ||
end) | end) | ||
if not success then | |||
if not | return handleError(errorContext, 'urlFailed', '[[' .. pageName .. '|' .. text .. ']]') | ||
return | |||
end | end | ||
local textStr = type(text) == "string" and text or tostring(text) | local textStr = type(text) == "string" and text or tostring(text) | ||
success, textStr = pcall(mw.text.encode, textStr) | |||
if not success then | |||
if not | return handleError(errorContext, 'encodeFailed', '[[' .. pageName .. '|' .. text .. ']]') | ||
return | |||
end | end | ||
success, pageUrl = pcall(string.format, '<a href="%s">%s</a>', pageUrl, textStr) | |||
if not success then | |||
return handleError(errorContext, 'formatFailed', '[[' .. pageName .. '|' .. text .. ']]') | |||
if not | |||
return | |||
end | end | ||
return | return pageUrl | ||
end | end | ||
}, | }, | ||
| Line 158: | Line 90: | ||
pattern = '%[%[#([^|%]]+)|([^%]]+)%]%]', | pattern = '%[%[#([^|%]]+)|([^%]]+)%]%]', | ||
processor = function(anchor, text, errorContext) | processor = function(anchor, text, errorContext) | ||
local success, encodedAnchor = pcall(mw.uri.anchorEncode, anchor) | |||
local | if not success then | ||
return handleError(errorContext, 'urlFailed', '[[#' .. anchor .. '|' .. text .. ']]') | |||
if not | |||
return | |||
end | end | ||
local textStr = type(text) == "string" and text or tostring(text) | local textStr = type(text) == "string" and text or tostring(text) | ||
success, textStr = pcall(mw.text.encode, textStr) | |||
if not success then | |||
if not | return handleError(errorContext, 'encodeFailed', '[[#' .. anchor .. '|' .. text .. ']]') | ||
return | |||
end | end | ||
success, encodedAnchor = pcall(string.format, '<a href="#%s">%s</a>', encodedAnchor, textStr) | |||
if not success then | |||
return handleError(errorContext, 'formatFailed', '[[#' .. anchor .. '|' .. text .. ']]') | |||
if not | |||
return | |||
end | end | ||
return | return encodedAnchor | ||
end | end | ||
} | } | ||
Revision as of 21:26, 1 August 2025
Documentation for this module may be created at Module:WikitextProcessor/doc
-- Module:WikitextProcessor
-- Clean, generalized content processor for wikitext formatting and frontend display
-- Handles placeholder replacement, wiki link conversion to HTML, and content normalization
--
-- Features:
-- - Simple, unified error handling
-- - Three wiki link patterns: [[Page]], [[Page|text]], [[#anchor|text]]
-- - Placeholder replacement with $VARIABLE$ syntax
-- - Content normalization and whitespace cleanup
-- - Resilient design that adapts to any context
local p = {}
-- Dependencies
local ErrorHandling = require('Module:ErrorHandling')
-- Constants for performance
local CONTEXT_NAME = 'wikitextProcessor'
local ERROR_MESSAGES = {
urlFailed = 'URL generation failed for wiki link',
encodeFailed = 'Text encoding failed for wiki link',
formatFailed = 'HTML formatting failed for wiki link'
}
-- Clean error handling
local function handleError(errorContext, operation, fallbackValue)
if errorContext then
ErrorHandling.addStatus(errorContext, CONTEXT_NAME, ERROR_MESSAGES[operation] or ERROR_MESSAGES.urlFailed, nil)
end
return fallbackValue
end
-- 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 success, pageUrl = pcall(function()
return tostring(mw.uri.fullUrl(spacesReplaced))
end)
if not success then
return handleError(errorContext, 'urlFailed', '[[' .. pageName .. ']]')
end
local pageNameStr = type(pageName) == "string" and pageName or tostring(pageName)
success, pageNameStr = pcall(mw.text.encode, pageNameStr)
if not success then
return handleError(errorContext, 'encodeFailed', '[[' .. pageName .. ']]')
end
success, pageUrl = pcall(string.format, '<a href="%s">%s</a>', pageUrl, pageNameStr)
if not success then
return handleError(errorContext, 'formatFailed', '[[' .. pageName .. ']]')
end
return pageUrl
end
},
-- Pattern 2: [[Page|text]] -> HTML page links with custom text
{
pattern = '%[%[([^#|%]]+)|([^%]]+)%]%]',
processor = function(pageName, text, errorContext)
local success, pageUrl = pcall(function()
return tostring(mw.uri.fullUrl((pageName:gsub(' ', '_'))))
end)
if not success then
return handleError(errorContext, 'urlFailed', '[[' .. pageName .. '|' .. text .. ']]')
end
local textStr = type(text) == "string" and text or tostring(text)
success, textStr = pcall(mw.text.encode, textStr)
if not success then
return handleError(errorContext, 'encodeFailed', '[[' .. pageName .. '|' .. text .. ']]')
end
success, pageUrl = pcall(string.format, '<a href="%s">%s</a>', pageUrl, textStr)
if not success then
return handleError(errorContext, 'formatFailed', '[[' .. pageName .. '|' .. text .. ']]')
end
return pageUrl
end
},
-- Pattern 3: [[#anchor|text]] -> HTML anchor links
{
pattern = '%[%[#([^|%]]+)|([^%]]+)%]%]',
processor = function(anchor, text, errorContext)
local success, encodedAnchor = pcall(mw.uri.anchorEncode, anchor)
if not success then
return handleError(errorContext, 'urlFailed', '[[#' .. anchor .. '|' .. text .. ']]')
end
local textStr = type(text) == "string" and text or tostring(text)
success, textStr = pcall(mw.text.encode, textStr)
if not success then
return handleError(errorContext, 'encodeFailed', '[[#' .. anchor .. '|' .. text .. ']]')
end
success, encodedAnchor = pcall(string.format, '<a href="#%s">%s</a>', encodedAnchor, textStr)
if not success then
return handleError(errorContext, 'formatFailed', '[[#' .. anchor .. '|' .. text .. ']]')
end
return encodedAnchor
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