Module:TemplateStructure: Difference between revisions
Appearance
// via Wikitext Extension for VSCode |
// via Wikitext Extension for VSCode |
||
| Line 1: | Line 1: | ||
-- Module:TemplateStructure | -- Module:TemplateStructure | ||
-- A module for rendering templates using a modular, block-based approach with error handling. | |||
local p = {} | local p = {} | ||
| Line 6: | Line 7: | ||
local function trim(s) | local function trim(s) | ||
return (s:gsub("^%s+", ""):gsub("%s+$", "")) | return (s:gsub("^%s+", ""):gsub("%s+$", "")) | ||
end | |||
-- Format an error as an HTML comment for debugging | |||
local function formatErrorComment(blockIndex, errorMsg) | |||
return string.format( | |||
"<!-- WARNING COMMENT: Block #%d failed with error: %s -->", | |||
blockIndex, | |||
tostring(errorMsg) | |||
) | |||
end | end | ||
| Line 20: | Line 30: | ||
blocks: Functions that generate table rows | blocks: Functions that generate table rows | ||
Each accepts (args, config) and returns a string | Each accepts (args, config) and returns a string | ||
continueOnError: Continue rendering if a block fails (default: true) | |||
Returns: | Returns: | ||
| Line 29: | Line 40: | ||
local tableAttrs = config.tableAttrs or 'cellpadding="2"' | local tableAttrs = config.tableAttrs or 'cellpadding="2"' | ||
local blocks = config.blocks or {} | local blocks = config.blocks or {} | ||
local continueOnError = config.continueOnError | |||
if continueOnError == nil then continueOnError = true end -- Default to true | |||
-- Begin the table markup. | -- Begin the table markup. | ||
local result = {} | local result = {} | ||
table.insert(result, string.format('{| class="%s" %s', tableClass, tableAttrs)) | table.insert(result, string.format('{| class="%s" %s', tableClass, tableAttrs)) | ||
-- Track errors for debugging | |||
local errors = {} | |||
-- Process each block function in the supplied order. | -- Process each block function in the supplied order. | ||
for i, block in ipairs(blocks) do | for i, block in ipairs(blocks) do | ||
if type(block) == "function" then | if type(block) == "function" then | ||
local blockOutput = block(args, config) | -- Protect block execution to avoid template failure | ||
blockOutput = trim(blockOutput) | local success, blockOutput = pcall(function() | ||
return block(args, config) | |||
table.insert(result, blockOutput) | end) | ||
if success then | |||
blockOutput = trim(blockOutput) | |||
if blockOutput ~= "" then | |||
table.insert(result, blockOutput) | |||
end | |||
else | |||
-- Record error | |||
table.insert(errors, { | |||
blockIndex = i, | |||
error = blockOutput -- In pcall, error message is returned as second value | |||
}) | |||
-- Add error comment | |||
table.insert(result, "<!-- WARNING COMMENT: Block #" .. i .. " failed with error: " .. tostring(blockOutput) .. " -->") | |||
-- If we shouldn't continue on error, break the loop | |||
if not continueOnError then | |||
break | |||
end | |||
end | end | ||
else | else | ||
-- Add warning | -- Add warning for non-function blocks | ||
table.insert(result, "<!-- | table.insert(result, "<!-- WARNING COMMENT: Block #" .. i .. " is not a function and will be skipped. -->") | ||
end | end | ||
end | end | ||
-- Close the table | |||
table.insert(result, "|}") | table.insert(result, "|}") | ||
-- Add error debug comments if any errors occurred | |||
if #errors > 0 then | |||
local errorOutput = {"<!-- TEMPLATE_STRUCTURE_DEBUG: errors=" .. #errors} | |||
for i, err in ipairs(errors) do | |||
table.insert(errorOutput, " E" .. i .. "=Block" .. err.blockIndex .. ":" .. tostring(err.error)) | |||
end | |||
table.insert(errorOutput, " -->") | |||
table.insert(result, table.concat(errorOutput, "")) | |||
end | |||
local finalOutput = table.concat(result, "\n") | local finalOutput = table.concat(result, "\n") | ||
Revision as of 04:50, 11 April 2025
Documentation for this module may be created at Module:TemplateStructure/doc
-- Module:TemplateStructure
-- A module for rendering templates using a modular, block-based approach with error handling.
local p = {}
-- Local trim function: removes leading and trailing whitespace.
local function trim(s)
return (s:gsub("^%s+", ""):gsub("%s+$", ""))
end
-- Format an error as an HTML comment for debugging
local function formatErrorComment(blockIndex, errorMsg)
return string.format(
"<!-- WARNING COMMENT: Block #%d failed with error: %s -->",
blockIndex,
tostring(errorMsg)
)
end
--[[
p.render(args, config)
Renders a table using a modular, block-based approach.
Parameters:
args - Template parameters (passed to each block function)
config - Configuration options:
tableClass: CSS class for the table (default: "template-table")
tableAttrs: Additional table attributes (default: 'cellpadding="2"')
blocks: Functions that generate table rows
Each accepts (args, config) and returns a string
continueOnError: Continue rendering if a block fails (default: true)
Returns:
Wikitext markup for the complete table
]]
function p.render(args, config)
config = config or {}
local tableClass = config.tableClass or "template-table"
local tableAttrs = config.tableAttrs or 'cellpadding="2"'
local blocks = config.blocks or {}
local continueOnError = config.continueOnError
if continueOnError == nil then continueOnError = true end -- Default to true
-- Begin the table markup.
local result = {}
table.insert(result, string.format('{| class="%s" %s', tableClass, tableAttrs))
-- Track errors for debugging
local errors = {}
-- Process each block function in the supplied order.
for i, block in ipairs(blocks) do
if type(block) == "function" then
-- Protect block execution to avoid template failure
local success, blockOutput = pcall(function()
return block(args, config)
end)
if success then
blockOutput = trim(blockOutput)
if blockOutput ~= "" then
table.insert(result, blockOutput)
end
else
-- Record error
table.insert(errors, {
blockIndex = i,
error = blockOutput -- In pcall, error message is returned as second value
})
-- Add error comment
table.insert(result, "<!-- WARNING COMMENT: Block #" .. i .. " failed with error: " .. tostring(blockOutput) .. " -->")
-- If we shouldn't continue on error, break the loop
if not continueOnError then
break
end
end
else
-- Add warning for non-function blocks
table.insert(result, "<!-- WARNING COMMENT: Block #" .. i .. " is not a function and will be skipped. -->")
end
end
-- Close the table
table.insert(result, "|}")
-- Add error debug comments if any errors occurred
if #errors > 0 then
local errorOutput = {"<!-- TEMPLATE_STRUCTURE_DEBUG: errors=" .. #errors}
for i, err in ipairs(errors) do
table.insert(errorOutput, " E" .. i .. "=Block" .. err.blockIndex .. ":" .. tostring(err.error))
end
table.insert(errorOutput, " -->")
table.insert(result, table.concat(errorOutput, ""))
end
local finalOutput = table.concat(result, "\n")
return trim(finalOutput)
end
return p