From Wikipedia, the free encyclopedia

local p = {}







local function dateCalculation(dateStr)

    local year , month, day = dateStr:match("(%d+)[/.,-](%d+)[/.,-](%d+)")

    if not year then

     day , month, year = dateStr:match("(%d+)[/.,-](%d+)[/.,-](%d+)")

    end 

    if not year then 

       return 'Invalid ' 

    end

    

        

    local currentDate = os.date("*t")

    local age = currentDate.year - tonumber(year)

    if currentDate.month < tonumber(month) or (currentDate.month == tonumber(month) and currentDate.day < tonumber(day)) then

        age = age - 1

    end

    

    local monthName = os.date("%B", os.time{year=tonumber(year), month=tonumber(month), day=tonumber(day)})

    return " ".. monthName .. " "..day..", " .. year.. " <br/>(Age " ..  age.. ")"

end











--[[ 

local function dateCalculation(dateStr)

    local year , month, day = dateStr:match("(%d+)[/.,-](%d+)[/.,-](%d+)")

    if not year then

        day , month, year = dateStr:match("(%d+)[/.,-](%d+)[/.,-](%d+)")

    end

    if not year then 

        return 'Invalid date format' 

    end

    

    local currentDate = os.date("*t")

    local age

        if tonumber(year) < 1582 or (tonumber(year) == 1582 and (tonumber(month) < 10 or (tonumber(month) == 10 and tonumber(day) < 4))) then

        age = currentDate.year - tonumber(year)

    else

         age = currentDate.year - tonumber(year)

        

         local leapYears = 0

        for i = tonumber(year), currentDate.year - 1 do

            if i % 4 == 0 then

                leapYears = leapYears + 1

            end

        end

                age = age - leapYears

    end

    

    if currentDate.month < tonumber(month) or (currentDate.month == tonumber(month) and currentDate.day < tonumber(day)) then

        age = age - 1

    end

    

    local monthName = os.date("%B", os.time{year=tonumber(year), month=tonumber(month), day=tonumber(day)})

    return " ".. monthName .. " "..day..", " .. year.. " <br/>(Age " ..  age.. ")"

end



]] 





--❗

--[[Volume conversions]] 

local function litersToGallons(liters)

    local litersValue = tonumber(liters:match("%d+%.?%d*"))

    if litersValue then

        local gallons = litersValue * 0.264172

        return "".. string.format("%.2f liters (%.2f gallons)", litersValue, gallons)

    end

    return liters

end



local function gallonsToLiters(gallons)

    local gallonsValue = tonumber(gallons:match("%d+%.?%d*"))

    if gallonsValue then

        local liters = gallonsValue * 3.78541

        return string.format("%.2f gallons (%.2f liters)", gallonsValue, liters)

    end

    return gallons

end



local function cubicMetersToCubicFeet(cubicMeters)

    local cubicMetersValue = tonumber(cubicMeters:match("%d+%.?%d*"))

    if cubicMetersValue then

        local cubicFeet = cubicMetersValue * 35.3147

        return string.format("%.2f cubic meters (%.2f cubic feet)", cubicMetersValue, cubicFeet)

    end

    return cubicMeters

end



local function cubicFeetToCubicMeters(cubicFeet)

    local cubicFeetValue = tonumber(cubicFeet:match("%d+%.?%d*"))

    if cubicFeetValue then

        local cubicMeters = cubicFeetValue * 0.0283168

        return string.format("%.2f cubic feet (%.2f cubic meters)", cubicFeetValue, cubicMeters)

    end

    return cubicFeet

end



-- Area conversions

local function squareMetersToSquareFeet(squareMeters)

    local squareMetersValue = tonumber(squareMeters:match("%d+%.?%d*"))

    if squareMetersValue then

        local squareFeet = squareMetersValue * 10.7639

        return string.format("%.2f square meters (%.2f square feet)", squareMetersValue, squareFeet)

    end

    return squareMeters

end



local function squareFeetToSquareMeters(squareFeet)

    local squareFeetValue = tonumber(squareFeet:match("%d+%.?%d*"))

    if squareFeetValue then

        local squareMeters = squareFeetValue * 0.092903

        return string.format("%.2f square feet (%.2f square meters)", squareFeetValue, squareMeters)

    end

    return squareFeet

end 



local function hectaresToAcres(hectares)

    local hectaresValue = tonumber(hectares:match("%d+%.?%d*"))

    if hectaresValue then

        local acres = hectaresValue * 2.47105

        return string.format("%.2f hectares (%.2f acres)", hectaresValue, acres)

    end

    return hectares

end



local function acresToHectares(acres)

    local acresValue = tonumber(acres:match("%d+%.?%d*"))

    if acresValue then

        local hectares = acresValue * 0.404686

        return string.format("%.2f acres (%.2f hectares)", acresValue, hectares)

    end

    return acres

end



-- Time conversions

local function hoursToMinutes(hours)

    local hoursValue = tonumber(hours:match("%d+%.?%d*"))

    if hoursValue then

        local minutes = hoursValue * 60

        return string.format("%.2f hours (%d minutes)", hoursValue, minutes)

    end

    return hours

end



local function minutesToHours(minutes)

    local minutesValue = tonumber(minutes:match("%d+%.?%d*"))

    if minutesValue then

        local hours = minutesValue / 60

        local decimalPart = minutes:match("%.(%d+)")

        if decimalPart then

            hours = hours + tonumber("0." .. decimalPart)

        end

        return string.format("%.2f minutes (%.2f hours)", minutesValue, hours)

    end

    return minutes

end





local function daysToHours(days)

    local daysValue = tonumber(days:match("%d+%.?%d*"))

    if daysValue then

        local hours = daysValue * 24

        return string.format("%.2f days (%d hours)", daysValue, hours)

    end

    return days

end



local function hoursToDays(hours)

    local hoursValue = tonumber(hours:match("%d+%.?%d*"))

    if hoursValue then

        local days = hoursValue / 24

        return string.format("%.2f hours (%.2f days)", hoursValue, days)

    end

    return hours

end



-- Energy conversions

local function joulesToCalories(joules)

    local joulesValue = tonumber(joules:match("%d+%.?%d*"))

    if joulesValue then

        local calories = joulesValue * 0.000239006

        return string.format("%.2f joules (%.6f calories)", joulesValue, calories)

    end

    return joules

end



local function caloriesToJoules(calories)

    local caloriesValue = tonumber(calories:match("%d+%.?%d*"))

    if caloriesValue then

        local joules = caloriesValue / 0.000239006

        return string.format("%.2f calories (%.2f joules)", caloriesValue, joules)

    end

    return calories

end



local function kilowattHoursToJoules(kWh)

    local kWhValue = tonumber(kWh:match("%d+%.?%d*"))

    if kWhValue then

        local joules = kWhValue * 3600000

        return string.format("%.2e kWh (%.2e joules)", kWhValue, joules)

    end

    return kWh

end



local function joulesToKilowattHours(joules)

    local joulesValue = tonumber(joules:match("%d+%.?%d*"))

    if joulesValue then

        local kWh = joulesValue / 3600000

        return string.format("%.2e joules (%d kWh)", joulesValue, kWh)

    end

    return joules

end



-- 🔴Pressure conversions

local function pascalsToPSI(pascals)

    local pascalsValue = tonumber(pascals:match("%d+"))

    if pascalsValue then

        local psi = pascalsValue * 0.000145038

        return string.format("%d pascals (%.6f PSI)", pascalsValue, psi)

    end

    return pascals

end



local function psiToPascals(psi)

    local psiValue = tonumber(psi:match("%d+"))

    if psiValue then

        local pascals = psiValue / 0.000145038

        return string.format("%.6f PSI (%d pascals)", psiValue, pascals)

    end

    return psi

end



local function atmospheresToPascals(atmospheres)

    local atmospheresValue = tonumber(atmospheres:match("%d+"))

    if atmospheresValue then

        local pascals = atmospheresValue * 101325

        return string.format("%d atmospheres (%d pascals)", atmospheresValue, pascals)

    end

    return atmospheres

end



local function pascalsToAtmospheres(pascals)

    local pascalsValue = tonumber(pascals:match("%d+"))

    if pascalsValue then

        local atmospheres = pascalsValue / 101325

        return string.format("%d pascals (%.6f atmospheres)", pascalsValue, atmospheres)

    end

    return pascals

end



-- Frequency conversions

local function hertzToRPM(hertz)

    local hertzValue = tonumber(hertz:match("%d+"))

    if hertzValue then

        local rpm = hertzValue * 60

        return string.format("%d Hertz (%d RPM)", hertzValue, rpm)

    end

    return hertz

end



local function rpmToHertz(rpm)

    local rpmValue = tonumber(rpm:match("%d+"))

    if rpmValue then

        local hertz = rpmValue / 60

        return string.format("%d RPM (%.2f Hertz)", rpmValue, hertz)

    end

    return rpm

end



local function kilohertzToHertz(kHz)

    local kHzValue = tonumber(kHz:match("%d+"))

    if kHzValue then

        local hertz = kHzValue * 1000

        return string.format("%d kHz (%d Hertz)", kHzValue, hertz)

    end

    return kHz

end



local function hertzToKilohertz(hertz)

    local hertzValue = tonumber(hertz:match("%d+"))

    if hertzValue then

        local kHz = hertzValue / 1000

        return string.format("%d Hertz (%.2f kHz)", hertzValue, kHz)

    end

    return hertz

end



-- Power conversions

local function wattsToHorsepower(watts)

    local wattsValue = tonumber(watts:match("%d+"))

    if wattsValue then

        local horsepower = wattsValue * 0.00134102

        return string.format("%d watts (%.6f horsepower)", wattsValue, horsepower)

    end

    return watts

end



local function horsepowerToWatts(horsepower)

    local horsepowerValue = tonumber(horsepower:match("%d+"))

    if horsepowerValue then

        local watts = horsepowerValue / 0.00134102

        return string.format("%.6f horsepower (%d watts)", horsepowerValue, watts)

    end

    return horsepower

end



local function megawattsToHorsepower(megawatts)

    local megawattsValue = tonumber(megawatts:match("%d+"))

    if megawattsValue then

        local horsepower = megawattsValue * 1341.02

        return string.format("%d megawatts (%.2f horsepower)", megawattsValue, horsepower)

    end

    return megawatts

end



local function horsepowerToMegawatts(horsepower)

    local horsepowerValue = tonumber(horsepower:match("%d+"))

    if horsepowerValue then

        local megawatts = horsepowerValue / 1341.02

        return string.format("%.2f horsepower (%d megawatts)", horsepowerValue, megawatts)

    end

    return horsepower

end



-- Add these functions to the p dynamic function to integrate them into the infobox

--❗

local function ftToCm(ft)

    local ftValue = tonumber(ft:match("%d+%.?%d*"))

    if ftValue then

        local cm = ftValue * 30.48

        return string.format("%.2f ft (%.2f cm)", ftValue, cm)

    end

    return ft

end 



local function cmToFeetAndInches(cm)

    local cmValue = tonumber(cm:match("%d+%.?%d*"))

    if cmValue then

        local totalInches = cmValue / 2.54

        local feet = math.floor(totalInches / 12)

        local inches = math.floor(totalInches % 12)

        return string.format("%.2f cm (%d feet %d inches)", cmValue, feet, inches)

    end

    return cm

end



local function mphToKmh(mph)

    local mphValue = tonumber(mph:match("%d+%.?%d*"))

    if mphValue then

        local kmh = mphValue * 1.60934

        return string.format("%.2f mph (%.2f km/h)", mphValue, kmh)

    end

    return mph

end



local function kmhToMph(kmh)

    local kmhValue = tonumber(kmh:match("%d+%.?%d*"))

    if kmhValue then

        local mph = kmhValue / 1.60934

        return string.format("%.2f km/h (%.2f mph)", kmhValue, mph)

    end

    return kmh

end



local function kmToMi(km)

    local kmValue = tonumber(km:match("%d+%.?%d*"))

    if kmValue then

        local miles = kmValue * 0.621371

        return string.format("%.2f km (%.2f mi)", kmValue, miles)

    end

    return km

end



local function miToKm(mi)

    local miValue = tonumber(mi:match("%d+%.?%d*"))

    if miValue then

        local km = miValue / 0.621371

        return string.format("%.2f miles (%.2f km)", miValue, km)

    end

    return mi

end



local function hpToKw(hp)

    local hpValue = tonumber(hp:match("%d+%.?%d*"))

    if hpValue then

        local kw = hpValue * 0.735499

        return string.format("%.2f horsepower (%.2f kW)", hpValue, kw)

    end

    return hp

end



local function kwToHp(kw)

    local kwValue = tonumber(kw:match("%d+%.?%d*"))

    if kwValue then

        local hp = kwValue / 0.735499

        return string.format("%.2f Kilowatt(%.2f hp)", kwValue, hp)

    end

    return kw

