Module:NavboxMobile: Difference between revisions

No edit summary
No edit summary
 
(162 intermediate revisions by the same user not shown)
Line 1: Line 1:
-- Module:NavboxMobile
-- This module implements {{navbox}} for MobileFrontend
-- This module implements {{navbox}} for MobileFrontend


Line 6: Line 7:
local cfg = mw.loadData('Module:NavboxMobile/configuration')
local cfg = mw.loadData('Module:NavboxMobile/configuration')
local navbar = require('Module:Navbar')._navbar
local navbar = require('Module:Navbar')._navbar
local getArgs -- lazily initialized
local getArgs -- Lazily initialized
local inArray = require('Module:TableTools').inArray
local inArray = require('Module:TableTools').inArray
local format = string.format
local format = string.format
Line 15: Line 16:
local listnums = {}
local listnums = {}


local function addNavboxMobileStyles()
-- Function to check if the given HTML class is a list class
local function has_list_class(htmlclass)
    local patterns = {
        '^' .. htmlclass .. '$',
        '%s' .. htmlclass .. '$',
        '^' .. htmlclass .. '%s',
        '%s' .. htmlclass .. '%s'
    }
   
    for arg, _ in pairs(args) do
        if type(arg) == 'string' and mw.ustring.find(arg, cfg.pattern.class) then
            for _, pattern in ipairs(patterns) do
                if mw.ustring.find(args[arg] or '', pattern) then
                    return true
                end
            end
        end
    end
    return false
end
 
-- Function to check if the navbar is enabled
local function has_navbar()
    return args[cfg.arg.navbar] ~= cfg.keyword.navbar_off
        and args[cfg.arg.navbar] ~= cfg.keyword.navbar_plain
        and (
            args[cfg.arg.name]
            or mw.getCurrentFrame():getParent():getTitle():gsub(cfg.pattern.sandbox, '')
                ~= cfg.pattern.navbox
        )
end
 
 
local function add_list_styles()
     local frame = mw.getCurrentFrame()
     local frame = mw.getCurrentFrame()
     return frame:extensionTag{
     local function add_list_templatestyles(htmlclass, templatestyles)
         name = 'templatestyles',
        if has_list_class(htmlclass) then
         args = { src = 'Module:NavboxMobile/styles.css' }
            return frame:extensionTag{
     }
                name = 'templatestyles', args = { src = templatestyles }
            }
        else
            return ''
        end
    end
          
    local hlist_styles = add_list_templatestyles('hlist', cfg.hlist_templatestyles)
    local plainlist_styles = add_list_templatestyles('plainlist', cfg.plainlist_templatestyles)
   
    -- a second workaround for [[phab:T303378]]
    -- when that issue is fixed, we can actually use has_navbar not to emit the
    -- tag here if we want
    if has_navbar() and hlist_styles == '' then
        hlist_styles = frame:extensionTag{
            name = 'templatestyles', args = { src = cfg.hlist_templatestyles }
         }
    end
   
    -- hlist -> plainlist is best-effort to preserve old Common.css ordering.
    -- this ordering is not a guarantee because most navboxes will emit only
    -- one of these classes [hlist_note]
    return hlist_styles .. plainlist_styles
end
 
-- Analogous function to add_navbox_styles from Module:Navbox
local function add_navbox_mobile_styles(hiding_templatestyles)
    local frame = mw.getCurrentFrame()
   
    -- Function to add user-defined templatestyles
    local function add_user_styles(templatestyles)
        if templatestyles and templatestyles ~= '' then
            return frame:extensionTag{
                name = 'templatestyles',
                args = { src = templatestyles }
            }
        end
        return ''
    end
 
    -- Combine list styles with base and user styles
    local list_styles = add_list_styles()
    local base_templatestyles = cfg.templatestyles
    local templatestyles = add_user_styles(args[cfg.arg.templatestyles])
    local child_templatestyles = add_user_styles(args[cfg.arg.child_templatestyles])
 
    -- Combine all styles into a single <div>
    return mw.html.create('div')
        :addClass(cfg.class.navbox_styles)
        :wikitext(
            list_styles ..
            base_templatestyles ..
            templatestyles ..
            child_templatestyles ..
            table.concat(hiding_templatestyles)
        )
        :done()
end
 
