Jump to content

Module:SemanticAnnotations: Difference between revisions

// via Wikitext Extension for VSCode
// via Wikitext Extension for VSCode
Line 1: Line 1:
-- Module:SemanticAnnotations
-- Module:SemanticAnnotations
-- A dedicated module for generating semantic annotations for templates
-- Generates semantic annotations for templates
-- Compatible with Semantic MediaWiki, Semantic Scribunto, Semantic Drilldown, and DynamicPageList3
-- Compatible with Semantic MediaWiki, Semantic Scribunto, Semantic Drilldown, and DynamicPageList3
-- Annotations via Lua documentation: https://github.com/SemanticMediaWiki/SemanticScribunto/tree/master/docs
-- Docs: https://github.com/SemanticMediaWiki/SemanticScribunto/tree/master/docs


local p = {}
local p = {}
Line 12: Line 12:


--[[
--[[
     p.generateAnnotations(args, mappings)
     Generates semantic annotations using SMW's #set parser function.
      
      
     Generates semantic annotations for MediaWiki templates using SMW's #set parser function.
     @param args    - Template parameters table
    @param mappings - Property to parameter mappings: {["Property"] = "param_name", ...}
    @param options  - Configuration options:
                    {
                      visible = false,  -- Show annotations (default: false)
                      prefix = "",      -- Property prefix
                      transform = {},    -- Transform functions: {["Property"] = function(val) ... end}
                      default = {},      -- Default values: {["Property"] = "default"}
                      conditional = {},  -- Conditional mappings: {["Property"] = {param="x", value="y"}}
                    }
      
      
     Parameters:
     @return Wikitext string containing semantic annotations
      args    - Table of template parameters.
      mappings - Table with mappings from semantic properties to template parameters:
                {
                    ["Has property name"] = "template_param_name",
                    ["Has another property"] = "another_param",
                    ...
                }
      options  - Optional table of configuration options:
                {
                    visible    = false,    -- Whether annotations should be visible (default: false)
                    prefix    = "",        -- Optional prefix for all properties
                    transform  = {},        -- Table of transform functions for specific properties
                                            -- e.g. { ["Has date"] = function(val) return format(val) end }
                    default    = {},        -- Default values for properties if arg is missing
                                            -- e.g. { ["Has type"] = "article" }
                    conditional = {},      -- Conditional property mapping that depend on other args
                                            -- e.g. { ["Has special"] = { param = "type", value = "special" } }
                }
   
    Returns:
      A string containing the wikitext for the semantic annotations.
]]
]]
function p.generateAnnotations(args, mappings, options)
function p.generateAnnotations(args, mappings, options)
Line 112: Line 100:


--[[
--[[
    p.renderWithSemantics(args, config, semanticMappings, semanticOptions)
   
     Renders a table using TemplateStructure and adds semantic annotations.
     Renders a table using TemplateStructure and adds semantic annotations.
      
      
     Parameters:
     @param args            - Template parameters
      args            - Table of template parameters.
    @param config          - TemplateStructure configuration
      config          - Configuration for TemplateStructure.render.
    @param semanticMappings - Property to parameter mappings
      semanticMappings - Mappings from semantic properties to template parameters.
    @param semanticOptions  - Annotation configuration options
      semanticOptions  - Optional configuration for semantic annotations.
      
      
     Returns:
     @return Rendered template with semantic annotations
      A string containing the rendered template with semantic annotations.
]]
]]
function p.renderWithSemantics(args, config, semanticMappings, semanticOptions)
function p.renderWithSemantics(args, config, semanticMappings, semanticOptions)
Line 138: Line 122:
end
end


-- This function is an alternative to using the full renderWithSemantics.
-- Allows templates to append semantic annotations directly via transclusion
-- It allows direct template transcusions to just append semantic annotations.
function p.appendToTemplate(frame)
function p.appendToTemplate(frame)
     local args = frame.args
     local args = frame.args
Line 165: Line 148:


--[[
--[[
    p.setSemanticProperties(args, mappings, options)
     Sets semantic properties using mw.smw API when available, with parser function fallback.
   
     Sets semantic properties using the native mw.smw API when available,
    falling back to the parser function approach if not.
      
      
     Parameters:
     @param args    - Template parameters
      args    - Table of template parameters.
    @param mappings - Property to parameter mappings
      mappings - Table with mappings from semantic properties to template parameters.
    @param options  - Configuration options (same as generateAnnotations)
      options  - Optional configuration options (same as generateAnnotations).
      
      
     Returns:
     @return Empty string if set via mw.smw, or generated annotations string
      Empty string if properties were set via mw.smw, otherwise the generated annotations.
]]
]]
function p.setSemanticProperties(args, mappings, options)
function p.setSemanticProperties(args, mappings, options)