end



local function lbToKg(lb)

    local lbValue = tonumber(lb:match("%d+%.?%d*"))

    if lbValue then

        local kg = lbValue * 0.453592

        return string.format("%.2f lb (%.2f kg)", lbValue, kg)

    end

    return lb

end



local function kgToPounds(kg)

    --local kgValu = tonumber(kg:match("%d+"))

    local kgValue = tonumber(kg:match("%d+%.?%d*"))

    if kgValue>1 then

        local pounds = kgValue * 2.20462

        return string.format("%.2f kgs (%.2f pounds)", kgValue, pounds)

        else

         local pounds = kgValue * 2.20462

        return string.format("%.2f kg (%.2f pounds)", kgValue, pounds)

    end

    return kg

end



local function mmToInches(mm)

    local mmValue = tonumber(mm:match("%d+%.?%d*"))

    if mmValue then

        local inches = mmValue * 0.0393701

        return string.format("%.2f mm (%.2f inches)", mmValue, inches)

    end

    return mm

end



local function inchesToMm(inches)

    local inchesValue = tonumber(inches:match("%d+%.?%d*")) 

    if inchesValue then

        local mm = inchesValue / 0.0393701

        return string.format("%.2f inches (%.2f mm)", inchesValue, mm)

    end

    return inches

end



local function msToFts(ms)

    local msValue = tonumber(ms:match("%d+%.?%d*"))

    if msValue then

        local fts = msValue * 3.28084

        return string.format("%.2f m/s(%.2f ft/s)", msValue, fts)

    end

    return ms

end



local function ftsToMs(fts)

    local ftsValue = tonumber(fts:match("%d+%.?%d*"))

    if ftsValue then

        local ms = ftsValue / 3.28084

        return string.format("%.2f ft/s(%.2f m/s)", ftsValue, ms)

    end

    return fts

end



local function mToFeet(m)

    local mValue = tonumber(m:match("%d+%.?%d*"))

    if mValue then

        local feet = mValue * 3.28084

        return string.format("%.2f meter (%.2f ft)", mValue, feet)

    end

    

    -- Check for variations of "m", "meter", and "metre"

    local mValueAlt = tonumber(m:match("(%d+%.?%d*)%s*[mM]"))

    if mValueAlt then

        local feetAlt = mValueAlt * 3.28084

        return string.format("%.2f m (%.2f ft)", mValueAlt, feetAlt)

    end

    

    local mValueAlt2 = tonumber(m:match("(%d+%.?%d*)%s*[mM][eE][tT][eE]?[rR]?"))

    if mValueAlt2 then

        local feetAlt2 = mValueAlt2 * 3.28084

        return string.format("%.2f metre (%.2f ft)", mValueAlt2, feetAlt2)

    end

    

    local mValueAlt3 = tonumber(m:match("(%d+%.?%d*)%s*[mM][eE][tT][eE][rR]?"))

    if mValueAlt3 then

        local feetAlt3 = mValueAlt3 * 3.28084

        return string.format("%.2f meter (%.2f ft)", mValueAlt3, feetAlt3)

    end

    

    return m

end

--//m///





local function celsiusToFahrenheit(c)

    local cValue = tonumber(c:match("%d+"))

    if cValue then

        local fahrenheit = cValue * 9/5 + 32

        return string.format("%.2f°C (%.2f°F)", cValue, fahrenheit)

    end

    return c  

end



local function fahrenheitToCelsius(f)

    local fValue = tonumber(f:match("%d+"))

    if fValue then

        local celsius = (fValue - 32) * 5/9

        return string.format("%.2f°F (%.2f°C)", fValue, celsius)

    end

    return f

end

function capitalizeFirstLetter(str)

    return str:gsub("^%l", string.upper)

end



-- Function to generate contrasting text color for a given background color

local function getContrastingTextColor(bgColor)

    -- Convert hex color to RGB

    local r = tonumber(bgColor:sub(2, 3), 16)

    local g = tonumber(bgColor:sub(4, 5), 16)

    local b = tonumber(bgColor:sub(6, 7), 16)



    -- Calculate relative luminance

    local luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255



    -- Choose white or black text color based on luminance

    if luminance > 0.5 then

        return "#000000"  -- Black text for light backgrounds

    else

        return "#FFFFFF"  -- White text for dark backgrounds

    end

end



-- Function to generate even lighter colors

function generateEvenLighterColor1()

    local r = math.random(0xF0, 0xFF) -- Red component

    local g = math.random(0xF0, 0xFF) -- Green component

    local b = math.random(0xF0, 0xFF) -- Blue component

    return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color

end



-- Function to generate a very light color

function generateVeryLightColor2()

    local r = math.random(0xE0, 0xFF) -- Red component

    local g = math.random(0xE0, 0xFF) -- Green component

    local b = math.random(0xE0, 0xFF) -- Blue component

    return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color

end



-- Function to generate a random light color

function generateLightColor3()

    local r = math.random(0xB0, 0xFF) -- Red component

    local g = math.random(0xB0, 0xFF) -- Green component

    local b = math.random(0xB0, 0xFF) -- Blue component

    return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color

end



-- Functions to generate mixed light-dark colors

function generateDarkColor4()

    local r = math.random(0x60, 0x80) -- Red component

    local g = math.random(0x60, 0x80) -- Green component

    local b = math.random(0x60, 0x80) -- Blue component

    return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color

end



function generateDarkColor5()

    local r = math.random(0x50, 0x70) -- Red component

    local g = math.random(0x50, 0x70) -- Green component

    local b = math.random(0x50, 0x70) -- Blue component

    return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color

end



function generateDarkColor6()

    local r = math.random(0x40, 0x60) -- Red component

    local g = math.random(0x40, 0x60) -- Green component

    local b = math.random(0x40, 0x60) -- Blue component

    return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color

end



function generateDarkColor7()

    local r = math.random(0x20, 0x40) -- Red component

    local g = math.random(0x20, 0x40) -- Green component

    local b = math.random(0x20, 0x40) -- Blue component

    return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color

end



function generateDarkColor8()

    local r = math.random(0x30, 0x70) -- Red component

    local g = math.random(0x30, 0x70) -- Green component

    local b = math.random(0x30, 0x70) -- Blue component

    return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color

end



function generateDarkColor9()

    return string.format("#%02x%02x%02x", math.random(0x30, 0x50), math.random(0x40, 0x70), math.random(0x50, 0x70))

end



function generateDarkColor10()

    return string.format("#%06x", math.random(0x30, 0x70))

end



-- Function to generate a random color

local function generateRandomColor()

    local r = math.random(0, 255)

    local g = math.random(0, 255)

    local b = math.random(0, 255)

    return string.format("#%02X%02X%02X", r, g, b)

end





--[[ local conversionPatterns = {

        { pattern = "%s*kilohertz%s*", convertedValue = kilohertzToHertz},

        { pattern = "%s*kg%s*", conversion = kgToPounds },

        { pattern = "%s*mph%s*", conversion = mphToKmh },

        -- Add more conversion patterns as needed

    } ]] 





function p.dynamic(frame)

    local args = frame:getParent().args

    local output = '<div colspan="2" class="infobox biography vcard" style="max-width: 100vw; width: auto; margin: 0 auto;">\n|-\n' 

    -- local firstDescriptionFound = false

    local cmProcessed = false

    local abvParams = {}  -- Store abv parameters separately

    local abvProcessed = false

    local upProcessed = false

    local imageProcessed =false 

    --[[go over arguments to find "up" and "abv" parameters

    for key, value in pairs(args) do

        if key:sub(1, 2) == 'up' then

            if value ~= "" then

                output = output .. '<tr><th style='..(args.header or"")..'"background:lightgra;font-size:20px;text-align: center; background-color: ' .. (args.headcolor or "#f2f2f2") .. '; color: ' .. (args.color or "inherit") .. '; font-weight: bold;"> ' .. value .. '\n</th></tr>\n'

                upProcessed = true

            end

        end

    end

]] 











local values = {}



for key, value in pairs(args) do

    if key:sub(1, 2) == 'up' and value ~= "" then

        table.insert(values, {key = key, value = value})

    end

end

table.sort(values, function(a, b) return a.key < b.key end)

for _, entry in ipairs(values) do

    local key = entry.key

    local value = entry.value

    value = value:gsub("^%l", string.upper)

    local first_char = value:match("%a") -- Find the first alphabet character

    if first_char then

    value = value:gsub("^" .. first_char, string.upper) -- Capitalize the first alphabet character

    end

    output = output .. '<tr><th style="font-size:20px;text-align:center;background-color:' .. (args.header or "") .. ';color:' .. (args.color or "") .. ';font-weight:bold;" colspan="2">' .. value .. '\n</th></tr>\n'

end



--[[ 

for key, value in pairs(args) do

        if value ~= "" then

            if key ~= 'image' and key ~= 'imagecaption' and key ~= 'caption' and key ~= 'headcolor' and key ~= 'color' and key ~= 'abvstyle' and key ~= 'abvheadcolor' and key ~= 'abvcolor'then

                if key ~= 'up' and not (key:sub(1, 2) == 'up' and upProcessed) and key ~= 'abv' and not abvProcessed then

                    -- Your existing conversion logic goes here

                end

            end

        end

end



for key, value in pairs(args) do

        if value ~= "" then

            if key ~= 'image' and key ~= 'imagecaption' and key ~= 'caption' and key ~= 'headcolor' and key ~= 'color' and key ~= 'abvstyle' and key ~= 'abvheadcolor' and key ~= 'abvcolor'then

                if key ~= 'abv' and not (key:sub(1, 3) == 'abv' and abvProcessed) and key ~= 'abv' and not upProcessed then

                    -- Your existing conversion logic goes here

                end

            end

        end

end

]] 

local hasImage = false

for key, _ in pairs(args) do

    if key:sub(1, 5) == "image" then

        hasImage = true

        break

    end

end



if not hasImage then

    local defaultImage = "[[File:default_image.jpg|thumb|center|Default Image]]\n"

    output = output .. defaultImage

end



