پرش به محتوا

پودمان:AlborzEducation: تفاوت میان نسخه‌ها

از ویکی البرز
جزبدون خلاصۀ ویرایش
جزبدون خلاصۀ ویرایش
خط ۲: خط ۲:
-- Module:AlborzEducation
-- Module:AlborzEducation
-- Wiki Alborz Education Infobox Engine
-- Wiki Alborz Education Infobox Engine
--
-- Rendering engine for education information boxes.
-- Configuration is stored in Module:AlborzEducation/Data
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local p = {}
local p = {}
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- CSS CLASSES
-- CONFIGURATION
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local INFOBOX_CLASS = "infobox education-infobox"
local INFOBOX_CLASS = "infobox education-infobox"
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- LOAD DATA
-- LOAD DATA
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local data = mw.loadData("Module:AlborzEducation/Data")
local data = mw.loadData("Module:AlborzEducation/Data")
--------------------------------------------------------------------------------
 
-- LOCAL REFERENCES
local lookup = data.lookup
--------------------------------------------------------------------------------
local fields = data.fieldDefinitions
local lookup = data.lookup
local fields = data.fieldDefinitions
local layouts = data.layouts
local layouts = data.layouts
local groups = data.groups
local groups = data.groups
 
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- BASIC UTILITIES
-- BASIC UTILITIES
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local function trim(value)
local function trim(value)
     if not value then
 
     if value == nil then
         return nil
         return nil
     end
     end
     value = mw.text.trim(tostring(value))
     value = mw.text.trim(tostring(value))
     return value ~= "" and value or nil
 
     if value == "" then
        return nil
    end
 
    return value
 
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- ARGUMENT HANDLING
-- ARGUMENTS
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local function getArgs(frame)
local function getArgs(frame)
     local args = {}
     local args = {}
     for key, value in pairs(frame.args) do
 
         key = trim(key)
     for k,v in pairs(frame.args) do
         value = trim(value)
 
         if key and value then
         k = trim(k)
             args[key] = value
         v = trim(v)
 
         if k and v then
             args[k] = v
         end
         end
     end
     end
     return args
     return args
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- NORMALIZE PARAMETERS
-- NORMALIZE PARAMETER NAMES
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local function normalizeArgs(args)
local function normalizeArgs(args)
     local result = {}
     local result = {}
     for key, value in pairs(args) do
 
         result[lookup[key] or key] = value
     for key,value in pairs(args) do
 
         local newKey = lookup[key] or key
 
        result[newKey] = value
 
     end
     end
     return result
     return result
end
--------------------------------------------------------------------------------
-- FIELD VALUE
--------------------------------------------------------------------------------
local function getFieldValue(args,name)
    if args[name] then
        return args[name]
    end
    local def = fields[name]
    if def and def.default then
        return def.default
    end
    return nil
end
--------------------------------------------------------------------------------
-- IMAGE HELPER
--------------------------------------------------------------------------------
local function imageMarkup(file,width)
    if not file then
        return nil
    end
    width = width or "250px"
    return string.format(
        "[[پرونده:%s|%s|center]]",
        file,
        width
    )
end
--------------------------------------------------------------------------------
-- URL NORMALIZER
--------------------------------------------------------------------------------
local function normalizeUrl(url)
    url = trim(url)
    if not url then
        return nil
    end
    if not url:match("^https?://") then
        url = "https://" .. url
    end
    return url
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- FIELD VALUE GETTER
-- SOCIAL ID EXTRACTOR
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local function getFieldValue(args, fieldName)
 
     local value = args[fieldName]
local function extractId(value)
     if value then
 
         return value
     value = trim(value)
 
     if not value then
         return nil
     end
     end
     local definition = fields[fieldName]
 
     return definition and definition.default or nil
    value = value:gsub("^https?://","")
    value = value:gsub("^www%.","")
    value = value:gsub("^instagram%.com/","")
    value = value:gsub("^t%.me/","")
     value = value:gsub("^aparat%.com/","")
    value = value:gsub("^@","")
    value = value:gsub("/$","")
 
     return value
 