-- Work around for style markers (similar to Navbox)
local function move_hiding_templatestyles(args)
    local gfind = string.gmatch
    local gsub = string.gsub
    local templatestyles_markers = {}
     local strip_marker_pattern = '(\127[^\127]*UNIQ%-%-templatestyles%-%x+%-QINU[^\127]*\127)'
    for k, arg in pairs(args) do
        for marker in gfind(arg, strip_marker_pattern) do
            table.insert(templatestyles_markers, marker)
        end
        args[k] = gsub(arg, strip_marker_pattern, '')
    end
    return templatestyles_markers
end
end


-- Helper function to trim whitespace
local function trim(s)
local function trim(s)
     return (mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1"))
     return (mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1"))
end
end


-- Helper function to add newlines based on content
local function addNewline(s)
local function addNewline(s)
     if s:match('^[*:;#]') or s:match('^{|') then
     if s:match('^[*:;#]') or s:match('^{|') then
Line 35: Line 142:
end
end


local function processItem(item, nowrapitems)
    if not item then
        return '' -- Prevent nil errors
    end
    if item:sub(1, 2) == '{|' then
        -- Applying nowrap to lines in a table does not make sense.
        -- Add newlines to compensate for trim of x in |parm=x in a template.
        item = item:gsub('|%s*width%s*=%s*"[%d%w]+"', '| width="100%"')
        return '\n' .. item .. '\n'
    end
    if nowrapitems == cfg.keyword.nowrapitems_yes or true then
        local lines = {}
        for line in (item .. '\n'):gmatch('([^\n]*)\n') do
            local prefix, content = line:match('^([*:;#]+)%s*(.*)')
            if prefix and not content:match(cfg.pattern.nowrap) then
                line = format(cfg.nowrap_item, prefix, content)
            end
            table.insert(lines, line)
        end
        item = table.concat(lines, '\n')
    end
    if item:match('^[*:;#]') then
        return '\n' .. item .. '\n'
    end
    -- Ensure no excessive whitespace
    item = mw.ustring.gsub(item, "%s+", " ")
    return item
end
-- Function to add a new table row with optional gutter
local function addTableRow(tbl)
local function addTableRow(tbl)
     -- If any other rows have already been added, then we add a 2px gutter row.
     -- Check if the spacer rows are necessary based on the listclass or bodyclass
     if tableRowAdded then
    local suppressSpacer = false
         tbl
    if args.listclass then
            :tag('tr')
        suppressSpacer = suppressSpacer or args.listclass:find("hlist")
                :css('height', '2px')
    end
                :tag('td')
    if args.bodyclass then
                    :attr('colspan',2)
        suppressSpacer = suppressSpacer or args.bodyclass:find("hlist")
    end
 
    -- Only add spacer rows if they are not explicitly suppressed
     if tableRowAdded and not suppressSpacer then
         tbl:tag('tr')
            :css('height', '2px')
            :tag('td')
                :attr('colspan', 2)
                :css('background-color', 'transparent') -- Ensure spacer is invisible
     end
     end


     tableRowAdded = true
     tableRowAdded = true
     return tbl:tag('tr')
     return tbl:tag('tr')
end
end


local function renderNavBar(titleCell)
-- Function to render the navigation bar
    -- Depending on the presence of the navbar and/or show/hide link, we may need to add a spacer div on the left
local function renderNavBar(cell)
    -- or right to keep the title centered.
    local spacerSide = nil
 
     if args.navbar == 'off' then
     if args.navbar == 'off' then
         -- No navbar, and client wants no spacer, i.e. wants the title to be shifted to the left. If there's
         return -- Don't render anything if Navbar is off
        -- also no show/hide link, then we need a spacer on the right to achieve the left shift.
        if args.state == 'plain' then spacerSide = 'right' end
    elseif args.navbar == 'plain' or (not args.name and mw.getCurrentFrame():getParent():getTitle():gsub('/sandbox$', '') == 'Template:navbox') then
        -- No navbar. Need a spacer on the left to balance out the width of the show/hide link.
        if args.state ~= 'plain' then spacerSide = 'left' end
    else
        -- Will render navbar (or error message). If there's no show/hide link, need a spacer on the right
        -- to balance out the width of the navbar.
        if args.state == 'plain' then spacerSide = 'right' end
 
        titleCell:wikitext(navbar{
            args.name,
            mini = 1,
            fontstyle = (args.basestyle or '') .. ';' .. (args.titlestyle or '') ..  ';background:none transparent;border:none;'
        })
     end
     end


     -- Render the spacer div.
     -- Render the Navbar
     if spacerSide then
     cell:wikitext(navbar{
         titleCell
        args.name,
            :tag('span')
         mini = 1,
                :css('float', spacerSide)
        fontstyle = (args.basestyle or '') .. ';' .. (args.titlestyle or '') .. ';background:none transparent;border:none;'
                :css('width', '6em')
     })
                :wikitext('&nbsp;')
     end
end
end


--
--
Line 91: Line 219:


     local titleRow = addTableRow(tbl)
     local titleRow = addTableRow(tbl)
    if args.titlegroup then
        titleRow
            :tag('th')
                :attr('scope', 'row')
                :addClass('navboxMobile-group')
                :addClass(args.titlegroupclass)
                :cssText(args.basestyle)
                :cssText(args.groupstyle)
                :cssText(args.titlegroupstyle)
                :wikitext(args.titlegroup)
    end
     local titleCell = titleRow:tag('th'):attr('scope', 'col')
     local titleCell = titleRow:tag('th'):attr('scope', 'col')
 
         :addClass('navboxMobile-title')
    if args.titlegroup then
        :addClass(cfg.class.navbox_list)
         titleCell
        :addClass(args[cfg.arg.titleclass])
            :css('border-left', '2px solid #fdfdfd')
        :attr('data-level', 1)
            :css('width', '100%')
        :attr('colspan', 2)
    end
 
    local titleColspan = 2
    --[[if args.imageleft then titleColspan = titleColspan + 1 end
    if args.image then titleColspan = titleColspan + 1 end]]
    if args.titlegroup then titleColspan = titleColspan - 1 end
 
    titleCell
         :cssText(args.basestyle)
         :cssText(args.basestyle)
         :cssText(args.titlestyle)
         :cssText(args.titlestyle)
         :addClass('navboxMobile-title')
         :css('position', 'relative') -- Ensure relative positioning for absolute children
        :attr('colspan', titleColspan)


     renderNavBar(titleCell)
     -- Add the title content, centered across the full width
    titleCell
        :tag('div')
            :css('margin', '0 auto')
            :css('text-align', 'center')
            :wikitext(addNewline(args.title))


     titleCell
     -- Add the navbar, positioned absolutely in the top-right corner
        :tag('div')
    if has_navbar() then
            :addClass(args.titleclass)
        titleCell
            :css('font-size', '114%')
            :tag('div')
            :wikitext(addNewline(args.title))
                :addClass('navboxMobile-navbar')
                :css('position', 'absolute')
                :css('top', '0')
                :css('right', '0')
                :css('padding', '0.2em') -- Optional: Adjust padding for alignment
                :wikitext(navbar{
                    args.name,
                    mini = 1,
                    fontstyle = (args.basestyle or '') .. ';' .. (args.titlestyle or '') .. ';background:none transparent;border:none;'
                })
    end
end
end


Line 137: Line 258:


local function getAboveBelowColspan()
local function getAboveBelowColspan()
     local ret = 2
     return 2
    --[[if args.imageleft then ret = ret + 1 end
    if args.image then ret = ret + 1 end]]
    return ret
end
end


Line 148: Line 266:
     addTableRow(tbl)
     addTableRow(tbl)
         :tag('td')
         :tag('td')
             :addClass('navboxMobile-abovebelow')
             :addClass('navboxMobile-abovebelow-content')
            :addClass(cfg.class.navbox_list) -- Add consistent list styling
             :addClass(args.aboveclass)
             :addClass(args.aboveclass)
             :cssText(args.basestyle)
             :cssText(args.basestyle)
             :cssText(args.abovestyle)
             :cssText(args.abovestyle)
            :css('padding', args[cfg.arg.abovepadding] or '0.5em') -- Optional padding
             :attr('colspan', getAboveBelowColspan())
             :attr('colspan', getAboveBelowColspan())
             :tag('div')
             :tag('div')
                 :wikitext(addNewline(args.above))
                 :wikitext(addNewline(args.above))
end
end


local function renderBelowRow(tbl)
local function renderBelowRow(tbl)
Line 162: Line 284:
     addTableRow(tbl)
     addTableRow(tbl)
         :tag('td')
         :tag('td')
             :addClass('navboxMobile-abovebelow')
             :addClass('navboxMobile-abovebelow-content')
            :addClass(cfg.class.navbox_list) -- Add consistent list styling
             :addClass(args.belowclass)
             :addClass(args.belowclass)
             :cssText(args.basestyle)
             :cssText(args.basestyle)
             :cssText(args.belowstyle)
             :cssText(args.belowstyle)
            :css('padding', args[cfg.arg.belowpadding] or '0.5em') -- Optional padding
             :attr('colspan', getAboveBelowColspan())
             :attr('colspan', getAboveBelowColspan())
             :tag('div')
             :tag('div')
Line 171: Line 295:
end
end


--
--  List rows
--
local function renderListRow(tbl, listnum)
    local row = addTableRow(tbl)


    -- Process group
    if args['group' .. listnum] then
        local groupCell = row:tag('th')
        groupCell
            :attr('scope', 'row')
            :addClass('navboxMobile-group')
            :cssText(args.basestyle)
            :cssText(args.groupstyle)
            :cssText(args['group' .. listnum .. 'style'])
            :wikitext(args['group' .. listnum])
    end


    -- Add table row for the list
local function renderListRow(tbl, path, parentLevel)
    row = addTableRow(tbl)
     -- Initialize path and parentLevel
    local listCell = row:tag('td')
     path = path or ""
    listCell:attr('colspan', 2)
     parentLevel = parentLevel or 2 -- Start at level 2 for child groups
    listCell:css('width', '100%')
     listCell:cssText(args.liststyle)
    listCell:addClass('navboxMobile-list')
      
     -- Check for nested lists (e.g., child1_groupX)
    local nestedGroup = args['child' .. listnum .. '_group1']
    local nestedList = args['child' .. listnum .. '_list1']


     if nestedGroup or nestedList then
     -- Keep track of rendered children to avoid duplicates
        local nestedTbl = mw.html.create('table')
    local renderedChildren = {}
            :addClass('navboxMobile-subgroup')
            :css('width', '100%')


        for i = 1, 10 do -- Assume a max of 10 nested groups/lists
    for i = 1, 10 do
            local nestedGroup = args['child' .. listnum .. '_group' .. i]
        local groupKey = (path ~= "" and "child" .. path .. "_" or "") .. "group" .. i
            local nestedList = args['child' .. listnum .. '_list' .. i]
        local listKey = (path ~= "" and "child" .. path .. "_" or "") .. "list" .. i


            if not nestedGroup and not nestedList then break end
        -- Skip if this group has already been rendered
        if not renderedChildren[listKey] and args[listKey] then
            renderedChildren[listKey] = true -- Track rendered lists


             local nestedRow = addTableRow(nestedTbl)
            -- Render the group (heading)
             local groupRow = addTableRow(tbl)
            local groupCell = groupRow:tag('th')
                :attr('scope', 'row')
                :addClass('navboxMobile-group-content')
                :addClass('navboxMobile-group-level' .. parentLevel) -- Correct level
                :attr('data-level', parentLevel) -- Optional attribute for CSS targeting
                :wikitext(processItem(args[groupKey]))


             if nestedGroup then
             -- Check if the list is non-empty before rendering content
                 nestedRow:tag('th')
            if args[listKey] and args[listKey] ~= "" then
                     :addClass('navboxMobile-group')
                 if args[listKey] == "child" then
                     :cssText(args.basestyle)
                     -- Check if the child contains valid groups or lists
                    :cssText(args['child' .. listnum .. '_group' .. i .. 'style'])
                    local childHasContent = false
                     :wikitext(nestedGroup)
                     for j = 1, 10 do
            end
                        local childGroupKey = "child" .. (path ~= "" and path .. "_" or "") .. i .. "_group" .. j
                        local childListKey = "child" .. (path ~= "" and path .. "_" or "") .. i .. "_list" .. j
                        if args[childGroupKey] or args[childListKey] then
                            childHasContent = true
                            break
                        end
                     end


            if nestedList then
                    if childHasContent then
                 nestedRow:tag('td')
                        -- Recursively render child lists
                    :addClass('navboxMobile-list')
                        local newPath = (path ~= "" and path .. "_" or "") .. i
                    :cssText(args['child' .. listnum .. '_list' .. i .. 'style'])
                        renderListRow(tbl, tostring(newPath), parentLevel + 1)
                    :wikitext(addNewline(nestedList))
                    end
                 else
                    -- Render flat lists
                    local listRow = addTableRow(tbl)
                    local listCell = listRow:tag('td')
                        :attr('colspan', 2)
                        :addClass('navboxMobile-list-content') -- Base content class
                        :addClass('navboxMobile-list-level' .. parentLevel) -- Correct level
                        :addClass((i % 2 == 1) and 'navboxMobile-odd' or 'navboxMobile-even') -- Odd/even class
                        :addClass(args.listclass or '') -- Apply `listclass` if defined in the template
                        :wikitext(processItem(args[listKey], args.nowrapitems))
                end
             end
             end
         end
         end
        listCell:node(nestedTbl)
    else
        listCell:wikitext(addNewline(args['list' .. listnum]))
     end
     end
end
end




Line 245: Line 369:


     local listClasses = {'plainlist', 'hlist', 'hlist hnum', 'hlist hwrap', 'hlist vcard', 'vcard hlist', 'hlist vevent'}
     local listClasses = {'plainlist', 'hlist', 'hlist hnum', 'hlist hwrap', 'hlist vcard', 'vcard hlist', 'hlist vevent'}
     for i, cls in ipairs(listClasses) do
     for _, cls in ipairs(listClasses) do
         if args.listclass == cls or args.bodyclass == cls then
         if args.listclass == cls or args.bodyclass == cls then
             return false
             return false
Line 255: Line 379:


local function hasBackgroundColors()
local function hasBackgroundColors()
     return mw.ustring.match(args.titlestyle or '','background') or mw.ustring.match(args.groupstyle or '','background') or mw.ustring.match(args.basestyle or '','background')
     return mw.ustring.match(args.titlestyle or '', 'background')  
        or mw.ustring.match(args.groupstyle or '', 'background')  
        or mw.ustring.match(args.basestyle or '', 'background')
end
end


Line 273: Line 399:
local function getTrackingCategories()
local function getTrackingCategories()
     local cats = {}
     local cats = {}
     if needsHorizontalLists() then table.insert(cats, 'Navigational boxes without horizontal lists') end
     if needsHorizontalLists() then table.insert(cats, cfg.category.horizontal_lists) end
     if hasBackgroundColors() then table.insert(cats, 'navboxMobiles using background colours') end
     if hasBackgroundColors() then table.insert(cats, cfg.category.background_colors) end
     if isIllegible() then table.insert(cats, 'Potentially illegible navboxMobiles') end
     if isIllegible() then table.insert(cats, cfg.category.illegible) end
    if border == 'subgroup' then table.insert(cats, cfg.category.subgroup) end
    if args.tracking == 'no' then table.insert(cats, cfg.category.no_tracking) end
     return cats
     return cats
end
end
Line 281: Line 409:
local function renderTrackingCategories(builder)
local function renderTrackingCategories(builder)
     local title = mw.title.getCurrentTitle()
     local title = mw.title.getCurrentTitle()
     if title.namespace ~= 10 then return end -- not in template space
     if title.namespace ~= 10 then return end -- Not in template space
     local subpage = title.subpageText
     local subpage = title.subpageText
     if subpage == 'doc' or subpage == 'sandbox' or subpage == 'testcases' then return end
     if subpage == 'doc' or subpage == 'sandbox' or subpage == 'testcases' then return end


     for i, cat in ipairs(getTrackingCategories()) do
     for _, cat in ipairs(getTrackingCategories()) do
         builder:wikitext('[[Category:' .. cat .. ']]')
         builder:wikitext('[[Category:' .. cat .. ']]')
     end
     end
Line 296: Line 424:
     local tbl = mw.html.create('table')
     local tbl = mw.html.create('table')
         :addClass('nowraplinks')
         :addClass('nowraplinks')
        :addClass(cfg.class.navbox)
         :addClass(args.bodyclass)
         :addClass(args.bodyclass)
        :addClass(args.listclass or '') -- Apply the `listclass` argument globally if applicable
        :cssText(args.bodystyle)
        :cssText(args.style)
        :css('margin-top', '0')
        :css('margin-bottom', '0')


     --[[if args.title and (args.state ~= 'plain' and args.state ~= 'off') then
     -- Add the title row
        tbl
    renderTitleRow(tbl)
            :addClass('collapsible')
 
            :addClass(args.state or 'autocollapse')
    -- Add the above row
    end]]
    renderAboveRow(tbl)


     tbl:css('border-spacing', 0)
     -- Render all group and list rows
    if border == 'subgroup' or border == 'child' or border == 'none' then
    for _, listnum in ipairs(listnums) do
        tbl
        local listKey = "list" .. listnum
            :addClass('navboxMobile-subgroup')
        local groupKey = "group" .. listnum
            :cssText(args.bodystyle)
 
            :cssText(args.style)
        if args[listKey] then
    else -- regular navbox - bodystyle and style will be applied to the wrapper table
            -- Render group row
        tbl
            local groupRow = addTableRow(tbl)
             :addClass('navboxMobile-inner')
            local groupCell = groupRow:tag('th')
            :css('background', 'transparent')
                :attr('scope', 'row')
            :css('color', 'inherit')
                :addClass('navboxMobile-group-content')
                :addClass('navboxMobile-group-level1')
                :addClass(args.listclass or '') -- Apply `listclass` for group rows
                :wikitext(processItem(args[groupKey]))
 
            -- Render list row
            if args[listKey] == 'child' then
                renderListRow(tbl, tostring(listnum), 2)
             else
                local listRow = addTableRow(tbl)
                listRow:tag('td')
                    :attr('colspan', 2)
                    :addClass('navboxMobile-list-content')
                    :addClass((listnum % 2 == 1) and 'navboxMobile-odd' or 'navboxMobile-even')
                    :addClass(args.listclass or '') -- Apply `listclass` to flat rows
                    :wikitext(processItem(args[listKey]))
            end
        end
     end
     end
    tbl:cssText(args.innerstyle)


     renderTitleRow(tbl)
     -- Add the below row
    renderAboveRow(tbl)
    for i, listnum in ipairs(listnums) do
        renderListRow(tbl, listnum)
    end
     renderBelowRow(tbl)
     renderBelowRow(tbl)


Line 328: Line 474:
end
end


--
--  Main NavboxMobile Function
--
-- In the main navboxMobile function
function p._navboxMobile(navboxMobileArgs)
function p._navboxMobile(navboxMobileArgs)
     args = navboxMobileArgs
     args = navboxMobileArgs
Line 335: Line 487:
     listnums = {}
     listnums = {}


    -- Move and collect hiding templatestyles
    local hiding_templatestyles = move_hiding_templatestyles(args)
    -- Collect top-level list numbers (list1, list2, etc.)
     for k, v in pairs(args) do
     for k, v in pairs(args) do
         local listnum = ('' .. k):match('^list(%d+)$')
         if type(k) == 'string' then
        if listnum then table.insert(listnums, tonumber(listnum)) end
            local listnum = k:match('^list(%d+)$')
            if listnum then table.insert(listnums, tonumber(listnum)) end
        end
     end
     end
     table.sort(listnums)
     table.sort(listnums)


     border = trim(args.border or args[1] or '')
     border = trim(args.border or args[1] or '')
    if border == cfg.keyword.border_child then
        border = cfg.keyword.border_subgroup
    end


     -- render the main body of the navboxMobile
     -- Render the main body of the navboxMobile
     local tbl = renderMainTable()
     local tbl = renderMainTable()


     -- Create the final HTML with styles
     -- Create the final HTML with styles
     local res = mw.html.create()
     local res = mw.html.create()
 
     res:node(add_navbox_mobile_styles(hiding_templatestyles))
    -- Inject styles
     res:node(tbl)
     res:node(addNavboxMobileStyles())
 
    -- Handle wrapping based on border parameter
    if border == 'none' then
        -- Wrap the table within a navigation div with ARIA attributes
        local navWrapper = mw.html.create('div')
            :attr('role', 'navigation')
            :attr('aria-label', cfg.aria_label)
            :node(tbl)
        res:node(navWrapper)
     elseif border == 'subgroup' or border == 'child' then
        -- Assume this navboxMobile is inside a parent navboxMobile's list cell
        -- Insert closing and opening divs to manage padding
        res
            :wikitext('</div>') -- Close parent div
            :node(tbl)
            :wikitext('<div>') -- Reopen parent div
    else
        -- Wrap the table within a navigation div with additional classes and styles
        local navWrapper = mw.html.create('div')
            :attr('role', 'navigation')
            :addClass('navboxMobile') -- Add appropriate classes
            :css('border-spacing', 0)
            :cssText(args.bodystyle)
            :cssText(args.style)
            :tag('tr')
                :tag('td')
                    :css('padding', '2px')
                    :node(tbl)
        res:node(navWrapper)
    end
 
    -- Render tracking categories
    renderTrackingCategories(res)


     return tostring(res)
     return tostring(res)
end
end


--
--  Main NavboxMobile Function
--
function p.navboxMobile(frame)
function p.navboxMobile(frame)
     if not getArgs then
     if not getArgs then