if args.image then

    local processedKeys = {}

    local processedSizeCaption = {}

    local images = {}

    local div = '<div style="display:grid;grid-template-columns: repeat(2, auto); gap: -2px; text-align: center; margin: 2px;">'



    for key, value in pairs(args) do

        if key:sub(1, 5) == "image" and value ~= "" and not processedKeyskey then

            processedKeyskey = true

            local captionKey = "caption" .. key:sub(6)

            local sizeKey = "size" .. key:sub(6)



            if not processedSizeCaptioncaptionKey and not processedSizeCaptionsizeKey then

                processedSizeCaptioncaptionKey = true

                processedSizeCaptionsizeKey = true



                local caption = argscaptionKey or ""

                local imagesize = argssizeKey or ""

                local isFrameless = string.match(value, '|frameless')

                local imageExtension = value:match("%.([^.]+)$")



               if not imageExtension then

                    value = value:gsub("|", "".. ".jpg|").. ".jpg"

                end

                local grid =""

                local wikiMarkup = ''

                if isFrameless then

                    local remo = value:gsub("(%[%[.-|)File:", "%1")

                    wikiMarkup = wikiMarkup .. '|' .. '<div style="text-align:center;">' .. remo .. '</div>' .. '<small style="display: block; text-align: center;">' .. caption .. '</small>\n|-\n'

                else

                    local imageName, imageSize = value:match("%[%[File:(.-)|([^|%]]+)]]")

                    if imageName then

                        wikiMarkup = wikiMarkup .. "[[File:" .. imageName

                        if imageSize then

                            wikiMarkup = wikiMarkup .. "|" .. imageSize

                        end

                        wikiMarkup = wikiMarkup .. "]]"

                    else

                        local imageSizeMarkup = ""

                        if imagesize ~= "" then

                            imageSizeMarkup = "|" .. imagesize

                        end

                        wikiMarkup = wikiMarkup .. "[[File:" .. value:gsub("%[%[", ""):gsub("%]%]", "") .. imageSizeMarkup .. "]]"

                    end

                    wikiMarkup = '<div style="text-align:center;">' .. wikiMarkup  .. '<small style="display: block; text-align: center;">' .. caption .. '</small></div>\n'

                   end



                -- Store the image markup along with its key

                table.insert(images, { key = key, markup = wikiMarkup, insertionOrder = #images + 1 })            end

        end

    end



    -- Sort the images based on their keys to maintain the insertion order

   --table.sort(images, function(a, b) return a.key < b.key end)



-- Generate the output markup

local columnCount = 0

local gridOpen = false

for _, imageData in ipairs(images) do

    local wikiMarkup = imageData.markup

    if imageData.key:sub(-1) == "+" then

        if not gridOpen then

            output = output .. '|<div colspan="2">' .. div.. '</div>\n|-\n' -- Open the grid container if it's not already open

            gridOpen = true

        end

        --output = output ..'|'.. wikiMarkup .. '\n|-\n' -- For keys not ending with '+', display normally



        output = output .. '|<div class="grid-item"colspan="2">' .. wikiMarkup .. '</div>\n'

        columnCount = (columnCount + 1) % 2

    else

        if gridOpen then

            output = output .. '</div>\n|-\n' -- Close the grid container if it's open

            gridOpen = false

        end

       output = output ..'<tr><th colspan="2">'.. wikiMarkup .. '</th><tr>\n|-\n' -- For keys not ending with '+', display normally

    end

end



-- If there are unclosed div tags, close them

if gridOpen then

    output = output .. '</div>\n|-\n'

end

end



local values = {}



for key, value in pairs(args) do

    if key:sub(1, 3) == "mdl"or key:match("^(%d+)mdl") and value ~= "" then

        table.insert(values, { key = key, value = value, position = mw.ustring.match(key, "%d+") })

    end

end



table.sort(values, function(a, b) return tonumber(a.position) < tonumber(b.position) end)



for _, entry in ipairs(values) do

    local key = entry.key

    local value = entry.value

    value = value:gsub("^%l", string.upper)

    local first_char = value:match("%a") -- Find the first alphabet character

    if first_char then

        value = value:gsub("^" .. first_char, string.upper) -- Capitalize the first alphabet character

    end

--   local transcludedContent = transcludeTemplate("User:Thisasia/sandbox3", { value = "" })

    --output = output .. '<tr><th colspan="2" style="font-size:20px;text-align:center;background-color:' .. (args.downheade or "rgba(0,0,0,0.020)") .. ';color:' .. (args.downcolo or "") .. ';font-weight:bold;"> {{User:Thisasia/Signature|'.. frame:preprocess('{{User:Thisasia/Signature|'.. value.. '}}').. value .. '}}</th></tr>\n|-\n'

    output = output .. '<tr><th colspan="2" style="font-size:20px;text-align:center;background-color:' .. (args.downheade or "rgba(0,0,0,0.020)") .. ';color:' .. (args.downcolo or "") .. ';font-weight:bold;">'.. value .. '</th></tr>\n|-\n'

end



--[[ 

 if key:sub(6, 6) == "+" then

                    table.insert(gridImages, {value = value, caption = caption, isFrameless = isFrameless})

                else

                    table.insert(normalImages, {value = value, caption = caption, imagesize = imagesize, isFrameless = isFrameless})

                end

            end

        end

    end

    

    -- Begin HTML output for grid layout

    local div='<div class="grid-container" style="  display: grid; grid-template-columns: repeat(2, 1fr); gap: 2px; text-align: center; margin-bottom: 5px; ">\n' 

    

    -- Output grid images

    for _, image in ipairs(gridImages) do

        local wikiMarkup = ""

        local remo = image.value

        wikiMarkup = wikiMarkup .. div.. '<div class="grid-item">' ..'<div style="text-align:center;">'.. remo.. '</div>'..'<small style="display: block; text-align: center;">' .. image.caption .. '</small>\n</div>\n'

        output = output .. wikiMarkup

    end

                  





   if args.image then

        local caption = args.caption or ""

        local imagesize = args.imagesize or ""  

        output = output .. '|' ..'<div style="text-align:center;">'.. args.image.. '</div>'..'<small style="display: block; text-align: center;">' .. caption .. '</small>\n|-\n'

    end

    --/// 

]] 



--[[ 

]] 

--

local values = {}

for key, value in pairs(args) do

    if key == key and value ~= "" then

        table.insert(values, {key = key, value = value})

    end

end

--[[local function generateUUID()

    return uuid()

end

]] 

local function extractNumber(key)

    return tonumber(key:match("^%d+")) or 0

end







--❗ Insertion Sort algorithm

for i = 1, #values do

    local current = valuesi

    local j = i - 1

    while j > 0 and (extractNumber(valuesj].key) > extractNumber(current.key) or 

                     (extractNumber(valuesj].key) == extractNumber(current.key) and valuesj].key > current.key)) do

        valuesj + 1 = valuesj

        j = j - 1

    end

    valuesj + 1 = current

end





 --[[ 

table.sort(values, function(a, b)

    local aKey = a.key:match(".*%*$") and 1 or 0

    local bKey = b.key:match(".*%*$") and 1 or 0



    -- Keys with asterisks should come before keys without asterisks

    if aKey ~= bKey then

        return aKey < bKey

    else

        if aKey == 1 and bKey == 1 then

            return a.key < b.key

        elseif aKey == 0 and bKey == 0 then

            local numA = tonumber(a.key)

            local numB = tonumber(b.key)

            if numA and numB then

                return numA < numB

            else

                return a.key < b.key

            end

        else

            -- If one has asterisk and the other doesn't, prioritize the one with the asterisk

            return aKey == 1

        end

    end

end)

]] 

--[[



--Insertion Sort algorithm for modified_key

for i = 2, #values do

    local current = values[i]

    local j = i - 1

    while j > 0 and values[j].key > current.key do

        values[j + 1] = values[j]

        j = j - 1

    end

    values[j + 1] = current

end

 

for i = 2, #values do

    local current = values[i]

    local j = i - 1

    while j > 0 and values[j].key > current.key do

        values[j + 1] = values[j]

        j = j - 1

    end

    values[j + 1] = current

end

]] 



local matchedKeys = {}

local bgStyles = {}  -- Table to store background styles for each matched key

local generatedColors = {}  





for _, entry in ipairs(values) do

    local key = entry.key

    local value = entry.value

    local modified_key = key:gsub("^[%d]*", "")

    local found_alpha = false 

    

    for i = 1, #modified_key do

        if modified_key:sub(i, i):match("%a") then

            modified_key = modified_key:sub(1, i - 1) .. modified_key:sub(i, i):upper() .. modified_key:sub(i + 1)

            found_alpha = true

            break

        end

    end

    

    if not found_alpha then

        modified_key = modified_key:gsub("^.", string.upper, 5) 

    end

    

    local matched = false

    repeat

        local bgs = modified_key:match(".*%*$") or ""

        if bgs ~= "" and not matchedKeysmodified_key then

            local bgStyle = bgStylesmodified_key

            if not bgStyle then

                local manualBgColor = args"bgColor_" .. (modified_key:match(".*%*$"))] or ""

                local manualTextColor = args"textColor_" .. (modified_key:match(".*%*$"))] or ""

                local bgColor, textColor



                if generatedColorsmodified_key then

                    bgColor, textColor = generatedColorsmodified_key].bgColor, generatedColorsmodified_key].textColor

                else

                    local randf1=args.rd1 =="yes" or args.Rd1=="yes" 

                    local randf2=args.rd2 =="yes" or args.Rd2=="yes" 

                    local randf3=args.rd3 =="yes" or args.Rd3=="yes" 

                    local randf4=args.rd4 =="yes" or args.Rd4=="yes" 

                    local randf5=args.rd5 =="yes" or args.Rd5=="yes" 

                    local randf6=args.rd6 =="yes" or args.Rd6=="yes" 

                    local randf7=args.rd7 =="yes" or args.Rd7=="yes" 

                    local randf8=args.rd8 =="yes" or args.Rd8=="yes" 

                    local randf9=args.rd9 =="yes" or args.Rd9=="yes" 

                    local randf10=args.rd10 =="yes" or args.Rd10=="yes" 

                    local randf11=args.rd11 =="yes" or args.Rd11=="yes" 

                    local randf12=args.rd12 =="yes" or args.Rd12=="yes" 



                    if manualBgColor ~= "" and manualTextColor ~= "" then

                        bgColor = manualBgColor

                        textColor = manualTextColor

                    elseif randf1 then

                        bgColor = generateEvenLighterColor1()

                        textColor = getContrastingTextColor(bgColor)

                    elseif randf2 then

                        bgColor = generateVeryLightColor2()

                        textColor = getContrastingTextColor(bgColor)

                    elseif randf3 then

                        bgColor = generateLightColor3()

                        textColor = getContrastingTextColor(bgColor)

                    elseif randf4 then

                        bgColor = generateDarkColor4()

                        textColor = getContrastingTextColor(bgColor)

                    elseif randf5 then

                        bgColor = generateDarkColor5()

                        textColor = getContrastingTextColor(bgColor)

                    elseif randf6 then

                        bgColor = generateDarkColor6()

                        textColor = getContrastingTextColor(bgColor) 

                    elseif randf7 then

                        bgColor = generateDarkColor7()

                        textColor = getContrastingTextColor(bgColor)

                    elseif randf8 then

                        bgColor = generateDarkColor8()

                        textColor = getContrastingTextColor(bgColor)

                    elseif randf9 then

                        bgColor = generateDarkColor9()

                        textColor = getContrastingTextColor(bgColor)

                    elseif randf10 then

                        bgColor = generateDarkColor10() 

                        textColor = getContrastingTextColor(bgColor)

                    elseif randf11 then

                        bgColor = generateRandomColor()

                        textColor = getContrastingTextColor(bgColor)

                    else

                        bgColor = "#" .. string.format("%06x", math.random(0x000000, 0xFFFFFF))

                        bgColor = bgColor .. "00" -- append alpha value (00 for fully transparent)

                        textColor = "#000000"

                    end



                    generatedColorsmodified_key = {bgColor = bgColor, textColor = textColor}

                end



                bgStyle = string.format("background-color: %s; color: %s;", bgColor, textColor)

                bgStylesmodified_key = bgStyle

            end

            for _, val in pairs(args) do

                if val == value and val ~= "" then

                    local alreadyAdded = string.match(output, val:gsub("^%l", string.upper))

                    if not alreadyAdded then

                        output = output .. string.format('<tr><th colspan="2" style="%s; %s; font-size:16px; text-align:center; font-weight:bold;">%s</th>\n</tr>\n', args.style or "", bgStyle, val:gsub("^%l", string.upper))

                        matchedKeysmodified_key = true

                        matched = true

                        break

                    end

                end

            end

        end

        modified_key = modified_key:gsub("%*+$", "")  -- Remove the last asterisks

    until not modified_key:match(".*%*+%*$") or matched



    

 --[[ local randFlag = args["*rand"] == "yes" -- Check if *rand=yes flag is present

    if randFlag then

        bgColor = generateRandomColor() -- Generate a random color

    else

        -- Handle other cases or default behavior for background color

    end 

   ]] 

-- Handle infinite occurrences of modified_key:match(".*%*$")

















    --local modified_key = key:gsub("^%D*(%d+).*", "%1")

  --[[

  if tonumber(string.sub(key, 1, 1)) ~= nil then

        modified_key= string.sub(key, 2)  -- Exclude the first character if it's a number

       

    end

   ]] 

   

   

        if key ~= 'image'and not key:match("^image[%a%d]+$") --[[and not (key:sub(1, 5)=="image")]] 

            and key ~= 'caption' and not key:match(".*%*$") 

            and key ~= 'headcolor' and key ~= 'color' and key~='header' 

            and not key:match("^abv%d+$")and not key:match("^up[%a%d]+$") and not key:match("^%d+mdl[%a%d]+$") then

            if key ~= 'up' and not (key:sub(1, 2) == 'up'=="image"and upProcessed) and key ~= 'abv'and key~="imagesize" and key~="rd" and not abvProcessed and not key:match("^Rd%d+$")then

              --if key ~= 'up' and not (key:sub(1, 2) == 'up' and upProcessed)  then

            if key ~= 'abv' and not (key:sub(1, 3) == 'abv' and abvProcessed) and not key:match("^rd%d+$") and not key:match("^mdl[%a%d]+$")then

            if key~="size" and not key:match("^size[%a%d]+$")and not(key:sub(-1)=="+") and not key:match("^caption[%a%d]+$") and key~="rd"and not(key:sub(1, 3)=="mdl")  and not key:match("^(%d+)mdl") then 

                  --//m 

                  

                  local convertedValue = value

                local originalValue = value  

                    if not cmProcessed and (value:match("%s*cm#%s*")or value:match("%s*centimeters#%s*")or value:match("%s*centimetres#%s*") or value:match("%s*centimeter#%s*") or value:match("%s*centimetre#%s*")) then

                    -- If centimeters conversion not done yet, do it here

                      --cmProcessed = true

                        convertedValue = cmToFeetAndInches(value)

                end

                    --/////❗ 

                 if type(value) == "string" then

                      

                       local age=dateCalculation(value)

                      --[[]] 

                       --local ag = calculateAg(value )

                      --if value:match("%d%d%d%d[/.-]%d%d[/.-]%d%d[./-]") then 

                      if value:match("%d+%d+%d+[./-]") then

                       --value =value:gsub("(%d%d%d%d)[/.-](%d%d)[/.-](%d%d)[./-]", "%1".. age )--:gsub("(%d%d%d%d)", "") 

                        value =value:gsub("(%d+%d+%d+)[/.-]", "".. age ):gsub("%d+[./-]", "")--:gsub("(%d%d%d%d)[/.-](%d%d)[/.-](%d%d)[./-]", "".. age ) 

                     --else 

                     	--value="Invalid date format"

                      end

                     --end

                        value = value:gsub("(%d+[/.%-]+%d+[/.%-]+%d+[%d/.%-]*)", ""):gsub("(%d+[/.%-]+%d+[/.%-]+%d+[%d/.%-]*)", ""):gsub("<i></i>", "")

                        value = value:gsub("(%d+[/.,-]%d+[/.,-]%d+)", "")

            