end
end
--------------------------------------------------------------------------------
-- BOOLEAN FORMATTER
--------------------------------------------------------------------------------
local function formatBoolean(value)
    local yes = {
        ["بله"]=true,
        ["بلی"]=true,
        ["yes"]=true,
        ["Yes"]=true,
        ["YES"]=true,
        ["true"]=true,
        ["True"]=true,
        ["TRUE"]=true,
        ["1"]=true
    }
    if yes[tostring(value)] then
        return "دارد"
    end
    return "ندارد"
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- FIELD RENDERING
-- FIELD RENDERING
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- FIELD RENDERING
--------------------------------------------------------------------------------
local function renderField(fieldName, value)
local function renderField(fieldName, value)
     local field = fields[fieldName]
     local field = fields[fieldName]
     if not field or not value then
     if not field or not value then
         return nil
         return nil
     end
     end
     local label = field.label
 
     local fieldType = field.type
     ------------------------------------------------------------------------
     -- Image fields
     -- IMAGE
     if fieldType == "image" then
     ------------------------------------------------------------------------
 
     if field.type == "image" then
 
        local width = "250px"
 
        if fieldName == "logo" then
            width = "120px"
        end
 
         return mw.html.create("tr")
         return mw.html.create("tr")
             :tag("td")
             :tag("td")
                 :attr("colspan", "2")
                 :attr("colspan", "2")
                 :addClass("education-infobox-image")
                 :addClass("education-infobox-image")
                 :wikitext(string.format("[[پرونده:%s|250px|center]]", value))
                 :css("text-align", "center")
                :wikitext(imageMarkup(value, width))
                 :done()
                 :done()
    end
    ------------------------------------------------------------------------
    -- BOOLEAN
    ------------------------------------------------------------------------
    if field.type == "boolean" then
        value = formatBoolean(value)
     end
     end
     -- Boolean fields
 
     if fieldType == "boolean" then
    ------------------------------------------------------------------------
         if value == "yes" or value == "بله" or value == "true" or value == "1" then
     -- WEBSITE
             value = "دارد"
    ------------------------------------------------------------------------
         else
 
             value = "ندارد"
     if fieldName == "website" then
 
        local url = normalizeUrl(value)
 
         value = string.format(
            "[%s وبگاه رسمی]",
            url
        )
 
    ------------------------------------------------------------------------
    -- EMAIL
    ------------------------------------------------------------------------
 
    elseif field.type == "email" then
 
        value = string.format(
            "[mailto:%s %s]",
            value,
            value
        )
 
    ------------------------------------------------------------------------
    -- INSTAGRAM
    ------------------------------------------------------------------------
 
    elseif fieldName == "instagram" then
 
        if not value:match("^{{") then
 
            local id = extractId(value)
 
            value = string.format(
                "[https://instagram.com/%s @%s]",
                id,
                id
            )
 
        end
 
    ------------------------------------------------------------------------
    -- TELEGRAM
    ------------------------------------------------------------------------
 
    elseif fieldName == "telegram" then
 
        if not value:match("^{{") then
 
            local id = extractId(value)
 
            value = string.format(
                "[https://t.me/%s @%s]",
                id,
                id
            )
 
        end
 
    ------------------------------------------------------------------------
    -- APARAT
    ------------------------------------------------------------------------
 
    elseif fieldName == "aparat" then
 
        if not value:match("^{{") then
 
            local id = extractId(value)
 
             value = string.format(
                "[https://www.aparat.com/%s صفحهٔ آپارات]",
                id
            )
 
         end
 
    ------------------------------------------------------------------------
    -- WIKIPEDIA
    ------------------------------------------------------------------------
 
    elseif fieldName == "wikipedia" then
 
        if not value:match("^%[%[") then
             value = string.format("[[%s]]", value)
         end
         end
    ------------------------------------------------------------------------
    -- OTHER URL FIELDS
    ------------------------------------------------------------------------
    elseif field.type == "url" then
        local url = normalizeUrl(value)
        value = string.format(
            "[%s %s]",
            url,
            value
        )
     end
     end
     -- URL fields
 
     if fieldType == "url" then
     ------------------------------------------------------------------------
        value = string.format("[%s %s]", value, value)
     -- NORMAL ROW
    end
     ------------------------------------------------------------------------
     -- Normal text fields
 
     local row = mw.html.create("tr")
     local row = mw.html.create("tr")
     row:tag("th"):wikitext(label):done()
 
     row:tag("td"):wikitext(value):done()
     row:tag("th")
        :wikitext(field.label)
 
     row:tag("td")
        :wikitext(value)
 
     return row
     return row
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- INFOBOX TITLE
-- TITLE
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local function renderTitle(args)
 
     local title = getFieldValue(args, "fullname") or getFieldValue(args, "name")
