Module:Main page: Difference between revisions

From MB Wiki
Jump to navigation Jump to search
No edit summary
Tag: Reverted
mNo edit summary
Tag: Manual revert
 
(9 intermediate revisions by 2 users not shown)
Line 4: Line 4:
-- merge args from frame and frame:getParent()
-- merge args from frame and frame:getParent()
function h.mergeArgs(frame)
function h.mergeArgs(frame)
local inputArgs = {}
    local inputArgs = {}
   
for k, v in pairs(frame.args) do
    -- Check if frame.args exists
v = mw.text.trim(tostring(v))
    if frame.args then
if v ~= '' then
        for k, v in pairs(frame.args) do
inputArgs[k] = v
            v = mw.text.trim(tostring(v))
end
            if v ~= '' then
end
                inputArgs[k] = v
            end
for k, v in pairs(frame:getParent().args) do
        end
v = mw.text.trim(v)
    end
if v ~= '' then
   
inputArgs[k] = v
    -- Check if frame:getParent() exists and has args
end
    local parent = frame:getParent()
end
    if parent and parent.args then
        for k, v in pairs(parent.args) do
return inputArgs
            v = mw.text.trim(tostring(v))
            if v ~= '' then
                inputArgs[k] = v
            end
        end
    end
   
    return inputArgs
end
end


Line 26: Line 33:


function p.main(frame)
function p.main(frame)
    if not frame then
        return "Error: No frame provided"
    end
   
    local args = h.mergeArgs(frame)
   
    -- use the rootpage parameter if given, otherwise use the current page name
    local rootpage = args['rootpage'] or mw.title.getCurrentTitle().fullText
   
    local layouts = {'desktop', 'tablet', 'mobile'}
   
    -- Initialize layout arguments if they don't exist
    for _, layout in pairs(layouts) do
        args[layout] = args[layout] or ''
        -- Clean up the layout string
        args[layout] = mw.text.trim(args[layout]):gsub("\n\n+", "\n"):gsub("  +", " "):gsub(" \n", "\n"):gsub("\n ", "\n")
       
        -- Check if columns are consistent in this layout (only if layout is not empty)
        if args[layout] ~= '' then
            local warn = false
            local last_column_count = 0
            local rows = mw.text.split(mw.text.trim(args[layout]), '\n')
            for _, row in pairs(rows) do
                if row ~= '' then
                    local current_column_count = #mw.text.split(row, '%s+')
                    if last_column_count == 0 then
                        last_column_count = current_column_count
                    elseif last_column_count ~= current_column_count then
                        warn = true
                    end
                end
            end
            if warn then
                mw.addWarning('ERROR: the ' .. layout .. ' layout does not have a consistent number of columns in each row. This will result in all the boxes merging into one.')
            end
        end
    end
   
    -- Parse the arguments into CSS variables
    local desktop_var = args['desktop'] ~= '' and "--main-page-layout--desktop: '" .. string.gsub(args['desktop'], '\n', "' '") .. "';" or ''
    local tablet_var = args['tablet'] ~= '' and "--main-page-layout--tablet: '" .. string.gsub(args['tablet'], '\n', "' '") .. "';" or ''
    local mobile_var = args['mobile'] ~= '' and "--main-page-layout--mobile: '" .. string.gsub(args['mobile'], '\n', "' '") .. "';" or ''
   
    -- grid-template-columns overrides
    local desktop_cols = mw.text.trim(string.gsub(args['desktop-columns'] or '', ';', ''))
    local tablet_cols = mw.text.trim(string.gsub(args['tablet-columns'] or '', ';', ''))
    local mobile_cols = mw.text.trim(string.gsub(args['mobile-columns'] or '', ';', ''))
   
    -- Set the variables used by grid-template-columns
    if desktop_cols ~= '' then
        desktop_var = desktop_var .. '--main-page-layout-columns--desktop: '.. desktop_cols ..';'
    end
    if tablet_cols ~= '' then
        tablet_var = tablet_var .. '--main-page-layout-columns--tablet: '.. tablet_cols ..';'
    end
    if mobile_cols ~= '' then
        mobile_var = mobile_var .. '--main-page-layout-columns--mobile: '.. mobile_cols ..';'
    end


local args = h.mergeArgs(frame)
    local boxes = {}
    local seen_boxes = {}
-- use the rootpage parameter if given, otherwise use the current page name
    local boxes_in_layout = {}
local rootpage = args['rootpage'] or mw.title.getCurrentTitle().fullText
    local missing_boxes = {}
   
local layouts = {'desktop', 'tablet', 'mobile'}
    -- Function to parse layout (moved inside main to access args)
    local function parse_layout(layout)
for _,layout in pairs(layouts) do
        if args[layout] and args[layout] ~= '' then