--[[ 

if value:match("%d+%d+%d+[/.,~]") then

    value = value:gsub("(%d+%d+%d+)[/.,~]", "%1<i></i>"..age)

end



value = value:gsub("(%d%d%d%d)[. /-] (%d%d)[/-.] (%d%d)", ""):gsub("(%d%d)[. - /] (%d%d)", ""):gsub("<i></i>", "")

--value = value:gsub("(%d%d%d%d)%p(%d%d)%p(%d%d)", ""):gsub("<i></i>", "")

]] 





                    if value:match("%s*cm%W%s*")or value:match("%s*centimeters#%s*")or value:match("%s*centimetres#%s*") or value:match("%s*centimeter#%s*") or value:match("%s*centimetre#%s*")   then

                        convertedValue = cmToFeetAndInches(value)..""

                    elseif value:match("%s*kg%W%s*") or value:match("%s*kgs#%s*")or value:match("%s*kilograms#%s*") or value:match("%s*kilogram#%s*") then

                        convertedValue = kgToPounds(value)

                    elseif value:match("%s*mph#%s*")or value:match("%s*mp/h#%s*")or value:match("%s*miles per hour#%s*")or value:match("%s*mile per hour#%s*") then

                        convertedValue = mphToKmh(value)

                    elseif value:match("%s*kmh#%s*")or value:match("%s*km/h#%s*")or value:match("%s*kilometers per hour#%s*")or value:match("%s*kilometer per hour#%s*")or value:match("%s*kilometres per hour#%s*")or value:match("%s*kilometre per hour#%s*") then

                        convertedValue = kmhToMph(value)

                    elseif value:match("%s*kms#%s*")or value:match("%s*km#%s*")or value:match("%s*kilometer#%s*")or value:match("%s*kilometers#%s*")or value:match("%s*kilometre#%s*")or value:match("%s*kilometres#%s*") then

                        convertedValue = kmToMi(value)

                    elseif value:match("%s*mi#%s*")or value:match("%s*mile#%s*")or value:match("%s*miles#%s*") then

                        convertedValue = miToKm(value)

                    elseif value:match("%s*hp#%s*")or value:match("%s*hps#%s*")or value:match("%s*horsepower#%s*")or value:match("%s*horsepowers#%s*") then

                        convertedValue = hpToKw(value)

                    elseif value:match("%s*kw#%s*")or value:match("%s*kws#%s*")or value:match("%s*kilowatt#%s*")or value:match("%s*kilowatts#%s*") then

                        convertedValue = kwToHp(value)                    elseif value:match("%s*ft#%s*") then                                          elseif value:match("%s*lb#%s*")or value:match("%s*pound#%s*")or value:match("%s*pounds#%s*") then

                        convertedValue = lbToKg(value)

                    elseif value:match("%s*mmms#%s*")or value:match("%s*mm#%s*")or value:match("%s*millimeter#%s*")or value:match("%s*millimetre#%s*")or value:match("%s*millimeters#%s*")or value:match("%s*millimetres#%s*") then

                        convertedValue = mmToInches(value)

                    elseif value:match("%s*in#%s*")or value:match("%s*ins#%s*")or value:match("%s*inch#%s*")or value:match("%s*inche#%s*")or value:match("%s*inches#%s*") then

                        convertedValue = inchesToMm(value)

                    elseif value:match("%s*ms#%s*")or value:match("%s*millisecond#%s*")or value:match("%s*milliseconds#%s*")  then

                        convertedValue = msToFts(value)

                    elseif value:match("%s*fts#%s*")or value:match("%s*ft/s#%s*")or value:match("%s*fps#%s*")or value:match("%s*footperseconds#%s*") then

                        convertedValue = ftsToMs(value)

                    elseif value:match("%s*°c#%s*") or value:match("%s*celsius#%s*") or value:match("%s*Celsius#%s*")  then

                        convertedValue = celsiusToFahrenheit(value)

                    elseif value:match("%s*°f#%s*") or value:match("%s*fahrenheit#%s*") then

                        convertedValue = fahrenheitToCelsius(value)

                   --❗ 

                        elseif value:match("%s*liters#%s*")or value:match("%s*litres#%s*")or value:match("%s*litre#%s*")or value:match("%s*liter#%s*") then

                        convertedValue = litersToGallons(value)

                    elseif value:match("%s*gallons#%s*")or value:match("%s*gallon#%s*") then

                        convertedValue = gallonsToLiters(value)

                    elseif value:match("%s*m³#%s*")or value:match("%s*m3#%s*")or value:match("%s*cubicmeters#%s*")or value:match("%s*cubicmetres#%s*")or value:match("%s*cubicmetre#%s*")or value:match("%s*cubicmeter#%s*") then

                        convertedValue = cubicMetersToCubicFeet(value)

                    elseif value:match("%s*ft³#%s*")or value:match("%s*ft3#%s*")or value:match("%s*cubicfeet#%s*")or value:match("%s*cubicfoot#%s*")or value:match("%s*cubicfeets#%s*")or value:match("%s*cubicfoots#%s*") then

                    	convertedValue = cubicFeetToCubicMeters(value)                                         elseif value:match("%s*sqm#%s*")or value:match("%s*sqms#%s*")or value:match("%s*sqmetre#%s*")or value:match("%s*sqmetres#%s*")or value:match("%s*squaremeter#%s*")or value:match("%s*squaremeters#%s*")or value:match("%s*sqmeter#%s*")or value:match("%s*sqmeters#%s*") then

                        convertedValue = squareMetersToSquareFeet(value)

                    elseif value:match("%s*sqft#%s*")or value:match("%s*sqfoot#%s*")or value:match("%s*sqfeet#%s*")or value:match("%s*squarefoots#%s*")or value:match("%s*squarefeets#%s*")or value:match("%s*squarefeet#%s*") then

                        convertedValue = squareFeetToSquareMeters(value)

                    elseif value:match("%s*hectares#%s*")or value:match("%s*hectare#%s*") then

                        convertedValue = hectaresToAcres(value)

                    elseif value:match("%s*acres#%s*")or value:match("%s*acre#%s*") then

                        convertedValue = acresToHectares(value)

                    elseif value:match("%s*hours#%s*")or value:match("%s*hour#%s*") then

                        convertedValue = hoursToMinutes(value)

                    elseif value:match("%s*minutes#%s*")or value:match("%s*minute#%s*") then

                        convertedValue = minutesToHours(value)

                    elseif value:match("%s*days#%s*")or value:match("%s*day#%s*") then

                        convertedValue = daysToHours(value)

                    elseif value:match("%s*joules#%s*")or value:match("%s*joule#%s*") then

                        convertedValue = joulesToCalories(value)

                    elseif value:match("%s*calories#%s*")or value:match("%s*calorie#%s*") then

                        convertedValue = caloriesToJoules(value)

                    elseif value:match("%s*kwh#%s*")or value:match("%s*kilowatthours#%s*")or value:match("%s*kilowatthour#%s*") then

                        convertedValue = kilowattHoursToJoules(value)

                    elseif value:match("%s*psi#%s*")or value:match("%s*pounds per square inch#%s*")or value:match("%s*pound per square inches#%s*") then

                        convertedValue = psiToPascals(value)

                    elseif value:match("%s*pascals#%s*")or value:match("%s*pascal#%s*") then

                        convertedValue = pascalsToPsi(value)

                    elseif value:match("%s*atm#%s*")or value:match("%s*atmospheres#%s*")or value:match("%s*atmosphere#%s*") then

                        convertedValue = atmospheresToPascals(value)

                    elseif value:match("%s*rpm#%s*") then

                        convertedValue = rpmToHertz(value)

                    elseif value:match("%s*kilohertz#%s*")or value:match("%s*khz#%s*") then

                        convertedValue = kilohertzToHertz(value)

                    elseif value:match("%s*hertz#%s*") then

                        convertedValue = hertzToRPM(value)

                    elseif value:match("%s*horsepower#%s*") then

                        convertedValue = horsepowerToWatts(value)

                    elseif value:match("%s*megawatts#%s*") or value:match("%s*megawatt#%s*")then

                        convertedValue = megawattsToHorsepower(value)

                    elseif value:match("%s*watts#%s*") or value:match("%s*watt#%s*")then

                        convertedValue = wattsToHorsepower(value)

                    elseif value:match("%s*hp#%s*") then

                        convertedValue = horsepowerToMegawatts(value)

                    elseif value:match("%s*m#%s*")or value:match("%s*meters#%s*")or value:match("%s*metres#%s*")or value:match("%s*meter#%s*")or value:match("%s*metre#%s*") then

                        convertedValue = mToFeet(value)

                    elseif value:match("%s*ft%W%s*") or value:match("%s*feet%P%s*")or value:match("%s*feets%P%s*")or value:match("%s*foot%P%s*")or value:match("%s*foots%P%s*") then

                       --local ft=convertedValue 

                        --convertedValue =convertValue:gsub("^ft[%a%d]+$", "" .. ft) --ftToCm(value)

                    value =ftToCm(value)

                    

                   end 

                    --local age=calculateAge(value)

                    --value = value:gsub("(%d+[/.,-]%d+[/.,-]%d+)", "")



                    

        --❗            modified_key = key:gsub("^[_%d]*", "")



        

                   value = value:gsub("^%l", string.upper)

                   local first_char = value:match("%a") -- Find the first alphabet character

                   if first_char then

                      value = value:gsub("^" .. first_char, string.upper) -- Capitalize the first alphabet character

                   end

                    output = output .. '| style="font-size:15px; font-weight:bolder;padding-right:1em;" | ' ..modified_key:gsub("^[_()%-%d]*", "") .. "\n"

                    if originalValue ~= convertedValue then

                       output = output .. '| '..convertedValue.. '\n|-\n'

                    else

                        output = output .. '| ' .. value .. '\n|-\n' 

                    end

                    



                  end

            	end

            

             end

          end

      end

end





                  

--[[



local values = {}



for key, value in pairs(args) do

    if key:sub(1, 3) == 'abv' and value ~= "" then

        table.insert(values, {key = key, value = value})

    end

end

table.sort(values, function(a, b) return a.key < b.key end)

for _, entry in ipairs(values) do

    local key = entry.key

    local value = entry.value

    output = output .. '| style="background:lightgray;font-size:20px;text-align:center;background-color:' .. (args.abvheadcolor or "#f2f2f2") .. ';color:' .. (args.abvcolor or "inherit") .. ';font-weight:bold;" | ' .. value .. '\n|-\n'

end

mw.text.unstrip



local frame = mw.getCurrentFrame()

--local infoboxContent = frame:preprocess('{{User:Thisasia/Signature|' ..value..'}}')



local function transcludeTemplate(templateName, args)

    local frame = mw.getCurrentFrame()

    local templateContent = frame:expandTemplate { title = templateName, args = args }

    return templateContent

end

]] 

--local frame = mw.getCurrentFrame()

local values = {}



for key, value in pairs(args) do

    if key:sub(1, 3) == "abv" and value ~= "" then

        table.insert(values, { key = key, value = value, position = mw.ustring.match(key, "%d+") })

    end

end



table.sort(values, function(a, b) return tonumber(a.position) < tonumber(b.position) end)



for _, entry in ipairs(values) do

    local key = entry.key

    local value = entry.value

    value = value:gsub("^%l", string.upper)

    local first_char = value:match("%a") -- Find the first alphabet character

    if first_char then

        value = value:gsub("^" .. first_char, string.upper) -- Capitalize the first alphabet character

    end

    output = output .. '<tr><th colspan="2" style="font-size:20px;text-align:center;background-color:' .. (args.downheader or "rgba(0,0,0,0.020)") .. ';color:' .. (args.downcolor or "") .. ';font-weight:bold;"> '.. value .. '</th></tr>\n|-\n'

--output = mw.getCurrentFrame():preprocess('{{User:Thisasia/sandbox3|\n' .. output .. '}}')

end

   output = output .. '</div>\n'

--   output = mw.getCurrentFrame():preprocess('{{User:Thisasia/sandbox3|\n' .. output .. '}}')

    return output

end



return p
From Wikipedia, the free encyclopedia

local p = {}