local function renderTitle(box, args)
     if not title then
 
         return nil
    local logo = getFieldValue(args, "logo")
     local title = getFieldValue(args, "fullname")
        or getFieldValue(args, "name")
 
    ------------------------------------------------------------------------
    -- LOGO
    ------------------------------------------------------------------------
 
    if logo then
 
        box:tag("tr")
            :tag("td")
                :attr("colspan", "2")
                :addClass("education-infobox-logo")
                :css("text-align", "center")
                :css("padding", "8px")
                :wikitext(imageMarkup(logo, "120px"))
 
    end
 
    ------------------------------------------------------------------------
    -- TITLE
    ------------------------------------------------------------------------
 
     if title then
 
         box:tag("tr")
            :tag("th")
                :attr("colspan", "2")
                :addClass("education-infobox-title")
                :css("text-align", "center")
                :css("font-size", "120%")
                :css("font-weight", "bold")
                :css("padding", "8px")
                :wikitext(title)
 
     end
     end
    return mw.html.create("tr")
 
        :tag("th")
            :attr("colspan", "2")
            :addClass("education-infobox-title")
            :css({
                ["text-align"] = "center",
                ["font-size"] = "1.15em",
                ["font-weight"] = "bold",
                ["padding"] = "8px 6px"
            })
            :wikitext(title)
            :done()
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- IMAGE RENDERING
-- MAIN IMAGE
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local function renderImage(args)
 
local function renderImage(box, args)
 
     local image = getFieldValue(args, "image")
     local image = getFieldValue(args, "image")
     if not image then
     if not image then
         return nil
         return
     end
     end
     return mw.html.create("tr")
 
     local caption = getFieldValue(args, "caption")
 
    box:tag("tr")
         :tag("td")
         :tag("td")
             :attr("colspan", "2")
             :attr("colspan", "2")
             :addClass("education-infobox-image")
             :addClass("education-infobox-image")
             :wikitext(string.format("[[پرونده:%s|250px|center]]", image))
            :css("text-align", "center")
            :done()
             :wikitext(imageMarkup(image, "250px"))
 
    ------------------------------------------------------------------------
    -- IMAGE CAPTION
    ------------------------------------------------------------------------
 
    if caption then
 
        box:tag("tr")
            :tag("td")
                :attr("colspan", "2")
                :addClass("education-infobox-caption")
                :css("text-align", "center")
                :css("font-size", "90%")
                :css("padding", "4px 8px")
                :wikitext(caption)
 
    end
 
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- GROUP RENDERING
-- GROUP
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local function renderGroup(box, groupName, fieldList, args)
local function renderGroup(box, groupName, fieldList, args)
    local group = groups[groupName]
 
    if not group then
     local hasData = false
        return
 
    end
     for _, field in ipairs(fieldList) do
    -- Check whether the group has at least one visible field
         if getFieldValue(args, field) then
     local hasValue = false
             hasData = true
     for _, fieldName in ipairs(fieldList) do
         if getFieldValue(args, fieldName) then
             hasValue = true
             break
             break
         end
         end
     end
     end
     if not hasValue then
 
     if not hasData then
         return
         return
     end
     end
     -- Group header (وسط‌چین)
 
     local group = groups[groupName]
 
     box:tag("tr")
     box:tag("tr")
         :tag("th")
         :tag("th")
             :attr("colspan", "2")
             :attr("colspan", "2")
             :addClass("education-infobox-group")
             :addClass("education-infobox-group")
             :css({
             :css("text-align", "center")
                ["text-align"] = "center",
            :css("font-weight", "bold")
                ["font-weight"] = "bold",
            :css("padding", "6px")
                ["padding"] = "6px"
            })
             :wikitext((group.icon or "") .. " " .. group.label)
             :wikitext((group.icon or "") .. " " .. group.label)
    -- Fields
 
     for _, fieldName in ipairs(fieldList) do
     for _, field in ipairs(fieldList) do
         local value = getFieldValue(args, fieldName)
 
         local value = getFieldValue(args, field)
 
         if value then
         if value then
             local row = renderField(fieldName, value)
             local row = renderField(field, value)
 
             if row then
             if row then
                 box:node(row)
                 box:node(row)
             end
             end
         end
         end
     end
     end
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- LAYOUT RENDERING
-- LAYOUT
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
local function renderLayout(layoutName, args)
local function renderLayout(layoutName, args)
     local layout = layouts[layoutName]
     local layout = layouts[layoutName]
     if not layout then
     if not layout then
         return nil
         layout = layouts.school
     end
     end
     local box = mw.html.create("table"):addClass(INFOBOX_CLASS)
 
    -- Header
     local box = mw.html.create("table")
     local title = renderTitle(args)
        :addClass(INFOBOX_CLASS)
     if title then
 
        box:node(title)
     renderTitle(box, args)
    end
     renderImage(box, args)
    local image = renderImage(args)
 
    if image then
        box:node(image)
    end
    -- Content Groups
     for _, section in ipairs(layout) do
     for _, section in ipairs(layout) do
         renderGroup(box, section.group, section.fields, args)
 
         renderGroup(
            box,
            section.group,
            section.fields,
            args
        )
 
     end
     end
     return box
 
     return tostring(box)
 
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- MAIN FUNCTION
-- MAIN
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
function p.main(frame)
function p.main(frame)
     local args = normalizeArgs(getArgs(frame))
 
     local result = renderLayout("school", args)
     local args = normalizeArgs(
     return result and tostring(result) or ""
        getArgs(frame)
    )
 
    ------------------------------------------------------------------------
    -- انتخاب نوع چیدمان
    ------------------------------------------------------------------------
 
     local layout = "school"
 
    local t = (args.type or ""):lower()
 
    if t == "دانشگاه" or t == "university" then
 
        layout = "university"
 
    elseif t == "حوزه علمیه" or t == "seminary" then
 
        layout = "seminary"
 
    elseif t == "آموزشگاه" or t == "training_center" then
 
        layout = "training_center"
 
    elseif t == "پژوهشکده" or t == "research_center" then
 
        layout = "research_center"
 
    elseif t == "کالج" or t == "college" then
 
        layout = "college"
 
    elseif t == "مهدکودک" or t == "kindergarten" then
 
        layout = "kindergarten"
 
    end
 
     return renderLayout(layout, args)
 