-- collapse consecutive line breaks and spaces, then trim
            for _, name in pairs(mw.text.split(mw.text.trim(args[layout]), '%s+')) do
-- we need to check for permutations of " \n" because trim can't clean that up if it's in the middle of the string
                if name ~= '' then
args[layout] = mw.text.trim(args[layout]):gsub("\n\n+", "\n"):gsub("  +", " "):gsub(" \n", "\n"):gsub("\n ", "\n")
                    if not seen_boxes[name] then
                        boxes[#boxes + 1] = name
-- check if columns are consistent in this layout
                        seen_boxes[name] = true
local warn = false
                    end
local last_column_count = 0
                    boxes_in_layout[layout][name] = true
local current_column_count = 0
                end
for _,row in pairs(mw.text.split(mw.text.trim(args[layout]), '\n')) do
            end
current_column_count = #mw.text.split(row, '%s') --count elements in this row
        end
if last_column_count == 0 then
    end
last_column_count = current_column_count
   
elseif last_column_count ~= current_column_count then
    -- Loop through the layouts to set up the box lists
warn = true
    for _, layout in pairs(layouts) do
end
        boxes_in_layout[layout] = {}
end
        missing_boxes[layout] = {}
if warn then
        parse_layout(layout)
mw.addWarning( 'ERROR: the ' .. layout .. ' layout does not have a consistent number of columns in each row. This will result in all the boxes merging into one.')
    end
end
   
end
    -- Check for missing boxes in each layout
    for _, layout in pairs(layouts) do
-- parse the arguments into CSS variables that contain legal syntax for grid-template-areas
        for _, name in pairs(boxes) do
local desktop_var = "--main-page-layout--desktop: '" .. string.gsub(args['desktop'], '\n', "' '") .. "';"
            if not boxes_in_layout[layout][name] then
local tablet_var =  "--main-page-layout--tablet: '"  .. string.gsub(args['tablet' ], '\n', "' '") .. "';"
                mw.addWarning('WARNING: the "' .. name .. '" box is missing in the ' .. layout .. ' layout. If this is intentional, you can ignore this warning.')
local mobile_var =  "--main-page-layout--mobile: '"  .. string.gsub(args['mobile' ], '\n', "' '") .. "';"
                missing_boxes[layout][name] = true
            end
-- grid-template-columns overrides
        end
local desktop_cols = mw.text.trim(string.gsub(args['desktop-columns'] or '', ';', ''))
    end
local  tablet_cols = mw.text.trim(string.gsub(args[ 'tablet-columns'] or '', ';', ''))
   
local  mobile_cols = mw.text.trim(string.gsub(args[ 'mobile-columns'] or '', ';', ''))
    -- Start our mp-container wrapper
    local output = mw.html.create('div')
-- set the variables used by grid-template-columns
    output:attr('id', 'mp-container')
if desktop_cols ~= '' then
        :cssText(desktop_var .. tablet_var .. mobile_var)
desktop_var = desktop_var .. '--main-page-layout-columns--desktop: '.. desktop_cols ..';'
        :attr('data-rootpage', rootpage)
end
   
if tablet_cols ~= '' then
    -- Loop through boxes and add the relevant main page subpages
tablet_var = tablet_var .. '--main-page-layout-columns--tablet: '.. tablet_cols ..';'
    for _, box in pairs(boxes) do
end
        -- FIX: Check if VariablesLua exists before using it
if mobile_cols ~= '' then
        if mw.ext and mw.ext.VariablesLua then
mobile_var = mobile_var .. '--main-page-layout-columns--mobile: '.. mobile_cols ..';'
            mw.ext.VariablesLua.vardefine('imp-variable-id', box)
end
           
            local pre_vardefine = ''
            for _, layout in pairs(layouts) do
                pre_vardefine = pre_vardefine .. (missing_boxes[layout][box] and '0' or '1') .. ','
            end
           
            mw.ext.VariablesLua.vardefine('imp-variable-display-box', pre_vardefine)
        else
            -- Alternative: Use frame:preprocess to set variables
            frame:preprocess('{{#vardefine:imp-variable-id|' .. box .. '}}')
           
            local pre_vardefine = ''
            for _, layout in pairs(layouts) do
                pre_vardefine = pre_vardefine .. (missing_boxes[layout][box] and '0' or '1') .. ','
            end
           
            frame:preprocess('{{#vardefine:imp-variable-display-box|' .. pre_vardefine .. '}}')
        end
       
        local box_page = rootpage .. '/' .. box
        if mw.title.new(box_page).exists then
            output:wikitext(frame:expandTemplate{ title = ':' .. box_page })
        else
            output:wikitext(frame:expandTemplate{
                title = 'Main page box/missing',
                args = { box, rootpage = rootpage }
            })
        end
    end
   
    return tostring(output)
end


local boxes = {} -- list of all boxes as a simple list, used to set the order of appearance
-- Add show function for compatibility
local seen_boxes = {} -- list of all boxes as a k:v pair, used to filter out duplicates
function p.show(frame)
local boxes_in_layout = {} -- list of layouts, then list of all boxes in that layout
    return p.main(frame)
local missing_boxes = {} -- list of layouts, then list of boxes that are *not* included in that layout
-- add every box referenced in the layout rules once
function parse_layout(layout)
for _,name in pairs(mw.text.split(mw.text.trim(args[layout]), '%s')) do
if not seen_boxes[name] then
boxes[#boxes+1] = name -- table with numerical keys for set html order
seen_boxes[name] = true
end
boxes_in_layout[layout][name] = true
end
end
-- loop through the layouts the first time to set up the box lists
for _,layout in pairs(layouts) do
boxes_in_layout[layout] = {}
missing_boxes[layout] = {}
parse_layout(layout)
end
-- then loop through the layouts a second time because we need to compare those completed lists to check for missing boxes
for _,layout in pairs(layouts) do
for _,name in pairs(boxes) do
if boxes_in_layout[layout][name] ~= true then
mw.addWarning( 'WARNING: the \"' .. name .. '\" box is missing in the ' .. layout .. ' layout. If this is intentional, you can ignore this warning.')
missing_boxes[layout][name] = true
end
end
end
-- start our mp-container wrapper, and add our variables from earlier as inline styles to declare them
-- the rootpage is added to the dataset so it's easily accessible by mp-edit-links.js and it doesn't need to make its own API call
local output = mw.html.create()
local container = output:tag('div'):attr('id', 'mp-container'):cssText(desktop_var .. tablet_var .. mobile_var):attr('data-rootpage', rootpage)
-- loop through boxes and add the relevant main page subpages into the output
for _,box in pairs(boxes) do
mw.ext.VariablesLua.vardefine('imp-variable-id', box) -- using a vardefine lets us pass this directly to the template without going through the user-facing box
local pre_vardefine = ''
for _,layout in pairs(layouts) do
pre_vardefine = pre_vardefine .. (missing_boxes[layout][box] and '0' or '1') .. ','
end
-- formatted as a psuedo-bitmask to reduce variable usage, "<display-on-destop>, <display-on-tablet>, <display-on-mobile>," each value is 0 or 1 (trailing comma is insignificant)
-- expected to be used with #explode in the template receiving the variable
mw.ext.VariablesLua.vardefine('imp-variable-display-box', pre_vardefine)
if mw.title.new(rootpage .. '/' .. box).exists then
container:wikitext(frame:expandTemplate{ title = ':' .. rootpage .. '/' .. box})
else
container:wikitext(frame:expandTemplate{ title = 'Main page box/missing', args = { box, rootpage = rootpage}}) -- See [[Template:Main page box/missing]]
end
end
return output
end
end


return p
return p

Latest revision as of 16:27, 10 December 2025


local p = {}
local h = {}

-- merge args from frame and frame:getParent()
function h.mergeArgs(frame)
    local inputArgs = {}
    
    -- Check if frame.args exists
    if frame.args then
        for k, v in pairs(frame.args) do
            v = mw.text.trim(tostring(v))
            if v ~= '' then
                inputArgs[k] = v
            end
        end
    end
    
    -- Check if frame:getParent() exists and has args
    local parent = frame:getParent()
    if parent and parent.args then
        for k, v in pairs(parent.args) do
            v = mw.text.trim(tostring(v))
            if v ~= '' then
                inputArgs[k] = v
            end
        end
    end
    
    return inputArgs
end

--------------------------------------------------------------------

function p.main(frame)
    if not frame then
        return "Error: No frame provided"
    end
    
    local args = h.mergeArgs(frame)
    
    -- use the rootpage parameter if given, otherwise use the current page name
    local rootpage = args['rootpage'] or mw.title.getCurrentTitle().fullText
    
    local layouts = {'desktop', 'tablet', 'mobile'}
    
    -- Initialize layout arguments if they don't exist
    for _, layout in pairs(layouts) do
        args[layout] = args[layout] or ''
        -- Clean up the layout string
        args[layout] = mw.text.trim(args[layout]):gsub("\n\n+", "\n"):gsub("  +", " "):gsub(" \n", "\n"):gsub("\n ", "\n")
        
        -- Check if columns are consistent in this layout (only if layout is not empty)
        if args[layout] ~= '' then
            local warn = false
            local last_column_count = 0
            local rows = mw.text.split(mw.text.trim(args[layout]), '\n')
            for _, row in pairs(rows) do
                if row ~= '' then
                    local current_column_count = #mw.text.split(row, '%s+')
                    if last_column_count == 0 then
                        last_column_count = current_column_count
                    elseif last_column_count ~= current_column_count then
                        warn = true
                    end
                end
            end
            if warn then
                mw.addWarning('ERROR: the ' .. layout .. ' layout does not have a consistent number of columns in each row. This will result in all the boxes merging into one.')
            end
        end
    end
    
    -- Parse the arguments into CSS variables
    local desktop_var = args['desktop'] ~= '' and "--main-page-layout--desktop: '" .. string.gsub(args['desktop'], '\n', "' '") .. "';" or ''
    local tablet_var = args['tablet'] ~= '' and "--main-page-layout--tablet: '" .. string.gsub(args['tablet'], '\n', "' '") .. "';" or ''
    local mobile_var = args['mobile'] ~= '' and "--main-page-layout--mobile: '" .. string.gsub(args['mobile'], '\n', "' '") .. "';" or ''
    
    -- grid-template-columns overrides
    local desktop_cols = mw.text.trim(string.gsub(args['desktop-columns'] or '', ';', ''))
    local tablet_cols = mw.text.trim(string.gsub(args['tablet-columns'] or '', ';', ''))
    local mobile_cols = mw.text.trim(string.gsub(args['mobile-columns'] or '', ';', ''))
    
    -- Set the variables used by grid-template-columns
    if desktop_cols ~= '' then
        desktop_var = desktop_var .. '--main-page-layout-columns--desktop: '.. desktop_cols ..';'
    end
    if tablet_cols ~= '' then
        tablet_var = tablet_var .. '--main-page-layout-columns--tablet: '.. tablet_cols ..';'
    end
    if mobile_cols ~= '' then
        mobile_var = mobile_var .. '--main-page-layout-columns--mobile: '.. mobile_cols ..';'
    end

    local boxes = {}
    local seen_boxes = {}
    local boxes_in_layout = {}
    local missing_boxes = {}
    
    -- Function to parse layout (moved inside main to access args)
    local function parse_layout(layout)
        if args[layout] and args[layout] ~= '' then
            for _, name in pairs(mw.text.split(mw.text.trim(args[layout]), '%s+')) do
                if name ~= '' then
                    if not seen_boxes[name] then
                        boxes[#boxes + 1] = name
                        seen_boxes[name] = true
                    end
                    boxes_in_layout[layout][name] = true
                end
            end
        end
    end
    
    -- Loop through the layouts to set up the box lists
    for _, layout in pairs(layouts) do
        boxes_in_layout[layout] = {}
        missing_boxes[layout] = {}
        parse_layout(layout)
    end
    
    -- Check for missing boxes in each layout
    for _, layout in pairs(layouts) do
        for _, name in pairs(boxes) do
            if not boxes_in_layout[layout][name] then
                mw.addWarning('WARNING: the "' .. name .. '" box is missing in the ' .. layout .. ' layout. If this is intentional, you can ignore this warning.')
                missing_boxes[layout][name] = true
            end
        end
    end
    
    -- Start our mp-container wrapper
    local output = mw.html.create('div')
    output:attr('id', 'mp-container')
        :cssText(desktop_var .. tablet_var .. mobile_var)
        :attr('data-rootpage', rootpage)
    
    -- Loop through boxes and add the relevant main page subpages
    for _, box in pairs(boxes) do
        -- FIX: Check if VariablesLua exists before using it
        if mw.ext and mw.ext.VariablesLua then
            mw.ext.VariablesLua.vardefine('imp-variable-id', box)
            
            local pre_vardefine = ''
            for _, layout in pairs(layouts) do
                pre_vardefine = pre_vardefine .. (missing_boxes[layout][box] and '0' or '1') .. ','
            end
            
            mw.ext.VariablesLua.vardefine('imp-variable-display-box', pre_vardefine)
        else
            -- Alternative: Use frame:preprocess to set variables
            frame:preprocess('{{#vardefine:imp-variable-id|' .. box .. '}}')
            
            local pre_vardefine = ''
            for _, layout in pairs(layouts) do
                pre_vardefine = pre_vardefine .. (missing_boxes[layout][box] and '0' or '1') .. ','
            end
            
            frame:preprocess('{{#vardefine:imp-variable-display-box|' .. pre_vardefine .. '}}')
        end
        
        local box_page = rootpage .. '/' .. box
        if mw.title.new(box_page).exists then
            output:wikitext(frame:expandTemplate{ title = ':' .. box_page })
        else
            output:wikitext(frame:expandTemplate{ 
                title = 'Main page box/missing', 
                args = { box, rootpage = rootpage }
            })
        end
    end
    
    return tostring(output)
end

-- Add show function for compatibility
function p.show(frame)
    return p.main(frame)
end

return p