local function dateCalculation(dateStr)

    local year , month, day = dateStr:match("(%d+)[/.,-](%d+)[/.,-](%d+)")

    if not year then

     day , month, year = dateStr:match("(%d+)[/.,-](%d+)[/.,-](%d+)")

    end 

    if not year then 

       return 'Invalid ' 

    end

    

        

    local currentDate = os.date("*t")

    local age = currentDate.year - tonumber(year)

    if currentDate.month < tonumber(month) or (currentDate.month == tonumber(month) and currentDate.day < tonumber(day)) then

        age = age - 1

    end

    

    local monthName = os.date("%B", os.time{year=tonumber(year), month=tonumber(month), day=tonumber(day)})

    return " ".. monthName .. " "..day..", " .. year.. " <br/>(Age " ..  age.. ")"

end











--[[ 

local function dateCalculation(dateStr)

    local year , month, day = dateStr:match("(%d+)[/.,-](%d+)[/.,-](%d+)")

    if not year then

        day , month, year = dateStr:match("(%d+)[/.,-](%d+)[/.,-](%d+)")

    end

    if not year then 

        return 'Invalid date format' 

    end

    

    local currentDate = os.date("*t")

    local age

        if tonumber(year) < 1582 or (tonumber(year) == 1582 and (tonumber(month) < 10 or (tonumber(month) == 10 and tonumber(day) < 4))) then

        age = currentDate.year - tonumber(year)

    else

         age = currentDate.year - tonumber(year)

        

         local leapYears = 0

        for i = tonumber(year), currentDate.year - 1 do

            if i % 4 == 0 then

                leapYears = leapYears + 1

            end

        end

                age = age - leapYears

    end

    

    if currentDate.month < tonumber(month) or (currentDate.month == tonumber(month) and currentDate.day < tonumber(day)) then

        age = age - 1

    end

    

    local monthName = os.date("%B", os.time{year=tonumber(year), month=tonumber(month), day=tonumber(day)})

    return " ".. monthName .. " "..day..", " .. year.. " <br/>(Age " ..  age.. ")"

end



]] 





--❗

--[[Volume conversions]] 

local function litersToGallons(liters)

    local litersValue = tonumber(liters:match("%d+%.?%d*"))

    if litersValue then

        local gallons = litersValue * 0.264172

        return "".. string.format("%.2f liters (%.2f gallons)", litersValue, gallons)

    end

    return liters

end



local function gallonsToLiters(gallons)

    local gallonsValue = tonumber(gallons:match("%d+%.?%d*"))

    if gallonsValue then

        local liters = gallonsValue * 3.78541

        return string.format("%.2f gallons (%.2f liters)", gallonsValue, liters)

    end

    return gallons

end



local function cubicMetersToCubicFeet(cubicMeters)

    local cubicMetersValue = tonumber(cubicMeters:match("%d+%.?%d*"))

    if cubicMetersValue then

        local cubicFeet = cubicMetersValue * 35.3147

        return string.format("%.2f cubic meters (%.2f cubic feet)", cubicMetersValue, cubicFeet)

    end

    return cubicMeters

end



local function cubicFeetToCubicMeters(cubicFeet)

    local cubicFeetValue = tonumber(cubicFeet:match("%d+%.?%d*"))

    if cubicFeetValue then

        local cubicMeters = cubicFeetValue * 0.0283168

        return string.format("%.2f cubic feet (%.2f cubic meters)", cubicFeetValue, cubicMeters)

    end

    return cubicFeet

end



-- Area conversions

local function squareMetersToSquareFeet(squareMeters)

    local squareMetersValue = tonumber(squareMeters:match("%d+%.?%d*"))

    if squareMetersValue then

        local squareFeet = squareMetersValue * 10.7639

        return string.format("%.2f square meters (%.2f square feet)", squareMetersValue, squareFeet)

    end

    return squareMeters

end



local function squareFeetToSquareMeters(squareFeet)

    local squareFeetValue = tonumber(squareFeet:match("%d+%.?%d*"))

    if squareFeetValue then

        local squareMeters = squareFeetValue * 0.092903

        return string.format("%.2f square feet (%.2f square meters)", squareFeetValue, squareMeters)

    end

    return squareFeet

end 



local function hectaresToAcres(hectares)

    local hectaresValue = tonumber(hectares:match("%d+%.?%d*"))

    if hectaresValue then

        local acres = hectaresValue * 2.47105

        return string.format("%.2f hectares (%.2f acres)", hectaresValue, acres)

    end

    return hectares

end



local function acresToHectares(acres)

    local acresValue = tonumber(acres:match("%d+%.?%d*"))

    if acresValue then

        local hectares = acresValue * 0.404686

        return string.format("%.2f acres (%.2f hectares)", acresValue, hectares)

    end

    return acres

end



-- Time conversions

local function hoursToMinutes(hours)

    local hoursValue = tonumber(hours:match("%d+%.?%d*"))

    if hoursValue then

        local minutes = hoursValue * 60

        return string.format("%.2f hours (%d minutes)", hoursValue, minutes)

    end

    return hours

end



local function minutesToHours(minutes)

    local minutesValue = tonumber(minutes:match("%d+%.?%d*"))

    if minutesValue then

        local hours = minutesValue / 60

        local decimalPart = minutes:match("%.(%d+)")

        if decimalPart then

            hours = hours + tonumber("0." .. decimalPart)

        end

        return string.format("%.2f minutes (%.2f hours)", minutesValue, hours)

    end

    return minutes

end





local function daysToHours(days)

    local daysValue = tonumber(days:match("%d+%.?%d*"))

    if daysValue then

        local hours = daysValue * 24

        return string.format("%.2f days (%d hours)", daysValue, hours)

    end

    return days

end



local function hoursToDays(hours)

    local hoursValue = tonumber(hours:match("%d+%.?%d*"))

    if hoursValue then

        local days = hoursValue / 24

        return string.format("%.2f hours (%.2f days)", hoursValue, days)

    end

    return hours

end



-- Energy conversions

local function joulesToCalories(joules)

    local joulesValue = tonumber(joules:match("%d+%.?%d*"))

    if joulesValue then

        local calories = joulesValue * 0.000239006

        return string.format("%.2f joules (%.6f calories)", joulesValue, calories)

    end

    return joules

end



local function caloriesToJoules(calories)

    local caloriesValue = tonumber(calories:match("%d+%.?%d*"))

    if caloriesValue then

        local joules = caloriesValue / 0.000239006

        return string.format("%.2f calories (%.2f joules)", caloriesValue, joules)

    end

    return calories

end



local function kilowattHoursToJoules(kWh)

    local kWhValue = tonumber(kWh:match("%d+%.?%d*"))

    if kWhValue then

        local joules = kWhValue * 3600000

        return string.format("%.2e kWh (%.2e joules)", kWhValue, joules)

    end

    return kWh

end



local function joulesToKilowattHours(joules)

    local joulesValue = tonumber(joules:match("%d+%.?%d*"))

    if joulesValue then

        local kWh = joulesValue / 3600000

        return string.format("%.2e joules (%d kWh)", joulesValue, kWh)

    end

    return joules

end



-- 🔴Pressure conversions

local function pascalsToPSI(pascals)

    local pascalsValue = tonumber(pascals:match("%d+"))

    if pascalsValue then

        local psi = pascalsValue * 0.000145038

        return string.format("%d pascals (%.6f PSI)", pascalsValue, psi)

    end

    return pascals

end



local function psiToPascals(psi)

    local psiValue = tonumber(psi:match("%d+"))

    if psiValue then

        local pascals = psiValue / 0.000145038

        return string.format("%.6f PSI (%d pascals)", psiValue, pascals)

    end

    return psi

end



local function atmospheresToPascals(atmospheres)

    local atmospheresValue = tonumber(atmospheres:match("%d+"))

    if atmospheresValue then

        local pascals = atmospheresValue * 101325

        return string.format("%d atmospheres (%d pascals)", atmospheresValue, pascals)

    end

    return atmospheres

end



local function pascalsToAtmospheres(pascals)

    local pascalsValue = tonumber(pascals:match("%d+"))

    if pascalsValue then

        local atmospheres = pascalsValue / 101325

        return string.format("%d pascals (%.6f atmospheres)", pascalsValue, atmospheres)

    end

    return pascals

end



-- Frequency conversions

local function hertzToRPM(hertz)

    local hertzValue = tonumber(hertz:match("%d+"))

    if hertzValue then

        local rpm = hertzValue * 60

        return string.format("%d Hertz (%d RPM)", hertzValue, rpm)

    end

    return hertz

end



local function rpmToHertz(rpm)

    local rpmValue = tonumber(rpm:match("%d+"))

    if rpmValue then

        local hertz = rpmValue / 60

        return string.format("%d RPM (%.2f Hertz)", rpmValue, hertz)

    end

    return rpm

end



local function kilohertzToHertz(kHz)

    local kHzValue = tonumber(kHz:match("%d+"))

    if kHzValue then

        local hertz = kHzValue * 1000

        return string.format("%d kHz (%d Hertz)", kHzValue, hertz)

    end

    return kHz

end



local function hertzToKilohertz(hertz)

    local hertzValue = tonumber(hertz:match("%d+"))

    if hertzValue then

        local kHz = hertzValue / 1000

        return string.format("%d Hertz (%.2f kHz)", hertzValue, kHz)

    end

    return hertz

end



-- Power conversions

local function wattsToHorsepower(watts)

    local wattsValue = tonumber(watts:match("%d+"))

    if wattsValue then

        local horsepower = wattsValue * 0.00134102

        return string.format("%d watts (%.6f horsepower)", wattsValue, horsepower)

    end

    return watts

end



local function horsepowerToWatts(horsepower)

    local horsepowerValue = tonumber(horsepower:match("%d+"))

    if horsepowerValue then

        local watts = horsepowerValue / 0.00134102

        return string.format("%.6f horsepower (%d watts)", horsepowerValue, watts)

    end

    return horsepower

end



local function megawattsToHorsepower(megawatts)

    local megawattsValue = tonumber(megawatts:match("%d+"))

    if megawattsValue then

        local horsepower = megawattsValue * 1341.02

        return string.format("%d megawatts (%.2f horsepower)", megawattsValue, horsepower)

    end

    return megawatts

end



local function horsepowerToMegawatts(horsepower)

    local horsepowerValue = tonumber(horsepower:match("%d+"))

    if horsepowerValue then

        local megawatts = horsepowerValue / 1341.02

        return string.format("%.2f horsepower (%d megawatts)", horsepowerValue, megawatts)

    end

    return horsepower

end



-- Add these functions to the p dynamic function to integrate them into the infobox

--❗

local function ftToCm(ft)

    local ftValue = tonumber(ft:match("%d+%.?%d*"))

    if ftValue then

        local cm = ftValue * 30.48

        return string.format("%.2f ft (%.2f cm)", ftValue, cm)

    end

    return ft

end 



local function cmToFeetAndInches(cm)

    local cmValue = tonumber(cm:match("%d+%.?%d*"))

    if cmValue then

        local totalInches = cmValue / 2.54

        local feet = math.floor(totalInches / 12)

        local inches = math.floor(totalInches % 12)

        return string.format("%.2f cm (%d feet %d inches)", cmValue, feet, inches)

    end

    return cm

end



local function mphToKmh(mph)

    local mphValue = tonumber(mph:match("%d+%.?%d*"))

    if mphValue then

        local kmh = mphValue * 1.60934

        return string.format("%.2f mph (%.2f km/h)", mphValue, kmh)

    end

    return mph

end



local function kmhToMph(kmh)

    local kmhValue = tonumber(kmh:match("%d+%.?%d*"))

    if kmhValue then

        local mph = kmhValue / 1.60934

        return string.format("%.2f km/h (%.2f mph)", kmhValue, mph)

    end

    return kmh

end



local function kmToMi(km)

    local kmValue = tonumber(km:match("%d+%.?%d*"))

    if kmValue then

        local miles = kmValue * 0.621371

        return string.format("%.2f km (%.2f mi)", kmValue, miles)

    end

    return km

end



local function miToKm(mi)

    local miValue = tonumber(mi:match("%d+%.?%d*"))

    if miValue then

        local km = miValue / 0.621371

        return string.format("%.2f miles (%.2f km)", miValue, km)

    end

    return mi

end



local function hpToKw(hp)

    local hpValue = tonumber(hp:match("%d+%.?%d*"))

    if hpValue then

        local kw = hpValue * 0.735499

        return string.format("%.2f horsepower (%.2f kW)", hpValue, kw)

    end

    return hp

end



local function kwToHp(kw)

    local kwValue = tonumber(kw:match("%d+%.?%d*"))

    if kwValue then

        local hp = kwValue / 0.735499

        return string.format("%.2f Kilowatt(%.2f hp)", kwValue, hp)

    end

    return kw

end