end
end
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- RETURN MODULE
-- RETURN
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
return p
return p

نسخهٔ ‏۲۸ ژوئیهٔ ۲۰۲۶، ساعت ۱۸:۰۶

توضیحات این پودمان می‌تواند در پودمان:AlborzEducation/توضیحات قرار گیرد.

--------------------------------------------------------------------------------
-- Module:AlborzEducation
-- Wiki Alborz Education Infobox Engine
--------------------------------------------------------------------------------

local p = {}

--------------------------------------------------------------------------------
-- CONFIGURATION
--------------------------------------------------------------------------------

local INFOBOX_CLASS = "infobox education-infobox"

--------------------------------------------------------------------------------
-- LOAD DATA
--------------------------------------------------------------------------------

local data = mw.loadData("Module:AlborzEducation/Data")

local lookup  = data.lookup
local fields  = data.fieldDefinitions
local layouts = data.layouts
local groups  = data.groups

--------------------------------------------------------------------------------
-- BASIC UTILITIES
--------------------------------------------------------------------------------

local function trim(value)

    if value == nil then
        return nil
    end

    value = mw.text.trim(tostring(value))

    if value == "" then
        return nil
    end

    return value

end

--------------------------------------------------------------------------------
-- ARGUMENTS
--------------------------------------------------------------------------------

local function getArgs(frame)

    local args = {}

    for k,v in pairs(frame.args) do

        k = trim(k)
        v = trim(v)

        if k and v then
            args[k] = v
        end

    end

    return args

end

--------------------------------------------------------------------------------
-- NORMALIZE PARAMETER NAMES
--------------------------------------------------------------------------------

local function normalizeArgs(args)

    local result = {}

    for key,value in pairs(args) do

        local newKey = lookup[key] or key

        result[newKey] = value

    end

    return result

end

--------------------------------------------------------------------------------
-- FIELD VALUE
--------------------------------------------------------------------------------

local function getFieldValue(args,name)

    if args[name] then
        return args[name]
    end

    local def = fields[name]

    if def and def.default then
        return def.default
    end

    return nil

end

--------------------------------------------------------------------------------
-- IMAGE HELPER
--------------------------------------------------------------------------------