Revision as of 01:23, 31 March 2025

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

-- Module:SemanticAnnotations
-- Generates semantic annotations for templates
-- Compatible with Semantic MediaWiki, Semantic Scribunto, Semantic Drilldown, and DynamicPageList3
-- Docs: https://github.com/SemanticMediaWiki/SemanticScribunto/tree/master/docs

local p = {}

-- Private helper function to trim whitespace
local function trim(s)
    return (s:gsub("^%s+", ""):gsub("%s+$", ""))
end

--[[
    Generates semantic annotations using SMW's #set parser function.
    
    @param args     - Template parameters table
    @param mappings - Property to parameter mappings: {["Property"] = "param_name", ...}
    @param options  - Configuration options:
                     {
                       visible = false,   -- Show annotations (default: false)
                       prefix = "",       -- Property prefix
                       transform = {},    -- Transform functions: {["Property"] = function(val) ... end}
                       default = {},      -- Default values: {["Property"] = "default"}
                       conditional = {},  -- Conditional mappings: {["Property"] = {param="x", value="y"}}
                     }
    
    @return Wikitext string containing semantic annotations
]]
function p.generateAnnotations(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
    
    -- Handle regular property mappings
    for property, param in pairs(mappings) do
        local fullPropertyName = prefix .. property
        local value = args[param]
        
        -- Apply transform if one exists for this property
        if value and transform[property] then
            value = transform[property](value)
        end
        
        -- Use the value if it exists, otherwise use default if provided
        if value and value ~= "" then
            table.insert(result, string.format('    |%s=%s', fullPropertyName, value))
            propertyCount = propertyCount + 1
        elseif default[property] then
            table.insert(result, string.format('    |%s=%s', fullPropertyName, default[property]))
            propertyCount = propertyCount + 1
        end
    end
    
    -- Handle conditional properties
    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

--[[
    Renders a table using TemplateStructure and adds semantic annotations.
    
    @param args             - Template parameters
    @param config           - TemplateStructure configuration
    @param semanticMappings - Property to parameter mappings
    @param semanticOptions  - Annotation configuration options
    
    @return Rendered template with semantic annotations
]]
function p.renderWithSemantics(args, config, semanticMappings, semanticOptions)
    local TemplateStructure = require('Module:TemplateStructure')
    
    -- Render the table structure
    local renderedTable = TemplateStructure.render(args, config)
    
    -- Generate the semantic annotations
    local annotations = p.generateAnnotations(args, semanticMappings, semanticOptions)
    
    -- Combine and return
    return renderedTable .. "\n" .. annotations
end

-- Allows templates to append semantic annotations directly via transclusion
function p.appendToTemplate(frame)
    local args = frame.args
    local parent = frame:getParent()
    local parentArgs = parent and parent.args or {}
    
    -- Mapping is defined as pairs of properties and parameters
    local mappings = {}
    local i = 1
    
    while args["property" .. i] and args["param" .. i] do
        mappings[args["property" .. i]] = args["param" .. i]
        i = i + 1
    end
    
    -- Extract options
    local options = {
        visible = args.visible == "true",
        prefix = args.prefix or ""
    }
    
    -- Generate and return the annotations
    return p.generateAnnotations(parentArgs, mappings, options)
end

--[[
    Sets semantic properties using mw.smw API when available, with parser function fallback.
    
    @param args     - Template parameters
    @param mappings - Property to parameter mappings
    @param options  - Configuration options (same as generateAnnotations)
    
    @return Empty string if set via mw.smw, or generated annotations string
]]
function p.setSemanticProperties(args, mappings, options)
    -- Check if mw.smw is available
    if not mw.smw then
        -- Fall back to the parser function approach if mw.smw is not available
        return p.generateAnnotations(args, mappings, options)
    end
    
    options = options or {}
    local transform = options.transform or {}
    local default = options.default or {}
    local prefix = options.prefix or ""
    
    -- Build the property table for mw.smw.set
    local properties = {}
    
    -- Process regular mappings
    for property, param in pairs(mappings) do
        local fullPropertyName = prefix .. property
        local value = args[param]
        
        -- Apply transform if one exists
        if value and transform[property] then
            value = transform[property](value)
        end
        
        -- Use value if it exists, otherwise use default
        if value and value ~= "" then
            properties[fullPropertyName] = value
        elseif default[property] then
            properties[fullPropertyName] = default[property]
        end
    end
    
    -- Only set properties if we have some
    if next(properties) then
        -- Set the properties using the native SMW interface
        local success, result = pcall(function()
            return mw.smw.set(properties)
        end)
        
        -- If successful, return empty string (properties are set behind the scenes)
        -- If failed, fall back to parser function approach
        if success then
            return ""
        else
            return p.generateAnnotations(args, mappings, options)
        end
    end
    
    return ""
end

return p