local function lbToKg(lb)

    local lbValue = tonumber(lb:match("%d+%.?%d*"))

    if lbValue then

        local kg = lbValue * 0.453592

        return string.format("%.2f lb (%.2f kg)", lbValue, kg)

    end

    return lb

end



local function kgToPounds(kg)

    --local kgValu = tonumber(kg:match("%d+"))

    local kgValue = tonumber(kg:match("%d+%.?%d*"))

    if kgValue>1 then

        local pounds = kgValue * 2.20462

        return string.format("%.2f kgs (%.2f pounds)", kgValue, pounds)

        else

         local pounds = kgValue * 2.20462

        return string.format("%.2f kg (%.2f pounds)", kgValue, pounds)

    end

    return kg

end



local function mmToInches(mm)

    local mmValue = tonumber(mm:match("%d+%.?%d*"))

    if mmValue then

        local inches = mmValue * 0.0393701

        return string.format("%.2f mm (%.2f inches)", mmValue, inches)

    end

    return mm

end



local function inchesToMm(inches)

    local inchesValue = tonumber(inches:match("%d+%.?%d*")) 

    if inchesValue then

        local mm = inchesValue / 0.0393701

        return string.format("%.2f inches (%.2f mm)", inchesValue, mm)

    end

    return inches

end



local function msToFts(ms)

    local msValue = tonumber(ms:match("%d+%.?%d*"))

    if msValue then

        local fts = msValue * 3.28084

        return string.format("%.2f m/s(%.2f ft/s)", msValue, fts)

    end

    return ms

end



local function ftsToMs(fts)

    local ftsValue = tonumber(fts:match("%d+%.?%d*"))

    if ftsValue then

        local ms = ftsValue / 3.28084

        return string.format("%.2f ft/s(%.2f m/s)", ftsValue, ms)

    end

    return fts

end



local function mToFeet(m)

    local mValue = tonumber(m:match("%d+%.?%d*"))

    if mValue then

        local feet = mValue * 3.28084

        return string.format("%.2f meter (%.2f ft)", mValue, feet)

    end

    

    -- Check for variations of "m", "meter", and "metre"

    local mValueAlt = tonumber(m:match("(%d+%.?%d*)%s*[mM]"))

    if mValueAlt then

        local feetAlt = mValueAlt * 3.28084

        return string.format("%.2f m (%.2f ft)", mValueAlt, feetAlt)

    end

    

    local mValueAlt2 = tonumber(m:match("(%d+%.?%d*)%s*[mM][eE][tT][eE]?[rR]?"))

    if mValueAlt2 then

        local feetAlt2 = mValueAlt2 * 3.28084

        return string.format("%.2f metre (%.2f ft)", mValueAlt2, feetAlt2)

    end

    

    local mValueAlt3 = tonumber(m:match("(%d+%.?%d*)%s*[mM][eE][tT][eE][rR]?"))

    if mValueAlt3 then

        local feetAlt3 = mValueAlt3 * 3.28084

        return string.format("%.2f meter (%.2f ft)", mValueAlt3, feetAlt3)

    end

    

    return m

end

--//m///





local function celsiusToFahrenheit(c)

    local cValue = tonumber(c:match("%d+"))

    if cValue then

        local fahrenheit = cValue * 9/5 + 32

        return string.format("%.2f°C (%.2f°F)", cValue, fahrenheit)

    end

    return c  

end



local function fahrenheitToCelsius(f)

    local fValue = tonumber(f:match("%d+"))

    if fValue then

        local celsius = (fValue - 32) * 5/9

        return string.format("%.2f°F (%.2f°C)", fValue, celsius)

    end

    return f

end

function capitalizeFirstLetter(str)

    return str:gsub("^%l", string.upper)

end



-- Function to generate contrasting text color for a given background color

local function getContrastingTextColor(bgColor)

    -- Convert hex color to RGB

    local r = tonumber(bgColor:sub(2, 3), 16)

    local g = tonumber(bgColor:sub(4, 5), 16)

    local b = tonumber(bgColor:sub(6, 7), 16)



    -- Calculate relative luminance

    local luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255



    -- Choose white or black text color based on luminance

    if luminance > 0.5 then

        return "#000000"  -- Black text for light backgrounds

    else

        return "#FFFFFF"  -- White text for dark backgrounds

    end

end



-- Function to generate even lighter colors

function generateEvenLighterColor1()

    local r = math.random(0xF0, 0xFF) -- Red component

    local g = math.random(0xF0, 0xFF) -- Green component

    local b = math.random(0xF0, 0xFF) -- Blue component

    return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color

end



-- Function to generate a very light color

function generateVeryLightColor2()

    local r = math.random(0xE0, 0xFF) -- Red component

    local g = math.random(0xE0, 0xFF) -- Green component

    local b = math.random(0xE0, 0xFF) -- Blue component

    return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color

end



-- Function to generate a random light color

function generateLightColor3()

    local r = math.random(0xB0, 0xFF) -- Red component

    local g = math.random(0xB0, 0xFF) -- Green component

    local b = math.random(0xB0, 0xFF) -- Blue component

    return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color

end



-- Functions to generate mixed light-dark colors

function generateDarkColor4()

    local r = math.random(0x60, 0x80) -- Red component

    local g = math.random(0x60, 0x80) -- Green component

    local b = math.random(0x60, 0x80) -- Blue component

    return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color

end



function generateDarkColor5()

    local r = math.random(0x50, 0x70) -- Red component

    local g = math.random(0x50, 0x70) -- Green component

    local b = math.random(0x50, 0x70) -- Blue component

    return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color

end



function generateDarkColor6()

    local r = math.random(0x40, 0x60) -- Red component

    local g = math.random(0x40, 0x60) -- Green component

    local b = math.random(0x40, 0x60) -- Blue component

    return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color

end



function generateDarkColor7()

    local r = math.random(0x20, 0x40) -- Red component

    local g = math.random(0x20, 0x40) -- Green component

    local b = math.random(0x20, 0x40) -- Blue component

    return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color

end



function generateDarkColor8()

    local r = math.random(0x30, 0x70) -- Red component

    local g = math.random(0x30, 0x70) -- Green component

    local b = math.random(0x30, 0x70) -- Blue component

    return string.format("#%02X%02X%02X", r, g, b) -- Format as hexadecimal color

end



function generateDarkColor9()

    return string.format("#%02x%02x%02x", math.random(0x30, 0x50), math.random(0x40, 0x70), math.random(0x50, 0x70))

end



function generateDarkColor10()

    return string.format("#%06x", math.random(0x30, 0x70))

end



-- Function to generate a random color

local function generateRandomColor()

    local r = math.random(0, 255)

    local g = math.random(0, 255)

    local b = math.random(0, 255)

    return string.format("#%02X%02X%02X", r, g, b)

end





--[[ local conversionPatterns = {

        { pattern = "%s*kilohertz%s*", convertedValue = kilohertzToHertz},

        { pattern = "%s*kg%s*", conversion = kgToPounds },

        { pattern = "%s*mph%s*", conversion = mphToKmh },

        -- Add more conversion patterns as needed

    } ]] 





function p.dynamic(frame)

    local args = frame:getParent().args

    local output = '<div colspan="2" class="infobox biography vcard" style="max-width: 100vw; width: auto; margin: 0 auto;">\n|-\n' 

    -- local firstDescriptionFound = false

    local cmProcessed = false

    local abvParams = {}  -- Store abv parameters separately

    local abvProcessed = false

    local upProcessed = false

    local imageProcessed =false 

    --[[go over arguments to find "up" and "abv" parameters

    for key, value in pairs(args) do

        if key:sub(1, 2) == 'up' then

            if value ~= "" then

                output = output .. '<tr><th style='..(args.header or"")..'"background:lightgra;font-size:20px;text-align: center; background-color: ' .. (args.headcolor or "#f2f2f2") .. '; color: ' .. (args.color or "inherit") .. '; font-weight: bold;"> ' .. value .. '\n</th></tr>\n'

                upProcessed = true

            end

        end

    end

]] 











local values = {}



for key, value in pairs(args) do

    if key:sub(1, 2) == 'up' and value ~= "" then

        table.insert(values, {key = key, value = value})

    end

end

table.sort(values, function(a, b) return a.key < b.key end)

for _, entry in ipairs(values) do

    local key = entry.key

    local value = entry.value

    value = value:gsub("^%l", string.upper)

    local first_char = value:match("%a") -- Find the first alphabet character

    if first_char then

    value = value:gsub("^" .. first_char, string.upper) -- Capitalize the first alphabet character

    end

    output = output .. '<tr><th style="font-size:20px;text-align:center;background-color:' .. (args.header or "") .. ';color:' .. (args.color or "") .. ';font-weight:bold;" colspan="2">' .. value .. '\n</th></tr>\n'

end



--[[ 

for key, value in pairs(args) do

        if value ~= "" then

            if key ~= 'image' and key ~= 'imagecaption' and key ~= 'caption' and key ~= 'headcolor' and key ~= 'color' and key ~= 'abvstyle' and key ~= 'abvheadcolor' and key ~= 'abvcolor'then

                if key ~= 'up' and not (key:sub(1, 2) == 'up' and upProcessed) and key ~= 'abv' and not abvProcessed then

                    -- Your existing conversion logic goes here

                end

            end

        end

end



for key, value in pairs(args) do

        if value ~= "" then

            if key ~= 'image' and key ~= 'imagecaption' and key ~= 'caption' and key ~= 'headcolor' and key ~= 'color' and key ~= 'abvstyle' and key ~= 'abvheadcolor' and key ~= 'abvcolor'then

                if key ~= 'abv' and not (key:sub(1, 3) == 'abv' and abvProcessed) and key ~= 'abv' and not upProcessed then

                    -- Your existing conversion logic goes here

                end

            end

        end

end

]] 

local hasImage = false

for key, _ in pairs(args) do

    if key:sub(1, 5) == "image" then

        hasImage = true

        break

    end

end



if not hasImage then

    local defaultImage = "[[File:default_image.jpg|thumb|center|Default Image]]\n"

    output = output .. defaultImage

end