local function imageMarkup(file,width)

    if not file then
        return nil
    end

    width = width or "250px"

    return string.format(
        "[[پرونده:%s|%s|center]]",
        file,
        width
    )

end

--------------------------------------------------------------------------------
-- URL NORMALIZER
--------------------------------------------------------------------------------

local function normalizeUrl(url)

    url = trim(url)

    if not url then
        return nil
    end

    if not url:match("^https?://") then
        url = "https://" .. url
    end

    return url

end

--------------------------------------------------------------------------------
-- SOCIAL ID EXTRACTOR
--------------------------------------------------------------------------------

local function extractId(value)

    value = trim(value)

    if not value then
        return nil
    end

    value = value:gsub("^https?://","")
    value = value:gsub("^www%.","")
    value = value:gsub("^instagram%.com/","")
    value = value:gsub("^t%.me/","")
    value = value:gsub("^aparat%.com/","")
    value = value:gsub("^@","")
    value = value:gsub("/$","")

    return value

end

--------------------------------------------------------------------------------
-- BOOLEAN FORMATTER
--------------------------------------------------------------------------------

local function formatBoolean(value)

    local yes = {

        ["بله"]=true,
        ["بلی"]=true,
        ["yes"]=true,
        ["Yes"]=true,
        ["YES"]=true,
        ["true"]=true,
        ["True"]=true,
        ["TRUE"]=true,
        ["1"]=true

    }

    if yes[tostring(value)] then
        return "دارد"
    end

    return "ندارد"

end

--------------------------------------------------------------------------------
-- FIELD RENDERING
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- FIELD RENDERING
--------------------------------------------------------------------------------

local function renderField(fieldName, value)

    local field = fields[fieldName]

    if not field or not value then
        return nil
    end

    ------------------------------------------------------------------------
    -- IMAGE
    ------------------------------------------------------------------------

    if field.type == "image" then

        local width = "250px"

        if fieldName == "logo" then
            width = "120px"
        end

        return mw.html.create("tr")
            :tag("td")
                :attr("colspan", "2")
                :addClass("education-infobox-image")
                :css("text-align", "center")
                :wikitext(imageMarkup(value, width))
                :done()

    end

    ------------------------------------------------------------------------
    -- BOOLEAN
    ------------------------------------------------------------------------

    if field.type == "boolean" then
        value = formatBoolean(value)
    end

    ------------------------------------------------------------------------
    -- WEBSITE
    ------------------------------------------------------------------------

    if fieldName == "website" then

        local url = normalizeUrl(value)

        value = string.format(
            "[%s وبگاه رسمی]",
            url
        )

    ------------------------------------------------------------------------
    -- EMAIL
    ------------------------------------------------------------------------

    elseif field.type == "email" then

        value = string.format(
            "[mailto:%s %s]",
            value,
            value
        )

    ------------------------------------------------------------------------
    -- INSTAGRAM
    ------------------------------------------------------------------------

    elseif fieldName == "instagram" then

        if not value:match("^{{") then

            local id = extractId(value)

            value = string.format(
                "[https://instagram.com/%s @%s]",
                id,
                id
            )

        end

    ------------------------------------------------------------------------
    -- TELEGRAM
    ------------------------------------------------------------------------

    elseif fieldName == "telegram" then

        if not value:match("^{{") then

            local id = extractId(value)

            value = string.format(
                "[https://t.me/%s @%s]",
                id,
                id
            )

        end

    ------------------------------------------------------------------------
    -- APARAT
    ------------------------------------------------------------------------

    elseif fieldName == "aparat" then

        if not value:match("^{{") then

            local id = extractId(value)

            value = string.format(
                "[https://www.aparat.com/%s صفحهٔ آپارات]",
                id
            )

        end

    ------------------------------------------------------------------------
    -- WIKIPEDIA
    ------------------------------------------------------------------------

    elseif fieldName == "wikipedia" then

        if not value:match("^%[%[") then
            value = string.format("[[%s]]", value)
        end

    ------------------------------------------------------------------------
    -- OTHER URL FIELDS
    ------------------------------------------------------------------------

    elseif field.type == "url" then

        local url = normalizeUrl(value)

        value = string.format(
            "[%s %s]",
            url,
            value
        )

    end

    ------------------------------------------------------------------------
    -- NORMAL ROW
    ------------------------------------------------------------------------

    local row = mw.html.create("tr")

    row:tag("th")
        :wikitext(field.label)

    row:tag("td")
        :wikitext(value)

    return row

