Module:SemanticAnnotations: Difference between revisions
// via Wikitext Extension for VSCode |
// via Wikitext Extension for VSCode |
||
| Line 145: | Line 145: | ||
-- Generate and return the annotations | -- Generate and return the annotations | ||
return p.generateAnnotations(parentArgs, mappings, options) | return p.generateAnnotations(parentArgs, mappings, options) | ||
end | |||
-- Helper function for processing a simple property mapping | |||
local function processSimpleMapping(properties, propertyName, value, transformFunc, defaultValue) | |||
-- Apply transform if one exists and we have a value | |||
if value and value ~= "" and transformFunc then | |||
value = transformFunc(value) | |||
end | |||
-- Use value if it exists, otherwise use default | |||
if value and value ~= "" then | |||
-- If property already exists, convert to array or append | |||
if properties[propertyName] then | |||
-- Convert to array if it's the first duplicate | |||
if type(properties[propertyName]) ~= "table" then | |||
properties[propertyName] = {properties[propertyName]} | |||
end | |||
-- Append new value | |||
table.insert(properties[propertyName], value) | |||
else | |||
-- First value for this property | |||
properties[propertyName] = value | |||
end | |||
elseif defaultValue then | |||
properties[propertyName] = defaultValue | |||
end | |||
end | |||
-- Helper function for processing a complex property mapping with metadata | |||
local function processComplexMapping(properties, propertyName, args, mappings, transformFunc) | |||
for _, mappingEntry in ipairs(mappings) do | |||
local param = mappingEntry.param | |||
local metadata = mappingEntry.metadata or {} | |||
local value = args[param] | |||
-- Process only if value exists | |||
if value and value ~= "" then | |||
-- Apply transform if available | |||
if transformFunc then | |||
value = transformFunc(value) | |||
end | |||
-- Add metadata qualifiers to property name if metadata exists | |||
local qualifiedProperty = propertyName | |||
if next(metadata) then | |||
local qualifiers = {} | |||
for metaKey, metaValue in pairs(metadata) do | |||
table.insert(qualifiers, metaKey .. "=" .. metaValue) | |||
end | |||
-- Sort for consistency | |||
table.sort(qualifiers) | |||
qualifiedProperty = propertyName .. "#" .. table.concat(qualifiers, ";") | |||
end | |||
-- Set the property with qualified name | |||
if properties[qualifiedProperty] then | |||
-- Convert to array if it's the first duplicate | |||
if type(properties[qualifiedProperty]) ~= "table" then | |||
properties[qualifiedProperty] = {properties[qualifiedProperty]} | |||
end | |||
-- Append new value | |||
table.insert(properties[qualifiedProperty], value) | |||
else | |||
-- First value for this property | |||
properties[qualifiedProperty] = value | |||
end | |||
end | |||
-- No need for goto continue - just continue the loop naturally | |||
end | |||
end | |||
-- Helper function for adding a simple property to parser function result | |||
local function addSimplePropertyToResult(result, propertyName, value, transformFunc, defaultValue) | |||
-- Apply transform if one exists and we have a value | |||
if value and value ~= "" and transformFunc then | |||
value = transformFunc(value) | |||
end | |||
-- Use value if it exists, otherwise use default | |||
if value and value ~= "" then | |||
table.insert(result, string.format(' |%s=%s', propertyName, value)) | |||
return 1 | |||
elseif defaultValue then | |||
table.insert(result, string.format(' |%s=%s', propertyName, defaultValue)) | |||
return 1 | |||
end | |||
return 0 | |||
end | end | ||
--[[ | --[[ | ||
Enhanced version of generateAnnotations that supports complex mappings | |||
Used as fallback when mw.smw is not available | |||
]] | |||
function p.generateEnhancedAnnotations(args, mappings, options) | |||
args = args or {} | |||
mappings = mappings or {} | |||
options = options or {} | |||
-- Set defaults for options | |||
local visible = options.visible or false | |||
local prefix = options.prefix or "" | |||
local transform = options.transform or {} | |||
local default = options.default or {} | |||
local conditional = options.conditional or {} | |||
-- Start building the annotation block | |||
local result = {} | |||
-- Determine if we need the hidden div wrapper | |||
if not visible then | |||
table.insert(result, '<div style="display:none;">') | |||
end | |||
-- Start the #set parser function | |||
table.insert(result, ' {{#set:') | |||
-- Process all property mappings | |||
local propertyCount = 0 | |||
-- Generate property sets for parser function | |||
for property, mapping in pairs(mappings) do | |||
local fullPropertyName = prefix .. property | |||
-- Handle different mapping types | |||
if type(mapping) == "string" then | |||
-- Legacy simple string mapping | |||
propertyCount = propertyCount + addSimplePropertyToResult(result, | |||
fullPropertyName, args[mapping], transform[property], default[property]) | |||
elseif type(mapping) == "table" then | |||
if mapping.param then | |||
-- Single mapping with object structure | |||
propertyCount = propertyCount + addSimplePropertyToResult(result, | |||
fullPropertyName, args[mapping.param], transform[property], default[property]) | |||
elseif mapping.mappings then | |||
-- Complex mapping with multiple parameters | |||
for _, mappingEntry in ipairs(mapping.mappings) do | |||
local param = mappingEntry.param | |||
local metadata = mappingEntry.metadata or {} | |||
local value = args[param] | |||
-- Process only if value exists | |||
if value and value ~= "" then | |||
-- Apply transform if available | |||
if transform[property] then | |||
value = transform[property](value) | |||
end | |||
-- Add metadata qualifiers to property name if metadata exists | |||
local qualifiedProperty = fullPropertyName | |||
if next(metadata) then | |||
local qualifiers = {} | |||
for metaKey, metaValue in pairs(metadata) do | |||
table.insert(qualifiers, metaKey .. "=" .. metaValue) | |||
end | |||
-- Sort for consistency | |||
table.sort(qualifiers) | |||
qualifiedProperty = fullPropertyName .. "#" .. table.concat(qualifiers, ";") | |||
end | |||
-- Add the property to result | |||
table.insert(result, string.format(' |%s=%s', qualifiedProperty, value)) | |||
propertyCount = propertyCount + 1 | |||
end | |||
-- No need for goto continue - just continue the loop naturally | |||
end | |||
end | |||
end | |||
end | |||
-- Handle conditional properties (maintain backwards compatibility) | |||
for property, condition in pairs(conditional) do | |||
local fullPropertyName = prefix .. property | |||
if args[condition.param] and args[condition.param] == condition.value then | |||
table.insert(result, string.format(' |%s=%s', fullPropertyName, condition.target or "true")) | |||
propertyCount = propertyCount + 1 | |||
end | |||
end | |||
-- Close the #set parser function | |||
table.insert(result, ' }}') | |||
-- Close the hidden div if we're using it | |||
if not visible then | |||
table.insert(result, '</div>') | |||
end | |||
-- If no properties were set, return an empty string | |||
if propertyCount == 0 then | |||
return "" | |||
end | |||
-- Join all lines and return | |||
return table.concat(result, "\n") | |||
end | |||
--[[ | |||
Enhanced version of setSemanticProperties that supports complex mappings | |||
@param args - Template parameters | @param args - Template parameters | ||
@param mappings - Property to parameter mappings | @param mappings - Property to parameter mappings with possible metadata | ||
Format can be: | |||
1. Simple: {["Property"] = "param_name"} | |||
2. Object: {["Property"] = {param = "param_name"}} | |||
3. Complex: {["Property"] = {mappings = {{param = "p1", metadata = {...}}, ...}}} | |||
@param options - Configuration options (same as generateAnnotations) | @param options - Configuration options (same as generateAnnotations) | ||
| Line 159: | Line 357: | ||
-- Check if mw.smw is available | -- Check if mw.smw is available | ||
if not mw.smw then | if not mw.smw then | ||
-- Fall back to | -- Fall back to enhanced parser function approach | ||
return p. | return p.generateEnhancedAnnotations(args, mappings, options) | ||
end | end | ||
| Line 171: | Line 369: | ||
local properties = {} | local properties = {} | ||
-- Process | -- Process all mappings | ||
for property, | for property, mapping in pairs(mappings) do | ||
local fullPropertyName = prefix .. property | local fullPropertyName = prefix .. property | ||
-- | -- Determine the type of mapping | ||
if | if type(mapping) == "string" then | ||
-- Legacy simple string mapping | |||
processSimpleMapping(properties, fullPropertyName, args[mapping], transform[property], default[property]) | |||
elseif type(mapping) == "table" then | |||
if mapping.param then | |||
-- Single mapping with object structure | |||
properties[ | processSimpleMapping(properties, fullPropertyName, args[mapping.param], transform[property], default[property]) | ||
elseif mapping.mappings then | |||
-- Complex mapping with multiple parameters | |||
processComplexMapping(properties, fullPropertyName, args, mapping.mappings, transform[property]) | |||
end | |||
end | end | ||
end | end | ||
| Line 201: | Line 400: | ||
return "" | return "" | ||
else | else | ||
return p. | return p.generateEnhancedAnnotations(args, mappings, options) | ||
end | end | ||
end | end | ||