if args.image then

    local processedKeys = {}

    local processedSizeCaption = {}

    local images = {}

    local div = '<div style="display:grid;grid-template-columns: repeat(2, auto); gap: -2px; text-align: center; margin: 2px;">'



    for key, value in pairs(args) do

        if key:sub(1, 5) == "image" and value ~= "" and not processedKeyskey then

            processedKeyskey = true

            local captionKey = "caption" .. key:sub(6)

            local sizeKey = "size" .. key:sub(6)



            if not processedSizeCaptioncaptionKey and not processedSizeCaptionsizeKey then

                processedSizeCaptioncaptionKey = true

                processedSizeCaptionsizeKey = true



                local caption = argscaptionKey or ""

                local imagesize = argssizeKey or ""

                local isFrameless = string.match(value, '|frameless')

                local imageExtension = value:match("%.([^.]+)$")



               if not imageExtension then

                    value = value:gsub("|", "".. ".jpg|").. ".jpg"

                end

                local grid =""

                local wikiMarkup = ''

                if isFrameless then

                    local remo = value:gsub("(%[%[.-|)File:", "%1")

                    wikiMarkup = wikiMarkup .. '|' .. '<div style="text-align:center;">' .. remo .. '</div>' .. '<small style="display: block; text-align: center;">' .. caption .. '</small>\n|-\n'

                else

                    local imageName, imageSize = value:match("%[%[File:(.-)|([^|%]]+)]]")

                    if imageName then

                        wikiMarkup = wikiMarkup .. "[[File:" .. imageName

                        if imageSize then

                            wikiMarkup = wikiMarkup .. "|" .. imageSize

                        end

                        wikiMarkup = wikiMarkup .. "]]"

                    else

                        local imageSizeMarkup = ""

                        if imagesize ~= "" then

                            imageSizeMarkup = "|" .. imagesize

                        end

                        wikiMarkup = wikiMarkup .. "[[File:" .. value:gsub("%[%[", ""):gsub("%]%]", "") .. imageSizeMarkup .. "]]"

                    end

                    wikiMarkup = '<div style="text-align:center;">' .. wikiMarkup  .. '<small style="display: block; text-align: center;">' .. caption .. '</small></div>\n'

                   end



                -- Store the image markup along with its key

                table.insert(images, { key = key, markup = wikiMarkup, insertionOrder = #images + 1 })            end

        end

    end



    -- Sort the images based on their keys to maintain the insertion order

   --table.sort(images, function(a, b) return a.key < b.key end)



-- Generate the output markup

local columnCount = 0

local gridOpen = false

for _, imageData in ipairs(images) do

    local wikiMarkup = imageData.markup

    if imageData.key:sub(-1) == "+" then

        if not gridOpen then

            output = output .. '|<div colspan="2">' .. div.. '</div>\n|-\n' -- Open the grid container if it's not already open

            gridOpen = true

        end

        --output = output ..'|'.. wikiMarkup .. '\n|-\n' -- For keys not ending with '+', display normally



        output = output .. '|<div class="grid-item"colspan="2">' .. wikiMarkup .. '</div>\n'

        columnCount = (columnCount + 1) % 2

    else

        if gridOpen then

            output = output .. '</div>\n|-\n' -- Close the grid container if it's open

            gridOpen = false

        end

       output = output ..'<tr><th colspan="2">'.. wikiMarkup .. '</th><tr>\n|-\n' -- For keys not ending with '+', display normally

    end

end



-- If there are unclosed div tags, close them

if gridOpen then

    output = output .. '</div>\n|-\n'

end

end



local values = {}



for key, value in pairs(args) do

    if key:sub(1, 3) == "mdl"or key:match("^(%d+)mdl") and value ~= "" then

        table.insert(values, { key = key, value = value, position = mw.ustring.match(key, "%d+") })

    end

end



table.sort(values, function(a, b) return tonumber(a.position) < tonumber(b.position) end)



for _, entry in ipairs(values) do

    local key = entry.key

    local value = entry.value

    value = value:gsub("^%l", string.upper)

    local first_char = value:match("%a") -- Find the first alphabet character

    if first_char then

        value = value:gsub("^" .. first_char, string.upper) -- Capitalize the first alphabet character

    end

--   local transcludedContent = transcludeTemplate("User:Thisasia/sandbox3", { value = "" })

    --output = output .. '<tr><th colspan="2" style="font-size:20px;text-align:center;background-color:' .. (args.downheade or "rgba(0,0,0,0.020)") .. ';color:' .. (args.downcolo or "") .. ';font-weight:bold;"> {{User:Thisasia/Signature|'.. frame:preprocess('{{User:Thisasia/Signature|'.. value.. '}}').. value .. '}}</th></tr>\n|-\n'

    output = output .. '<tr><th colspan="2" style="font-size:20px;text-align:center;background-color:' .. (args.downheade or "rgba(0,0,0,0.020)") .. ';color:' .. (args.downcolo or "") .. ';font-weight:bold;">'.. value .. '</th></tr>\n|-\n'

end



--[[ 

 if key:sub(6, 6) == "+" then

                    table.insert(gridImages, {value = value, caption = caption, isFrameless = isFrameless})

                else

                    table.insert(normalImages, {value = value, caption = caption, imagesize = imagesize, isFrameless = isFrameless})

                end

            end

        end

    end

    

    -- Begin HTML output for grid layout

    local div='<div class="grid-container" style="  display: grid; grid-template-columns: repeat(2, 1fr); gap: 2px; text-align: center; margin-bottom: 5px; ">\n' 

    

    -- Output grid images

    for _, image in ipairs(gridImages) do

        local wikiMarkup = ""

        local remo = image.value

        wikiMarkup = wikiMarkup .. div.. '<div class="grid-item">' ..'<div style="text-align:center;">'.. remo.. '</div>'..'<small style="display: block; text-align: center;">' .. image.caption .. '</small>\n</div>\n'

        output = output .. wikiMarkup

    end

                  





   if args.image then

        local caption = args.caption or ""

        local imagesize = args.imagesize or ""  

        output = output .. '|' ..'<div style="text-align:center;">'.. args.image.. '</div>'..'<small style="display: block; text-align: center;">' .. caption .. '</small>\n|-\n'

    end

    --/// 

]] 



--[[ 

]] 

--

local values = {}

for key, value in pairs(args) do

    if key == key and value ~= "" then

        table.insert(values, {key = key, value = value})

    end

end

--[[local function generateUUID()

    return uuid()

end

]] 

local function extractNumber(key)

    return tonumber(key:match("^%d+")) or 0

end







--❗ Insertion Sort algorithm

for i = 1, #values do

    local current = valuesi

    local j = i - 1

    while j > 0 and (extractNumber(valuesj].key) > extractNumber(current.key) or 

                     (extractNumber(valuesj].key) == extractNumber(current.key) and valuesj].key > current.key)) do

        valuesj + 1 = valuesj

        j = j - 1

    end

    valuesj + 1 = current

end





 --[[ 

table.sort(values, function(a, b)

    local aKey = a.key:match(".*%*$") and 1 or 0

    local bKey = b.key:match(".*%*$") and 1 or 0



    -- Keys with asterisks should come before keys without asterisks

    if aKey ~= bKey then

        return aKey < bKey

    else

        if aKey == 1 and bKey == 1 then

            return a.key < b.key

        elseif aKey == 0 and bKey == 0 then

            local numA = tonumber(a.key)

            local numB = tonumber(b.key)

            if numA and numB then

                return numA < numB

            else

                return a.key < b.key

            end

        else

            -- If one has asterisk and the other doesn't, prioritize the one with the asterisk

            return aKey == 1

        end

    end

end)

]] 

--[[



--Insertion Sort algorithm for modified_key

for i = 2, #values do

    local current = values[i]

    local j = i - 1

    while j > 0 and values[j].key > current.key do

        values[j + 1] = values[j]

        j = j - 1

    end

    values[j + 1] = current

end

 

for i = 2, #values do

    local current = values[i]

    local j = i - 1

    while j > 0 and values[j].key > current.key do

        values[j + 1] = values[j]

        j = j - 1

    end

    values[j + 1] = current

end

]] 



local matchedKeys = {}

local bgStyles = {}  -- Table to store background styles for each matched key

local generatedColors = {}  





for _, entry in ipairs(values) do

    local key = entry.key

    local value = entry.value

    local modified_key = key:gsub("^[%d]*", "")

    local found_alpha = false 

    

    for i = 1, #modified_key do

        if modified_key:sub(i, i):match("%a") then

            modified_key = modified_key:sub(1, i - 1) .. modified_key:sub(i, i):upper() .. modified_key:sub(i + 1)

            found_alpha = true

            break

        end

    end

    

    if not found_alpha then

        modified_key = modified_key:gsub("^.", string.upper, 5) 

    end

    

    local matched = false

    repeat

        local bgs = modified_key:match(".*%*$") or ""

        if bgs ~= "" and not matchedKeysmodified_key then

            local bgStyle = bgStylesmodified_key

            if not bgStyle then

                local manualBgColor = args"bgColor_" .. (modified_key:match(".*%*$"))] or ""

                local manualTextColor = args"textColor_" .. (modified_key:match(".*%*$"))] or ""

                local bgColor, textColor



                if generatedColorsmodified_key then

                    bgColor, textColor = generatedColorsmodified_key].bgColor, generatedColorsmodified_key].textColor

                else

                    local randf1=args.rd1 =="yes" or args.Rd1=="yes" 

                    local randf2=args.rd2 =="yes" or args.Rd2=="yes" 

                    local randf3=args.rd3 =="yes" or args.Rd3=="yes" 

                    local randf4=args.rd4 =="yes" or args.Rd4=="yes" 

                    local randf5=args.rd5 =="yes" or args.Rd5=="yes" 

                    local randf6=args.rd6 =="yes" or args.Rd6=="yes" 

                    local randf7=args.rd7 =="yes" or args.Rd7=="yes" 

                    local randf8=args.rd8 =="yes" or args.Rd8=="yes" 

                    local randf9=args.rd9 =="yes" or args.Rd9=="yes" 

                    local randf10=args.rd10 =="yes" or args.Rd10=="yes" 

                    local randf11=args.rd11 =="yes" or args.Rd11=="yes" 

                    local randf12=args.rd12 =="yes" or args.Rd12=="yes" 



                    if manualBgColor ~= "" and manualTextColor ~= "" then

                        bgColor = manualBgColor

                        textColor = manualTextColor

                    elseif randf1 then

                        bgColor = generateEvenLighterColor1()

                        textColor = getContrastingTextColor(bgColor)

                    elseif randf2 then

                        bgColor = generateVeryLightColor2()

                        textColor = getContrastingTextColor(bgColor)

                    elseif randf3 then

                        bgColor = generateLightColor3()

                        textColor = getContrastingTextColor(bgColor)

                    elseif randf4 then

                        bgColor = generateDarkColor4()

                        textColor = getContrastingTextColor(bgColor)

                    elseif randf5 then

                        bgColor = generateDarkColor5()

                        textColor = getContrastingTextColor(bgColor)

                    elseif randf6 then

                        bgColor = generateDarkColor6()

                        textColor = getContrastingTextColor(bgColor) 

                    elseif randf7 then

                        bgColor = generateDarkColor7()

                        textColor = getContrastingTextColor(bgColor)

                    elseif randf8 then

                        bgColor = generateDarkColor8()

                        textColor = getContrastingTextColor(bgColor)

                    elseif randf9 then

                        bgColor = generateDarkColor9()

                        textColor = getContrastingTextColor(bgColor)

                    elseif randf10 then

                        bgColor = generateDarkColor10() 

                        textColor = getContrastingTextColor(bgColor)

                    elseif randf11 then

                        bgColor = generateRandomColor()

                        textColor = getContrastingTextColor(bgColor)

                    else

                        bgColor = "#" .. string.format("%06x", math.random(0x000000, 0xFFFFFF))

                        bgColor = bgColor .. "00" -- append alpha value (00 for fully transparent)

                        textColor = "#000000"

                    end



                    generatedColorsmodified_key = {bgColor = bgColor, textColor = textColor}

                end



                bgStyle = string.format("background-color: %s; color: %s;", bgColor, textColor)

                bgStylesmodified_key = bgStyle

            end

            for _, val in pairs(args) do

                if val == value and val ~= "" then

                    local alreadyAdded = string.match(output, val:gsub("^%l", string.upper))

                    if not alreadyAdded then

                        output = output .. string.format('<tr><th colspan="2" style="%s; %s; font-size:16px; text-align:center; font-weight:bold;">%s</th>\n</tr>\n', args.style or "", bgStyle, val:gsub("^%l", string.upper))

                        matchedKeysmodified_key = true

                        matched = true

                        break

                    end

                end

            end

        end

        modified_key = modified_key:gsub("%*+$", "")  -- Remove the last asterisks

    until not modified_key:match(".*%*+%*$") or matched



    

 --[[ local randFlag = args["*rand"] == "yes" -- Check if *rand=yes flag is present

    if randFlag then

        bgColor = generateRandomColor() -- Generate a random color

    else

        -- Handle other cases or default behavior for background color

    end 

   ]] 

-- Handle infinite occurrences of modified_key:match(".*%*$")

















    --local modified_key = key:gsub("^%D*(%d+).*", "%1")

  --[[

  if tonumber(string.sub(key, 1, 1)) ~= nil then

        modified_key= string.sub(key, 2)  -- Exclude the first character if it's a number

       

    end

   ]] 

   

   

        if key ~= 'image'and not key:match("^image[%a%d]+$") --[[and not (key:sub(1, 5)=="image")]] 

            and key ~= 'caption' and not key:match(".*%*$") 

            and key ~= 'headcolor' and key ~= 'color' and key~='header' 

            and not key:match("^abv%d+$")and not key:match("^up[%a%d]+$") and not key:match("^%d+mdl[%a%d]+$") then

            if key ~= 'up' and not (key:sub(1, 2) == 'up'=="image"and upProcessed) and key ~= 'abv'and key~="imagesize" and key~="rd" and not abvProcessed and not key:match("^Rd%d+$")then

              --if key ~= 'up' and not (key:sub(1, 2) == 'up' and upProcessed)  then

            if key ~= 'abv' and not (key:sub(1, 3) == 'abv' and abvProcessed) and not key:match("^rd%d+$") and not key:match("^mdl[%a%d]+$")then

            if key~="size" and not key:match("^size[%a%d]+$")and not(key:sub(-1)=="+") and not key:match("^caption[%a%d]+$") and key~="rd"and not(key:sub(1, 3)=="mdl")  and not key:match("^(%d+)mdl") then 

                  --//m 

                  

                  local convertedValue = value

                local originalValue = value  

                    if not cmProcessed and (value:match("%s*cm#%s*")or value:match("%s*centimeters#%s*")or value:match("%s*centimetres#%s*") or value:match("%s*centimeter#%s*") or value:match("%s*centimetre#%s*")) then

                    -- If centimeters conversion not done yet, do it here

                      --cmProcessed = true

                        convertedValue = cmToFeetAndInches(value)

                end

                    --/////❗ 

                 if type(value) == "string" then

                      

                       local age=dateCalculation(value)

                      --[[]] 

                       --local ag = calculateAg(value )

                      --if value:match("%d%d%d%d[/.-]%d%d[/.-]%d%d[./-]") then 

                      if value:match("%d+%d+%d+[./-]") then

                       --value =value:gsub("(%d%d%d%d)[/.-](%d%d)[/.-](%d%d)[./-]", "%1".. age )--:gsub("(%d%d%d%d)", "") 

                        value =value:gsub("(%d+%d+%d+)[/.-]", "".. age ):gsub("%d+[./-]", "")--:gsub("(%d%d%d%d)[/.-](%d%d)[/.-](%d%d)[./-]", "".. age ) 

                     --else 

                     	--value="Invalid date format"

                      end

                     --end

                        value = value:gsub("(%d+[/.%-]+%d+[/.%-]+%d+[%d/.%-]*)", ""):gsub("(%d+[/.%-]+%d+[/.%-]+%d+[%d/.%-]*)", ""):gsub("<i></i>", "")

                        value = value:gsub("(%d+[/.,-]%d+[/.,-]%d+)", "")

            