end
--------------------------------------------------------------------------------
-- TITLE
--------------------------------------------------------------------------------

local function renderTitle(box, args)

    local logo = getFieldValue(args, "logo")
    local title = getFieldValue(args, "fullname")
        or getFieldValue(args, "name")

    ------------------------------------------------------------------------
    -- LOGO
    ------------------------------------------------------------------------

    if logo then

        box:tag("tr")
            :tag("td")
                :attr("colspan", "2")
                :addClass("education-infobox-logo")
                :css("text-align", "center")
                :css("padding", "8px")
                :wikitext(imageMarkup(logo, "120px"))

    end

    ------------------------------------------------------------------------
    -- TITLE
    ------------------------------------------------------------------------

    if title then

        box:tag("tr")
            :tag("th")
                :attr("colspan", "2")
                :addClass("education-infobox-title")
                :css("text-align", "center")
                :css("font-size", "120%")
                :css("font-weight", "bold")
                :css("padding", "8px")
                :wikitext(title)

    end

end

--------------------------------------------------------------------------------
-- MAIN IMAGE
--------------------------------------------------------------------------------

local function renderImage(box, args)

    local image = getFieldValue(args, "image")

    if not image then
        return
    end

    local caption = getFieldValue(args, "caption")

    box:tag("tr")
        :tag("td")
            :attr("colspan", "2")
            :addClass("education-infobox-image")
            :css("text-align", "center")
            :wikitext(imageMarkup(image, "250px"))

    ------------------------------------------------------------------------
    -- IMAGE CAPTION
    ------------------------------------------------------------------------

    if caption then

        box:tag("tr")
            :tag("td")
                :attr("colspan", "2")
                :addClass("education-infobox-caption")
                :css("text-align", "center")
                :css("font-size", "90%")
                :css("padding", "4px 8px")
                :wikitext(caption)

    end

end
--------------------------------------------------------------------------------
-- GROUP
--------------------------------------------------------------------------------

local function renderGroup(box, groupName, fieldList, args)

    local hasData = false

    for _, field in ipairs(fieldList) do
        if getFieldValue(args, field) then
            hasData = true
            break
        end
    end

    if not hasData then
        return
    end

    local group = groups[groupName]

    box:tag("tr")
        :tag("th")
            :attr("colspan", "2")
            :addClass("education-infobox-group")
            :css("text-align", "center")
            :css("font-weight", "bold")
            :css("padding", "6px")
            :wikitext((group.icon or "") .. " " .. group.label)

    for _, field in ipairs(fieldList) do

        local value = getFieldValue(args, field)

        if value then
            local row = renderField(field, value)

            if row then
                box:node(row)
            end
        end

    end

end

--------------------------------------------------------------------------------
-- LAYOUT
--------------------------------------------------------------------------------

local function renderLayout(layoutName, args)

    local layout = layouts[layoutName]

    if not layout then
        layout = layouts.school
    end

    local box = mw.html.create("table")
        :addClass(INFOBOX_CLASS)

    renderTitle(box, args)
    renderImage(box, args)

    for _, section in ipairs(layout) do

        renderGroup(
            box,
            section.group,
            section.fields,
            args
        )

    end

    return tostring(box)

end

--------------------------------------------------------------------------------
-- MAIN
--------------------------------------------------------------------------------

function p.main(frame)

    local args = normalizeArgs(
        getArgs(frame)
    )

    ------------------------------------------------------------------------
    -- انتخاب نوع چیدمان
    ------------------------------------------------------------------------

    local layout = "school"

    local t = (args.type or ""):lower()

    if t == "دانشگاه" or t == "university" then

        layout = "university"

    elseif t == "حوزه علمیه" or t == "seminary" then

        layout = "seminary"

    elseif t == "آموزشگاه" or t == "training_center" then

        layout = "training_center"

    elseif t == "پژوهشکده" or t == "research_center" then

        layout = "research_center"

    elseif t == "کالج" or t == "college" then

        layout = "college"

    elseif t == "مهدکودک" or t == "kindergarten" then

        layout = "kindergarten"

    end

    return renderLayout(layout, args)

end

--------------------------------------------------------------------------------
-- RETURN
--------------------------------------------------------------------------------

return p