--[[ 

if value:match("%d+%d+%d+[/.,~]") then

    value = value:gsub("(%d+%d+%d+)[/.,~]", "%1<i></i>"..age)

end



value = value:gsub("(%d%d%d%d)[. /-] (%d%d)[/-.] (%d%d)", ""):gsub("(%d%d)[. - /] (%d%d)", ""):gsub("<i></i>", "")

--value = value:gsub("(%d%d%d%d)%p(%d%d)%p(%d%d)", ""):gsub("<i></i>", "")

]] 





                    if value:match("%s*cm%W%s*")or value:match("%s*centimeters#%s*")or value:match("%s*centimetres#%s*") or value:match("%s*centimeter#%s*") or value:match("%s*centimetre#%s*")   then

                        convertedValue = cmToFeetAndInches(value)..""

                    elseif value:match("%s*kg%W%s*") or value:match("%s*kgs#%s*")or value:match("%s*kilograms#%s*") or value:match("%s*kilogram#%s*") then

                        convertedValue = kgToPounds(value)

                    elseif value:match("%s*mph#%s*")or value:match("%s*mp/h#%s*")or value:match("%s*miles per hour#%s*")or value:match("%s*mile per hour#%s*") then

                        convertedValue = mphToKmh(value)

                    elseif value:match("%s*kmh#%s*")or value:match("%s*km/h#%s*")or value:match("%s*kilometers per hour#%s*")or value:match("%s*kilometer per hour#%s*")or value:match("%s*kilometres per hour#%s*")or value:match("%s*kilometre per hour#%s*") then

                        convertedValue = kmhToMph(value)

                    elseif value:match("%s*kms#%s*")or value:match("%s*km#%s*")or value:match("%s*kilometer#%s*")or value:match("%s*kilometers#%s*")or value:match("%s*kilometre#%s*")or value:match("%s*kilometres#%s*") then

                        convertedValue = kmToMi(value)

                    elseif value:match("%s*mi#%s*")or value:match("%s*mile#%s*")or value:match("%s*miles#%s*") then

                        convertedValue = miToKm(value)

                    elseif value:match("%s*hp#%s*")or value:match("%s*hps#%s*")or value:match("%s*horsepower#%s*")or value:match("%s*horsepowers#%s*") then

                        convertedValue = hpToKw(value)

                    elseif value:match("%s*kw#%s*")or value:match("%s*kws#%s*")or value:match("%s*kilowatt#%s*")or value:match("%s*kilowatts#%s*") then

                        convertedValue = kwToHp(value)                    elseif value:match("%s*ft#%s*") then                                          elseif value:match("%s*lb#%s*")or value:match("%s*pound#%s*")or value:match("%s*pounds#%s*") then

                        convertedValue = lbToKg(value)

                    elseif value:match("%s*mmms#%s*")or value:match("%s*mm#%s*")or value:match("%s*millimeter#%s*")or value:match("%s*millimetre#%s*")or value:match("%s*millimeters#%s*")or value:match("%s*millimetres#%s*") then

                        convertedValue = mmToInches(value)

                    elseif value:match("%s*in#%s*")or value:match("%s*ins#%s*")or value:match("%s*inch#%s*")or value:match("%s*inche#%s*")or value:match("%s*inches#%s*") then

                        convertedValue = inchesToMm(value)

                    elseif value:match("%s*ms#%s*")or value:match("%s*millisecond#%s*")or value:match("%s*milliseconds#%s*")  then

                        convertedValue = msToFts(value)

                    elseif value:match("%s*fts#%s*")or value:match("%s*ft/s#%s*")or value:match("%s*fps#%s*")or value:match("%s*footperseconds#%s*") then

                        convertedValue = ftsToMs(value)

                    elseif value:match("%s*°c#%s*") or value:match("%s*celsius#%s*") or value:match("%s*Celsius#%s*")  then

                        convertedValue = celsiusToFahrenheit(value)

                    elseif value:match("%s*°f#%s*") or value:match("%s*fahrenheit#%s*") then

                        convertedValue = fahrenheitToCelsius(value)

                   --❗ 

                        elseif value:match("%s*liters#%s*")or value:match("%s*litres#%s*")or value:match("%s*litre#%s*")or value:match("%s*liter#%s*") then

                        convertedValue = litersToGallons(value)

                    elseif value:match("%s*gallons#%s*")or value:match("%s*gallon#%s*") then

                        convertedValue = gallonsToLiters(value)

                    elseif value:match("%s*m³#%s*")or value:match("%s*m3#%s*")or value:match("%s*cubicmeters#%s*")or value:match("%s*cubicmetres#%s*")or value:match("%s*cubicmetre#%s*")or value:match("%s*cubicmeter#%s*") then

                        convertedValue = cubicMetersToCubicFeet(value)

                    elseif value:match("%s*ft³#%s*")or value:match("%s*ft3#%s*")or value:match("%s*cubicfeet#%s*")or value:match("%s*cubicfoot#%s*")or value:match("%s*cubicfeets#%s*")or value:match("%s*cubicfoots#%s*") then

                    	convertedValue = cubicFeetToCubicMeters(value)                                         elseif value:match("%s*sqm#%s*")or value:match("%s*sqms#%s*")or value:match("%s*sqmetre#%s*")or value:match("%s*sqmetres#%s*")or value:match("%s*squaremeter#%s*")or value:match("%s*squaremeters#%s*")or value:match("%s*sqmeter#%s*")or value:match("%s*sqmeters#%s*") then

                        convertedValue = squareMetersToSquareFeet(value)

                    elseif value:match("%s*sqft#%s*")or value:match("%s*sqfoot#%s*")or value:match("%s*sqfeet#%s*")or value:match("%s*squarefoots#%s*")or value:match("%s*squarefeets#%s*")or value:match("%s*squarefeet#%s*") then

                        convertedValue = squareFeetToSquareMeters(value)

                    elseif value:match("%s*hectares#%s*")or value:match("%s*hectare#%s*") then

                        convertedValue = hectaresToAcres(value)

                    elseif value:match("%s*acres#%s*")or value:match("%s*acre#%s*") then

                        convertedValue = acresToHectares(value)

                    elseif value:match("%s*hours#%s*")or value:match("%s*hour#%s*") then

                        convertedValue = hoursToMinutes(value)

                    elseif value:match("%s*minutes#%s*")or value:match("%s*minute#%s*") then

                        convertedValue = minutesToHours(value)

                    elseif value:match("%s*days#%s*")or value:match("%s*day#%s*") then

                        convertedValue = daysToHours(value)

                    elseif value:match("%s*joules#%s*")or value:match("%s*joule#%s*") then

                        convertedValue = joulesToCalories(value)

                    elseif value:match("%s*calories#%s*")or value:match("%s*calorie#%s*") then

                        convertedValue = caloriesToJoules(value)

                    elseif value:match("%s*kwh#%s*")or value:match("%s*kilowatthours#%s*")or value:match("%s*kilowatthour#%s*") then

                        convertedValue = kilowattHoursToJoules(value)

                    elseif value:match("%s*psi#%s*")or value:match("%s*pounds per square inch#%s*")or value:match("%s*pound per square inches#%s*") then

                        convertedValue = psiToPascals(value)

                    elseif value:match("%s*pascals#%s*")or value:match("%s*pascal#%s*") then

                        convertedValue = pascalsToPsi(value)

                    elseif value:match("%s*atm#%s*")or value:match("%s*atmospheres#%s*")or value:match("%s*atmosphere#%s*") then

                        convertedValue = atmospheresToPascals(value)

                    elseif value:match("%s*rpm#%s*") then

                        convertedValue = rpmToHertz(value)

                    elseif value:match("%s*kilohertz#%s*")or value:match("%s*khz#%s*") then

                        convertedValue = kilohertzToHertz(value)

                    elseif value:match("%s*hertz#%s*") then

                        convertedValue = hertzToRPM(value)

                    elseif value:match("%s*horsepower#%s*") then

                        convertedValue = horsepowerToWatts(value)

                    elseif value:match("%s*megawatts#%s*") or value:match("%s*megawatt#%s*")then

                        convertedValue = megawattsToHorsepower(value)

                    elseif value:match("%s*watts#%s*") or value:match("%s*watt#%s*")then

                        convertedValue = wattsToHorsepower(value)

                    elseif value:match("%s*hp#%s*") then

                        convertedValue = horsepowerToMegawatts(value)

                    elseif value:match("%s*m#%s*")or value:match("%s*meters#%s*")or value:match("%s*metres#%s*")or value:match("%s*meter#%s*")or value:match("%s*metre#%s*") then

                        convertedValue = mToFeet(value)

                    elseif value:match("%s*ft%W%s*") or value:match("%s*feet%P%s*")or value:match("%s*feets%P%s*")or value:match("%s*foot%P%s*")or value:match("%s*foots%P%s*") then

                       --local ft=convertedValue 

                        --convertedValue =convertValue:gsub("^ft[%a%d]+$", "" .. ft) --ftToCm(value)

                    value =ftToCm(value)

                    

                   end 

                    --local age=calculateAge(value)

                    --value = value:gsub("(%d+[/.,-]%d+[/.,-]%d+)", "")



                    

        --❗            modified_key = key:gsub("^[_%d]*", "")



        

                   value = value:gsub("^%l", string.upper)

                   local first_char = value:match("%a") -- Find the first alphabet character

                   if first_char then

                      value = value:gsub("^" .. first_char, string.upper) -- Capitalize the first alphabet character

                   end

                    output = output .. '| style="font-size:15px; font-weight:bolder;padding-right:1em;" | ' ..modified_key:gsub("^[_()%-%d]*", "") .. "\n"

                    if originalValue ~= convertedValue then

                       output = output .. '| '..convertedValue.. '\n|-\n'

                    else

                        output = output .. '| ' .. value .. '\n|-\n' 

                    end

                    



                  end

            	end

            

             end

          end

      end

end





                  

--[[



local values = {}



for key, value in pairs(args) do

    if key:sub(1, 3) == 'abv' and value ~= "" then

        table.insert(values, {key = key, value = value})

    end

end

table.sort(values, function(a, b) return a.key < b.key end)

for _, entry in ipairs(values) do

    local key = entry.key

    local value = entry.value

    output = output .. '| style="background:lightgray;font-size:20px;text-align:center;background-color:' .. (args.abvheadcolor or "#f2f2f2") .. ';color:' .. (args.abvcolor or "inherit") .. ';font-weight:bold;" | ' .. value .. '\n|-\n'

end

mw.text.unstrip



local frame = mw.getCurrentFrame()

--local infoboxContent = frame:preprocess('{{User:Thisasia/Signature|' ..value..'}}')



local function transcludeTemplate(templateName, args)

    local frame = mw.getCurrentFrame()

    local templateContent = frame:expandTemplate { title = templateName, args = args }

    return templateContent

end

]] 

--local frame = mw.getCurrentFrame()

local values = {}



for key, value in pairs(args) do

    if key:sub(1, 3) == "abv" and value ~= "" then

        table.insert(values, { key = key, value = value, position = mw.ustring.match(key, "%d+") })

    end

end



table.sort(values, function(a, b) return tonumber(a.position) < tonumber(b.position) end)



for _, entry in ipairs(values) do

    local key = entry.key

    local value = entry.value

    value = value:gsub("^%l", string.upper)

    local first_char = value:match("%a") -- Find the first alphabet character

    if first_char then

        value = value:gsub("^" .. first_char, string.upper) -- Capitalize the first alphabet character

    end

    output = output .. '<tr><th colspan="2" style="font-size:20px;text-align:center;background-color:' .. (args.downheader or "rgba(0,0,0,0.020)") .. ';color:' .. (args.downcolor or "") .. ';font-weight:bold;"> '.. value .. '</th></tr>\n|-\n'

--output = mw.getCurrentFrame():preprocess('{{User:Thisasia/sandbox3|\n' .. output .. '}}')

end

   output = output .. '</div>\n'

--   output = mw.getCurrentFrame():preprocess('{{User:Thisasia/sandbox3|\n' .. output .. '}}')

    return output

end



return p

Videos

Youtube | Vimeo | Bing

Websites

Google | Yahoo | Bing

Encyclopedia

Google | Yahoo | Bing

Facebook